]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Core internal driver stub for sVirt support (Jams Morris & Dan Walsh)
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 3 Mar 2009 09:44:41 +0000 (09:44 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 3 Mar 2009 09:44:41 +0000 (09:44 +0000)
18 files changed:
ChangeLog
Makefile.maint
docs/schemas/capability.rng
docs/schemas/domain.rng
include/libvirt/virterror.h
po/POTFILES.in
src/Makefile.am
src/capabilities.c
src/capabilities.h
src/domain_conf.c
src/domain_conf.h
src/libvirt_private.syms
src/security.c [new file with mode: 0644]
src/security.h [new file with mode: 0644]
src/storage_backend.c
src/virterror.c
src/xml.c
src/xml.h

index 74b8b4e893df64b1d956e4818b3acc82722fcaea..0453790cc43311154698e54ee3f4a479b5a9fb52 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+Tue Mar  3 09:40:13 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
+
+       Core internal driver stub for sVirt support (Jams Morris & Dan Walsh)
+       * Makefile.maint: Add virSecurityReportError as a msggen
+       function
+       * docs/schemas/capability.rng: Add <secmodel> element
+       * docs/schemas/domain.rng: Add <seclabel> 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
+       <secmodel> element / data
+       * src/domain_conf.c, src/domain_conf.h: Handling of
+       <seclabel> 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 <berrange@redhat.com>
 
        Remote protocol / RPC API for sVirt support (James Morris & Dan Walsh)
index d257a8014bb6120f82cc24c3f416029da94dcd4d..b3e31b11fc4f97f558ce4993e795e25212a34270 100644 (file)
@@ -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
index f848da21827020703a0d6d49a4d68b957155e406..2c8559a8d273842c007995b9b995b8e2a1467fe7 100644 (file)
       <optional>
        <ref name='topology'/>
       </optional>
+      <optional>
+       <ref name='secmodel'/>
+      </optional>
+    </element>
+  </define>
+
+  <define name='secmodel'>
+    <element name='secmodel'>
+      <element name='model'>
+        <text/>
+      </element>
+      <element name='doi'>
+        <text/>
+      </element>
     </element>
   </define>
 
+
   <define name='cpufeatures'>
     <element name='features'>
       <optional>
index 8bd3ffb029b18351eb91ec1f0db1baed102deb3d..2e2e4089a3bb2371a900f423f5724cfe54f73426 100644 (file)
        <optional>
           <ref name='devices'/>
        </optional>
+       <optional>
+          <ref name='seclabel'/>
+       </optional>
       </interleave>
     </element>
   </define>
 
+  <define name='seclabel'>
+    <element name='seclabel'>
+      <attribute name='model'>
+       <text/>
+      </attribute>
+      <element name='label'>
+       <text/>
+      </element>
+    </element>
+  </define>
+
+
   <define name='hvs'>
     <attribute name='type'>
       <choice>
index d68201f1d2f1eef385b49c9fa5840d808c65973e..2c3777da0cdb0f8b12576f97681f83204f6ed4d4 100644 (file)
@@ -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;
 
 /**
index 237d462017b6d130363d64be1caf8f9e8a4a185a..146d6550a8c7ae3e7ff9eb9ae5b63a5515538308 100644 (file)
@@ -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
index a636e8aa3c8c23a9b3fdadf67ed3afa74350f22f..9fd81ec97d6037a31a5a5f930eeeaa142033abdf 100644 (file)
@@ -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)                          \
index 3a2333207d08d9c912355f49c3099a53b043e502..fb21d875ae9b1413d6a05b7bb0c7e00c25d46942 100644 (file)
@@ -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, "      </cells>\n");
         virBufferAddLit(&xml, "    </topology>\n");
     }
+
+    if (caps->host.secModel.model) {
+        virBufferAddLit(&xml, "    <secmodel>\n");
+        virBufferVSprintf(&xml, "      <model>%s</model>\n", caps->host.secModel.model);
+        virBufferVSprintf(&xml, "      <doi>%s</doi>\n", caps->host.secModel.doi);
+        virBufferAddLit(&xml, "    </secmodel>\n");
+    }
+
     virBufferAddLit(&xml, "  </host>\n\n");
 
 
index be3296c1ef28ef018680b5d5752fbce5dfbc3b05..db3229129be3244ecce277913ffdcae43d118834 100644 (file)
@@ -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;
index 30c8b8b63d5b66f43c54a0dd0946d49e8a8996e1..43c51eb25e807b84491a45a5ad958fb744e7794f 100644 (file)
@@ -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, "  </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");
+    }
+
     virBufferAddLit(&buf, "</domain>\n");
 
     if (virBufferError(&buf))
index 428c0fa7b5d06b93eeb0d7c95479eecfabfcb247..fe83e0b19a020b0bb4a46b191edcc288a5d07b35 100644 (file)
@@ -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 */
index 734ba5eace69a575e6029a4950c76465460ff300..f0d8afac15ed0409bcaf712e18349412b283044d 100644 (file)
@@ -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 (file)
index 0000000..e8294f2
--- /dev/null
@@ -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 <jmorris@namei.org>
+ *
+ */
+#include <config.h>
+#include <string.h>
+
+#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 (file)
index 0000000..db17b26
--- /dev/null
@@ -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 <jmorris@namei.org>
+ *
+ */
+#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__ */
index 8408f3466904e221618b54871efe345494ad6dba..787630c3af86fbc3f1baf15d5ab7e4e7cd9136f9 100644 (file)
@@ -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,
index 42a7cf578be12836f6828ee316bfbc65f4049b40..d2514dbeae8df45011f417d840814a8b2aad5ac5 100644 (file)
@@ -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);
 }
index a4465b22088a69c21dd2a99397e804e320857082..575d14e7707820fbd0479872e455267522ea9cbf 100644 (file)
--- 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
index 34b0f10c4edd03f574588889b864787c41f0669f..cddd42bcf7b104ab21fb945c908155a399183506 100644 (file)
--- 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,