[libvirt] [PATCH v2] LXC: Detect fs support. Mount only supported filesystems

Gao feng gaofeng at cn.fujitsu.com
Fri Oct 4 09:54:48 UTC 2013


On 10/02/2013 10:05 PM, Bogdan Purcareata wrote:
> Kept ((access(dstpath, R_OK) < 0) || (!lxcCheckFSSupport(mnt->type)))
> when determining support for the mount. Even if the filesystem type is
> supported, there is still a chance to fail when building the dstpath
> (virFileMakePath). If that call fails, starting the container will fail.
> Specifically encountered this problem for securityfs, as I was unable
> to mkdir /sys/kernel/security.
> 
> Signed-off-by: Bogdan Purcareata <bogdan.purcareata at freescale.com>
> ---
>  src/lxc/lxc_container.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 67 insertions(+)
> 
> diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
> index 989e920..496443d 100644
> --- a/src/lxc/lxc_container.c
> +++ b/src/lxc/lxc_container.c
> @@ -509,6 +509,67 @@ static int lxcContainerChildMountSort(const void *a, const void *b)
>  # define MS_SLAVE                (1<<19)
>  #endif
>  
> +/*
> + * This function attempts to detect kernel support
> + * for a specific filesystem type. This is done by
> + * inspecting /proc/filesystems.
> + */
> +static int lxcCheckFSSupport(const char *fs_type)
> +{
> +    FILE *fp = NULL;
> +    int ret = -1;
> +    const char *fslist = "/proc/filesystems";
> +    char *line = NULL;
> +    char *type;
> +    size_t n;
> +
> +    /* there should be no problem mounting an entry
> +     * with NULL fs type, hence NULL fs types are
> +     * supported */
> +    if (!fs_type) {
> +	ret = 1;
> +	goto out;
> +    }
> +
> +    VIR_DEBUG("Checking kernel support for %s in %s", fs_type, fslist);
> +
> +    if (!(fp = fopen(fslist, "r"))) {

I don't know if we can open /proc/filesystems successfully here if container shares
root directory with host, since the /proc filesystem has been unmounted in
lxcContainerUnmountForSharedRoot.

> +        virReportSystemError(errno,
> +                             _("Unable to read %s"),
> +                             fslist);
> +        goto out;
> +    }
> +
> +    while(getline(&line, &n, fp) > 0) {
> +	type = strstr(line, fs_type);
> +
> +	if (!type)
> +		continue;
> +
> +	if (!strncmp(type, fs_type, strlen(type))) {

The strncmp() function compares the only first (at most) n bytes of s1 and s2.
please use STREQ here.

> +		ret = 1;
> +		goto cleanup;
> +	}
> +    }
> +
> +    if (ferror(fp)) {
> +	virReportSystemError(errno,
> +                             _("Error reading line from %s"),
> +                             fslist);
> +        goto cleanup;
> +    }
> +
> +    VIR_DEBUG("No kernel support for %s", fs_type);
> +
> +    ret = 0;
> +

You set ret to 0 here, so the return value 0 means this filesystem
is unsupported by kernel, right? what the meaning of return value -1?

you return -1 when ferror(fp) is true.

> +cleanup:
> +    VIR_FREE(line);
> +    VIR_FORCE_FCLOSE(fp);
> +out:
> +    return ret;
> +}
> +
>  static int lxcContainerGetSubtree(const char *prefix,
>                                    char ***mountsret,
>                                    size_t *nmountsret)
> @@ -789,17 +850,23 @@ static int lxcContainerMountBasicFS(bool userns_enabled)
>      for (i = 0; i < ARRAY_CARDINALITY(lxcBasicMounts); i++) {
>          virLXCBasicMountInfo const *mnt = &lxcBasicMounts[i];
>          const char *srcpath = NULL;
> +	const char *dstpath = NULL;
>  
>          VIR_DEBUG("Processing %s -> %s",
>                    mnt->src, mnt->dst);
>  
>          srcpath = mnt->src;
> +	dstpath = mnt->dst;
>  
>          /* Skip if mount doesn't exist in source */
>          if ((srcpath[0] == '/') &&
>              (access(srcpath, R_OK) < 0))
>              continue;
>  
> +	if ((access(dstpath, R_OK) < 0) || /* mount is not present on host */
> +	    (!lxcCheckFSSupport(mnt->type))) /* no fs support in kernel */
> +		continue;
> +

The access is in the incorrect place, it should be called after we create mnt->dst.
so Move this check after virFileMakePath(mnt->dst).

>  #if WITH_SELINUX
>          if (STREQ(mnt->src, SELINUX_MOUNT) &&
>              (!is_selinux_enabled() || userns_enabled))
> 

Thanks




More information about the libvir-list mailing list