Skip to content

Commit

Permalink
always ensure a /proc while setting up container
Browse files Browse the repository at this point in the history
Otherwise we can't open /proc/self/fd to find the fds to close.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
  • Loading branch information
hallyn committed Feb 15, 2014
1 parent f8744a9 commit 5112cd7
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 82 deletions.
77 changes: 74 additions & 3 deletions src/lxc/conf.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
3 changes: 2 additions & 1 deletion src/lxc/conf.h
Expand Up @@ -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;
Expand Down Expand Up @@ -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
73 changes: 0 additions & 73 deletions src/lxc/lsm/lsm.c
Expand Up @@ -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
4 changes: 0 additions & 4 deletions src/lxc/lsm/lsm.h
Expand Up @@ -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
4 changes: 3 additions & 1 deletion src/lxc/start.c
Expand Up @@ -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;
Expand Down

0 comments on commit 5112cd7

Please sign in to comment.