Core internal driver stub for sVirt support (Jams Morris & Dan Walsh)

This commit is contained in:
Daniel P. Berrange 2009-03-03 09:44:41 +00:00
parent a8cd24b346
commit 8bd1604cb7
18 changed files with 395 additions and 1 deletions

View File

@ -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> 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) Remote protocol / RPC API for sVirt support (James Morris & Dan Walsh)

View File

@ -343,6 +343,7 @@ msg_gen_function += umlLog
msg_gen_function += umlReportError msg_gen_function += umlReportError
msg_gen_function += virConfError msg_gen_function += virConfError
msg_gen_function += virDomainReportError msg_gen_function += virDomainReportError
msg_gen_function += virSecurityReportError
msg_gen_function += virHashError msg_gen_function += virHashError
msg_gen_function += virLibConnError msg_gen_function += virLibConnError
msg_gen_function += virLibDomainError msg_gen_function += virLibDomainError

View File

@ -33,9 +33,24 @@
<optional> <optional>
<ref name='topology'/> <ref name='topology'/>
</optional> </optional>
<optional>
<ref name='secmodel'/>
</optional>
</element> </element>
</define> </define>
<define name='secmodel'>
<element name='secmodel'>
<element name='model'>
<text/>
</element>
<element name='doi'>
<text/>
</element>
</element>
</define>
<define name='cpufeatures'> <define name='cpufeatures'>
<element name='features'> <element name='features'>
<optional> <optional>

View File

@ -22,10 +22,25 @@
<optional> <optional>
<ref name='devices'/> <ref name='devices'/>
</optional> </optional>
<optional>
<ref name='seclabel'/>
</optional>
</interleave> </interleave>
</element> </element>
</define> </define>
<define name='seclabel'>
<element name='seclabel'>
<attribute name='model'>
<text/>
</attribute>
<element name='label'>
<text/>
</element>
</element>
</define>
<define name='hvs'> <define name='hvs'>
<attribute name='type'> <attribute name='type'>
<choice> <choice>

View File

@ -61,6 +61,7 @@ typedef enum {
VIR_FROM_UML, /* Error at the UML driver */ VIR_FROM_UML, /* Error at the UML driver */
VIR_FROM_NODEDEV, /* Error from node device monitor */ VIR_FROM_NODEDEV, /* Error from node device monitor */
VIR_FROM_XEN_INOTIFY, /* Error from xen inotify layer */ VIR_FROM_XEN_INOTIFY, /* Error from xen inotify layer */
VIR_FROM_SECURITY, /* Error from security framework */
} virErrorDomain; } virErrorDomain;
@ -154,6 +155,7 @@ typedef enum {
VIR_WAR_NO_NODE, /* failed to start node driver */ VIR_WAR_NO_NODE, /* failed to start node driver */
VIR_ERR_INVALID_NODE_DEVICE,/* invalid node device object */ VIR_ERR_INVALID_NODE_DEVICE,/* invalid node device object */
VIR_ERR_NO_NODE_DEVICE,/* node device not found */ VIR_ERR_NO_NODE_DEVICE,/* node device not found */
VIR_ERR_NO_SECURITY_MODEL, /* security model not found */
} virErrorNumber; } virErrorNumber;
/** /**

View File

@ -23,6 +23,7 @@ src/proxy_internal.c
src/qemu_conf.c src/qemu_conf.c
src/qemu_driver.c src/qemu_driver.c
src/remote_internal.c src/remote_internal.c
src/security.c
src/storage_backend.c src/storage_backend.c
src/storage_backend_disk.c src/storage_backend_disk.c
src/storage_backend_fs.c src/storage_backend_fs.c

View File

@ -140,7 +140,7 @@ UML_DRIVER_SOURCES = \
NETWORK_DRIVER_SOURCES = \ NETWORK_DRIVER_SOURCES = \
network_driver.h network_driver.c network_driver.h network_driver.c
# And finally storage backend specific impls # Storage backend specific impls
STORAGE_DRIVER_SOURCES = \ STORAGE_DRIVER_SOURCES = \
storage_driver.h storage_driver.c \ storage_driver.h storage_driver.c \
storage_backend.h storage_backend.c storage_backend.h storage_backend.c
@ -166,6 +166,11 @@ STORAGE_HELPER_DISK_SOURCES = \
parthelper.c parthelper.c
# Security framework and drivers for various models
SECURITY_DRIVER_SOURCES = \
security.h security.c
NODE_DEVICE_DRIVER_SOURCES = \ NODE_DEVICE_DRIVER_SOURCES = \
node_device.c node_device.h node_device.c node_device.h
@ -379,6 +384,10 @@ endif
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... # Add all conditional sources just in case...
EXTRA_DIST += \ EXTRA_DIST += \
$(TEST_DRIVER_SOURCES) \ $(TEST_DRIVER_SOURCES) \

View File

@ -150,6 +150,8 @@ virCapabilitiesFree(virCapsPtr caps) {
VIR_FREE(caps->host.migrateTrans); VIR_FREE(caps->host.migrateTrans);
VIR_FREE(caps->host.arch); VIR_FREE(caps->host.arch);
VIR_FREE(caps->host.secModel.model);
VIR_FREE(caps->host.secModel.doi);
VIR_FREE(caps); VIR_FREE(caps);
} }
@ -599,6 +601,14 @@ virCapabilitiesFormatXML(virCapsPtr caps)
virBufferAddLit(&xml, " </cells>\n"); virBufferAddLit(&xml, " </cells>\n");
virBufferAddLit(&xml, " </topology>\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"); virBufferAddLit(&xml, " </host>\n\n");

View File

@ -78,6 +78,12 @@ struct _virCapsHostNUMACell {
int *cpus; int *cpus;
}; };
typedef struct _virCapsHostSecModel virCapsHostSecModel;
struct _virCapsHostSecModel {
char *model;
char *doi;
};
typedef struct _virCapsHost virCapsHost; typedef struct _virCapsHost virCapsHost;
typedef virCapsHost *virCapsHostPtr; typedef virCapsHost *virCapsHostPtr;
struct _virCapsHost { struct _virCapsHost {
@ -90,6 +96,7 @@ struct _virCapsHost {
char **migrateTrans; char **migrateTrans;
int nnumaCell; int nnumaCell;
virCapsHostNUMACellPtr *numaCell; virCapsHostNUMACellPtr *numaCell;
virCapsHostSecModel secModel;
}; };
typedef struct _virCaps virCaps; typedef struct _virCaps virCaps;

View File

@ -387,6 +387,15 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
VIR_FREE(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) void virDomainDefFree(virDomainDefPtr def)
{ {
unsigned int i; unsigned int i;
@ -445,6 +454,8 @@ void virDomainDefFree(virDomainDefPtr def)
VIR_FREE(def->cpumask); VIR_FREE(def->cpumask);
VIR_FREE(def->emulator); VIR_FREE(def->emulator);
virSecurityLabelDefFree(def);
VIR_FREE(def); VIR_FREE(def);
} }
@ -1833,6 +1844,34 @@ static int virDomainLifecycleParseXML(virConnectPtr conn,
return 0; 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, virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn,
virCapsPtr caps, virCapsPtr caps,
@ -2418,6 +2457,10 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
} }
VIR_FREE(nodes); VIR_FREE(nodes);
/* analysis of security label */
if (virSecurityLabelDefParseXML(conn, def, ctxt) == -1)
goto error;
return def; return def;
no_memory: no_memory:
@ -3435,6 +3478,13 @@ char *virDomainDefFormat(virConnectPtr conn,
goto cleanup; goto cleanup;
virBufferAddLit(&buf, " </devices>\n"); 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"); virBufferAddLit(&buf, "</domain>\n");
if (virBufferError(&buf)) if (virBufferError(&buf))

View File

@ -410,6 +410,15 @@ struct _virDomainOSDef {
char *bootloaderArgs; 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 #define VIR_DOMAIN_CPUMASK_LEN 1024
/* Guest VM main configuration */ /* Guest VM main configuration */
@ -467,6 +476,7 @@ struct _virDomainDef {
/* Only 1 */ /* Only 1 */
virDomainChrDefPtr console; virDomainChrDefPtr console;
virSecurityLabelDef seclabel;
}; };
/* Guest VM runtime state */ /* Guest VM runtime state */

View File

@ -247,6 +247,14 @@ qparam_query_parse;
free_qparam_set; free_qparam_set;
# security.h
virSecurityDriverStartup;
virSecurityDriverInit;
virSecurityDriverSetDOI;
virSecurityDriverGetDOI;
virSecurityDriverGetModel;
# storage_conf.h # storage_conf.h
virStoragePoolDefFormat; virStoragePoolDefFormat;
virStoragePoolDefFree; virStoragePoolDefFree;
@ -351,3 +359,4 @@ virXPathNode;
virXPathNodeSet; virXPathNodeSet;
virXPathString; virXPathString;
virXMLPropString; virXMLPropString;
virXPathStringLimit;

113
src/security.c Normal file
View File

@ -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;
}

