deploy: Warn if we find content in the deployment's /var
authorColin Walters <walters@verbum.org>
Wed, 9 Jun 2021 13:44:09 +0000 (09:44 -0400)
committerColin Walters <walters@verbum.org>
Thu, 10 Jun 2021 11:33:17 +0000 (07:33 -0400)
This will be ignored, so let's make it very clear
people are doing something wrong.  Motivated by a bug
in a build pipeline that injected `/var/lib/rpm` into an ostree
commit which ended up crashing rpm-ostree because it was an empty db
which it wasn't expecting.

It *also* turns out rpm-ostree is incorrectly dumping content in the
deployment `/var` today, which is another bug.

src/libostree/ostree-sysroot-deploy.c
tests/kolainst/destructive/deployment-lint [new file with mode: 0755]

index 32748a62f58d808ad5d863c0f090ae186f0545c8..840775d4091c0afb1d7e96531cc6c787bf4bab6a 100644 (file)
@@ -2632,6 +2632,39 @@ _ostree_deployment_set_bootconfig_from_kargs (OstreeDeployment *deployment,
     }
 }
 
+// Perform some basic static analysis and emit warnings for things
+// that are likely to fail later.  This function only returns
+// a hard error if something unexpected (e.g. I/O error) occurs.
+static gboolean
+lint_deployment_fs (OstreeSysroot     *self,
+                    OstreeDeployment  *deployment,
+                    int                deployment_dfd,
+                    GCancellable      *cancellable,
+                    GError           **error)
+{
+  g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
+  glnx_autofd int dest_dfd = -1;
+  gboolean exists;
+
+  if (!ot_dfd_iter_init_allow_noent (deployment_dfd, "var", &dfd_iter, &exists, error))
+    return FALSE;
+  while (exists)
+    {
+      struct dirent *dent;
+
+      if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error))
+        return FALSE;
+      if (dent == NULL)
+        break;
+
+      fprintf (stderr, "note: Deploying commit %s which contains content in /var/%s that will be ignored.\n",
+                        ostree_deployment_get_csum (deployment),
+                        dent->d_name);
+    }
+
+  return TRUE;
+}
+
 /* The first part of writing a deployment. This primarily means doing the
  * hardlink farm checkout, but we also compute some initial state.
  */
@@ -2680,6 +2713,9 @@ sysroot_initialize_deployment (OstreeSysroot     *self,
                                cancellable, error))
     return FALSE;
 
+  if (!lint_deployment_fs (self, new_deployment, deployment_dfd, cancellable, error))
+    return FALSE;
+
   ot_transfer_out_value (out_new_deployment, &new_deployment);
   return TRUE;
 }
diff --git a/tests/kolainst/destructive/deployment-lint b/tests/kolainst/destructive/deployment-lint
new file mode 100755 (executable)
index 0000000..6981ebb
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+set -xeuo pipefail
+
+. ${KOLA_EXT_DATA}/libinsttest.sh
+
+require_writable_sysroot
+prepare_tmpdir
+
+mkdir -p rootfs/var/shouldntdothis/subdir
+ostree commit -b testlint --no-bindings --selinux-policy-from-base --tree=ref="${host_refspec}" --consume --tree=dir=rootfs
+ostree admin deploy testlint 2>err.txt
+assert_file_has_content err.txt 'Deploying commit.*which contains content in /var/shouldntdothis'
+echo "ok content in /var"