[libvirt] [PATCH] Add support for disks backed by plain files in LXC

From: "Daniel P. Berrange" <berrange@redhat.com> By using a loopback device, disks backed by plain files can be made available to LXC containers. We make no attempt to auto-detect format if <driver type="raw"/> is not set, instead we unconditionally treat that as meaning raw. This is to avoid the security issues inherant with format auto-detection Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_controller.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index a7e715e..176e1be 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -356,7 +356,7 @@ static int virLXCControllerValidateConsoles(virLXCControllerPtr ctrl) } -static int virLXCControllerSetupLoopDevice(virDomainFSDefPtr fs) +static int virLXCControllerSetupLoopDeviceFS(virDomainFSDefPtr fs) { int lofd; char *loname = NULL; @@ -377,6 +377,27 @@ static int virLXCControllerSetupLoopDevice(virDomainFSDefPtr fs) } +static int virLXCControllerSetupLoopDeviceDisk(virDomainDiskDefPtr disk) +{ + int lofd; + char *loname = NULL; + + if ((lofd = virFileLoopDeviceAssociate(disk->src, &loname)) < 0) + return -1; + + /* + * We now change it into a block device type, so that + * the rest of container setup 'just works' + */ + disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK; + VIR_FREE(disk->src); + disk->src = loname; + loname = NULL; + + return lofd; +} + + static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl) { size_t i; @@ -389,7 +410,7 @@ static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl) if (fs->type != VIR_DOMAIN_FS_TYPE_FILE) continue; - fd = virLXCControllerSetupLoopDevice(fs); + fd = virLXCControllerSetupLoopDeviceFS(fs); if (fd < 0) goto cleanup; @@ -402,6 +423,48 @@ static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl) ctrl->loopDevFds[ctrl->nloopDevs - 1] = fd; } + for (i = 0 ; i < ctrl->def->ndisks ; i++) { + virDomainDiskDefPtr disk = ctrl->def->disks[i]; + int fd; + + if (disk->type != VIR_DOMAIN_DISK_TYPE_FILE) + continue; + + switch (disk->format) { + /* We treat 'none' as meaning 'raw' since we + * don't want to go into the auto-probing + * business for security reasons + */ + case VIR_STORAGE_FILE_RAW: + case VIR_STORAGE_FILE_NONE: + if (disk->driverName && + STRNEQ(disk->driverName, "loop")) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk driver %s is not supported"), + disk->driverName); + goto cleanup; + } + + fd = virLXCControllerSetupLoopDeviceDisk(disk); + if (fd < 0) + goto cleanup; + + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk format %s is not supported"), + virStorageFileFormatTypeToString(disk->format)); + goto cleanup; + } + + VIR_DEBUG("Saving loop fd %d", fd); + if (VIR_EXPAND_N(ctrl->loopDevFds, ctrl->nloopDevs, 1) < 0) { + VIR_FORCE_CLOSE(fd); + virReportOOMError(); + goto cleanup; + } + ctrl->loopDevFds[ctrl->nloopDevs - 1] = fd; + } + VIR_DEBUG("Setup all loop devices"); ret = 0; -- 1.7.11.7

On 03/07/13 12:41, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
By using a loopback device, disks backed by plain files can be made available to LXC containers. We make no attempt to auto-detect format if <driver type="raw"/> is not set, instead we unconditionally treat that as meaning raw. This is to avoid the security issues inherant with format
s/inherant/inherent/
auto-detection
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_controller.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-)
ACK. Peter

