logYesNo(nsjconf->clone_newuts), logYesNo(nsjconf->clone_newcgroup),
logYesNo(nsjconf->apply_sandbox), logYesNo(nsjconf->keep_caps), nsjconf->tmpfs_size);
- struct mounts_t *p;
- TAILQ_FOREACH(p, &nsjconf->mountpts, pointers) {
- LOG_I("Mount point: src:'%s' dst:'%s' type:'%s' flags:0x%tx options:'%s'",
- p->src, p->dst, p->fs_type, p->flags, p->options);
+ {
+ struct mounts_t *p;
+ TAILQ_FOREACH(p, &nsjconf->mountpts, pointers) {
+ LOG_I("Mount point: src:'%s' dst:'%s' type:'%s' flags:0x%tx options:'%s'",
+ p->src, p->dst, p->fs_type, p->flags, p->options);
+ }
+ }
+ {
+ struct mapping_t *p;
+ TAILQ_FOREACH(p, &nsjconf->uid_mappings, pointers) {
+ LOG_I("Uid mapping: inside_uid:'%s' outside_uid:'%s' count:'%s'",
+ p->inside_id, p->outside_id, p->count);
+ }
+
+ TAILQ_FOREACH(p, &nsjconf->gid_mappings, pointers) {
+ LOG_I("Gid mapping: inside_uid:'%s' outside_uid:'%s' count:'%s'",
+ p->inside_id, p->outside_id, p->count);
+ }
}
}
TAILQ_INIT(&nsjconf->pids);
TAILQ_INIT(&nsjconf->mountpts);
TAILQ_INIT(&nsjconf->open_fds);
+ TAILQ_INIT(&nsjconf->uid_mappings);
+ TAILQ_INIT(&nsjconf->gid_mappings);
char *user = NULL;
char *group = NULL;
{{"disable_clone_newipc", no_argument, NULL, 0x0405}, "Don't use CLONE_NEWIPC"},
{{"disable_clone_newuts", no_argument, NULL, 0x0406}, "Don't use CLONE_NEWUTS"},
{{"enable_clone_newcgroup", no_argument, NULL, 0x0407}, "Use CLONE_NEWCGROUP"},
+ {{"uid_mapping", required_argument, NULL, 'U'}, "Add a custom uid mapping of the form inside_uid:outside_uid:count. Setting this requires newuidmap to be present"},
+ {{"gid_mapping", required_argument, NULL, 'G'}, "Add a custom gid mapping of the form inside_gid:outside_gid:count. Setting this requires newuidmap to be present"},
{{"bindmount_ro", required_argument, NULL, 'R'}, "List of mountpoints to be mounted --bind (ro) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'"},
{{"bindmount", required_argument, NULL, 'B'}, "List of mountpoints to be mounted --bind (rw) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'"},
{{"tmpfsmount", required_argument, NULL, 'T'}, "List of mountpoints to be mounted as RW/tmpfs inside the container. Can be specified multiple times. Supports 'dest' syntax"},
int opt_index = 0;
for (;;) {
- int c = getopt_long(argc, argv, "H:D:c:p:i:u:g:l:t:M:Ndveh?E:R:B:T:I:", opts,
+ int c = getopt_long(argc, argv, "H:D:c:p:i:u:g:l:t:M:Ndveh?E:R:B:T:I:U:G:", opts,
&opt_index);
if (c == -1) {
break;
TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
}
break;
+ case 'U':
+ case 'G':
+ {
+ struct mapping_t *p = utilMalloc(sizeof(struct mapping_t));
+ p->inside_id = optarg;
+ char *outside_id = cmdlineSplitStrByColon(optarg);
+ p->outside_id = outside_id;
+ p->count = cmdlineSplitStrByColon(outside_id);
+ if (c == 'U') {
+ TAILQ_INSERT_TAIL(&nsjconf->uid_mappings, p, pointers);
+ } else {
+ TAILQ_INSERT_TAIL(&nsjconf->gid_mappings, p, pointers);
+ }
+ }
+ break;
case 'R':
{
struct mounts_t *p = utilMalloc(sizeof(struct mounts_t));
TAILQ_ENTRY(mounts_t) pointers;
};
+struct mapping_t {
+ const char *inside_id;
+ const char *outside_id;
+ const char *count;
+ TAILQ_ENTRY(mapping_t) pointers;
+};
+
struct fds_t {
int fd;
TAILQ_ENTRY(fds_t) pointers;
TAILQ_HEAD(pidslist, pids_t) pids;
TAILQ_HEAD(mountptslist, mounts_t) mountpts;
TAILQ_HEAD(fdslistt, fds_t) open_fds;
+ TAILQ_HEAD(uidmaplistt, mapping_t) uid_mappings;
+ TAILQ_HEAD(gidmaplistt, mapping_t) gid_mappings;
};
#endif /* NS_COMMON_H */
return true;
}
-static bool userUidGidMap(struct nsjconf_t *nsjconf, pid_t pid)
-{
+static bool userUidMapSelf(struct nsjconf_t *nsjconf, pid_t pid) {
char fname[PATH_MAX];
char map[128];
return false;
}
+ return true;
+}
+
+static bool userGidMapSelf(struct nsjconf_t *nsjconf, pid_t pid) {
+ char fname[PATH_MAX];
+ char map[128];
+
snprintf(fname, sizeof(fname), "/proc/%d/gid_map", pid);
snprintf(map, sizeof(map), "%lu %lu 1", (unsigned long)nsjconf->inside_gid,
(unsigned long)nsjconf->outside_gid);
return true;
}
+// use /usr/bin/newgidmap for writing the uid and gid map
+static bool userGidMapExternal(struct nsjconf_t *nsjconf, pid_t pid) {
+ char cmd_buf[1024];
+ char *cmd_ptr = cmd_buf;
+ size_t len = sizeof(cmd_buf);
+ int write_size;
+
+ write_size = snprintf(cmd_ptr, len, "/usr/bin/newgidmap %lu %lu %lu 1",
+ (unsigned long)pid,
+ (unsigned long)nsjconf->inside_gid,
+ (unsigned long)nsjconf->outside_gid);
+ if (write_size <= 0 || (size_t) write_size > len) {
+ LOG_E("snprintf writing the new{u,g}idmap command failed");
+ return false;
+ }
+ cmd_ptr += write_size;
+ len -= write_size;
+
+ struct mapping_t *p;
+ TAILQ_FOREACH(p, &nsjconf->gid_mappings, pointers) {
+ write_size = snprintf(cmd_ptr, len, " %s %s %s",
+ p->inside_id, p->outside_id, p->count);
+ if (write_size <= 0 || (size_t) write_size > len) {
+ LOG_E("snprintf writing the new{u,g}idmap command failed");
+ return false;
+ }
+ cmd_ptr += write_size;
+ len -= write_size;
+ }
+
+ if (system(cmd_buf) != 0) {
+ LOG_E("system('%s') failed", cmd_buf);
+ while(1) ;
+ return false;
+ }
+
+ return true;
+}
+
+// use /usr/bin/newuidmap for writing the uid and gid map
+static bool userUidMapExternal(struct nsjconf_t *nsjconf, pid_t pid) {
+ char cmd_buf[1024];
+ char *cmd_ptr = cmd_buf;
+ size_t len = sizeof(cmd_buf);
+ int write_size;
+
+ write_size = snprintf(cmd_ptr, len, "/usr/bin/newuidmap %lu %lu %lu 1",
+ (unsigned long)pid,
+ (unsigned long)nsjconf->inside_uid,
+ (unsigned long)nsjconf->outside_uid);
+ if (write_size <= 0 || (size_t) write_size > len) {
+ LOG_E("snprintf writing the new{u,g}idmap command failed");
+ return false;
+ }
+ cmd_ptr += write_size;
+ len -= write_size;
+
+ struct mapping_t *p;
+ TAILQ_FOREACH(p, &nsjconf->uid_mappings, pointers) {
+ write_size = snprintf(cmd_ptr, len, " %s %s %s",
+ p->inside_id, p->outside_id, p->count);
+ if (write_size <= 0 || (size_t) write_size > len) {
+ LOG_E("snprintf writing the new{u,g}idmap command failed");
+ return false;
+ }
+ cmd_ptr += write_size;
+ len -= write_size;
+ }
+
+ if (system(cmd_buf) != 0) {
+ LOG_E("system('%s') failed", cmd_buf);
+ return false;
+ }
+
+ return true;
+}
+
+static bool userUidGidMap(struct nsjconf_t *nsjconf, pid_t pid)
+{
+ if (TAILQ_EMPTY(&nsjconf->gid_mappings)) {
+ if (!userGidMapSelf(nsjconf, pid)) {
+ return false;
+ }
+ } else {
+ if (!userGidMapExternal(nsjconf, pid)) {
+ return false;
+ }
+ }
+ if (TAILQ_EMPTY(&nsjconf->uid_mappings)) {
+ return userUidMapSelf(nsjconf, pid);
+ } else {
+ return userUidMapExternal(nsjconf, pid);
+ }
+}
+
bool userInitNsFromParent(struct nsjconf_t * nsjconf, pid_t pid)
{
if (nsjconf->clone_newuser == false) {