[lxc-devel] [PATCH 1/1] always check whether rootfs is shared

Dwight Engen dwight.engen at oracle.com
Tue Feb 25 14:16:15 UTC 2014


On Mon, 24 Feb 2014 23:08:26 -0600
Serge Hallyn <serge.hallyn at ubuntu.com> wrote:

> (this expands on Dwight's recent patch, commit c597baa8f9)
> 
> After unshare(CLONE_NEWNS) and before doing any mounting, always
> check whether rootfs is shared.  Otherwise template runs or clone
> scripts can bleed mount activity to the host.
> 
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>

Acked-by: Dwight Engen <dwight.engen at oracle.com>

(You might want to change/genericize the error message since those
 are not rsync)

> ---
>  src/lxc/attach.c         |  7 +++++++
>  src/lxc/bdev.c           |  7 +++++++
>  src/lxc/conf.c           | 40
> ---------------------------------------- src/lxc/lxc_usernsexec.c |
> 7 +++++++ src/lxc/lxccontainer.c   |  6 ++++++
>  src/lxc/utils.c          | 40
> ++++++++++++++++++++++++++++++++++++++++ src/lxc/utils.h          |
> 2 ++ 7 files changed, 69 insertions(+), 40 deletions(-)
> 
> diff --git a/src/lxc/attach.c b/src/lxc/attach.c
> index f12d216..9136ec2 100644
> --- a/src/lxc/attach.c
> +++ b/src/lxc/attach.c
> @@ -220,6 +220,13 @@ static int lxc_attach_remount_sys_proc(void)
>  		return -1;
>  	}
>  
> +	if (detect_shared_rootfs()) {
> +		if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
> +			SYSERROR("Failed to make / rslave to run
> rsync");
> +			ERROR("Continuing...");
> +		}
> +	}
> +
>  	/* assume /proc is always mounted, so remount it */
>  	ret = umount2("/proc", MNT_DETACH);
>  	if (ret < 0) {
> diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c
> index 952cfeb..40f70c5 100644
> --- a/src/lxc/bdev.c
> +++ b/src/lxc/bdev.c
> @@ -302,6 +302,13 @@ static int detect_fs(struct bdev *bdev, char
> *type, int len) if (unshare(CLONE_NEWNS) < 0)
>  		exit(1);
>  
> +	if (detect_shared_rootfs()) {
> +		if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
> +			SYSERROR("Failed to make / rslave to run
> rsync");
> +			ERROR("Continuing...");
> +		}
> +	}
> +
>  	ret = mount_unknown_fs(srcdev, bdev->dest, bdev->mntopts);
>  	if (ret < 0) {
>  		ERROR("failed mounting %s onto %s to detect fstype",
> srcdev, bdev->dest); diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> index c9dd7ac..fc39897 100644
> --- a/src/lxc/conf.c
> +++ b/src/lxc/conf.c
> @@ -1427,46 +1427,6 @@ static int setup_autodev(const char *root)
>  }
>  
>  /*
> - * Detect whether / is mounted MS_SHARED.  The only way I know of to
> - * check that is through /proc/self/mountinfo.
> - * I'm only checking for /.  If the container rootfs or mount
> location
> - * is MS_SHARED, but not '/', then you're out of luck - figuring that
> - * out would be too much work to be worth it.
> - */
> -#define LINELEN 4096
> -int detect_shared_rootfs(void)
> -{
> -	char buf[LINELEN], *p;
> -	FILE *f;
> -	int i;
> -	char *p2;
> -
> -	f = fopen("/proc/self/mountinfo", "r");
> -	if (!f)
> -		return 0;
> -	while (fgets(buf, LINELEN, f)) {
> -		for (p = buf, i=0; p && i < 4; i++)
> -			p = index(p+1, ' ');
> -		if (!p)
> -			continue;
> -		p2 = index(p+1, ' ');
> -		if (!p2)
> -			continue;
> -		*p2 = '\0';
> -		if (strcmp(p+1, "/") == 0) {
> -			// this is '/'.  is it shared?
> -			p = index(p2+1, ' ');
> -			if (p && strstr(p, "shared:")) {
> -				fclose(f);
> -				return 1;
> -			}
> -		}
> -	}
> -	fclose(f);
> -	return 0;
> -}
> -
> -/*
>   * I'll forgive you for asking whether all of this is needed :)  The
>   * answer is yes.
>   * pivot_root will fail if the new root, the put_old dir, or the
> parent diff --git a/src/lxc/lxc_usernsexec.c
> b/src/lxc/lxc_usernsexec.c index e40fa53..6784633 100644
> --- a/src/lxc/lxc_usernsexec.c
> +++ b/src/lxc/lxc_usernsexec.c
> @@ -35,6 +35,7 @@
>  #include <fcntl.h>
>  #include <sys/stat.h>
>  #include <sys/types.h>
> +#include <sys/mount.h>
>  #include <sys/wait.h>
>  #include <sched.h>
>  #include <pwd.h>
> @@ -111,6 +112,12 @@ static int do_child(void *vargv)
>  		perror("unshare CLONE_NEWNS");
>  		return -1;
>  	}
> +	if (detect_shared_rootfs()) {
> +		if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
> +			printf("Failed to make / rslave to run
> rsync");
> +			return -1;
> +		}
> +	}
>  	execvp(argv[0], argv);
>  	perror("execvpe");
>  	return -1;
> diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> index 0d89d11..8eb2d8b 100644
> --- a/src/lxc/lxccontainer.c
> +++ b/src/lxc/lxccontainer.c
> @@ -2502,6 +2502,12 @@ static int clone_update_rootfs(struct
> clone_update_data *data) bdev_put(bdev);
>  			return -1;
>  		}
> +		if (detect_shared_rootfs()) {
> +			if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC,
> NULL)) {
> +				SYSERROR("Failed to make / rslave to
> run rsync");
> +				ERROR("Continuing...");
> +			}
> +		}
>  		if (bdev->ops->mount(bdev) < 0) {
>  			bdev_put(bdev);
>  			return -1;
> diff --git a/src/lxc/utils.c b/src/lxc/utils.c
> index 52e4c86..da7c3b4 100644
> --- a/src/lxc/utils.c
> +++ b/src/lxc/utils.c
> @@ -1194,3 +1194,43 @@ uint64_t fnv_64a_buf(void *buf, size_t len,
> uint64_t hval) 
>  	return hval;
>  }
> +
> +/*
> + * Detect whether / is mounted MS_SHARED.  The only way I know of to
> + * check that is through /proc/self/mountinfo.
> + * I'm only checking for /.  If the container rootfs or mount
> location
> + * is MS_SHARED, but not '/', then you're out of luck - figuring that
> + * out would be too much work to be worth it.
> + */
> +#define LINELEN 4096
> +int detect_shared_rootfs(void)
> +{
> +	char buf[LINELEN], *p;
> +	FILE *f;
> +	int i;
> +	char *p2;
> +
> +	f = fopen("/proc/self/mountinfo", "r");
> +	if (!f)
> +		return 0;
> +	while (fgets(buf, LINELEN, f)) {
> +		for (p = buf, i=0; p && i < 4; i++)
> +			p = index(p+1, ' ');
> +		if (!p)
> +			continue;
> +		p2 = index(p+1, ' ');
> +		if (!p2)
> +			continue;
> +		*p2 = '\0';
> +		if (strcmp(p+1, "/") == 0) {
> +			// this is '/'.  is it shared?
> +			p = index(p2+1, ' ');
> +			if (p && strstr(p, "shared:")) {
> +				fclose(f);
> +				return 1;
> +			}
> +		}
> +	}
> +	fclose(f);
> +	return 0;
> +}
> diff --git a/src/lxc/utils.h b/src/lxc/utils.h
> index f6f3373..dcf0e34 100644
> --- a/src/lxc/utils.h
> +++ b/src/lxc/utils.h
> @@ -276,3 +276,5 @@ extern bool dir_exists(const char *path);
>  #define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL)
>  uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval);
>  #endif
> +
> +int detect_shared_rootfs(void);



More information about the lxc-devel mailing list