From 7d6d1805f30f5ea30c39741a6f38c19a3fc9d9a8 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Wed, 6 May 2015 11:24:47 +0200 Subject: [PATCH] xbps-uchroot: replace -D/-H/-S with -b src/dest and switch to getopt(3). --- NEWS | 3 + bin/xbps-uchroot/main.c | 141 ++++++++++++++++++-------------- bin/xbps-uchroot/xbps-uchroot.8 | 27 +++--- 3 files changed, 96 insertions(+), 75 deletions(-) diff --git a/NEWS b/NEWS index 1e3daabe..459b717d 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,8 @@ xbps-0.45 (???): + * xbps-uchroot(8): replaced -D, -H and -S with -b src:dest. This bind mounts + src into dir/dest and allows unlimited mounts. + * configure: added --dbdir to customize path to pkgdb. * xbps-uchroot(8): added -o option to pass arguments to the tmpfs mount, diff --git a/bin/xbps-uchroot/main.c b/bin/xbps-uchroot/main.c index acd7b9ee..f9e1f12b 100644 --- a/bin/xbps-uchroot/main.c +++ b/bin/xbps-uchroot/main.c @@ -27,7 +27,6 @@ * This is based on linux-user-chroot by Colin Walters, but has been adapted * specifically for xbps-src use: * - * - This bind mounts exactly what we need, no support for additional mounts. * - This uses IPC/PID/UTS namespaces, nothing more. * - Disables namespace features if running in OpenVZ containers. * - Supports overlayfs on a temporary directory or a tmpfs mount. @@ -53,6 +52,7 @@ #include #include +#include "queue.h" #ifndef SECBIT_NOROOT #define SECBIT_NOROOT (1 << 0) @@ -70,8 +70,27 @@ #pragma clang diagnostic ignored "-Wformat-nonliteral" #endif +struct bindmnt { + SIMPLEQ_ENTRY(bindmnt) entries; + char *src; + const char *dest; +}; + static char *tmpdir; static bool overlayfs_on_tmpfs; +static SIMPLEQ_HEAD(bindmnt_head, bindmnt) bindmnt_queue = + SIMPLEQ_HEAD_INITIALIZER(bindmnt_queue); + +static void __attribute__((noreturn)) +usage(const char *p) +{ + printf("Usage: %s [-b src:dest] [-O -t -o ] []\n\n" + "-b src:dest Bind mounts into / (may be specified multiple times)\n" + "-O Creates a tempdir and mounts read-only via overlayfs\n" + "-t Creates tempdir and mounts it on tmpfs (for use with -O)\n" + "-o opts Options to be passed to the tmpfs mount (for use with -t)\n", p); + exit(EXIT_FAILURE); +} static void __attribute__((noreturn)) die(const char *fmt, ...) @@ -80,7 +99,7 @@ die(const char *fmt, ...) int save_errno = errno; va_start(ap, fmt); - fprintf(stderr, "ERROR "); + fprintf(stderr, "ERROR: "); vfprintf(stderr, fmt, ap); fprintf(stderr, " (%s)\n", strerror(save_errno)); va_end(ap); @@ -125,14 +144,30 @@ cleanup_overlayfs(void) rmdir(tmpdir); } -static void __attribute__((noreturn)) -usage(const char *p) +static void +add_bindmount(char *bm) { - printf("Usage: %s [-D dir] [-H dir] [-S dir] [-O -t -o ] \n\n" - "-D Directory to be bind mounted at /void-packages\n" - "-H Directory to be bind mounted at /host\n" - "-S Directory to be bind mounted at /\n", p); - exit(EXIT_FAILURE); + struct bindmnt *bmnt; + char *b, *src, *dest; + size_t len; + + src = strdup(bm); + dest = strchr(bm, ':'); + if (dest == NULL || *dest == '\0') { + errno = EINVAL; + die("invalid argument for bindmount: %s", bm); + } + dest++; + b = strchr(bm, ':'); + len = strlen(bm) - strlen(b); + src[len] = '\0'; + + bmnt = malloc(sizeof(struct bindmnt)); + assert(bmnt); + + bmnt->src = src; + bmnt->dest = dest; + SIMPLEQ_INSERT_TAIL(&bindmnt_queue, bmnt, entries); } static int @@ -227,55 +262,48 @@ main(int argc, char **argv) { uid_t ruid, euid, suid; gid_t rgid, egid, sgid; - const char *chrootdir, *distdir, *hostdir, *shmdir, *tmpfs_opts, *cmd, *argv0; + const char *chrootdir, *tmpfs_opts, *cmd, *argv0; char **cmdargs, *b, mountdir[PATH_MAX-1]; - int aidx = 0, clone_flags, child_status = 0; + int c, clone_flags, child_status = 0; pid_t child; bool overlayfs = false; - tmpfs_opts = chrootdir = distdir = hostdir = shmdir = cmd = NULL; + tmpfs_opts = chrootdir = cmd = NULL; argv0 = argv[0]; - argc--; - argv++; + + while ((c = getopt(argc, argv, "Oto:b:V")) != -1) { + switch (c) { + case 'O': + overlayfs = true; + break; + case 't': + overlayfs_on_tmpfs = true; + break; + case 'o': + tmpfs_opts = optarg; + break; + case 'b': + if (optarg == NULL || *optarg == '\0') + break; + add_bindmount(optarg); + break; + case 'V': + printf("%s\n", XBPS_RELVER); + exit(EXIT_SUCCESS); + case '?': + default: + usage(argv0); + } + } + argc -= optind; + argv += optind; if (argc < 2) usage(argv0); - while (aidx < argc) { - if (strcmp(argv[aidx], "-O") == 0) { - /* use overlayfs */ - overlayfs = true; - aidx++; - } else if (strcmp(argv[aidx], "-t") == 0) { - /* overlayfs on tmpfs */ - overlayfs_on_tmpfs = true; - aidx++; - } else if (strcmp(argv[aidx], "-o") == 0) { - /* tmpfs args with overlayfs */ - tmpfs_opts = argv[aidx+1]; - aidx += 2; - } else if (strcmp(argv[aidx], "-D") == 0) { - /* distdir */ - distdir = argv[aidx+1]; - aidx += 2; - } else if (strcmp(argv[aidx], "-H") == 0) { - /* hostdir */ - hostdir = argv[aidx+1]; - aidx += 2; - } else if (strcmp(argv[aidx], "-S") == 0) { - /* shmdir */ - shmdir = argv[aidx+1]; - aidx += 2; - } else { - break; - } - } - if ((argc - aidx) < 2) - usage(argv0); - - chrootdir = argv[aidx]; - cmd = argv[aidx+1]; - cmdargs = argv + aidx + 1; + chrootdir = argv[0]; + cmd = argv[1]; + cmdargs = argv + 1; /* Never allow chrootdir == / */ if (strcmp(chrootdir, "/") == 0) @@ -312,6 +340,7 @@ main(int argc, char **argv) die("clone"); if (child == 0) { + struct bindmnt *bmnt; /* * Restrict privileges on the child. */ @@ -339,17 +368,9 @@ main(int argc, char **argv) /* bind mount /dev */ bindmount(ruid, chrootdir, "/dev", NULL); - /* bind mount hostdir if set */ - if (hostdir) - bindmount(ruid, chrootdir, hostdir, "/host"); - - /* bind mount distdir (if set) */ - if (distdir) - bindmount(ruid, chrootdir, distdir, "/void-packages"); - - /* bind mount shmdir (if set) */ - if (shmdir) - bindmount(ruid, chrootdir, shmdir, NULL); + /* bind mount all user specified mnts */ + SIMPLEQ_FOREACH(bmnt, &bindmnt_queue, entries) + bindmount(ruid, chrootdir, bmnt->src, bmnt->dest); /* move chrootdir to / and chroot to it */ if (fsuid_chdir(ruid, chrootdir) == -1) diff --git a/bin/xbps-uchroot/xbps-uchroot.8 b/bin/xbps-uchroot/xbps-uchroot.8 index 04f412b8..bb110632 100644 --- a/bin/xbps-uchroot/xbps-uchroot.8 +++ b/bin/xbps-uchroot/xbps-uchroot.8 @@ -1,4 +1,4 @@ -.Dd April 27, 2014 +.Dd May 6, 2014 .Dt XBPS-UCHROOT 8 .Sh NAME .Nm xbps-uchroot @@ -24,20 +24,17 @@ the calling process. If running in a OpenVZ container, these namespace features are simply disabled. .Sh OPTIONS .Bl -tag -width -x -.It Fl D Ar dir -Specifies a full path to a directory that will be bind mounted at -.Ar CHROOTDIR/void-packages . -.It Fl H Ar dir -Specifies a full path to a directory that will be bind mounted at -.Ar CHROOTDIR/host . -.It Fl S Ar dir -Specifies a full path to a directory to allow shm functionality to be used -in the target -.Ar CHROOTDIR/dir . -If your system uses -.Sy /dev/shm -use it, otherwise use -.Sy /run/shm . +.It Fl b Ar src:dest +Bind mounts +.Ar src +into +.Ar CHROOTDIR/dest . +This option may be specified multiple times. +Please note that both +.Ar src +and +.Ar dest +must be absolute paths and must exist. .It Fl O Setups a temporary directory and then creates an overlay layer (via overlayfs) with the lowerdir set to CHROOTDIR. Useful to create a temporary tree that does not