test-container: unshare hints and su mode

Message ID xn4lbus7f7.fsf@greed.delorie.com
State New
Headers show
Series
  • test-container: unshare hints and su mode
Related show

Commit Message

DJ Delorie Dec. 3, 2018, 8:05 p.m.
Adding "su" to your <test>.script causes the test to run with uid/gid
0/0 instead of the user's uid/gid.

Also a repeat of the unshare hints patch, with all corrections as
requested.

	* support/test-container.c (check_for_unshare_hints): New.
	(main): Call it if unshare fails.  Add support for "su" scriptlet
	command.

Comments

Carlos O'Donell Dec. 3, 2018, 8:14 p.m. | #1
On 12/3/18 3:05 PM, DJ Delorie wrote:
> Adding "su" to your <test>.script causes the test to run with uid/gid

> 0/0 instead of the user's uid/gid.


This is exactly what I need for my tst-localedef-hardlinks test which
exercises the --no-hard-link option.

OK with additional documentation requested below:

Reviewed-by: Carlos O'Donell <carlos@redhat.com>


> Also a repeat of the unshare hints patch, with all corrections as

> requested.

> 

> 	* support/test-container.c (check_for_unshare_hints): New.

> 	(main): Call it if unshare fails.  Add support for "su" scriptlet

> 	command.

> 

> diff --git a/support/test-container.c b/support/test-container.c

> index b58f0f7b3d..52ee787544 100644

> --- a/support/test-container.c

> +++ b/support/test-container.c

> @@ -91,6 +91,7 @@ int verbose = 0;

>     * mytest.root/mytset.script has a list of "commands" to run:

>         syntax:

>           # comment

> +         su


OK.

>           mv FILE FILE

>  	 cp FILE FILE

>  	 rm FILE


Underneth "syntax:" and nested at the same level I think we should
write:

 91    * mytest.root/mytset.script has a list of "commands" to run:
 92        syntax:
 93          # comment
 94          mv FILE FILE
 95          cp FILE FILE
 96          rm FILE
 97          FILE must start with $B/, $S/, $I/, $L/, or /
 98           (expands to build dir, source dir, install dir, library dir
 99            (in container), or container's root)
           details:
             - '#': A comment.
	     - 'mv': A minimal move files command.
             - 'cp': A minimal copy files command.
             - 'rm': A minimal remove files command.
             - 'su': Enables running test as root in the container.

These lines describe what we have above.

> @@ -610,6 +611,47 @@ rsync (char *src, char *dest, int and_delete)

>  }

>  

>  

> +

> +/* See if we can detect what the user needs to do to get unshare

> +   support working for us.  */

> +void

> +check_for_unshare_hints (void)

> +{

> +  FILE *f;

> +  int i;

> +

> +  /* Default Debian Linux disables user namespaces, but allows a way

> +     to enable them.  */

> +  f = fopen ("/proc/sys/kernel/unprivileged_userns_clone", "r");


OK.

> +  if (f != NULL)

> +    {

> +      i = 99; /* Sentinel.  */

> +      fscanf (f, "%d", &i);

> +      if (i == 0)

> +	{

> +	  printf ("To enable test-container, please run this as root:\n");

> +	  printf ("  echo 1 > /proc/sys/kernel/unprivileged_userns_clone\n");

> +	}

> +      fclose (f);

> +      return;

> +    }

> +

> +  /* ALT Linux has an alternate way of doing the same.  */

> +  f = fopen ("/proc/sys/kernel/userns_restrict", "r");

> +  if (f != NULL)

> +    {

> +      i = 99; /* Sentinel.  */

> +      fscanf (f, "%d", &i);

> +      if (i == 1)

> +	{

> +	  printf ("To enable test-container, please run this as root:\n");

> +	  printf ("  echo 0 > /proc/sys/kernel/userns_restrict\n");

> +	}

> +      fclose (f);

> +      return;

> +    }

> +}


OK.

> +

>  int

>  main (int argc, char **argv)

>  {

> @@ -628,6 +670,8 @@ main (int argc, char **argv)

>  

>    uid_t original_uid;

>    gid_t original_gid;

> +  /* If set, the test runs as root instead of the user running the testsuite.  */

> +  int be_su = 0;


OK.

>    int UMAP;

>    int GMAP;

>    /* Used for "%lld %lld 1" so need not be large.  */

> @@ -857,6 +901,10 @@ main (int argc, char **argv)

>  	      {

>  		maybe_xunlink (the_words[1]);

>  	      }

> +	    else if (nt == 1 && strcmp (the_words[0], "su") == 0)

> +	      {

> +		be_su = 1;

> +	      }


OK.

>  	    else if (nt > 0 && the_words[0][0] != '#')

>  	      {

>  		printf ("\033[31minvalid [%s]\033[0m\n", the_words[0]);

> @@ -873,7 +921,12 @@ main (int argc, char **argv)

>        /* Older kernels may not support all the options, or security

>  	 policy may block this call.  */

>        if (errno == EINVAL || errno == EPERM)

> -	FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (errno));

> +	{

> +	  int saved_errno = errno;

> +	  if (errno == EPERM)

> +	    check_for_unshare_hints ();

> +	  FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (saved_errno));

> +	}


