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