Discussion:
[patch] test-container: unshare hints and su mode
(too old to reply)
DJ Delorie
2018-12-03 20:05:00 UTC
Permalink
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.

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);
Carlos O'Donell
2018-12-03 20:14:36 UTC
Permalink
Post by DJ Delorie
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.
Post by DJ Delorie
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;
# comment
+ su
OK.
Post by DJ Delorie
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.
Post by DJ Delorie
@@ -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.
Post by DJ Delorie
+ 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.
Post by DJ Delorie
+
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.
Post by DJ Delorie
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.
Post by DJ Delorie
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.
Post by DJ Delorie
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.
Post by DJ Delorie
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.
Post by DJ Delorie
write (GMAP, tmp, strlen (tmp));
xclose (GMAP);
--
Cheers,
Carlos.
DJ Delorie
2018-12-04 05:04:53 UTC
Permalink
Pushed. Thanks.
I keep forgetting to add that to my commit message :-P
Carlos O'Donell
2018-12-04 21:54:33 UTC
Permalink
Post by DJ Delorie
Pushed. Thanks.
I keep forgetting to add that to my commit message :-P
That's OK, I don't do it for the fame :-)

... but it does provide me with useful metrics for
figuring out if I'm doing enough reviews for the
community, or helping me hit review targets I set for
myself :-)
--
Cheers,
Carlos.
Loading...