[libvirt] [RFC 3/3] lxc: Mount NBD devices before clone
John Ferlan
jferlan at redhat.com
Thu Apr 26 18:09:50 UTC 2018
On 04/15/2018 05:25 PM, Radostin Stoyanov wrote:
> When user-namespace is enabled we are not allowed
> to mount block/NBD devices.
>
> Instead, mount /dev/nbdX to /run/libvirt/lxc/<domain>.root
> and set:
>
> fs->src->path = /run/libvirt/lxc/<domain>.root
> fs->type = VIR_DOMAIN_FS_TYPE_MOUNT
> ---
> src/lxc/lxc_container.c | 53 ------------------------------------------------
> src/lxc/lxc_controller.c | 49 +++++++++++++++++++++++++++++---------------
> 2 files changed, 33 insertions(+), 69 deletions(-)
>
> diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
> index 3b8cb966e..420bb20ab 100644
> --- a/src/lxc/lxc_container.c
> +++ b/src/lxc/lxc_container.c
> @@ -658,55 +658,6 @@ static int lxcContainerResolveSymlinks(virDomainFSDefPtr fs, bool gentle)
> return 0;
> }
>
Why is this being removed? Not clear from commit message...
> -static int lxcContainerPrepareRoot(virDomainDefPtr def,
> - virDomainFSDefPtr root,
> - const char *sec_mount_options)
> -{
> - char *dst;
> - char *tmp;
> -
> - VIR_DEBUG("Prepare root %d", root->type);
> -
> - if (root->type == VIR_DOMAIN_FS_TYPE_MOUNT)
> - return 0;
> -
> - if (root->type == VIR_DOMAIN_FS_TYPE_FILE) {
> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> - _("Unexpected root filesystem without loop device"));
> - return -1;
> - }
> -
> - if (root->type != VIR_DOMAIN_FS_TYPE_BLOCK) {
> - virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> - _("Unsupported root filesystem type %s"),
> - virDomainFSTypeToString(root->type));
> - return -1;
> - }
> -
> - if (lxcContainerResolveSymlinks(root, false) < 0)
> - return -1;
> -
> - if (virAsprintf(&dst, "%s/%s.root",
> - LXC_STATE_DIR, def->name) < 0)
> - return -1;
> -
> - tmp = root->dst;
> - root->dst = dst;
> -
> - if (lxcContainerMountFSBlock(root, "", sec_mount_options) < 0) {
> - root->dst = tmp;
> - VIR_FREE(dst);
> - return -1;
> - }
> -
> - root->dst = tmp;
> - root->type = VIR_DOMAIN_FS_TYPE_MOUNT;
> - VIR_FREE(root->src->path);
> - root->src->path = dst;
> -
> - return 0;
> -}
> -
> static int lxcContainerPivotRoot(virDomainFSDefPtr root)
> {
> int ret;
> @@ -1755,10 +1706,6 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
> if (virFileResolveAllLinks(LXC_STATE_DIR, &stateDir) < 0)
> goto cleanup;
>
> - /* Ensure the root filesystem is mounted */
> - if (lxcContainerPrepareRoot(vmDef, root, sec_mount_options) < 0)
> - goto cleanup;
> -
> /* Gives us a private root, leaving all parent OS mounts on /.oldroot */
> if (lxcContainerPivotRoot(root) < 0)
> goto cleanup;
> diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
> index 61d9ed07b..d1ae60b1d 100644
> --- a/src/lxc/lxc_controller.c
> +++ b/src/lxc/lxc_controller.c
> @@ -530,9 +530,12 @@ static int virLXCControllerAppendNBDPids(virLXCControllerPtr ctrl,
> }
>
>
> -static int virLXCControllerSetupNBDDeviceFS(virDomainFSDefPtr fs)
> +static int virLXCControllerSetupNBDDeviceFS(virLXCControllerPtr ctrl,
> + virDomainFSDefPtr fs)
> {
> - char *dev;
> + char *dev, *dst, *tmp, *sec_mount_options;
There are those that prefer one per line.
> + virDomainDefPtr def = ctrl->def;
> + virSecurityManagerPtr securityDriver = ctrl->securityManager;
>
> if (fs->format <= VIR_STORAGE_FILE_NONE) {
> virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> @@ -540,22 +543,42 @@ static int virLXCControllerSetupNBDDeviceFS(virDomainFSDefPtr fs)
> return -1;
> }
>
> + if (virAsprintf(&dst, "%s/%s.root/",
> + LXC_STATE_DIR, def->name) < 0)
> + return -1;
> +
> + if (!(sec_mount_options = virSecurityManagerGetMountOptions(securityDriver, def)))
> + return -1;
This would leak dst
> +
> if (virFileNBDDeviceAssociate(fs->src->path,
> fs->format,
> fs->readonly,
> &dev) < 0)
> return -1;
This would leak dst, sec_mount_options
>
> - VIR_DEBUG("Changing fs %s to use type=block for dev %s",
> - fs->src->path, dev);
> - /*
> - * We now change it into a block device type, so that
> - * the rest of container setup 'just works'
> - */
> - fs->type = VIR_DOMAIN_FS_TYPE_BLOCK;
> VIR_FREE(fs->src->path);
> fs->src->path = dev;
>
> + tmp = fs->dst;
> + fs->dst = dst;
> +
> + if (lxcContainerMountFSBlock(fs, "", sec_mount_options) < 0) {
> + fs->dst = tmp;
> + VIR_FREE(dst);
This would leak sec_mount_options
> + return -1;
> + }
> +
> + fs->dst = tmp;
> + fs->type = VIR_DOMAIN_FS_TYPE_MOUNT;
> +
> + /* The NBD device will be cleaned up while the cgroup will end.
> + * For this we need to remember the qemu-nbd pid and add it to
> + * the cgroup*/
> + if (virLXCControllerAppendNBDPids(ctrl, fs->src->path) < 0)
Bad cut-n-paste...
What would we do if < 0?? VIR_FREE(fs->src->path);
otherwise, we'd leak it and just set @dst to fs->src->path
> +
> + VIR_FREE(fs->src->path);
> + fs->src->path = dst;
> +
still leaving sec_mount_options leaked.
Perhaps real cleanup type processing should be used instead and an
initialized "int ret = -1;" with the ret = 0 once everything is
successful. You can use VIR_STEAL_PTR for dst and dev and have cleanup
have the VIR_FREE for dev, dst, and sec_mount_options assuming they are
all initialized to NULL.
> return 0;
> }
>
> @@ -637,13 +660,7 @@ static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl)
> }
> ctrl->loopDevFds[ctrl->nloopDevs - 1] = fd;
> } else if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_NBD) {
> - if (virLXCControllerSetupNBDDeviceFS(fs) < 0)
> - goto cleanup;
> -
> - /* The NBD device will be cleaned up while the cgroup will end.
> - * For this we need to remember the qemu-nbd pid and add it to
> - * the cgroup*/
> - if (virLXCControllerAppendNBDPids(ctrl, fs->src->path) < 0)
> + if (virLXCControllerSetupNBDDeviceFS(ctrl, fs) < 0)
> goto cleanup;
Perhaps a patch between this and the last one to move the call to
virLXCControllerAppendNBDPids into virLXCControllerSetupNBDDeviceFS
would be appropriate and return -1 instead of cleanup just before return
0.
That may make this followup patch a bit easier to follow.
John
> } else {
> virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
>
More information about the libvir-list
mailing list