On Wed, Oct 23, 2013 at 01:02:58AM +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>

Acked-by: Stéphane Graber <stgra...@ubuntu.com>

> Changelog:
>     Jul 22: remove hardcoded path for /bin/chown
>     Jul 22: use new lxc-usernsexec
> 
> Conflicts:
>       src/lxc/lxccontainer.c
> ---
>  src/lxc/conf.c         | 126 
> +++++++++++++++++++++++--------------------------
>  src/lxc/conf.h         |   6 +--
>  src/lxc/lxccontainer.c |  54 +--------------------
>  src/lxc/start.c        |  10 ++--
>  4 files changed, 69 insertions(+), 127 deletions(-)
> 
> diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> index 3f7f0ef..bba6379 100644
> --- a/src/lxc/conf.c
> +++ b/src/lxc/conf.c
> @@ -2858,7 +2858,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;
> @@ -2869,9 +2869,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)
> @@ -3020,89 +3020,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[] = {"lxc-usernsexec", "-m", map1, "-m", map2, "--", 
> "chown",
> +                              "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("lxc-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 445867d..71399b9 100644
> --- a/src/lxc/conf.h
> +++ b/src/lxc/conf.h
> @@ -350,8 +350,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
>   */
> @@ -362,7 +360,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 816eb39..38b67ca 100644
> --- a/src/lxc/lxccontainer.c
> +++ b/src/lxc/lxccontainer.c
> @@ -694,49 +694,6 @@ 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[] = {"lxc-usernsexec", "-m", map1, "-m", map2, "--", 
> "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("lxc-usernsexec", args);
> -             SYSERROR("Failed executing lxc-usernsexec");
> -             exit(1);
> -     }
> -     return wait_for_pid(pid);
> -}
> -
> -/*
>   * do_bdev_create: thin wrapper around bdev_create().  Like bdev_create(),
>   * it returns a mounted bdev on success, NULL on error.
>   */
> @@ -768,15 +725,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 e46f3a0..1cadc09 100644
> --- a/src/lxc/start.c
> +++ b/src/lxc/start.c
> @@ -353,6 +353,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;
>  
> @@ -784,11 +789,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.1.2
> 
> 
> ------------------------------------------------------------------------------
> October Webinars: Code for Performance
> Free Intel webinars can help you accelerate application performance.
> Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from 
> the latest Intel processors and coprocessors. See abstracts and register >
> http://pubads.g.doubleclick.net/gampad/clk?id=60135991&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

Attachment: signature.asc
Description: Digital signature

------------------------------------------------------------------------------
October Webinars: Code for Performance
Free Intel webinars can help you accelerate application performance.
Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from 
the latest Intel processors and coprocessors. See abstracts and register >
http://pubads.g.doubleclick.net/gampad/clk?id=60135991&iu=/4140/ostg.clktrk
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to