86
src/security.h Normal file
View File

@ -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__ */

View File

@ -276,6 +276,7 @@ virStorageBackendUpdateVolTargetInfoFD(virConnectPtr conn,
VIR_FREE(target->perms.label); VIR_FREE(target->perms.label);
#if HAVE_SELINUX #if HAVE_SELINUX
/* XXX: make this a security driver call */
if (fgetfilecon(fd, &filecon) == -1) { if (fgetfilecon(fd, &filecon) == -1) {
if (errno != ENODATA && errno != ENOTSUP) { if (errno != ENODATA && errno != ENOTSUP) {
virReportSystemError(conn, errno, virReportSystemError(conn, errno,

View File

@ -151,6 +151,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
case VIR_FROM_UML: case VIR_FROM_UML:
dom = "UML "; dom = "UML ";
break; break;
case VIR_FROM_SECURITY:
dom = "Security Labeling ";
break;
} }
return(dom); return(dom);
} }
@ -995,6 +998,12 @@ virErrorMsg(virErrorNumber error, const char *info)
else else
errmsg = _("Node device not found: %s"); errmsg = _("Node device not found: %s");
break; 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); return (errmsg);
} }

View File

@ -76,6 +76,36 @@ virXPathString(virConnectPtr conn,
return (ret); 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: * virXPathNumber:
* @xpath: the XPath string to evaluate * @xpath: the XPath string to evaluate

View File

@ -17,6 +17,10 @@ int virXPathBoolean (virConnectPtr conn,
char * virXPathString (virConnectPtr conn, char * virXPathString (virConnectPtr conn,
const char *xpath, const char *xpath,
xmlXPathContextPtr ctxt); xmlXPathContextPtr ctxt);
char * virXPathStringLimit(virConnectPtr conn,
const char *xpath,
size_t maxlen,
xmlXPathContextPtr ctxt);
int virXPathNumber (virConnectPtr conn, int virXPathNumber (virConnectPtr conn,
const char *xpath, const char *xpath,
xmlXPathContextPtr ctxt, xmlXPathContextPtr ctxt,