[libvirt] PATCH: Mark <seclabel> as dynamic generated, or statically pre-defined

This patch implements the behaviour I was refering to earlier, whereby the domain XML explicitly says whether the security label is a statically pre-defined one, or dynamically generated on VM boot by libvirtd So when creating a new guest, apps like virt-install have 2 options: - Leave out the <seclabel> tag completely -> If no security driver is active, just works as normal unconfined VM -> If a security driver is active, a dynamic seclabel is generated <seclabel type='dynamic' model='selinux'> <label>system_u:system_r:qemu_t:s0:c424,c719</label> <imagelabel>system_u:object_r:virt_image_t:s0:c424,c719</imagelabel> </seclabel> - Add an explicit <seclabel> tag with type='static' attribute -> Security driver uses the defined label & imagelabel <seclabel type='static' model='selinux'> <label>system_u:system_r:qemu_t:s0:c25,c100</label> <imagelabel>system_u:system_r:virt_image_t:s0:c25,c100</imagelabel> </seclabel> A static seclabel is visible in the XML, at all times, whether the VM is active or inactive. A dynamic seclabel is only visible when the VM is running, since it is auto-generated at VM boot. If you migrate the VM, or save/restore it, the dynamic seclabel will change on each boot. The seclabel isn't visible when not running, or if asking for the inactive XML dump This patch implements parsing of the 'type' attribute, and makes the seclabel generation key off this attribute. It also adds the 'imagelabel' XML element, since that was being used internally, but was not including in the XML output, or parsing routines, making it impossible to specify a pre-defined image label or see the dyanmic one domain_conf.c | 65 +++++++++++++++++++++++++++++++++++++++++++---------- domain_conf.h | 9 +++++++ qemu_driver.c | 13 ++++++++-- security_selinux.c | 1 4 files changed, 73 insertions(+), 15 deletions(-) Daniel Index: src/domain_conf.c =================================================================== RCS file: /data/cvs/libvirt/src/domain_conf.c,v retrieving revision 1.70 diff -u -p -r1.70 domain_conf.c --- src/domain_conf.c 3 Mar 2009 09:44:42 -0000 1.70 +++ src/domain_conf.c 3 Mar 2009 15:36:02 -0000 @@ -168,6 +168,10 @@ VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN "shutoff", "crashed") +VIR_ENUM_IMPL(virDomainSeclabel, VIR_DOMAIN_SECLABEL_LAST, + "dynamic", + "static") + #define virDomainReportError(conn, code, fmt...) \ virReportErrorHelper(conn, VIR_FROM_DOMAIN, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) @@ -1847,24 +1851,46 @@ static int virDomainLifecycleParseXML(vi static int virSecurityLabelDefParseXML(virConnectPtr conn, const virDomainDefPtr def, - xmlXPathContextPtr ctxt) + xmlXPathContextPtr ctxt, + int flags) { char *p; if (virXPathNode(conn, "./seclabel", ctxt) == NULL) return 0; - p = virXPathStringLimit(conn, "string(./seclabel/label[1])", + p = virXPathStringLimit(conn, "string(./seclabel/@type)", VIR_SECURITY_LABEL_BUFLEN-1, ctxt); if (p == NULL) goto error; - def->seclabel.label = p; - - p = virXPathStringLimit(conn, "string(./seclabel/@model)", - VIR_SECURITY_MODEL_BUFLEN-1, ctxt); - if (p == NULL) + if ((def->seclabel.type = virDomainSeclabelTypeFromString(p)) < 0) goto error; - def->seclabel.model = p; + VIR_FREE(p); + + /* Only parse details, if using static labels, or + * if the 'live' VM XML is requested + */ + if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC || + !(flags & VIR_DOMAIN_XML_INACTIVE)) { + p = virXPathStringLimit(conn, "string(./seclabel/@model)", + VIR_SECURITY_MODEL_BUFLEN-1, ctxt); + if (p == NULL) + goto error; + def->seclabel.model = p; + + p = virXPathStringLimit(conn, "string(./seclabel/label[1])", + VIR_SECURITY_LABEL_BUFLEN-1, ctxt); + if (p == NULL) + goto error; + def->seclabel.label = p; + + p = virXPathStringLimit(conn, "string(./seclabel/imagelabel[1])", + VIR_SECURITY_LABEL_BUFLEN-1, ctxt); + if (p == NULL) + goto error; + def->seclabel.imagelabel = p; + + } return 0; @@ -2458,7 +2484,7 @@ static virDomainDefPtr virDomainDefParse VIR_FREE(nodes); /* analysis of security label */ - if (virSecurityLabelDefParseXML(conn, def, ctxt) == -1) + if (virSecurityLabelDefParseXML(conn, def, ctxt, flags) == -1) goto error; return def; @@ -3480,9 +3506,24 @@ char *virDomainDefFormat(virConnectPtr c virBufferAddLit(&buf, " </devices>\n"); if (def->seclabel.model) { - virBufferEscapeString(&buf, " <seclabel model='%s'>\n", def->seclabel.model); - virBufferEscapeString(&buf, " <label>%s</label>\n", def->seclabel.label); - virBufferAddLit(&buf, " </seclabel>\n"); + const char *sectype = virDomainSeclabelTypeToString(def->seclabel.type); + if (!sectype) + goto cleanup; + if (!def->seclabel.label || + (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && + (flags & VIR_DOMAIN_XML_INACTIVE))) { + virBufferVSprintf(&buf, " <seclabel type='%s' model='%s'/>\n", + sectype, def->seclabel.model); + } else { + virBufferVSprintf(&buf, " <seclabel type='%s' model='%s'>\n", + sectype, def->seclabel.model); + virBufferEscapeString(&buf, " <label>%s</label>\n", + def->seclabel.label); + if (def->seclabel.imagelabel) + virBufferEscapeString(&buf, " <imagelabel>%s</imagelabel>\n", + def->seclabel.imagelabel); + virBufferAddLit(&buf, " </seclabel>\n"); + } } virBufferAddLit(&buf, "</domain>\n"); Index: src/domain_conf.h =================================================================== RCS file: /data/cvs/libvirt/src/domain_conf.h,v retrieving revision 1.39 diff -u -p -r1.39 domain_conf.h --- src/domain_conf.h 3 Mar 2009 09:44:42 -0000 1.39 +++ src/domain_conf.h 3 Mar 2009 15:36:02 -0000 @@ -410,6 +410,13 @@ struct _virDomainOSDef { char *bootloaderArgs; }; +enum virDomainSeclabelType { + VIR_DOMAIN_SECLABEL_DYNAMIC, + VIR_DOMAIN_SECLABEL_STATIC, + + VIR_DOMAIN_SECLABEL_LAST, +}; + /* Security configuration for domain */ typedef struct _virSecurityLabelDef virSecurityLabelDef; typedef virSecurityLabelDef *virSecurityLabelDefPtr; @@ -417,6 +424,7 @@ struct _virSecurityLabelDef { char *model; /* name of security model */ char *label; /* security label string */ char *imagelabel; /* security image label string */ + int type; }; #define VIR_DOMAIN_CPUMASK_LEN 1024 @@ -650,5 +658,6 @@ VIR_ENUM_DECL(virDomainInputBus) VIR_ENUM_DECL(virDomainGraphics) /* from libvirt.h */ VIR_ENUM_DECL(virDomainState) +VIR_ENUM_DECL(virDomainSeclabel) #endif /* __DOMAIN_CONF_H */ Index: src/qemu_driver.c =================================================================== RCS file: /data/cvs/libvirt/src/qemu_driver.c,v retrieving revision 1.213 diff -u -p -r1.213 qemu_driver.c --- src/qemu_driver.c 3 Mar 2009 15:18:24 -0000 1.213 +++ src/qemu_driver.c 3 Mar 2009 15:36:02 -0000 @@ -1314,9 +1314,9 @@ static int qemudStartVMDaemon(virConnect hookData.vm = vm; hookData.driver = driver; - /* If you are using a SecurityDriver and there was no security label in - database, then generate a security label for isolation */ - if (vm->def->seclabel.label == NULL && + /* If you are using a SecurityDriver with dynamic labelling, + then generate a security label for isolation */ + if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && driver->securityDriver && driver->securityDriver->domainGenSecurityLabel && driver->securityDriver->domainGenSecurityLabel(conn, vm) < 0) @@ -1525,6 +1525,13 @@ static void qemudShutdownVMDaemon(virCon if (driver->securityDriver) driver->securityDriver->domainRestoreSecurityLabel(conn, vm); + /* Clear out dynamically assigned labels */ + if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) { + VIR_FREE(vm->def->seclabel.model); + VIR_FREE(vm->def->seclabel.label); + VIR_FREE(vm->def->seclabel.imagelabel); + } + if (qemudRemoveDomainStatus(conn, driver, vm) < 0) { VIR_WARN(_("Failed to remove domain status for %s"), vm->def->name); Index: src/security_selinux.c =================================================================== RCS file: /data/cvs/libvirt/src/security_selinux.c,v retrieving revision 1.2 diff -u -p -r1.2 security_selinux.c --- src/security_selinux.c 3 Mar 2009 15:18:24 -0000 1.2 +++ src/security_selinux.c 3 Mar 2009 15:36:02 -0000 @@ -161,6 +161,7 @@ SELinuxGenSecurityLabel(virConnectPtr co char *scontext = NULL; int c1 = 0; int c2 = 0; + if ( ( vm->def->seclabel.label ) || ( vm->def->seclabel.model ) || ( vm->def->seclabel.imagelabel )) { -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Tue, Mar 03, 2009 at 03:42:58PM +0000, Daniel P. Berrange wrote:
This patch implements the behaviour I was refering to earlier, whereby the domain XML explicitly says whether the security label is a statically pre-defined one, or dynamically generated on VM boot by libvirtd
So when creating a new guest, apps like virt-install have 2 options:
- Leave out the <seclabel> tag completely -> If no security driver is active, just works as normal unconfined VM -> If a security driver is active, a dynamic seclabel is generated
<seclabel type='dynamic' model='selinux'> <label>system_u:system_r:qemu_t:s0:c424,c719</label> <imagelabel>system_u:object_r:virt_image_t:s0:c424,c719</imagelabel> </seclabel>
- Add an explicit <seclabel> tag with type='static' attribute -> Security driver uses the defined label & imagelabel
<seclabel type='static' model='selinux'> <label>system_u:system_r:qemu_t:s0:c25,c100</label> <imagelabel>system_u:system_r:virt_image_t:s0:c25,c100</imagelabel> </seclabel>
A static seclabel is visible in the XML, at all times, whether the VM is active or inactive.
A dynamic seclabel is only visible when the VM is running, since it is auto-generated at VM boot. If you migrate the VM, or save/restore it, the dynamic seclabel will change on each boot. The seclabel isn't visible when not running, or if asking for the inactive XML dump
This patch implements parsing of the 'type' attribute, and makes the seclabel generation key off this attribute.
It also adds the 'imagelabel' XML element, since that was being used internally, but was not including in the XML output, or parsing routines, making it impossible to specify a pre-defined image label or see the dyanmic one
The patch looks sane to me, I didn't spot anything suspect, but I'm not really able to validate the principle itself. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch implements the behaviour I was refering to earlier, whereby the domain XML explicitly says whether the security label is a statically pre-defined one, or dynamically generated on VM boot by libvirtd
So when creating a new guest, apps like virt-install have 2 options:
- Leave out the <seclabel> tag completely -> If no security driver is active, just works as normal unconfined VM I want to make sure of terminology. The VM will be confined, but will not be separated. IE the host machine will be protected from the VM, while other VM's will not be. svirt is concerned with protecting VM's from each other. Normal SELinux protects the Apache server from rogue VMs. If we want to have a truly unconfined vm, we need additional
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Daniel P. Berrange wrote: policy. I would suggest permissive mode or a permissive domain. semanage permissive -a qemu_t Would give you this.
-> If a security driver is active, a dynamic seclabel is generated
<seclabel type='dynamic' model='selinux'> <label>system_u:system_r:qemu_t:s0:c424,c719</label> <imagelabel>system_u:object_r:virt_image_t:s0:c424,c719</imagelabel> </seclabel>
- Add an explicit <seclabel> tag with type='static' attribute -> Security driver uses the defined label & imagelabel
<seclabel type='static' model='selinux'> <label>system_u:system_r:qemu_t:s0:c25,c100</label> <imagelabel>system_u:system_r:virt_image_t:s0:c25,c100</imagelabel> </seclabel>
Not sure imagelabel is required in the second case since, libvirt will not change the label. This is the biggest difference between static and dynamic, static will never run setfilecon, while dynamic runs it at startup and shutdown. DYNAMIC: start setfilecon(image, imagelabel) setexeccon(label) exec() Finish ChildExit() setfilecon(image, DEFAULT_LABEL) Exit() STATIC: start setexecon(label) exec() Finish: ChildExit() Exit()
A static seclabel is visible in the XML, at all times, whether the VM is active or inactive.
A dynamic seclabel is only visible when the VM is running, since it is auto-generated at VM boot. If you migrate the VM, or save/restore it, the dynamic seclabel will change on each boot. The seclabel isn't visible when not running, or if asking for the inactive XML dump
This patch implements parsing of the 'type' attribute, and makes the seclabel generation key off this attribute.
It also adds the 'imagelabel' XML element, since that was being used internally, but was not including in the XML output, or parsing routines, making it impossible to specify a pre-defined image label or see the dyanmic one
domain_conf.c | 65 +++++++++++++++++++++++++++++++++++++++++++---------- domain_conf.h | 9 +++++++ qemu_driver.c | 13 ++++++++-- security_selinux.c | 1 4 files changed, 73 insertions(+), 15 deletions(-)
Daniel
Index: src/domain_conf.c =================================================================== RCS file: /data/cvs/libvirt/src/domain_conf.c,v retrieving revision 1.70 diff -u -p -r1.70 domain_conf.c --- src/domain_conf.c 3 Mar 2009 09:44:42 -0000 1.70 +++ src/domain_conf.c 3 Mar 2009 15:36:02 -0000 @@ -168,6 +168,10 @@ VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN "shutoff", "crashed")
+VIR_ENUM_IMPL(virDomainSeclabel, VIR_DOMAIN_SECLABEL_LAST, + "dynamic", + "static") + #define virDomainReportError(conn, code, fmt...) \ virReportErrorHelper(conn, VIR_FROM_DOMAIN, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) @@ -1847,24 +1851,46 @@ static int virDomainLifecycleParseXML(vi static int virSecurityLabelDefParseXML(virConnectPtr conn, const virDomainDefPtr def, - xmlXPathContextPtr ctxt) + xmlXPathContextPtr ctxt, + int flags) { char *p;
if (virXPathNode(conn, "./seclabel", ctxt) == NULL) return 0;
- p = virXPathStringLimit(conn, "string(./seclabel/label[1])", + p = virXPathStringLimit(conn, "string(./seclabel/@type)", VIR_SECURITY_LABEL_BUFLEN-1, ctxt); if (p == NULL) goto error; - def->seclabel.label = p; - - p = virXPathStringLimit(conn, "string(./seclabel/@model)", - VIR_SECURITY_MODEL_BUFLEN-1, ctxt); - if (p == NULL) + if ((def->seclabel.type = virDomainSeclabelTypeFromString(p)) < 0) goto error; - def->seclabel.model = p; + VIR_FREE(p); + + /* Only parse details, if using static labels, or + * if the 'live' VM XML is requested + */ + if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC || + !(flags & VIR_DOMAIN_XML_INACTIVE)) { + p = virXPathStringLimit(conn, "string(./seclabel/@model)", + VIR_SECURITY_MODEL_BUFLEN-1, ctxt); + if (p == NULL) + goto error; + def->seclabel.model = p; + + p = virXPathStringLimit(conn, "string(./seclabel/label[1])", + VIR_SECURITY_LABEL_BUFLEN-1, ctxt); + if (p == NULL) + goto error; + def->seclabel.label = p; + + p = virXPathStringLimit(conn, "string(./seclabel/imagelabel[1])", + VIR_SECURITY_LABEL_BUFLEN-1, ctxt); + if (p == NULL) + goto error; + def->seclabel.imagelabel = p; + + }
return 0;
@@ -2458,7 +2484,7 @@ static virDomainDefPtr virDomainDefParse VIR_FREE(nodes);
/* analysis of security label */ - if (virSecurityLabelDefParseXML(conn, def, ctxt) == -1) + if (virSecurityLabelDefParseXML(conn, def, ctxt, flags) == -1) goto error;
return def; @@ -3480,9 +3506,24 @@ char *virDomainDefFormat(virConnectPtr c virBufferAddLit(&buf, " </devices>\n");
if (def->seclabel.model) { - virBufferEscapeString(&buf, " <seclabel model='%s'>\n", def->seclabel.model); - virBufferEscapeString(&buf, " <label>%s</label>\n", def->seclabel.label); - virBufferAddLit(&buf, " </seclabel>\n"); + const char *sectype = virDomainSeclabelTypeToString(def->seclabel.type); + if (!sectype) + goto cleanup; + if (!def->seclabel.label || + (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && + (flags & VIR_DOMAIN_XML_INACTIVE))) { + virBufferVSprintf(&buf, " <seclabel type='%s' model='%s'/>\n", + sectype, def->seclabel.model); + } else { + virBufferVSprintf(&buf, " <seclabel type='%s' model='%s'>\n", + sectype, def->seclabel.model); + virBufferEscapeString(&buf, " <label>%s</label>\n", + def->seclabel.label); + if (def->seclabel.imagelabel) + virBufferEscapeString(&buf, " <imagelabel>%s</imagelabel>\n", + def->seclabel.imagelabel); + virBufferAddLit(&buf, " </seclabel>\n"); + } }
virBufferAddLit(&buf, "</domain>\n"); Index: src/domain_conf.h =================================================================== RCS file: /data/cvs/libvirt/src/domain_conf.h,v retrieving revision 1.39 diff -u -p -r1.39 domain_conf.h --- src/domain_conf.h 3 Mar 2009 09:44:42 -0000 1.39 +++ src/domain_conf.h 3 Mar 2009 15:36:02 -0000 @@ -410,6 +410,13 @@ struct _virDomainOSDef { char *bootloaderArgs; };
+enum virDomainSeclabelType { + VIR_DOMAIN_SECLABEL_DYNAMIC, + VIR_DOMAIN_SECLABEL_STATIC, + + VIR_DOMAIN_SECLABEL_LAST, +}; + /* Security configuration for domain */ typedef struct _virSecurityLabelDef virSecurityLabelDef; typedef virSecurityLabelDef *virSecurityLabelDefPtr; @@ -417,6 +424,7 @@ struct _virSecurityLabelDef { char *model; /* name of security model */ char *label; /* security label string */ char *imagelabel; /* security image label string */ + int type; };
#define VIR_DOMAIN_CPUMASK_LEN 1024 @@ -650,5 +658,6 @@ VIR_ENUM_DECL(virDomainInputBus) VIR_ENUM_DECL(virDomainGraphics) /* from libvirt.h */ VIR_ENUM_DECL(virDomainState) +VIR_ENUM_DECL(virDomainSeclabel)
#endif /* __DOMAIN_CONF_H */ Index: src/qemu_driver.c =================================================================== RCS file: /data/cvs/libvirt/src/qemu_driver.c,v retrieving revision 1.213 diff -u -p -r1.213 qemu_driver.c --- src/qemu_driver.c 3 Mar 2009 15:18:24 -0000 1.213 +++ src/qemu_driver.c 3 Mar 2009 15:36:02 -0000 @@ -1314,9 +1314,9 @@ static int qemudStartVMDaemon(virConnect hookData.vm = vm; hookData.driver = driver;
- /* If you are using a SecurityDriver and there was no security label in - database, then generate a security label for isolation */ - if (vm->def->seclabel.label == NULL && + /* If you are using a SecurityDriver with dynamic labelling, + then generate a security label for isolation */ + if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && driver->securityDriver && driver->securityDriver->domainGenSecurityLabel && driver->securityDriver->domainGenSecurityLabel(conn, vm) < 0) @@ -1525,6 +1525,13 @@ static void qemudShutdownVMDaemon(virCon if (driver->securityDriver) driver->securityDriver->domainRestoreSecurityLabel(conn, vm);
+ /* Clear out dynamically assigned labels */ + if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) { + VIR_FREE(vm->def->seclabel.model); + VIR_FREE(vm->def->seclabel.label); + VIR_FREE(vm->def->seclabel.imagelabel); + } + if (qemudRemoveDomainStatus(conn, driver, vm) < 0) { VIR_WARN(_("Failed to remove domain status for %s"), vm->def->name); Index: src/security_selinux.c =================================================================== RCS file: /data/cvs/libvirt/src/security_selinux.c,v retrieving revision 1.2 diff -u -p -r1.2 security_selinux.c --- src/security_selinux.c 3 Mar 2009 15:18:24 -0000 1.2 +++ src/security_selinux.c 3 Mar 2009 15:36:02 -0000 @@ -161,6 +161,7 @@ SELinuxGenSecurityLabel(virConnectPtr co char *scontext = NULL; int c1 = 0; int c2 = 0; + if ( ( vm->def->seclabel.label ) || ( vm->def->seclabel.model ) || ( vm->def->seclabel.imagelabel )) {
Patch looks good. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org iEYEARECAAYFAkmtVF4ACgkQrlYvE4MpobMTxQCg1Ym4QXTta8keZCuJoyL/rPQ2 6NIAoJoPV1OtRxLO0JV/X0FjncWdt1rk =KKq6 -----END PGP SIGNATURE-----

On Tue, Mar 03, 2009 at 11:01:34AM -0500, Daniel J Walsh wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Daniel P. Berrange wrote:
This patch implements the behaviour I was refering to earlier, whereby the domain XML explicitly says whether the security label is a statically pre-defined one, or dynamically generated on VM boot by libvirtd
So when creating a new guest, apps like virt-install have 2 options:
- Leave out the <seclabel> tag completely -> If no security driver is active, just works as normal unconfined VM
I want to make sure of terminology. The VM will be confined, but will not be separated. IE the host machine will be protected from the VM, while other VM's will not be. svirt is concerned with protecting VM's from each other. Normal SELinux protects the Apache server from rogue VMs. If we want to have a truly unconfined vm, we need additional policy. I would suggest permissive mode or a permissive domain.
This was my bad terminolgy. There are two scenarios where a security driver is not active - Admin turned it off in /etc/libvirt/qemu.conf, but SELinux is still active on the host in general. The VM will still be confined here, but not isolated from each other - Admin turned off SELinux for the entire host. The VM will be unconfined
-> If a security driver is active, a dynamic seclabel is generated
<seclabel type='dynamic' model='selinux'> <label>system_u:system_r:qemu_t:s0:c424,c719</label> <imagelabel>system_u:object_r:virt_image_t:s0:c424,c719</imagelabel> </seclabel>
- Add an explicit <seclabel> tag with type='static' attribute -> Security driver uses the defined label & imagelabel
<seclabel type='static' model='selinux'> <label>system_u:system_r:qemu_t:s0:c25,c100</label> <imagelabel>system_u:system_r:virt_image_t:s0:c25,c100</imagelabel> </seclabel>
Not sure imagelabel is required in the second case since, libvirt will not change the label.
This is the biggest difference between static and dynamic, static will never run setfilecon, while dynamic runs it at startup and shutdown.
DYNAMIC: start setfilecon(image, imagelabel) setexeccon(label) exec()
Finish ChildExit() setfilecon(image, DEFAULT_LABEL) Exit()
STATIC: start setexecon(label) exec()
Finish: ChildExit() Exit()
This new patch implements this logic now. It only parses the <imagelabel> element from the XML, if parsing the 'live' XML config for a dynamic label - this is basically just used for libvirt's state file in /var/run, so it can remember config across libvirtd restarts. The <imagelabel> is now never used for static labels, and thus no setfilecon() will take place for them. Index: src/domain_conf.c =================================================================== RCS file: /data/cvs/libvirt/src/domain_conf.c,v retrieving revision 1.70 diff -u -p -r1.70 domain_conf.c --- src/domain_conf.c 3 Mar 2009 09:44:42 -0000 1.70 +++ src/domain_conf.c 3 Mar 2009 16:36:17 -0000 @@ -168,6 +168,10 @@ VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN "shutoff", "crashed") +VIR_ENUM_IMPL(virDomainSeclabel, VIR_DOMAIN_SECLABEL_LAST, + "dynamic", + "static") + #define virDomainReportError(conn, code, fmt...) \ virReportErrorHelper(conn, VIR_FROM_DOMAIN, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) @@ -1847,24 +1851,49 @@ static int virDomainLifecycleParseXML(vi static int virSecurityLabelDefParseXML(virConnectPtr conn, const virDomainDefPtr def, - xmlXPathContextPtr ctxt) + xmlXPathContextPtr ctxt, + int flags) { char *p; if (virXPathNode(conn, "./seclabel", ctxt) == NULL) return 0; - p = virXPathStringLimit(conn, "string(./seclabel/label[1])", + p = virXPathStringLimit(conn, "string(./seclabel/@type)", VIR_SECURITY_LABEL_BUFLEN-1, ctxt); if (p == NULL) goto error; - def->seclabel.label = p; - - p = virXPathStringLimit(conn, "string(./seclabel/@model)", - VIR_SECURITY_MODEL_BUFLEN-1, ctxt); - if (p == NULL) + if ((def->seclabel.type = virDomainSeclabelTypeFromString(p)) < 0) goto error; - def->seclabel.model = p; + VIR_FREE(p); + + /* Only parse details, if using static labels, or + * if the 'live' VM XML is requested + */ + if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC || + !(flags & VIR_DOMAIN_XML_INACTIVE)) { + p = virXPathStringLimit(conn, "string(./seclabel/@model)", + VIR_SECURITY_MODEL_BUFLEN-1, ctxt); + if (p == NULL) + goto error; + def->seclabel.model = p; + + p = virXPathStringLimit(conn, "string(./seclabel/label[1])", + VIR_SECURITY_LABEL_BUFLEN-1, ctxt); + if (p == NULL) + goto error; + def->seclabel.label = p; + } + + /* Only parse imagelabel, if requested live XML for dynamic label */ + if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && + !(flags & VIR_DOMAIN_XML_INACTIVE)) { + p = virXPathStringLimit(conn, "string(./seclabel/imagelabel[1])", + VIR_SECURITY_LABEL_BUFLEN-1, ctxt); + if (p == NULL) + goto error; + def->seclabel.imagelabel = p; + } return 0; @@ -2458,7 +2487,7 @@ static virDomainDefPtr virDomainDefParse VIR_FREE(nodes); /* analysis of security label */ - if (virSecurityLabelDefParseXML(conn, def, ctxt) == -1) + if (virSecurityLabelDefParseXML(conn, def, ctxt, flags) == -1) goto error; return def; @@ -3480,9 +3509,25 @@ char *virDomainDefFormat(virConnectPtr c virBufferAddLit(&buf, " </devices>\n"); if (def->seclabel.model) { - virBufferEscapeString(&buf, " <seclabel model='%s'>\n", def->seclabel.model); - virBufferEscapeString(&buf, " <label>%s</label>\n", def->seclabel.label); - virBufferAddLit(&buf, " </seclabel>\n"); + const char *sectype = virDomainSeclabelTypeToString(def->seclabel.type); + if (!sectype) + goto cleanup; + if (!def->seclabel.label || + (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && + (flags & VIR_DOMAIN_XML_INACTIVE))) { + virBufferVSprintf(&buf, " <seclabel type='%s' model='%s'/>\n", + sectype, def->seclabel.model); + } else { + virBufferVSprintf(&buf, " <seclabel type='%s' model='%s'>\n", + sectype, def->seclabel.model); + virBufferEscapeString(&buf, " <label>%s</label>\n", + def->seclabel.label); + if (def->seclabel.imagelabel && + def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) + virBufferEscapeString(&buf, " <imagelabel>%s</imagelabel>\n", + def->seclabel.imagelabel); + virBufferAddLit(&buf, " </seclabel>\n"); + } } virBufferAddLit(&buf, "</domain>\n"); Index: src/domain_conf.h =================================================================== RCS file: /data/cvs/libvirt/src/domain_conf.h,v retrieving revision 1.39 diff -u -p -r1.39 domain_conf.h --- src/domain_conf.h 3 Mar 2009 09:44:42 -0000 1.39 +++ src/domain_conf.h 3 Mar 2009 16:36:17 -0000 @@ -410,6 +410,13 @@ struct _virDomainOSDef { char *bootloaderArgs; }; +enum virDomainSeclabelType { + VIR_DOMAIN_SECLABEL_DYNAMIC, + VIR_DOMAIN_SECLABEL_STATIC, + + VIR_DOMAIN_SECLABEL_LAST, +}; + /* Security configuration for domain */ typedef struct _virSecurityLabelDef virSecurityLabelDef; typedef virSecurityLabelDef *virSecurityLabelDefPtr; @@ -417,6 +424,7 @@ struct _virSecurityLabelDef { char *model; /* name of security model */ char *label; /* security label string */ char *imagelabel; /* security image label string */ + int type; }; #define VIR_DOMAIN_CPUMASK_LEN 1024 @@ -650,5 +658,6 @@ VIR_ENUM_DECL(virDomainInputBus) VIR_ENUM_DECL(virDomainGraphics) /* from libvirt.h */ VIR_ENUM_DECL(virDomainState) +VIR_ENUM_DECL(virDomainSeclabel) #endif /* __DOMAIN_CONF_H */ Index: src/qemu_driver.c =================================================================== RCS file: /data/cvs/libvirt/src/qemu_driver.c,v retrieving revision 1.213 diff -u -p -r1.213 qemu_driver.c --- src/qemu_driver.c 3 Mar 2009 15:18:24 -0000 1.213 +++ src/qemu_driver.c 3 Mar 2009 16:36:18 -0000 @@ -1314,9 +1314,9 @@ static int qemudStartVMDaemon(virConnect hookData.vm = vm; hookData.driver = driver; - /* If you are using a SecurityDriver and there was no security label in - database, then generate a security label for isolation */ - if (vm->def->seclabel.label == NULL && + /* If you are using a SecurityDriver with dynamic labelling, + then generate a security label for isolation */ + if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && driver->securityDriver && driver->securityDriver->domainGenSecurityLabel && driver->securityDriver->domainGenSecurityLabel(conn, vm) < 0) @@ -1525,6 +1525,13 @@ static void qemudShutdownVMDaemon(virCon if (driver->securityDriver) driver->securityDriver->domainRestoreSecurityLabel(conn, vm); + /* Clear out dynamically assigned labels */ + if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) { + VIR_FREE(vm->def->seclabel.model); + VIR_FREE(vm->def->seclabel.label); + VIR_FREE(vm->def->seclabel.imagelabel); + } + if (qemudRemoveDomainStatus(conn, driver, vm) < 0) { VIR_WARN(_("Failed to remove domain status for %s"), vm->def->name); Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
participants (3)
-
Daniel J Walsh
-
Daniel P. Berrange
-
Daniel Veillard