xbps-uchroot: replace -D/-H/-S with -b src/dest and switch to getopt(3).
This commit is contained in:
parent
e9b8ff7360
commit
7d6d1805f3
3
NEWS
3
NEWS
@ -1,5 +1,8 @@
|
|||||||
xbps-0.45 (???):
|
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.
|
* configure: added --dbdir to customize path to pkgdb.
|
||||||
|
|
||||||
* xbps-uchroot(8): added -o option to pass arguments to the tmpfs mount,
|
* xbps-uchroot(8): added -o option to pass arguments to the tmpfs mount,
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
* This is based on linux-user-chroot by Colin Walters, but has been adapted
|
* This is based on linux-user-chroot by Colin Walters, but has been adapted
|
||||||
* specifically for xbps-src use:
|
* 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.
|
* - This uses IPC/PID/UTS namespaces, nothing more.
|
||||||
* - Disables namespace features if running in OpenVZ containers.
|
* - Disables namespace features if running in OpenVZ containers.
|
||||||
* - Supports overlayfs on a temporary directory or a tmpfs mount.
|
* - Supports overlayfs on a temporary directory or a tmpfs mount.
|
||||||
@ -53,6 +52,7 @@
|
|||||||
#include <ftw.h>
|
#include <ftw.h>
|
||||||
|
|
||||||
#include <xbps.h>
|
#include <xbps.h>
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
#ifndef SECBIT_NOROOT
|
#ifndef SECBIT_NOROOT
|
||||||
#define SECBIT_NOROOT (1 << 0)
|
#define SECBIT_NOROOT (1 << 0)
|
||||||
@ -70,8 +70,27 @@
|
|||||||
#pragma clang diagnostic ignored "-Wformat-nonliteral"
|
#pragma clang diagnostic ignored "-Wformat-nonliteral"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct bindmnt {
|
||||||
|
SIMPLEQ_ENTRY(bindmnt) entries;
|
||||||
|
char *src;
|
||||||
|
const char *dest;
|
||||||
|
};
|
||||||
|
|
||||||
static char *tmpdir;
|
static char *tmpdir;
|
||||||
static bool overlayfs_on_tmpfs;
|
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 <opts>] <dir> <cmd> [<cmdargs>]\n\n"
|
||||||
|
"-b src:dest Bind mounts <src> into <dir>/<dest> (may be specified multiple times)\n"
|
||||||
|
"-O Creates a tempdir and mounts <dir> 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))
|
static void __attribute__((noreturn))
|
||||||
die(const char *fmt, ...)
|
die(const char *fmt, ...)
|
||||||
@ -80,7 +99,7 @@ die(const char *fmt, ...)
|
|||||||
int save_errno = errno;
|
int save_errno = errno;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
fprintf(stderr, "ERROR ");
|
fprintf(stderr, "ERROR: ");
|
||||||
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
||||||
fprintf(stderr, " (%s)\n", strerror(save_errno));
|
fprintf(stderr, " (%s)\n", strerror(save_errno));
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
@ -125,14 +144,30 @@ cleanup_overlayfs(void)
|
|||||||
rmdir(tmpdir);
|
rmdir(tmpdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __attribute__((noreturn))
|
static void
|
||||||
usage(const char *p)
|
add_bindmount(char *bm)
|
||||||
{
|
{
|
||||||
printf("Usage: %s [-D dir] [-H dir] [-S dir] [-O -t -o <opts>] <chrootdir> <command>\n\n"
|
struct bindmnt *bmnt;
|
||||||
"-D <distdir> Directory to be bind mounted at <chrootdir>/void-packages\n"
|
char *b, *src, *dest;
|
||||||
"-H <hostdir> Directory to be bind mounted at <chrootdir>/host\n"
|
size_t len;
|
||||||
"-S <shmdir> Directory to be bind mounted at <chrootdir>/<shmdir>\n", p);
|
|
||||||
exit(EXIT_FAILURE);
|
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
|
static int
|
||||||
@ -227,55 +262,48 @@ main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
uid_t ruid, euid, suid;
|
uid_t ruid, euid, suid;
|
||||||
gid_t rgid, egid, sgid;
|
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];
|
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;
|
pid_t child;
|
||||||
bool overlayfs = false;
|
bool overlayfs = false;
|
||||||
|
|
||||||
tmpfs_opts = chrootdir = distdir = hostdir = shmdir = cmd = NULL;
|
tmpfs_opts = chrootdir = cmd = NULL;
|
||||||
argv0 = argv[0];
|
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)
|
if (argc < 2)
|
||||||
usage(argv0);
|
usage(argv0);
|
||||||
|
|
||||||
while (aidx < argc) {
|
chrootdir = argv[0];
|
||||||
if (strcmp(argv[aidx], "-O") == 0) {
|
cmd = argv[1];
|
||||||
/* use overlayfs */
|
cmdargs = argv + 1;
|
||||||
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;
|
|
||||||
|
|
||||||
/* Never allow chrootdir == / */
|
/* Never allow chrootdir == / */
|
||||||
if (strcmp(chrootdir, "/") == 0)
|
if (strcmp(chrootdir, "/") == 0)
|
||||||
@ -312,6 +340,7 @@ main(int argc, char **argv)
|
|||||||
die("clone");
|
die("clone");
|
||||||
|
|
||||||
if (child == 0) {
|
if (child == 0) {
|
||||||
|
struct bindmnt *bmnt;
|
||||||
/*
|
/*
|
||||||
* Restrict privileges on the child.
|
* Restrict privileges on the child.
|
||||||
*/
|
*/
|
||||||
@ -339,17 +368,9 @@ main(int argc, char **argv)
|
|||||||
/* bind mount /dev */
|
/* bind mount /dev */
|
||||||
bindmount(ruid, chrootdir, "/dev", NULL);
|
bindmount(ruid, chrootdir, "/dev", NULL);
|
||||||
|
|
||||||
/* bind mount hostdir if set */
|
/* bind mount all user specified mnts */
|
||||||
if (hostdir)
|
SIMPLEQ_FOREACH(bmnt, &bindmnt_queue, entries)
|
||||||
bindmount(ruid, chrootdir, hostdir, "/host");
|
bindmount(ruid, chrootdir, bmnt->src, bmnt->dest);
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* move chrootdir to / and chroot to it */
|
/* move chrootdir to / and chroot to it */
|
||||||
if (fsuid_chdir(ruid, chrootdir) == -1)
|
if (fsuid_chdir(ruid, chrootdir) == -1)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.Dd April 27, 2014
|
.Dd May 6, 2014
|
||||||
.Dt XBPS-UCHROOT 8
|
.Dt XBPS-UCHROOT 8
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm xbps-uchroot
|
.Nm xbps-uchroot
|
||||||
@ -24,20 +24,17 @@ the calling process. If running in a OpenVZ container, these namespace features
|
|||||||
are simply disabled.
|
are simply disabled.
|
||||||
.Sh OPTIONS
|
.Sh OPTIONS
|
||||||
.Bl -tag -width -x
|
.Bl -tag -width -x
|
||||||
.It Fl D Ar dir
|
.It Fl b Ar src:dest
|
||||||
Specifies a full path to a directory that will be bind mounted at
|
Bind mounts
|
||||||
.Ar CHROOTDIR/void-packages .
|
.Ar src
|
||||||
.It Fl H Ar dir
|
into
|
||||||
Specifies a full path to a directory that will be bind mounted at
|
.Ar CHROOTDIR/dest .
|
||||||
.Ar CHROOTDIR/host .
|
This option may be specified multiple times.
|
||||||
.It Fl S Ar dir
|
Please note that both
|
||||||
Specifies a full path to a directory to allow shm functionality to be used
|
.Ar src
|
||||||
in the target
|
and
|
||||||
.Ar CHROOTDIR/dir .
|
.Ar dest
|
||||||
If your system uses
|
must be absolute paths and must exist.
|
||||||
.Sy /dev/shm
|
|
||||||
use it, otherwise use
|
|
||||||
.Sy /run/shm .
|
|
||||||
.It Fl O
|
.It Fl O
|
||||||
Setups a temporary directory and then creates an overlay layer (via overlayfs)
|
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
|
with the lowerdir set to CHROOTDIR. Useful to create a temporary tree that does not
|
||||||
|
Loading…
Reference in New Issue
Block a user