diff options
author | Mike Frysinger <vapier@google.com> | 2017-06-01 17:26:08 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-06-01 17:26:08 +0000 |
commit | f002ee30f0636abdb5c674a3321215ae4d3c0f80 (patch) | |
tree | 0e34536b91aca828a472ae8cccca2e592fc348a8 | |
parent | 5eab52009fddbe93a1845672bbb669bda3e45432 (diff) | |
parent | b59613b1b60abf2fcad0bb4546c16fa9004542fa (diff) | |
download | minijail-f002ee30f0636abdb5c674a3321215ae4d3c0f80.tar.gz |
support creating new uts namespaces (and setting hostnames) am: b9a7b16859 am: 0c23afe620
am: b59613b1b6
Change-Id: Ie1467053cc236a5b05f7e104e40c8ec2d8debba8
-rw-r--r-- | libminijail.c | 43 | ||||
-rw-r--r-- | libminijail.h | 2 | ||||
-rw-r--r-- | minijail0.1 | 4 | ||||
-rw-r--r-- | minijail0.c | 115 |
4 files changed, 110 insertions, 54 deletions
diff --git a/libminijail.c b/libminijail.c index 1da4e19..81cea4b 100644 --- a/libminijail.c +++ b/libminijail.c @@ -106,6 +106,7 @@ struct minijail { int skip_remount_private : 1; int pids : 1; int ipc : 1; + int uts : 1; int net : 1; int enter_net : 1; int ns_cgroups : 1; @@ -144,6 +145,7 @@ struct minijail { char *pid_file_path; char *uidmap; char *gidmap; + char *hostname; size_t filter_len; struct sock_fprog *filter_prog; char *alt_syscall_table; @@ -439,6 +441,22 @@ void API minijail_namespace_ipc(struct minijail *j) j->flags.ipc = 1; } +void API minijail_namespace_uts(struct minijail *j) +{ + j->flags.uts = 1; +} + +int API minijail_namespace_set_hostname(struct minijail *j, const char *name) +{ + if (j->hostname) + return -EINVAL; + minijail_namespace_uts(j); + j->hostname = strdup(name); + if (!j->hostname) + return -ENOMEM; + return 0; +} + void API minijail_namespace_net(struct minijail *j) { j->flags.net = 1; @@ -869,6 +887,8 @@ void minijail_marshal_helper(struct marshal_state *state, } if (j->chrootdir) marshal_append(state, j->chrootdir, strlen(j->chrootdir) + 1); + if (j->hostname) + marshal_append(state, j->hostname, strlen(j->hostname) + 1); if (j->alt_syscall_table) { marshal_append(state, j->alt_syscall_table, strlen(j->alt_syscall_table) + 1); @@ -956,6 +976,15 @@ int minijail_unmarshal(struct minijail *j, char *serialized, size_t length) goto bad_chrootdir; } + if (j->hostname) { /* stale pointer */ + char *hostname = consumestr(&serialized, &length); + if (!hostname) + goto bad_hostname; + j->hostname = strdup(hostname); + if (!j->hostname) + goto bad_hostname; + } + if (j->alt_syscall_table) { /* stale pointer */ char *alt_syscall_table = consumestr(&serialized, &length); if (!alt_syscall_table) @@ -1062,6 +1091,9 @@ bad_syscall_table: if (j->chrootdir) free(j->chrootdir); bad_chrootdir: + if (j->hostname) + free(j->hostname); +bad_hostname: if (j->suppl_gid_list) free(j->suppl_gid_list); bad_gid_list: @@ -1071,6 +1103,7 @@ clear_pointers: j->user = NULL; j->suppl_gid_list = NULL; j->chrootdir = NULL; + j->hostname = NULL; j->alt_syscall_table = NULL; j->cgroup_count = 0; out: @@ -1594,6 +1627,14 @@ void API minijail_enter(const struct minijail *j) pdie("unshare(CLONE_NEWIPC) failed"); } + if (j->flags.uts) { + if (unshare(CLONE_NEWUTS)) + pdie("unshare(CLONE_NEWUTS) failed"); + + if (j->hostname && sethostname(j->hostname, strlen(j->hostname))) + pdie("sethostname(%s) failed", j->hostname); + } + if (j->flags.enter_net) { if (setns(j->netns_fd, CLONE_NEWNET)) pdie("setns(CLONE_NEWNET) failed"); @@ -2345,6 +2386,8 @@ void API minijail_destroy(struct minijail *j) free(j->uidmap); if (j->gidmap) free(j->gidmap); + if (j->hostname) + free(j->hostname); if (j->alt_syscall_table) free(j->alt_syscall_table); for (i = 0; i < j->cgroup_count; ++i) diff --git a/libminijail.h b/libminijail.h index a1f2f74..08fdf2b 100644 --- a/libminijail.h +++ b/libminijail.h @@ -71,6 +71,8 @@ void minijail_new_session_keyring(struct minijail *j); */ void minijail_skip_remount_private(struct minijail *j); void minijail_namespace_ipc(struct minijail *j); +void minijail_namespace_uts(struct minijail *j); +int minijail_namespace_set_hostname(struct minijail *j, const char *name); void minijail_namespace_net(struct minijail *j); void minijail_namespace_enter_net(struct minijail *j, const char *ns_path); void minijail_namespace_cgroups(struct minijail *j); diff --git a/minijail0.1 b/minijail0.1 index e186fef..11579c2 100644 --- a/minijail0.1 +++ b/minijail0.1 @@ -147,6 +147,10 @@ Keep the current user's supplementary groups. .TP \fB-Y\fR Synchronize seccomp filters across thread group. +.TP +\fB--uts[=hostname]\fR +Create a new UTS/hostname namespace, and optionally set the hostname in the new +namespace to \fIhostname\fR. .SH IMPLEMENTATION This program is broken up into two parts: \fBminijail0\fR (the frontend) and a helper library called \fBlibminijailpreload\fR. Some jailings can only be achieved from diff --git a/minijail0.c b/minijail0.c index b9f4e5a..72353f6 100644 --- a/minijail0.c +++ b/minijail0.c @@ -118,32 +118,32 @@ static void usage(const char *progn) " [-m[<uid> <loweruid> <count>]*] [-M[<gid> <lowergid> <count>]*]\n" " [-S <file>] [-t[size]] [-T <type>] [-u <user>] [-V <file>]\n" " <program> [args...]\n" - " -a <table>: Use alternate syscall table <table>.\n" - " -b: Bind <src> to <dest> in chroot.\n" - " Multiple instances allowed.\n" - " -k: Mount <src> at <dest> in chroot.\n" - " <flags> and <data> can be specified as in mount(2).\n" - " Multiple instances allowed.\n" - " -c <caps>: Restrict caps to <caps>.\n" - " -C <dir>: chroot(2) to <dir>.\n" - " Not compatible with -P.\n" - " -P <dir>: pivot_root(2) to <dir> (implies -v).\n" - " Not compatible with -C.\n" - " -e[file]: Enter new network namespace, or existing one if |file| is provided.\n" - " -f <file>: Write the pid of the jailed process to <file>.\n" - " -g <group>: Change gid to <group>.\n" - " -G: Inherit supplementary groups from uid.\n" - " Not compatible with -y.\n" - " -y: Keep uid's supplementary groups.\n" - " Not compatible with -G.\n" - " -h: Help (this message).\n" - " -H: Seccomp filter help message.\n" - " -i: Exit immediately after fork (do not act as init).\n" - " -I: Run <program> as init (pid 1) inside a new pid namespace (implies -p).\n" - " -K: Don't mark all existing mounts as MS_PRIVATE.\n" - " -l: Enter new IPC namespace.\n" - " -L: Report blocked syscalls to syslog when using seccomp filter.\n" - " Forces the following syscalls to be allowed:\n" + " -a <table>: Use alternate syscall table <table>.\n" + " -b: Bind <src> to <dest> in chroot.\n" + " Multiple instances allowed.\n" + " -k: Mount <src> at <dest> in chroot.\n" + " <flags> and <data> can be specified as in mount(2).\n" + " Multiple instances allowed.\n" + " -c <caps>: Restrict caps to <caps>.\n" + " -C <dir>: chroot(2) to <dir>.\n" + " Not compatible with -P.\n" + " -P <dir>: pivot_root(2) to <dir> (implies -v).\n" + " Not compatible with -C.\n" + " -e[file]: Enter new network namespace, or existing one if |file| is provided.\n" + " -f <file>: Write the pid of the jailed process to <file>.\n" + " -g <group>: Change gid to <group>.\n" + " -G: Inherit supplementary groups from uid.\n" + " Not compatible with -y.\n" + " -y: Keep uid's supplementary groups.\n" + " Not compatible with -G.\n" + " -h: Help (this message).\n" + " -H: Seccomp filter help message.\n" + " -i: Exit immediately after fork (do not act as init).\n" + " -I: Run <program> as init (pid 1) inside a new pid namespace (implies -p).\n" + " -K: Don't mark all existing mounts as MS_PRIVATE.\n" + " -l: Enter new IPC namespace.\n" + " -L: Report blocked syscalls to syslog when using seccomp filter.\n" + " Forces the following syscalls to be allowed:\n" " ", progn); /* clang-format on */ for (i = 0; i < log_syscalls_len; i++) @@ -151,34 +151,35 @@ static void usage(const char *progn) /* clang-format off */ printf("\n" - " -m[map]: Set the uid map of a user namespace (implies -pU).\n" - " Same arguments as newuidmap(1), multiple mappings should be separated by ',' (comma).\n" - " With no mapping, map the current uid to root inside the user namespace.\n" - " Not compatible with -b without the 'writable' option.\n" - " -M[map]: Set the gid map of a user namespace (implies -pU).\n" - " Same arguments as newgidmap(1), multiple mappings should be separated by ',' (comma).\n" - " With no mapping, map the current gid to root inside the user namespace.\n" - " Not compatible with -b without the 'writable' option.\n" - " -n: Set no_new_privs.\n" - " -N: Enter a new cgroup namespace.\n" - " -p: Enter new pid namespace (implies -vr).\n" - " -r: Remount /proc read-only (implies -v).\n" - " -s: Use seccomp.\n" - " -S <file>: Set seccomp filter using <file>.\n" - " E.g., '-S /usr/share/filters/<prog>.$(uname -m)'.\n" - " Requires -n when not running as root.\n" - " -t[size]: Mount tmpfs at /tmp (implies -v).\n" - " Optional argument specifies size (default \"64M\").\n" - " -T <type>: Don't access <program> before execve(2), assume <type> ELF binary.\n" - " <type> must be 'static' or 'dynamic'.\n" - " -u <user>: Change uid to <user>.\n" - " -U: Enter new user namespace (implies -p).\n" - " -v: Enter new mount namespace.\n" - " -V <file>: Enter specified mount namespace.\n" - " -w: Create and join a new anonymous session keyring.\n" - " -Y: Synchronize seccomp filters across thread group.\n" - " -z: Don't forward signals to jailed process.\n" - " --ambient: Raise ambient capabilities. Requires -c.\n"); + " -m[map]: Set the uid map of a user namespace (implies -pU).\n" + " Same arguments as newuidmap(1), multiple mappings should be separated by ',' (comma).\n" + " With no mapping, map the current uid to root inside the user namespace.\n" + " Not compatible with -b without the 'writable' option.\n" + " -M[map]: Set the gid map of a user namespace (implies -pU).\n" + " Same arguments as newgidmap(1), multiple mappings should be separated by ',' (comma).\n" + " With no mapping, map the current gid to root inside the user namespace.\n" + " Not compatible with -b without the 'writable' option.\n" + " -n: Set no_new_privs.\n" + " -N: Enter a new cgroup namespace.\n" + " -p: Enter new pid namespace (implies -vr).\n" + " -r: Remount /proc read-only (implies -v).\n" + " -s: Use seccomp.\n" + " -S <file>: Set seccomp filter using <file>.\n" + " E.g., '-S /usr/share/filters/<prog>.$(uname -m)'.\n" + " Requires -n when not running as root.\n" + " -t[size]: Mount tmpfs at /tmp (implies -v).\n" + " Optional argument specifies size (default \"64M\").\n" + " -T <type>: Don't access <program> before execve(2), assume <type> ELF binary.\n" + " <type> must be 'static' or 'dynamic'.\n" + " -u <user>: Change uid to <user>.\n" + " -U: Enter new user namespace (implies -p).\n" + " -v: Enter new mount namespace.\n" + " -V <file>: Enter specified mount namespace.\n" + " -w: Create and join a new anonymous session keyring.\n" + " -Y: Synchronize seccomp filters across thread group.\n" + " -z: Don't forward signals to jailed process.\n" + " --ambient: Raise ambient capabilities. Requires -c.\n" + " --uts[=name]: Enter a new UTS namespace (and set hostname).\n"); /* clang-format on */ } @@ -217,6 +218,7 @@ static int parse_args(struct minijail *j, int argc, char *argv[], /* clang-format off */ const struct option long_options[] = { {"ambient", no_argument, 0, 128}, + {"uts", optional_argument, 0, 129}, {0, 0, 0, 0}, }; /* clang-format on */ @@ -444,6 +446,11 @@ static int parse_args(struct minijail *j, int argc, char *argv[], ambient_caps = 1; minijail_set_ambient_caps(j); break; + case 129: /* UTS/hostname namespace. */ + minijail_namespace_uts(j); + if (optarg) + minijail_namespace_set_hostname(j, optarg); + break; default: usage(argv[0]); exit(1); |