d8307d
From 304c61a24f909168c16793ccf7c686237e53d003 Mon Sep 17 00:00:00 2001
d8307d
From: DJ Delorie <dj@redhat.com>
d8307d
Date: Wed, 5 Dec 2018 12:39:47 -0500
d8307d
Subject: test-container: move postclean outside of namespace changes
d8307d
d8307d
During postclean.req testing it was found that the fork in the
d8307d
parent process (after the unshare syscall) would fail with ENOMEM
d8307d
(see recursive_remove() in test-container.c).  While failing with
d8307d
ENOMEM is certainly unexpected, it is simply easier to refactor
d8307d
the design and have the parent remain outside of the namespace.
d8307d
This change moves the postclean.req processing to a distinct
d8307d
process (the parent) that then forks the test process (which will
d8307d
have to fork once more to complete uid/gid transitions). When the
d8307d
test process exists the cleanup process will ensure all files are
d8307d
deleted when a post clean is requested.
d8307d
d8307d
Signed-off-by: DJ Delorie <dj@redhat.com>
d8307d
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
d8307d
d8307d
[BZ #23948]
d8307d
* support/test-container.c: Move postclean step to before we
d8307d
change namespaces.
d8307d
d8307d
diff --git a/support/test-container.c b/support/test-container.c
d8307d
index df450adfdb..1d1aebeaf3 100644
d8307d
--- a/support/test-container.c
d8307d
+++ b/support/test-container.c
d8307d
@@ -921,6 +921,43 @@ main (int argc, char **argv)
d8307d
       }
d8307d
   }
d8307d
 
d8307d
+  if (do_postclean)
d8307d
+    {
d8307d
+      pid_t pc_pid = fork ();
d8307d
+
d8307d
+      if (pc_pid < 0)
d8307d
+	{
d8307d
+	  FAIL_EXIT1 ("Can't fork for post-clean");
d8307d
+	}
d8307d
+      else if (pc_pid > 0)
d8307d
+	{
d8307d
+	  /* Parent.  */
d8307d
+	  int status;
d8307d
+	  waitpid (pc_pid, &status, 0);
d8307d
+
d8307d
+	  /* Child has exited, we can post-clean the test root.  */
d8307d
+	  printf("running post-clean rsync\n");
d8307d
+	  rsync (pristine_root_path, new_root_path, 1);
d8307d
+
d8307d
+	  if (WIFEXITED (status))
d8307d
+	    exit (WEXITSTATUS (status));
d8307d
+
d8307d
+	  if (WIFSIGNALED (status))
d8307d
+	    {
d8307d
+	      printf ("%%SIGNALLED%%\n");
d8307d
+	      exit (77);
d8307d
+	    }
d8307d
+
d8307d
+	  printf ("%%EXITERROR%%\n");
d8307d
+	  exit (78);
d8307d
+	}
d8307d
+
d8307d
+      /* Child continues.  */
d8307d
+    }
d8307d
+
d8307d
+  /* This is the last point in the program where we're still in the
d8307d
+     "normal" namespace.  */
d8307d
+
d8307d
 #ifdef CLONE_NEWNS
d8307d
   /* The unshare here gives us our own spaces and capabilities.  */
d8307d
   if (unshare (CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNS) < 0)
d8307d
@@ -974,14 +1011,6 @@ main (int argc, char **argv)
d8307d
       int status;
d8307d
       waitpid (child, &status, 0);
d8307d
 
d8307d
-      /* There's a bit of magic here, since the buildroot is mounted
d8307d
-	 in our space, the paths are still valid, and since the mounts
d8307d
-	 aren't recursive, it sees *only* the built root, not anything
d8307d
-	 we would normally se if we rsync'd to "/" like mounted /dev
d8307d
-	 files.  */
d8307d
-      if (do_postclean)
d8307d
-	  rsync (pristine_root_path, new_root_path, 1);
d8307d
-
d8307d
       if (WIFEXITED (status))
d8307d
 	exit (WEXITSTATUS (status));
d8307d