|
|
e354a5 |
commit b2e93de0ffedcfe2cfba100d47a4d4f6f85cea0b
|
|
|
e354a5 |
Author: DJ Delorie <dj@redhat.com>
|
|
|
e354a5 |
Date: Tue Dec 4 00:03:12 2018 -0500
|
|
|
e354a5 |
|
|
|
e354a5 |
test-container: add "su" command to run test as root, add unshare hints
|
|
|
e354a5 |
|
|
|
e354a5 |
* support/test-container.c (check_for_unshare_hints): New.
|
|
|
e354a5 |
(main): Call it if unshare fails. Add support for "su" scriptlet
|
|
|
e354a5 |
command.
|
|
|
e354a5 |
|
|
|
e354a5 |
diff --git a/support/test-container.c b/support/test-container.c
|
|
|
e354a5 |
index fe0ebbd07df83da7..1d1aebeaf3412573 100644
|
|
|
e354a5 |
--- a/support/test-container.c
|
|
|
e354a5 |
+++ b/support/test-container.c
|
|
|
e354a5 |
@@ -88,15 +88,22 @@ int verbose = 0;
|
|
|
e354a5 |
* mytest.root/ is rsync'd into container
|
|
|
e354a5 |
* mytest.root/preclean.req causes fresh rsync (with delete) before
|
|
|
e354a5 |
test if present
|
|
|
e354a5 |
- * mytest.root/mytset.script has a list of "commands" to run:
|
|
|
e354a5 |
+ * mytest.root/mytest.script has a list of "commands" to run:
|
|
|
e354a5 |
syntax:
|
|
|
e354a5 |
# comment
|
|
|
e354a5 |
+ su
|
|
|
e354a5 |
mv FILE FILE
|
|
|
e354a5 |
cp FILE FILE
|
|
|
e354a5 |
rm FILE
|
|
|
e354a5 |
FILE must start with $B/, $S/, $I/, $L/, or /
|
|
|
e354a5 |
(expands to build dir, source dir, install dir, library dir
|
|
|
e354a5 |
(in container), or container's root)
|
|
|
e354a5 |
+ details:
|
|
|
e354a5 |
+ - '#': A comment.
|
|
|
e354a5 |
+ - 'su': Enables running test as root in the container.
|
|
|
e354a5 |
+ - 'mv': A minimal move files command.
|
|
|
e354a5 |
+ - 'cp': A minimal copy files command.
|
|
|
e354a5 |
+ - 'rm': A minimal remove files command.
|
|
|
e354a5 |
* mytest.root/postclean.req causes fresh rsync (with delete) after
|
|
|
e354a5 |
test if present
|
|
|
e354a5 |
|
|
|
e354a5 |
@@ -349,6 +356,7 @@ recursive_remove (char *path)
|
|
|
e354a5 |
|
|
|
e354a5 |
switch (child) {
|
|
|
e354a5 |
case -1:
|
|
|
e354a5 |
+ perror("fork");
|
|
|
e354a5 |
FAIL_EXIT1 ("Unable to fork");
|
|
|
e354a5 |
case 0:
|
|
|
e354a5 |
/* Child. */
|
|
|
e354a5 |
@@ -610,6 +618,47 @@ rsync (char *src, char *dest, int and_delete)
|
|
|
e354a5 |
}
|
|
|
e354a5 |
|
|
|
e354a5 |
|
|
|
e354a5 |
+
|
|
|
e354a5 |
+/* See if we can detect what the user needs to do to get unshare
|
|
|
e354a5 |
+ support working for us. */
|
|
|
e354a5 |
+void
|
|
|
e354a5 |
+check_for_unshare_hints (void)
|
|
|
e354a5 |
+{
|
|
|
e354a5 |
+ FILE *f;
|
|
|
e354a5 |
+ int i;
|
|
|
e354a5 |
+
|
|
|
e354a5 |
+ /* Default Debian Linux disables user namespaces, but allows a way
|
|
|
e354a5 |
+ to enable them. */
|
|
|
e354a5 |
+ f = fopen ("/proc/sys/kernel/unprivileged_userns_clone", "r");
|
|
|
e354a5 |
+ if (f != NULL)
|
|
|
e354a5 |
+ {
|
|
|
e354a5 |
+ i = 99; /* Sentinel. */
|
|
|
e354a5 |
+ fscanf (f, "%d", &i);
|
|
|
e354a5 |
+ if (i == 0)
|
|
|
e354a5 |
+ {
|
|
|
e354a5 |
+ printf ("To enable test-container, please run this as root:\n");
|
|
|
e354a5 |
+ printf (" echo 1 > /proc/sys/kernel/unprivileged_userns_clone\n");
|
|
|
e354a5 |
+ }
|
|
|
e354a5 |
+ fclose (f);
|
|
|
e354a5 |
+ return;
|
|
|
e354a5 |
+ }
|
|
|
e354a5 |
+
|
|
|
e354a5 |
+ /* ALT Linux has an alternate way of doing the same. */
|
|
|
e354a5 |
+ f = fopen ("/proc/sys/kernel/userns_restrict", "r");
|
|
|
e354a5 |
+ if (f != NULL)
|
|
|
e354a5 |
+ {
|
|
|
e354a5 |
+ i = 99; /* Sentinel. */
|
|
|
e354a5 |
+ fscanf (f, "%d", &i);
|
|
|
e354a5 |
+ if (i == 1)
|
|
|
e354a5 |
+ {
|
|
|
e354a5 |
+ printf ("To enable test-container, please run this as root:\n");
|
|
|
e354a5 |
+ printf (" echo 0 > /proc/sys/kernel/userns_restrict\n");
|
|
|
e354a5 |
+ }
|
|
|
e354a5 |
+ fclose (f);
|
|
|
e354a5 |
+ return;
|
|
|
e354a5 |
+ }
|
|
|
e354a5 |
+}
|
|
|
e354a5 |
+
|
|
|
e354a5 |
int
|
|
|
e354a5 |
main (int argc, char **argv)
|
|
|
e354a5 |
{
|
|
|
e354a5 |
@@ -628,6 +677,8 @@ main (int argc, char **argv)
|
|
|
e354a5 |
|
|
|
e354a5 |
uid_t original_uid;
|
|
|
e354a5 |
gid_t original_gid;
|
|
|
e354a5 |
+ /* If set, the test runs as root instead of the user running the testsuite. */
|
|
|
e354a5 |
+ int be_su = 0;
|
|
|
e354a5 |
int UMAP;
|
|
|
e354a5 |
int GMAP;
|
|
|
e354a5 |
/* Used for "%lld %lld 1" so need not be large. */
|
|
|
e354a5 |
@@ -857,6 +908,10 @@ main (int argc, char **argv)
|
|
|
e354a5 |
{
|
|
|
e354a5 |
maybe_xunlink (the_words[1]);
|
|
|
e354a5 |
}
|
|
|
e354a5 |
+ else if (nt == 1 && strcmp (the_words[0], "su") == 0)
|
|
|
e354a5 |
+ {
|
|
|
e354a5 |
+ be_su = 1;
|
|
|
e354a5 |
+ }
|
|
|
e354a5 |
else if (nt > 0 && the_words[0][0] != '#')
|
|
|
e354a5 |
{
|
|
|
e354a5 |
printf ("\033[31minvalid [%s]\033[0m\n", the_words[0]);
|
|
|
e354a5 |
@@ -910,7 +965,12 @@ main (int argc, char **argv)
|
|
|
e354a5 |
/* Older kernels may not support all the options, or security
|
|
|
e354a5 |
policy may block this call. */
|
|
|
e354a5 |
if (errno == EINVAL || errno == EPERM)
|
|
|
e354a5 |
- FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (errno));
|
|
|
e354a5 |
+ {
|
|
|
e354a5 |
+ int saved_errno = errno;
|
|
|
e354a5 |
+ if (errno == EPERM)
|
|
|
e354a5 |
+ check_for_unshare_hints ();
|
|
|
e354a5 |
+ FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (saved_errno));
|
|
|
e354a5 |
+ }
|
|
|
e354a5 |
else
|
|
|
e354a5 |
FAIL_EXIT1 ("unable to unshare user/fs: %s", strerror (errno));
|
|
|
e354a5 |
}
|
|
|
e354a5 |
@@ -981,7 +1041,7 @@ main (int argc, char **argv)
|
|
|
e354a5 |
FAIL_EXIT1 ("can't write to /proc/self/uid_map\n");
|
|
|
e354a5 |
|
|
|
e354a5 |
sprintf (tmp, "%lld %lld 1\n",
|
|
|
e354a5 |
- (long long) original_uid, (long long) original_uid);
|
|
|
e354a5 |
+ (long long) (be_su ? 0 : original_uid), (long long) original_uid);
|
|
|
e354a5 |
write (UMAP, tmp, strlen (tmp));
|
|
|
e354a5 |
xclose (UMAP);
|
|
|
e354a5 |
|
|
|
e354a5 |
@@ -1002,7 +1062,7 @@ main (int argc, char **argv)
|
|
|
e354a5 |
FAIL_EXIT1 ("can't write to /proc/self/gid_map\n");
|
|
|
e354a5 |
|
|
|
e354a5 |
sprintf (tmp, "%lld %lld 1\n",
|
|
|
e354a5 |
- (long long) original_gid, (long long) original_gid);
|
|
|
e354a5 |
+ (long long) (be_su ? 0 : original_gid), (long long) original_gid);
|
|
|
e354a5 |
write (GMAP, tmp, strlen (tmp));
|
|
|
e354a5 |
xclose (GMAP);
|
|
|
e354a5 |
|