On Fri, Jul 19, 2013 at 02:26:55PM +0000, Serge Hallyn wrote: > From: Serge Hallyn <serge.hal...@ubuntu.com> > > It needs to be done from the handler, not the container, since > the container may not have the rights. > > Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com> > --- > src/lxc/conf.c | 126 > +++++++++++++++++++++++-------------------------- > src/lxc/conf.h | 6 +-- > src/lxc/lxccontainer.c | 53 +-------------------- > src/lxc/start.c | 10 ++-- > 4 files changed, 69 insertions(+), 126 deletions(-) > > diff --git a/src/lxc/conf.c b/src/lxc/conf.c > index 2e202ec..e8399a9 100644 > --- a/src/lxc/conf.c > +++ b/src/lxc/conf.c > @@ -2615,7 +2615,7 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) > * return the host uid to which the container root is mapped, or -1 on > * error > */ > -int get_mapped_rootid(struct lxc_conf *conf) > +uid_t get_mapped_rootid(struct lxc_conf *conf) > { > struct lxc_list *it; > struct id_map *map; > @@ -2626,9 +2626,9 @@ int get_mapped_rootid(struct lxc_conf *conf) > continue; > if (map->nsid != 0) > continue; > - return map->hostid; > + return (uid_t) map->hostid; > } > - return -1; > + return (uid_t)-1; > } > > bool hostid_is_mapped(int id, struct lxc_conf *conf) > @@ -2772,89 +2772,81 @@ void lxc_delete_tty(struct lxc_tty_info *tty_info) > } > > /* > - * given a host uid, return the ns uid if it is mapped. > - * if it is not mapped, return the original host id. > + * chown_mapped_root: for an unprivileged user with uid X to chown a dir > + * to subuid Y, he needs to run chown as root in a userns where > + * nsid 0 is mapped to hostuid Y, and nsid Y is mapped to hostuid > + * X. That way, the container root is privileged with respect to > + * hostuid X, allowing him to do the chown. > */ > -static int shiftid(struct lxc_conf *c, int uid, enum idtype w) > +int chown_mapped_root(char *path, struct lxc_conf *conf) > { > - struct lxc_list *iterator; > - struct id_map *map; > - int low, high; > + uid_t rootid; > + pid_t pid; > > - lxc_list_for_each(iterator, &c->id_map) { > - map = iterator->elem; > - if (map->idtype != w) > - continue; > - > - low = map->nsid; > - high = map->nsid + map->range; > - if (uid < low || uid >= high) > - continue; > - > - return uid - low + map->hostid; > + if ((rootid = get_mapped_rootid(conf)) <= 0) { > + ERROR("No mapping for container root"); > + return -1; > } > - > - return uid; > -} > - > -/* > - * Take a pathname for a file created on the host, and map the uid and gid > - * into the container if needed. (Used for ttys) > - */ > -static int uid_shift_file(char *path, struct lxc_conf *c) > -{ > - struct stat statbuf; > - int newuid, newgid; > - > - if (stat(path, &statbuf)) { > - SYSERROR("stat(%s)", path); > + if (geteuid() == 0) { > + if (chown(path, rootid, -1) < 0) { > + ERROR("Error chowning %s", path); > + return -1; > + } > + return 0; > + } > + pid = fork(); > + if (pid < 0) { > + SYSERROR("Failed forking"); > return -1; > } > + if (!pid) { > + int hostuid = geteuid(), ret; > + char map1[100], map2[100]; > + char *args[] = {"usernsexec", "-m", map1, "-m", map2, "--", > "/bin/chown",
I know I'm annoying with my hardcoded paths, but here's one more ;) > + "0", path, NULL}; > > - newuid = shiftid(c, statbuf.st_uid, ID_TYPE_UID); > - newgid = shiftid(c, statbuf.st_gid, ID_TYPE_GID); > - if (newuid != statbuf.st_uid || newgid != statbuf.st_gid) { > - DEBUG("chowning %s from %d:%d to %d:%d\n", path, > (int)statbuf.st_uid, (int)statbuf.st_gid, newuid, newgid); > - if (chown(path, newuid, newgid)) { > - SYSERROR("chown(%s)", path); > + // "b:0:rootid:1" > + ret = snprintf(map1, 100, "b:0:%d:1", rootid); > + if (ret < 0 || ret >= 100) { > + ERROR("Error uid printing map string"); > return -1; > } > + > + // "b:hostuid:hostuid:1" > + ret = snprintf(map2, 100, "b:%d:%d:1", hostuid, hostuid); > + if (ret < 0 || ret >= 100) { > + ERROR("Error uid printing map string"); > + return -1; > + } > + > + ret = execvp("usernsexec", args); > + SYSERROR("Failed executing usernsexec"); > + exit(1); > } > - return 0; > + return wait_for_pid(pid); > } > > -int uid_shift_ttys(int pid, struct lxc_conf *conf) > +int ttys_shift_ids(struct lxc_conf *c) > { > - int i, ret; > - struct lxc_tty_info *tty_info = &conf->tty_info; > - char path[MAXPATHLEN]; > - char *ttydir = conf->ttydir; > + int i; > > - if (!conf->rootfs.path) > + if (lxc_list_empty(&c->id_map)) > return 0; > - /* first the console */ > - ret = snprintf(path, sizeof(path), "/proc/%d/root/dev/%s/console", pid, > ttydir ? ttydir : ""); > - if (ret < 0 || ret >= sizeof(path)) { > - ERROR("console path too long\n"); > - return -1; > - } > - if (uid_shift_file(path, conf)) { > - DEBUG("Failed to chown the console %s.\n", path); > - return -1; > - } > - for (i=0; i< tty_info->nbtty; i++) { > - ret = snprintf(path, sizeof(path), "/proc/%d/root/dev/%s/tty%d", > - pid, ttydir ? ttydir : "", i + 1); > - if (ret < 0 || ret >= sizeof(path)) { > - ERROR("pathname too long for ttys"); > - return -1; > - } > - if (uid_shift_file(path, conf)) { > - DEBUG("Failed to chown pty %s.\n", path); > + > + for (i = 0; i < c->tty_info.nbtty; i++) { > + struct lxc_pty_info *pty_info = &c->tty_info.pty_info[i]; > + > + if (chown_mapped_root(pty_info->name, c) < 0) { > + ERROR("Failed to chown %s", pty_info->name); > return -1; > } > } > > + if (chown_mapped_root(c->console.name, c) < 0) { > + ERROR("Failed to chown %s", c->console.name); > + return -1; > + } > + > return 0; > } > > diff --git a/src/lxc/conf.h b/src/lxc/conf.h > index 065b1df..bb3b456 100644 > --- a/src/lxc/conf.h > +++ b/src/lxc/conf.h > @@ -321,8 +321,6 @@ extern int lxc_clear_cgroups(struct lxc_conf *c, const > char *key); > extern int lxc_clear_mount_entries(struct lxc_conf *c); > extern int lxc_clear_hooks(struct lxc_conf *c, const char *key); > > -extern int uid_shift_ttys(int pid, struct lxc_conf *conf); > - > /* > * Configure the container from inside > */ > @@ -332,7 +330,9 @@ extern int lxc_setup(const char *name, struct lxc_conf > *lxc_conf, > > extern void lxc_rename_phys_nics_on_shutdown(struct lxc_conf *conf); > > -extern int get_mapped_rootid(struct lxc_conf *conf); > +extern uid_t get_mapped_rootid(struct lxc_conf *conf); > extern int find_unmapped_nsuid(struct lxc_conf *conf); > extern bool hostid_is_mapped(int id, struct lxc_conf *conf); > +extern int chown_mapped_root(char *path, struct lxc_conf *conf); > +extern int ttys_shift_ids(struct lxc_conf *c); > #endif > diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c > index f9ce7d3..6790ac6 100644 > --- a/src/lxc/lxccontainer.c > +++ b/src/lxc/lxccontainer.c > @@ -677,48 +677,6 @@ static bool create_container_dir(struct lxc_container *c) > static const char *lxcapi_get_config_path(struct lxc_container *c); > static bool lxcapi_set_config_item(struct lxc_container *c, const char *key, > const char *v); > > -/* > - * chown_mapped: for an unprivileged user with uid X to chown a dir > - * to subuid Y, he needs to run chown as root in a userns where > - * nsid 0 is mapped to hostuid Y, and nsid Y is mapped to hostuid > - * X. That way, the container root is privileged with respect to > - * hostuid X, allowing him to do the chown. > - */ > -static int chown_mapped(int nsrootid, char *path) > -{ > - if (nsrootid < 0) > - return nsrootid; > - pid_t pid = fork(); > - if (pid < 0) { > - SYSERROR("Failed forking"); > - return -1; > - } > - if (!pid) { > - int hostuid = geteuid(), ret; > - char map1[100], map2[100]; > - char *args[] = {"usernsexec", "-m", map1, "-m", map2, "--", > "/bin/chown", > - "0", path, NULL}; > - > - // "b:0:nsrootid:1" > - ret = snprintf(map1, 100, "b:0:%d:1", nsrootid); > - if (ret < 0 || ret >= 100) { > - ERROR("Error uid printing map string"); > - return -1; > - } > - > - // "b:hostuid:hostuid:1" > - ret = snprintf(map2, 100, "b:%d:%d:1", hostuid, hostuid); > - if (ret < 0 || ret >= 100) { > - ERROR("Error uid printing map string"); > - return -1; > - } > - > - ret = execvp("usernsexec", args); > - SYSERROR("Failed executing usernsexec"); > - exit(1); > - } > - return wait_for_pid(pid); > -} > > /* > * do_bdev_create: thin wrapper around bdev_create(). Like bdev_create(), > @@ -749,15 +707,8 @@ static struct bdev *do_bdev_create(struct lxc_container > *c, const char *type, > * target uidmap */ > > if (geteuid() != 0) { > - int rootid; > - if ((rootid = get_mapped_rootid(c->lxc_conf)) <= 0) { > - ERROR("No mapping for container root"); > - bdev_put(bdev); > - return NULL; > - } > - ret = chown_mapped(rootid, bdev->dest); > - if (ret < 0) { > - ERROR("Error chowning %s to %d\n", bdev->dest, rootid); > + if (chown_mapped_root(bdev->dest, c->lxc_conf) < 0) { > + ERROR("Error chowning %s to container root\n", > bdev->dest); > bdev_put(bdev); > return NULL; > } > diff --git a/src/lxc/start.c b/src/lxc/start.c > index 00020de..745e677 100644 > --- a/src/lxc/start.c > +++ b/src/lxc/start.c > @@ -333,6 +333,11 @@ struct lxc_handler *lxc_init(const char *name, struct > lxc_conf *conf, const char > goto out_restore_sigmask; > } > > + if (ttys_shift_ids(conf) < 0) { > + ERROR("Failed to shift tty into container"); > + goto out_restore_sigmask; > + } > + > INFO("'%s' is initialized", name); > return handler; > > @@ -731,11 +736,6 @@ int lxc_spawn(struct lxc_handler *handler) > if (detect_shared_rootfs()) > umount2(handler->conf->rootfs.mount, MNT_DETACH); > > - /* If child is in a fresh user namespace, chown his ptys for > - * it */ > - if (uid_shift_ttys(handler->pid, handler->conf)) > - DEBUG("Failed to chown ptys.\n"); > - > if (handler->ops->post_start(handler, handler->data)) > goto out_abort; > > -- > 1.8.3.2 > > > ------------------------------------------------------------------------------ > See everything from the browser to the database with AppDynamics > Get end-to-end visibility with application monitoring from AppDynamics > Isolate bottlenecks and diagnose root cause in seconds. > Start your free trial of AppDynamics Pro today! > http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk > _______________________________________________ > Lxc-devel mailing list > Lxc-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/lxc-devel -- Stéphane Graber Ubuntu developer http://www.ubuntu.com
signature.asc
Description: Digital signature
------------------------------------------------------------------------------ See everything from the browser to the database with AppDynamics Get end-to-end visibility with application monitoring from AppDynamics Isolate bottlenecks and diagnose root cause in seconds. Start your free trial of AppDynamics Pro today! http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel