aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@google.com>2017-06-01 17:26:08 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-06-01 17:26:08 +0000
commitf002ee30f0636abdb5c674a3321215ae4d3c0f80 (patch)
tree0e34536b91aca828a472ae8cccca2e592fc348a8
parent5eab52009fddbe93a1845672bbb669bda3e45432 (diff)
parentb59613b1b60abf2fcad0bb4546c16fa9004542fa (diff)
downloadminijail-f002ee30f0636abdb5c674a3321215ae4d3c0f80.tar.gz
support creating new uts namespaces (and setting hostnames) am: b9a7b16859 am: 0c23afe620
am: b59613b1b6 Change-Id: Ie1467053cc236a5b05f7e104e40c8ec2d8debba8
-rw-r--r--libminijail.c43
-rw-r--r--libminijail.h2
-rw-r--r--minijail0.14
-rw-r--r--minijail0.c115
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);