OK.

>        else

>  	FAIL_EXIT1 ("unable to unshare user/fs: %s", strerror (errno));

>      }

> @@ -952,7 +1005,7 @@ main (int argc, char **argv)

>      FAIL_EXIT1 ("can't write to /proc/self/uid_map\n");

>  

>    sprintf (tmp, "%lld %lld 1\n",

> -	   (long long) original_uid, (long long) original_uid);

> +	   (long long) (be_su ? 0 : original_uid), (long long) original_uid);


OK.

>    write (UMAP, tmp, strlen (tmp));

>    xclose (UMAP);

>  

> @@ -973,7 +1026,7 @@ main (int argc, char **argv)

>      FAIL_EXIT1 ("can't write to /proc/self/gid_map\n");

>  

>    sprintf (tmp, "%lld %lld 1\n",

> -	   (long long) original_gid, (long long) original_gid);

> +	   (long long) (be_su ? 0 : original_gid), (long long) original_gid);


OK.

>    write (GMAP, tmp, strlen (tmp));

>    xclose (GMAP);

>  

> 



-- 
Cheers,
Carlos.

Patch

diff --git a/support/test-container.c b/support/test-container.c
index b58f0f7b3d..52ee787544 100644
--- a/support/test-container.c
+++ b/support/test-container.c
@@ -91,6 +91,7 @@  int verbose = 0;
    * mytest.root/mytset.script has a list of "commands" to run:
        syntax:
          # comment
+         su
          mv FILE FILE
 	 cp FILE FILE
 	 rm FILE
@@ -610,6 +611,47 @@  rsync (char *src, char *dest, int and_delete)
 }
 
 
+
+/* See if we can detect what the user needs to do to get unshare
+   support working for us.  */
+void
+check_for_unshare_hints (void)
+{
+  FILE *f;
+  int i;
+
+  /* Default Debian Linux disables user namespaces, but allows a way
+     to enable them.  */
+  f = fopen ("/proc/sys/kernel/unprivileged_userns_clone", "r");
+  if (f != NULL)
+    {
+      i = 99; /* Sentinel.  */
+      fscanf (f, "%d", &i);
+      if (i == 0)
+	{
+	  printf ("To enable test-container, please run this as root:\n");
+	  printf ("  echo 1 > /proc/sys/kernel/unprivileged_userns_clone\n");
+	}
+      fclose (f);
+      return;
+    }
+
+  /* ALT Linux has an alternate way of doing the same.  */
+  f = fopen ("/proc/sys/kernel/userns_restrict", "r");
+  if (f != NULL)
+    {
+      i = 99; /* Sentinel.  */
+      fscanf (f, "%d", &i);
+      if (i == 1)
+	{
+	  printf ("To enable test-container, please run this as root:\n");
+	  printf ("  echo 0 > /proc/sys/kernel/userns_restrict\n");
+	}
+      fclose (f);
+      return;
+    }
+}
+
 int
 main (int argc, char **argv)
 {
@@ -628,6 +670,8 @@  main (int argc, char **argv)
 
   uid_t original_uid;
   gid_t original_gid;
+  /* If set, the test runs as root instead of the user running the testsuite.  */
+  int be_su = 0;
   int UMAP;
   int GMAP;
   /* Used for "%lld %lld 1" so need not be large.  */
@@ -857,6 +901,10 @@  main (int argc, char **argv)
 	      {
 		maybe_xunlink (the_words[1]);
 	      }
+	    else if (nt == 1 && strcmp (the_words[0], "su") == 0)
+	      {
+		be_su = 1;
+	      }
 	    else if (nt > 0 && the_words[0][0] != '#')
 	      {
 		printf ("\033[31minvalid [%s]\033[0m\n", the_words[0]);
@@ -873,7 +921,12 @@  main (int argc, char **argv)
       /* Older kernels may not support all the options, or security
 	 policy may block this call.  */
       if (errno == EINVAL || errno == EPERM)
-	FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (errno));
+	{
+	  int saved_errno = errno;
+	  if (errno == EPERM)
+	    check_for_unshare_hints ();
+	  FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (saved_errno));
+	}
       else
 	FAIL_EXIT1 ("unable to unshare user/fs: %s", strerror (errno));
     }
@@ -952,7 +1005,7 @@  main (int argc, char **argv)
     FAIL_EXIT1 ("can't write to /proc/self/uid_map\n");
 
   sprintf (tmp, "%lld %lld 1\n",
-	   (long long) original_uid, (long long) original_uid);
+	   (long long) (be_su ? 0 : original_uid), (long long) original_uid);
   write (UMAP, tmp, strlen (tmp));
   xclose (UMAP);
 
@@ -973,7 +1026,7 @@  main (int argc, char **argv)
     FAIL_EXIT1 ("can't write to /proc/self/gid_map\n");
 
   sprintf (tmp, "%lld %lld 1\n",
-	   (long long) original_gid, (long long) original_gid);
+	   (long long) (be_su ? 0 : original_gid), (long long) original_gid);
   write (GMAP, tmp, strlen (tmp));
   xclose (GMAP);