diff --git a/ChangeLog b/ChangeLog index 74b8b4e893..0453790cc4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +Tue Mar 3 09:40:13 GMT 2009 Daniel P. Berrange + + Core internal driver stub for sVirt support (Jams Morris & Dan Walsh) + * Makefile.maint: Add virSecurityReportError as a msggen + function + * docs/schemas/capability.rng: Add element + * docs/schemas/domain.rng: Add element + * include/libvirt/virterror.h, src/virterror.c: Add + VIR_FROM_SECURITY and VIR_ERR_NO_SECURITY_MODEL + * po/POTFILES.in: Add src/security.c + * src/Makefile.am: Build security driver into libvirt.so + * src/capabilities.c, src/capabilities.h: Handling of + element / data + * src/domain_conf.c, src/domain_conf.h: Handling of + element / data + * src/libvirt_private.syms: Add virXPathStringLimit and + virSecurity* methods + * src/security.c, src/security.h: Add internal driver + stub impl + * src/storage_backend.c: TODO item about seclabel + * src/xml.c, src/xml.h: Add virXPathStringLimit + Tue Mar 3 09:25:13 GMT 2009 Daniel P. Berrange Remote protocol / RPC API for sVirt support (James Morris & Dan Walsh) diff --git a/Makefile.maint b/Makefile.maint index d257a8014b..b3e31b11fc 100644 --- a/Makefile.maint +++ b/Makefile.maint @@ -343,6 +343,7 @@ msg_gen_function += umlLog msg_gen_function += umlReportError msg_gen_function += virConfError msg_gen_function += virDomainReportError +msg_gen_function += virSecurityReportError msg_gen_function += virHashError msg_gen_function += virLibConnError msg_gen_function += virLibDomainError diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng index f848da2182..2c8559a8d2 100644 --- a/docs/schemas/capability.rng +++ b/docs/schemas/capability.rng @@ -33,9 +33,24 @@ + + + + + + + + + + + + + + + diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 8bd3ffb029..2e2e4089a3 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -22,10 +22,25 @@ + + + + + + + + + + + + + + + diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index d68201f1d2..2c3777da0c 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -61,6 +61,7 @@ typedef enum { VIR_FROM_UML, /* Error at the UML driver */ VIR_FROM_NODEDEV, /* Error from node device monitor */ VIR_FROM_XEN_INOTIFY, /* Error from xen inotify layer */ + VIR_FROM_SECURITY, /* Error from security framework */ } virErrorDomain; @@ -154,6 +155,7 @@ typedef enum { VIR_WAR_NO_NODE, /* failed to start node driver */ VIR_ERR_INVALID_NODE_DEVICE,/* invalid node device object */ VIR_ERR_NO_NODE_DEVICE,/* node device not found */ + VIR_ERR_NO_SECURITY_MODEL, /* security model not found */ } virErrorNumber; /** diff --git a/po/POTFILES.in b/po/POTFILES.in index 237d462017..146d6550a8 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -23,6 +23,7 @@ src/proxy_internal.c src/qemu_conf.c src/qemu_driver.c src/remote_internal.c +src/security.c src/storage_backend.c src/storage_backend_disk.c src/storage_backend_fs.c diff --git a/src/Makefile.am b/src/Makefile.am index a636e8aa3c..9fd81ec97d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -140,7 +140,7 @@ UML_DRIVER_SOURCES = \ NETWORK_DRIVER_SOURCES = \ network_driver.h network_driver.c -# And finally storage backend specific impls +# Storage backend specific impls STORAGE_DRIVER_SOURCES = \ storage_driver.h storage_driver.c \ storage_backend.h storage_backend.c @@ -166,6 +166,11 @@ STORAGE_HELPER_DISK_SOURCES = \ parthelper.c +# Security framework and drivers for various models +SECURITY_DRIVER_SOURCES = \ + security.h security.c + + NODE_DEVICE_DRIVER_SOURCES = \ node_device.c node_device.h @@ -379,6 +384,10 @@ endif endif +libvirt_driver_security_la_SOURCES = $(SECURITY_DRIVER_SOURCES) +noinst_LTLIBRARIES += libvirt_driver_security.la +libvirt_la_LIBADD += libvirt_driver_security.la + # Add all conditional sources just in case... EXTRA_DIST += \ $(TEST_DRIVER_SOURCES) \ diff --git a/src/capabilities.c b/src/capabilities.c index 3a2333207d..fb21d875ae 100644 --- a/src/capabilities.c +++ b/src/capabilities.c @@ -150,6 +150,8 @@ virCapabilitiesFree(virCapsPtr caps) { VIR_FREE(caps->host.migrateTrans); VIR_FREE(caps->host.arch); + VIR_FREE(caps->host.secModel.model); + VIR_FREE(caps->host.secModel.doi); VIR_FREE(caps); } @@ -599,6 +601,14 @@ virCapabilitiesFormatXML(virCapsPtr caps) virBufferAddLit(&xml, " \n"); virBufferAddLit(&xml, " \n"); } + + if (caps->host.secModel.model) { + virBufferAddLit(&xml, " \n"); + virBufferVSprintf(&xml, " %s\n", caps->host.secModel.model); + virBufferVSprintf(&xml, " %s\n", caps->host.secModel.doi); + virBufferAddLit(&xml, " \n"); + } + virBufferAddLit(&xml, " \n\n"); diff --git a/src/capabilities.h b/src/capabilities.h index be3296c1ef..db3229129b 100644 --- a/src/capabilities.h +++ b/src/capabilities.h @@ -78,6 +78,12 @@ struct _virCapsHostNUMACell { int *cpus; }; +typedef struct _virCapsHostSecModel virCapsHostSecModel; +struct _virCapsHostSecModel { + char *model; + char *doi; +}; + typedef struct _virCapsHost virCapsHost; typedef virCapsHost *virCapsHostPtr; struct _virCapsHost { @@ -90,6 +96,7 @@ struct _virCapsHost { char **migrateTrans; int nnumaCell; virCapsHostNUMACellPtr *numaCell; + virCapsHostSecModel secModel; }; typedef struct _virCaps virCaps; diff --git a/src/domain_conf.c b/src/domain_conf.c index 30c8b8b63d..43c51eb25e 100644 --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -387,6 +387,15 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def) VIR_FREE(def); } +void virSecurityLabelDefFree(virDomainDefPtr def); + +void virSecurityLabelDefFree(virDomainDefPtr def) +{ + VIR_FREE(def->seclabel.model); + VIR_FREE(def->seclabel.label); + VIR_FREE(def->seclabel.imagelabel); +} + void virDomainDefFree(virDomainDefPtr def) { unsigned int i; @@ -445,6 +454,8 @@ void virDomainDefFree(virDomainDefPtr def) VIR_FREE(def->cpumask); VIR_FREE(def->emulator); + virSecurityLabelDefFree(def); + VIR_FREE(def); } @@ -1833,6 +1844,34 @@ static int virDomainLifecycleParseXML(virConnectPtr conn, return 0; } +static int +virSecurityLabelDefParseXML(virConnectPtr conn, + const virDomainDefPtr def, + xmlXPathContextPtr ctxt) +{ + char *p; + + if (virXPathNode(conn, "./seclabel", ctxt) == NULL) + return 0; + + 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/@model)", + VIR_SECURITY_MODEL_BUFLEN-1, ctxt); + if (p == NULL) + goto error; + def->seclabel.model = p; + + return 0; + +error: + virSecurityLabelDefFree(def); + return -1; +} virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn, virCapsPtr caps, @@ -2418,6 +2457,10 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn, } VIR_FREE(nodes); + /* analysis of security label */ + if (virSecurityLabelDefParseXML(conn, def, ctxt) == -1) + goto error; + return def; no_memory: @@ -3435,6 +3478,13 @@ char *virDomainDefFormat(virConnectPtr conn, goto cleanup; virBufferAddLit(&buf, " \n"); + + if (def->seclabel.model) { + virBufferEscapeString(&buf, " \n", def->seclabel.model); + virBufferEscapeString(&buf, " \n", def->seclabel.label); + virBufferAddLit(&buf, " \n"); + } + virBufferAddLit(&buf, "\n"); if (virBufferError(&buf)) diff --git a/src/domain_conf.h b/src/domain_conf.h index 428c0fa7b5..fe83e0b19a 100644 --- a/src/domain_conf.h +++ b/src/domain_conf.h @@ -410,6 +410,15 @@ struct _virDomainOSDef { char *bootloaderArgs; }; +/* Security configuration for domain */ +typedef struct _virSecurityLabelDef virSecurityLabelDef; +typedef virSecurityLabelDef *virSecurityLabelDefPtr; +struct _virSecurityLabelDef { + char *model; /* name of security model */ + char *label; /* security label string */ + char *imagelabel; /* security image label string */ +}; + #define VIR_DOMAIN_CPUMASK_LEN 1024 /* Guest VM main configuration */ @@ -467,6 +476,7 @@ struct _virDomainDef { /* Only 1 */ virDomainChrDefPtr console; + virSecurityLabelDef seclabel; }; /* Guest VM runtime state */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 734ba5eace..f0d8afac15 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -247,6 +247,14 @@ qparam_query_parse; free_qparam_set; +# security.h +virSecurityDriverStartup; +virSecurityDriverInit; +virSecurityDriverSetDOI; +virSecurityDriverGetDOI; +virSecurityDriverGetModel; + + # storage_conf.h virStoragePoolDefFormat; virStoragePoolDefFree; @@ -351,3 +359,4 @@ virXPathNode; virXPathNodeSet; virXPathString; virXMLPropString; +virXPathStringLimit; diff --git a/src/security.c b/src/security.c new file mode 100644 index 0000000000..e8294f2640 --- /dev/null +++ b/src/security.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Authors: + * James Morris + * + */ +#include +#include + +#include "virterror_internal.h" + +#include "security.h" + +static virSecurityDriverPtr security_drivers[] = { + NULL +}; + +int +virSecurityDriverStartup(virSecurityDriverPtr *drv, + const char *name) +{ + unsigned int i; + + if (name && STREQ(name, "none")) + return -2; + + for (i = 0; security_drivers[i] != NULL ; i++) { + virSecurityDriverPtr tmp = security_drivers[i]; + + if (name && STRNEQ(tmp->name, name)) + continue; + + switch (tmp->probe()) { + case SECURITY_DRIVER_ENABLE: + virSecurityDriverInit(tmp); + if (tmp->open(NULL, tmp) == -1) { + return -1; + } else { + *drv = tmp; + return 0; + } + break; + + case SECURITY_DRIVER_DISABLE: + break; + + default: + return -1; + } + } + return -2; +} + +void +virSecurityReportError(virConnectPtr conn, int code, const char *fmt, ...) +{ + va_list args; + char errorMessage[1024]; + + if (fmt) { + va_start(args, fmt); + vsnprintf(errorMessage, sizeof(errorMessage) - 1, fmt, args); + va_end(args); + } else + errorMessage[0] = '\0'; + + virRaiseError(conn, NULL, NULL, VIR_FROM_SECURITY, code, + VIR_ERR_ERROR, NULL, NULL, NULL, -1, -1, "%s", + errorMessage); +} + +/* + * Helpers + */ +void +virSecurityDriverInit(virSecurityDriverPtr drv) +{ + memset(&drv->_private, 0, sizeof drv->_private); +} + +int +virSecurityDriverSetDOI(virConnectPtr conn, + virSecurityDriverPtr drv, + const char *doi) +{ + if (strlen(doi) >= VIR_SECURITY_DOI_BUFLEN) { + virSecurityReportError(conn, VIR_ERR_ERROR, + _("%s: DOI \'%s\' is " + "longer than the maximum allowed length of %d"), + __func__, doi, VIR_SECURITY_DOI_BUFLEN - 1); + return -1; + } + strcpy(drv->_private.doi, doi); + return 0; +} + +const char * +virSecurityDriverGetDOI(virSecurityDriverPtr drv) +{ + return drv->_private.doi; +} + +const char * +virSecurityDriverGetModel(virSecurityDriverPtr drv) +{ + return drv->name; +} diff --git a/src/security.h b/src/security.h new file mode 100644 index 0000000000..db17b2603c --- /dev/null +++ b/src/security.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Authors: + * James Morris + * + */ +#ifndef __VIR_SECURITY_H__ +#define __VIR_SECURITY_H__ + +#include "internal.h" +#include "domain_conf.h" + +/* + * Return values for security driver probing: the driver will determine + * whether it should be enabled or disabled. + */ +typedef enum { + SECURITY_DRIVER_ENABLE = 0, + SECURITY_DRIVER_ERROR = -1, + SECURITY_DRIVER_DISABLE = -2, +} virSecurityDriverStatus; + +typedef struct _virSecurityDriver virSecurityDriver; +typedef virSecurityDriver *virSecurityDriverPtr; +typedef virSecurityDriverStatus (*virSecurityDriverProbe) (void); +typedef int (*virSecurityDriverOpen) (virConnectPtr conn, + virSecurityDriverPtr drv); +typedef int (*virSecurityDomainRestoreImageLabel) (virConnectPtr conn, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev); +typedef int (*virSecurityDomainSetImageLabel) (virConnectPtr conn, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev); +typedef int (*virSecurityDomainGenLabel) (virDomainObjPtr sec); +typedef int (*virSecurityDomainGetLabel) (virConnectPtr conn, + virDomainObjPtr vm, + virSecurityLabelPtr sec); +typedef int (*virSecurityDomainRestoreLabel) (virConnectPtr conn, + virDomainObjPtr vm); +typedef int (*virSecurityDomainSetLabel) (virConnectPtr conn, + virSecurityDriverPtr drv, + virDomainObjPtr vm); + +struct _virSecurityDriver { + const char *name; + virSecurityDriverProbe probe; + virSecurityDriverOpen open; + virSecurityDomainRestoreImageLabel domainRestoreSecurityImageLabel; + virSecurityDomainSetImageLabel domainSetSecurityImageLabel; + virSecurityDomainGenLabel domainGenSecurityLabel; + virSecurityDomainGetLabel domainGetSecurityLabel; + virSecurityDomainSetLabel domainSetSecurityLabel; + virSecurityDomainRestoreLabel domainRestoreSecurityLabel; + + /* + * This is internally managed driver state and should only be accessed + * via helpers below. + */ + struct { + char doi[VIR_SECURITY_DOI_BUFLEN]; + } _private; +}; + +/* Global methods */ +int virSecurityDriverStartup(virSecurityDriverPtr *drv, + const char *name); + +void +virSecurityReportError(virConnectPtr conn, int code, const char *fmt, ...) + ATTRIBUTE_FORMAT(printf, 3, 4); + +/* Helpers */ +void virSecurityDriverInit(virSecurityDriverPtr drv); +int virSecurityDriverSetDOI(virConnectPtr conn, + virSecurityDriverPtr drv, + const char *doi); +const char *virSecurityDriverGetDOI(virSecurityDriverPtr drv); +const char *virSecurityDriverGetModel(virSecurityDriverPtr drv); + +#endif /* __VIR_SECURITY_H__ */ diff --git a/src/storage_backend.c b/src/storage_backend.c index 8408f34669..787630c3af 100644 --- a/src/storage_backend.c +++ b/src/storage_backend.c @@ -276,6 +276,7 @@ virStorageBackendUpdateVolTargetInfoFD(virConnectPtr conn, VIR_FREE(target->perms.label); #if HAVE_SELINUX + /* XXX: make this a security driver call */ if (fgetfilecon(fd, &filecon) == -1) { if (errno != ENODATA && errno != ENOTSUP) { virReportSystemError(conn, errno, diff --git a/src/virterror.c b/src/virterror.c index 42a7cf578b..d2514dbeae 100644 --- a/src/virterror.c +++ b/src/virterror.c @@ -151,6 +151,9 @@ static const char *virErrorDomainName(virErrorDomain domain) { case VIR_FROM_UML: dom = "UML "; break; + case VIR_FROM_SECURITY: + dom = "Security Labeling "; + break; } return(dom); } @@ -995,6 +998,12 @@ virErrorMsg(virErrorNumber error, const char *info) else errmsg = _("Node device not found: %s"); break; + case VIR_ERR_NO_SECURITY_MODEL: + if (info == NULL) + errmsg = _("Security model not found"); + else + errmsg = _("Security model not found: %s"); + break; } return (errmsg); } diff --git a/src/xml.c b/src/xml.c index a4465b2208..575d14e770 100644 --- a/src/xml.c +++ b/src/xml.c @@ -76,6 +76,36 @@ virXPathString(virConnectPtr conn, return (ret); } +/** + * virXPathStringLimit: + * @xpath: the XPath string to evaluate + * @maxlen: maximum length permittred string + * @ctxt: an XPath context + * + * Wrapper for virXPathString, which validates the length of the returned + * string. + * + * Returns a new string which must be deallocated by the caller or NULL if + * the evaluation failed. + */ +char * +virXPathStringLimit(virConnectPtr conn, + const char *xpath, + size_t maxlen, + xmlXPathContextPtr ctxt) +{ + char *tmp = virXPathString(conn, xpath, ctxt); + + if (tmp != NULL && strlen(tmp) >= maxlen) { + virXMLError(conn, VIR_ERR_INTERNAL_ERROR, + _("\'%s\' value longer than %Zd bytes in virXPathStringLimit()"), + xpath, maxlen); + return NULL; + } + + return tmp; +} + /** * virXPathNumber: * @xpath: the XPath string to evaluate diff --git a/src/xml.h b/src/xml.h index 34b0f10c4e..cddd42bcf7 100644 --- a/src/xml.h +++ b/src/xml.h @@ -17,6 +17,10 @@ int virXPathBoolean (virConnectPtr conn, char * virXPathString (virConnectPtr conn, const char *xpath, xmlXPathContextPtr ctxt); +char * virXPathStringLimit(virConnectPtr conn, + const char *xpath, + size_t maxlen, + xmlXPathContextPtr ctxt); int virXPathNumber (virConnectPtr conn, const char *xpath, xmlXPathContextPtr ctxt,