On 03/07/2013 06:41 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
By using a loopback device, disks backed by plain files can be made available to LXC containers. We make no attempt to auto-detect format if <driver type="raw"/> is not set, instead we unconditionally treat that as meaning raw. This is to avoid the security issues inherant with format auto-detection
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_controller.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-)
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index a7e715e..176e1be 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -356,7 +356,7 @@ static int virLXCControllerValidateConsoles(virLXCControllerPtr ctrl) }
-static int virLXCControllerSetupLoopDevice(virDomainFSDefPtr fs) +static int virLXCControllerSetupLoopDeviceFS(virDomainFSDefPtr fs) { int lofd; char *loname = NULL; @@ -377,6 +377,27 @@ static int virLXCControllerSetupLoopDevice(virDomainFSDefPtr fs) }
+static int virLXCControllerSetupLoopDeviceDisk(virDomainDiskDefPtr disk) +{ + int lofd; + char *loname = NULL; + + if ((lofd = virFileLoopDeviceAssociate(disk->src, &loname)) < 0) + return -1; + + /* + * We now change it into a block device type, so that + * the rest of container setup 'just works' + */ + disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK; + VIR_FREE(disk->src); + disk->src = loname; + loname = NULL; + + return lofd; +} + + static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl) { size_t i; @@ -389,7 +410,7 @@ static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl) if (fs->type != VIR_DOMAIN_FS_TYPE_FILE) continue;
- fd = virLXCControllerSetupLoopDevice(fs); + fd = virLXCControllerSetupLoopDeviceFS(fs); if (fd < 0) goto cleanup;
@@ -402,6 +423,48 @@ static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl) ctrl->loopDevFds[ctrl->nloopDevs - 1] = fd; }
+ for (i = 0 ; i < ctrl->def->ndisks ; i++) { + virDomainDiskDefPtr disk = ctrl->def->disks[i]; + int fd; + + if (disk->type != VIR_DOMAIN_DISK_TYPE_FILE) + continue; + + switch (disk->format) { + /* We treat 'none' as meaning 'raw' since we + * don't want to go into the auto-probing + * business for security reasons + */ + case VIR_STORAGE_FILE_RAW: + case VIR_STORAGE_FILE_NONE: + if (disk->driverName && + STRNEQ(disk->driverName, "loop")) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk driver %s is not supported"), + disk->driverName); + goto cleanup; + } + + fd = virLXCControllerSetupLoopDeviceDisk(disk); + if (fd < 0) + goto cleanup;
Is there a missing break; here? (to be fair, Coverity found this one when I was trying to reset my baseline today)
+ + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk format %s is not supported"), + virStorageFileFormatTypeToString(disk->format)); + goto cleanup; + } + + VIR_DEBUG("Saving loop fd %d", fd); + if (VIR_EXPAND_N(ctrl->loopDevFds, ctrl->nloopDevs, 1) < 0) { + VIR_FORCE_CLOSE(fd); + virReportOOMError(); + goto cleanup; + } + ctrl->loopDevFds[ctrl->nloopDevs - 1] = fd; + } + VIR_DEBUG("Setup all loop devices"); ret = 0;

On Thu, Mar 07, 2013 at 03:55:01PM -0500, John Ferlan wrote:
On 03/07/2013 06:41 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
By using a loopback device, disks backed by plain files can be made available to LXC containers. We make no attempt to auto-detect format if <driver type="raw"/> is not set, instead we unconditionally treat that as meaning raw. This is to avoid the security issues inherant with format auto-detection
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_controller.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-)
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index a7e715e..176e1be 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -356,7 +356,7 @@ static int virLXCControllerValidateConsoles(virLXCControllerPtr ctrl) }
-static int virLXCControllerSetupLoopDevice(virDomainFSDefPtr fs) +static int virLXCControllerSetupLoopDeviceFS(virDomainFSDefPtr fs) { int lofd; char *loname = NULL; @@ -377,6 +377,27 @@ static int virLXCControllerSetupLoopDevice(virDomainFSDefPtr fs) }
+static int virLXCControllerSetupLoopDeviceDisk(virDomainDiskDefPtr disk) +{ + int lofd; + char *loname = NULL; + + if ((lofd = virFileLoopDeviceAssociate(disk->src, &loname)) < 0) + return -1; + + /* + * We now change it into a block device type, so that + * the rest of container setup 'just works' + */ + disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK; + VIR_FREE(disk->src); + disk->src = loname; + loname = NULL; + + return lofd; +} + + static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl) { size_t i; @@ -389,7 +410,7 @@ static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl) if (fs->type != VIR_DOMAIN_FS_TYPE_FILE) continue;
- fd = virLXCControllerSetupLoopDevice(fs); + fd = virLXCControllerSetupLoopDeviceFS(fs); if (fd < 0) goto cleanup;
@@ -402,6 +423,48 @@ static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl) ctrl->loopDevFds[ctrl->nloopDevs - 1] = fd; }
+ for (i = 0 ; i < ctrl->def->ndisks ; i++) { + virDomainDiskDefPtr disk = ctrl->def->disks[i]; + int fd; + + if (disk->type != VIR_DOMAIN_DISK_TYPE_FILE) + continue; + + switch (disk->format) { + /* We treat 'none' as meaning 'raw' since we + * don't want to go into the auto-probing + * business for security reasons + */ + case VIR_STORAGE_FILE_RAW: + case VIR_STORAGE_FILE_NONE: + if (disk->driverName && + STRNEQ(disk->driverName, "loop")) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk driver %s is not supported"), + disk->driverName); + goto cleanup; + } + + fd = virLXCControllerSetupLoopDeviceDisk(disk); + if (fd < 0) + goto cleanup;
Is there a missing break; here?
Yes, you are right. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (3)
-
Daniel P. Berrange
-
John Ferlan
-
Peter Krempa