mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-11-05 04:41:20 +00:00
Fix save and restore with non-privileged guests and SELinux
When running qemu:///system instance, libvirtd runs as root, but QEMU may optionally be configured to run non-root. When then saving a guest to a state file, the file is initially created as root, and thus QEMU cannot write to it. It is also missing labelling required to allow access via SELinux. * src/qemu/qemu_driver.c: Set ownership on save image before running migrate command in virDomainSave impl. Call out to security driver to set save image labelling * src/security/security_driver.h: Add driver APIs for setting and restoring saved state file labelling * src/security/security_selinux.c: Implement saved state file labelling for SELinux
This commit is contained in:
parent
fedad93d9e
commit
bc0010b3d1
@ -3347,6 +3347,7 @@ static int qemudDomainSave(virDomainPtr dom,
|
|||||||
char *xml = NULL;
|
char *xml = NULL;
|
||||||
struct qemud_save_header header;
|
struct qemud_save_header header;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
int rc;
|
||||||
virDomainEventPtr event = NULL;
|
virDomainEventPtr event = NULL;
|
||||||
|
|
||||||
memset(&header, 0, sizeof(header));
|
memset(&header, 0, sizeof(header));
|
||||||
@ -3435,11 +3436,24 @@ static int qemudDomainSave(virDomainPtr dom,
|
|||||||
}
|
}
|
||||||
fd = -1;
|
fd = -1;
|
||||||
|
|
||||||
|
if (driver->privileged &&
|
||||||
|
chown(path, driver->user, driver->group) < 0) {
|
||||||
|
virReportSystemError(NULL, errno,
|
||||||
|
_("unable to set ownership of '%s' to user %d:%d"),
|
||||||
|
path, driver->user, driver->group);
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (driver->securityDriver &&
|
||||||
|
driver->securityDriver->domainSetSavedStateLabel &&
|
||||||
|
driver->securityDriver->domainSetSavedStateLabel(dom->conn, vm, path) == -1)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
if (header.compressed == QEMUD_SAVE_FORMAT_RAW) {
|
if (header.compressed == QEMUD_SAVE_FORMAT_RAW) {
|
||||||
const char *args[] = { "cat", NULL };
|
const char *args[] = { "cat", NULL };
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
qemuDomainObjEnterMonitor(vm);
|
qemuDomainObjEnterMonitor(vm);
|
||||||
ret = qemuMonitorMigrateToCommand(priv->mon, 0, args, path);
|
rc = qemuMonitorMigrateToCommand(priv->mon, 0, args, path);
|
||||||
qemuDomainObjExitMonitor(vm);
|
qemuDomainObjExitMonitor(vm);
|
||||||
} else {
|
} else {
|
||||||
const char *prog = qemudSaveCompressionTypeToString(header.compressed);
|
const char *prog = qemudSaveCompressionTypeToString(header.compressed);
|
||||||
@ -3450,13 +3464,28 @@ static int qemudDomainSave(virDomainPtr dom,
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
qemuDomainObjEnterMonitor(vm);
|
qemuDomainObjEnterMonitor(vm);
|
||||||
ret = qemuMonitorMigrateToCommand(priv->mon, 0, args, path);
|
rc = qemuMonitorMigrateToCommand(priv->mon, 0, args, path);
|
||||||
qemuDomainObjExitMonitor(vm);
|
qemuDomainObjExitMonitor(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0)
|
if (rc < 0)
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
|
if (driver->privileged &&
|
||||||
|
chown(path, 0, 0) < 0) {
|
||||||
|
virReportSystemError(NULL, errno,
|
||||||
|
_("unable to set ownership of '%s' to user %d:%d"),
|
||||||
|
path, 0, 0);
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (driver->securityDriver &&
|
||||||
|
driver->securityDriver->domainRestoreSavedStateLabel &&
|
||||||
|
driver->securityDriver->domainRestoreSavedStateLabel(dom->conn, path) == -1)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
/* Shut it down */
|
/* Shut it down */
|
||||||
qemudShutdownVMDaemon(dom->conn, driver, vm);
|
qemudShutdownVMDaemon(dom->conn, driver, vm);
|
||||||
event = virDomainEventNewFromObj(vm,
|
event = virDomainEventNewFromObj(vm,
|
||||||
|
@ -42,6 +42,11 @@ typedef int (*virSecurityDomainRestoreHostdevLabel) (virConnectPtr conn,
|
|||||||
typedef int (*virSecurityDomainSetHostdevLabel) (virConnectPtr conn,
|
typedef int (*virSecurityDomainSetHostdevLabel) (virConnectPtr conn,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
virDomainHostdevDefPtr dev);
|
virDomainHostdevDefPtr dev);
|
||||||
|
typedef int (*virSecurityDomainSetSavedStateLabel) (virConnectPtr conn,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
const char *savefile);
|
||||||
|
typedef int (*virSecurityDomainRestoreSavedStateLabel) (virConnectPtr conn,
|
||||||
|
const char *savefile);
|
||||||
typedef int (*virSecurityDomainGenLabel) (virConnectPtr conn,
|
typedef int (*virSecurityDomainGenLabel) (virConnectPtr conn,
|
||||||
virDomainObjPtr sec);
|
virDomainObjPtr sec);
|
||||||
typedef int (*virSecurityDomainReserveLabel) (virConnectPtr conn,
|
typedef int (*virSecurityDomainReserveLabel) (virConnectPtr conn,
|
||||||
@ -71,6 +76,8 @@ struct _virSecurityDriver {
|
|||||||
virSecurityDomainRestoreLabel domainRestoreSecurityLabel;
|
virSecurityDomainRestoreLabel domainRestoreSecurityLabel;
|
||||||
virSecurityDomainRestoreHostdevLabel domainRestoreSecurityHostdevLabel;
|
virSecurityDomainRestoreHostdevLabel domainRestoreSecurityHostdevLabel;
|
||||||
virSecurityDomainSetHostdevLabel domainSetSecurityHostdevLabel;
|
virSecurityDomainSetHostdevLabel domainSetSecurityHostdevLabel;
|
||||||
|
virSecurityDomainSetSavedStateLabel domainSetSavedStateLabel;
|
||||||
|
virSecurityDomainRestoreSavedStateLabel domainRestoreSavedStateLabel;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is internally managed driver state and should only be accessed
|
* This is internally managed driver state and should only be accessed
|
||||||
|
@ -523,6 +523,7 @@ done:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
SELinuxRestoreSecurityPCILabel(virConnectPtr conn,
|
SELinuxRestoreSecurityPCILabel(virConnectPtr conn,
|
||||||
pciDevice *dev ATTRIBUTE_UNUSED,
|
pciDevice *dev ATTRIBUTE_UNUSED,
|
||||||
@ -623,6 +624,26 @@ SELinuxRestoreSecurityLabel(virConnectPtr conn,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
SELinuxSetSavedStateLabel(virConnectPtr conn,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
const char *savefile)
|
||||||
|
{
|
||||||
|
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
|
||||||
|
|
||||||
|
return SELinuxSetFilecon(conn, savefile, secdef->imagelabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
SELinuxRestoreSavedStateLabel(virConnectPtr conn,
|
||||||
|
const char *savefile)
|
||||||
|
{
|
||||||
|
return SELinuxRestoreSecurityFileLabel(conn, savefile);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
SELinuxSecurityVerify(virConnectPtr conn, virDomainDefPtr def)
|
SELinuxSecurityVerify(virConnectPtr conn, virDomainDefPtr def)
|
||||||
{
|
{
|
||||||
@ -692,4 +713,6 @@ virSecurityDriver virSELinuxSecurityDriver = {
|
|||||||
.domainSetSecurityLabel = SELinuxSetSecurityLabel,
|
.domainSetSecurityLabel = SELinuxSetSecurityLabel,
|
||||||
.domainSetSecurityHostdevLabel = SELinuxSetSecurityHostdevLabel,
|
.domainSetSecurityHostdevLabel = SELinuxSetSecurityHostdevLabel,
|
||||||
.domainRestoreSecurityHostdevLabel = SELinuxRestoreSecurityHostdevLabel,
|
.domainRestoreSecurityHostdevLabel = SELinuxRestoreSecurityHostdevLabel,
|
||||||
|
.domainSetSavedStateLabel = SELinuxSetSavedStateLabel,
|
||||||
|
.domainRestoreSavedStateLabel = SELinuxRestoreSavedStateLabel,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user