From: Serge Hallyn Date: Sat, 15 Feb 2014 05:57:12 +0000 (-0600) Subject: always ensure a /proc while setting up container X-Git-Tag: lxc-1.0.0.rc3~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5112cd709005169b1afad76b1e4de3c4cc86716f;p=thirdparty%2Flxc.git always ensure a /proc while setting up container Otherwise we can't open /proc/self/fd to find the fds to close. Signed-off-by: Serge Hallyn --- diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 4336258af..e5df68bff 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2617,7 +2617,7 @@ struct lxc_conf *lxc_conf_init(void) lxc_list_init(&new->groups); new->lsm_aa_profile = NULL; new->lsm_se_context = NULL; - new->lsm_umount_proc = 0; + new->tmp_umount_proc = 0; for (i = 0; i < LXC_NS_MAX; i++) new->inherit_ns_fd[i] = -1; @@ -3518,6 +3518,77 @@ static int check_autodev( const char *rootfs, void *data ) return 0; } +/* + * _do_tmp_proc_mount: Mount /proc inside container if not already + * mounted + * + * @rootfs : the rootfs where proc should be mounted + * + * Returns < 0 on failure, 0 if the correct proc was already mounted + * and 1 if a new proc was mounted. + */ +static int do_tmp_proc_mount(const char *rootfs) +{ + char path[MAXPATHLEN]; + char link[20]; + int linklen, ret; + + ret = snprintf(path, MAXPATHLEN, "%s/proc/self", rootfs); + if (ret < 0 || ret >= MAXPATHLEN) { + SYSERROR("proc path name too long"); + return -1; + } + memset(link, 0, 20); + linklen = readlink(path, link, 20); + INFO("I am %d, /proc/self points to '%s'", getpid(), link); + ret = snprintf(path, MAXPATHLEN, "%s/proc", rootfs); + if (linklen < 0) /* /proc not mounted */ + goto domount; + /* can't be longer than rootfs/proc/1 */ + if (strncmp(link, "1", linklen) != 0) { + /* wrong /procs mounted */ + umount2(path, MNT_DETACH); /* ignore failure */ + goto domount; + } + /* the right proc is already mounted */ + return 0; + +domount: + if (mount("proc", path, "proc", 0, NULL)) + return -1; + INFO("Mounted /proc in container for security transition"); + return 1; +} + +int tmp_proc_mount(struct lxc_conf *lxc_conf) +{ + int mounted; + + if (lxc_conf->rootfs.path == NULL || strlen(lxc_conf->rootfs.path) == 0) { + if (mount("proc", "/proc", "proc", 0, NULL)) { + SYSERROR("Failed mounting /proc, proceeding"); + mounted = 0; + } else + mounted = 1; + } else + mounted = do_tmp_proc_mount(lxc_conf->rootfs.mount); + if (mounted == -1) { + SYSERROR("failed to mount /proc in the container."); + return -1; + } else if (mounted == 1) { + lxc_conf->tmp_umount_proc = 1; + } + return 0; +} + +void tmp_proc_unmount(struct lxc_conf *lxc_conf) +{ + if (lxc_conf->tmp_umount_proc == 1) { + umount("/proc"); + lxc_conf->tmp_umount_proc = 0; + } +} + int lxc_setup(struct lxc_handler *handler) { const char *name = handler->name; @@ -3621,8 +3692,8 @@ int lxc_setup(struct lxc_handler *handler) return -1; } - /* mount /proc if needed for LSM transition */ - if (lsm_proc_mount(lxc_conf) < 0) { + /* mount /proc if it's not already there */ + if (tmp_proc_mount(lxc_conf) < 0) { ERROR("failed to LSM mount proc for '%s'", name); return -1; } diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 16d712242..4591470df 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -301,7 +301,7 @@ struct lxc_conf { char *lsm_aa_profile; char *lsm_se_context; - int lsm_umount_proc; + int tmp_umount_proc; char *seccomp; // filename with the seccomp rules #if HAVE_SCMP_FILTER_CTX scmp_filter_ctx *seccomp_ctx; @@ -378,4 +378,5 @@ extern int ttys_shift_ids(struct lxc_conf *c); extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data); extern int parse_mntopts(const char *mntopts, unsigned long *mntflags, char **mntdata); +extern void tmp_proc_unmount(struct lxc_conf *lxc_conf); #endif diff --git a/src/lxc/lsm/lsm.c b/src/lxc/lsm/lsm.c index a41ab8806..c9940461f 100644 --- a/src/lxc/lsm/lsm.c +++ b/src/lxc/lsm/lsm.c @@ -94,77 +94,4 @@ int lsm_process_label_set(const char *label, int use_default, int on_exec) return drv->process_label_set(label, use_default, on_exec); } -/* - * _lsm_mount_proc: Mount /proc inside container to enable - * security domain transition - * - * @rootfs : the rootfs where proc should be mounted - * - * Returns < 0 on failure, 0 if the correct proc was already mounted - * and 1 if a new proc was mounted. - */ -static int _lsm_proc_mount(const char *rootfs) -{ - char path[MAXPATHLEN]; - char link[20]; - int linklen, ret; - - ret = snprintf(path, MAXPATHLEN, "%s/proc/self", rootfs); - if (ret < 0 || ret >= MAXPATHLEN) { - SYSERROR("proc path name too long"); - return -1; - } - memset(link, 0, 20); - linklen = readlink(path, link, 20); - INFO("I am %d, /proc/self points to '%s'", getpid(), link); - ret = snprintf(path, MAXPATHLEN, "%s/proc", rootfs); - if (linklen < 0) /* /proc not mounted */ - goto domount; - /* can't be longer than rootfs/proc/1 */ - if (strncmp(link, "1", linklen) != 0) { - /* wrong /procs mounted */ - umount2(path, MNT_DETACH); /* ignore failure */ - goto domount; - } - /* the right proc is already mounted */ - return 0; - -domount: - if (mount("proc", path, "proc", 0, NULL)) - return -1; - INFO("Mounted /proc in container for security transition"); - return 1; -} - -int lsm_proc_mount(struct lxc_conf *lxc_conf) -{ - int mounted; - - if (!drv || strcmp(drv->name, "nop") == 0) - return 0; - - if (lxc_conf->rootfs.path == NULL || strlen(lxc_conf->rootfs.path) == 0) { - if (mount("proc", "/proc", "proc", 0, NULL)) { - SYSERROR("Failed mounting /proc, proceeding"); - mounted = 0; - } else - mounted = 1; - } else - mounted = _lsm_proc_mount(lxc_conf->rootfs.mount); - if (mounted == -1) { - SYSERROR("failed to mount /proc in the container."); - return -1; - } else if (mounted == 1) { - lxc_conf->lsm_umount_proc = 1; - } - return 0; -} - -void lsm_proc_unmount(struct lxc_conf *lxc_conf) -{ - if (lxc_conf->lsm_umount_proc == 1) { - umount("/proc"); - lxc_conf->lsm_umount_proc = 0; - } -} #endif diff --git a/src/lxc/lsm/lsm.h b/src/lxc/lsm/lsm.h index d14caf4e2..93f5b87c2 100644 --- a/src/lxc/lsm/lsm.h +++ b/src/lxc/lsm/lsm.h @@ -43,16 +43,12 @@ int lsm_enabled(void); const char *lsm_name(void); char *lsm_process_label_get(pid_t pid); int lsm_process_label_set(const char *label, int use_default, int on_exec); -int lsm_proc_mount(struct lxc_conf *lxc_conf); -void lsm_proc_unmount(struct lxc_conf *lxc_conf); #else static inline void lsm_init(void) { } static inline int lsm_enabled(void) { return 0; } static inline const char *lsm_name(void) { return "none"; } static inline char *lsm_process_label_get(pid_t pid) { return NULL; } static inline int lsm_process_label_set(const char *label, int use_default, int on_exec) { return 0; } -static inline int lsm_proc_mount(struct lxc_conf *lxc_conf) { return 0; } -static inline void lsm_proc_unmount(struct lxc_conf *lxc_conf) { } #endif #endif diff --git a/src/lxc/start.c b/src/lxc/start.c index 81d3f47cc..60699c323 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -649,7 +649,9 @@ static int do_start(void *data) lsm_label = handler->conf->lsm_se_context; if (lsm_process_label_set(lsm_label, 1, 1) < 0) goto out_warn_father; - lsm_proc_unmount(handler->conf); + + /* If we mounted a temporary proc, then unmount it now */ + tmp_proc_unmount(handler->conf); if (lxc_seccomp_load(handler->conf) != 0) goto out_warn_father;