Message ID | xn4lbus7f7.fsf@greed.delorie.com |
---|---|
State | New |
Headers | show |
Series | test-container: unshare hints and su mode | expand |
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); > >
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);