All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] sVirt v0.10 - initial prototype
@ 2008-10-21  2:06 James Morris
  2008-10-21 13:57 ` Daniel J Walsh
                   ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: James Morris @ 2008-10-21  2:06 UTC (permalink / raw)
  To: libvir-list
  Cc: Daniel P. Berrange, Daniel Veillard, Daniel J Walsh,
	Stephen Smalley, selinux

[-- Attachment #1: Type: TEXT/PLAIN, Size: 5346 bytes --]

This is a request for comments on the initial prototype release of sVirt, 
a project to add security labeling support to Linux-based virtualization.

Project page: 
  http://www.selinuxproject.org/page/SVirt

Previous libvirt discussions:

  High-level requirements:
    https://www.redhat.com/archives/libvir-list/2008-August/msg00255.html

  XML security labels:
    https://www.redhat.com/archives/libvir-list/2008-August/msg00740.html

A patch for libvirt is attached; and also included in a release tarball at 
http://namei.org/svirt/.  See 'readme.txt' there for more details on 
building and running the code.

The purpose of this release is to establish a proof of concept of applying 
security labels to VMs, and for discussion of the underlying technical 
approach.

With this release, it is possible to define a security label for a 
kvm/qemu domain in its XML configuration ('virsh edit'), launch the domain 
and have it transition to the specified security label ('virsh start'), 
then query the security label of the running domain ('virsh dominfo').

The following changes were made to libvirt:

1. Implementing a pluggable security label driver framework;

2. Implementing an SELinux security label driver for (1);

3. Wiring the security label framework into the Qemu driver;

4. Implementing basic libvirt API calls for initializing the driver, 
   and getting/setting domain security labels;

5. Extending the domain XML configuration to include security labels;

6. Adding domain security label display/edit/dump support to virsh.

One of the design principles I've followed with this is to reduce or 
eliminate configuration wherever possible.  If a variety of security 
labeling drivers are present, libvirtd automatically detects which one to 
enable and enables it.  e.g. if SELinux is enabled on the system, the 
SELinux labeling driver is enabled automatically when livbirtd starts.

Another is to treat security labels as opaque unless they're actually 
being used for security purposes (e.g. to launch the domain).  So, virsh 
and the domain configuration code currently do not need to semantically 
interpet security labels, just understand their format.  This should suit 
the initial simple goal of isolated domains, which only requires security 
labels to be distinct.

The domain security label configuration format is as follows:

# virsh dumpxml sys1
<domain>
    ....
  <seclabel model='selinux'>
    <label>system_u:system_r:virtd_t:s0</label>
    <policytype>targeted</policytype>
  </seclabel>
</domain>

It's possible to query the security label of a running domain via virsh:

# virsh dominfo sys1
Id:             1
Name:           sys1
UUID:           fa3c8e06-0877-2a08-06fd-f2479b7bacb4
OS Type:        hvm
State:          running
CPU(s):         1
CPU time:       11.4s
Max memory:     524288 kB
Used memory:    524288 kB
Autostart:      disable
Security label: system_u:system_r:virtd_t:s0 (selinux/targeted/enforcing)

The security label is deterimed via the new virDomainGetSecLabel() API 
method, which is transported over RPC to the backend driver (qemu in this 
case), and is entirely independent of the local security model, if any.  
e.g. this command could be run remotely from an entirely different 
platform: you just see what's happening on the remote system, as with 
other attributes of the domain.

Feedback on the design thus far is sought before proceeding to more 
comprehensive integration.

In particular, I'd be interested in any thoughts on the placement of the 
security labeling driver within libvirt, as this seems to be the most 
critical architectural issue (I've already refactored this aspect once).  

Currently, the idea is to attach the security labeling driver to the virt 
driver, rather than implement it independently as a top-level component as 
in the case of other types of drivers (e.g. storage).  This is because 
process-based security labeling is highly dependent on the kind of 
virtualization in use, and may not make sense at all in some cases (e.g. 
when using a non-Linux hypervisor, or containers).

In the case of qemu, a security labeling driver is added to qemud:

@@ -63,6 +64,7 @@ struct qemud_driver {
     char *vncListen;
 
     virCapsPtr caps;
+    virSecLabelDriverPtr secLabelDriver;
 };

and then initialized during qemud startup from qemudSecLabelInit().  

During initialization, any available security labeling drivers are probed, 
and the first one which thinks it should be used is installed. Top-level 
libvirt API calls are then dispatched to the active security labeling 
driver via the backend virt driver, as necessary.

Note that the security labeling framework in this release is always 
built-in -- it can be made a compile-time option later if desired.

Requirements not yet addressed include:
- Labeling of resources and generally comprehensive labeling management
- Automatic labeling (e.g. for the simple isolation use-case)
- Integration of labeling support into higher-level management tools such 
  as virt-manager
- Integration with the audit subsystem to help with administration and 
  debugging
- Domain of interpretation (DOI) checking/translation
- Python bindings

As mentioned, the goal at this stage is to get feedback on the underlying 
design: comments welcome!


- James
-- 
James Morris
<jmorris@namei.org>

[-- Attachment #2: Type: TEXT/PLAIN, Size: 53678 bytes --]

diff --git a/Makefile.maint b/Makefile.maint
index d856469..5d03365 100644
--- a/Makefile.maint
+++ b/Makefile.maint
@@ -353,6 +353,7 @@ msg_gen_function += qemudReportError
 msg_gen_function += openvzLog
 msg_gen_function += openvzError
 msg_gen_function += virDomainReportError
+msg_gen_function += virSecLabelReportError
 
 # Uncomment the following and run "make syntax-check" to see diagnostics
 # that are not yet marked for translation, but that need to be rewritten
diff --git a/autobuild.sh b/autobuild.sh
index e62926c..49d4b5d 100755
--- a/autobuild.sh
+++ b/autobuild.sh
@@ -14,10 +14,18 @@ rm -rf coverage
 #mkdir build
 #cd build
 
+SELINUXENABLED=/usr/sbin/selinuxenabled
+
+if [ -x $SELINUXENABLED ] && $SELINUXENABLED ; then
+    WITH_SELINUX="--with-selinux=yes"
+else
+    WITH_SELINUX=""
+fi
+
 ./autogen.sh --prefix="$AUTOBUILD_INSTALL_ROOT" \
   --enable-test-coverage \
   --enable-compile-warnings=error \
-  --with-xen-proxy
+  --with-xen-proxy $WITH_SELINUX
 
 # If the MAKEFLAGS envvar does not yet include a -j option,
 # add -jN where N depends on the number of processors.
diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
index 35b80d0..58ded58 100644
--- a/include/libvirt/libvirt.h
+++ b/include/libvirt/libvirt.h
@@ -111,6 +111,53 @@ typedef enum {
 } virDomainCreateFlags;
 
 /**
+ * VIR_SECLABEL_LABEL_BUFLEN:
+ *
+ * Macro providing the maximum length of the virDomainSecLabel
+ * label string.  Note that this value is based on that used
+ * by Labeled NFS.
+ */
+#define VIR_SECLABEL_LABEL_BUFLEN (4096 + 1)
+
+/**
+ * VIR_SECLABEL_MODEL_BUFLEN:
+ *
+ * Macro providing the maximum length of the virDomainSecLabel
+ * model string.
+ */
+#define VIR_SECLABEL_MODEL_BUFLEN (256 + 1)
+
+/**
+ * VIR_SECLABEL_POLICYTYPE_BUFLEN:
+ *
+ * Macro providing the maximum length of the virDomainSecLabel
+ * policy string.
+ */
+#define VIR_SECLABEL_POLICYTYPE_BUFLEN (256 + 1)
+
+/**
+ * virDomainSecLabel:
+ *
+ * a virDomainSecLabel is a structure filled by virDomainGetSecLabel(),
+ * providing the security label and associated attributes for the specified
+ * domain.
+ *
+ */
+typedef struct _virDomainSecLabel {
+    char model[VIR_SECLABEL_MODEL_BUFLEN];              /* name of security labeling model */
+    char label[VIR_SECLABEL_LABEL_BUFLEN];              /* security label string */
+    char policytype[VIR_SECLABEL_POLICYTYPE_BUFLEN];    /* policy type */
+    int enforcing;                                      /* 1 if security policy is being enforced for domain */
+} virDomainSecLabel;
+
+/**
+ * virDomainSecLabelPtr:
+ *
+ * a virDomainSecLabelPtr is a pointer to a virDomainSecLabel.
+ */
+typedef virDomainSecLabel *virDomainSecLabelPtr;
+
+/**
  * virNodeInfoPtr:
  *
  * a virNodeInfo is a structure filled by virNodeGetInfo() and providing
@@ -504,6 +551,8 @@ int                     virDomainSetMaxMemory   (virDomainPtr domain,
 int                     virDomainSetMemory      (virDomainPtr domain,
                                                  unsigned long memory);
 int                     virDomainGetMaxVcpus    (virDomainPtr domain);
+int                     virDomainGetSecLabel	(virDomainPtr domain,
+                                                 virDomainSecLabelPtr seclabel);
 
 /*
  * XML domain description
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 3624367..e876c00 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -111,6 +111,53 @@ typedef enum {
 } virDomainCreateFlags;
 
 /**
+ * VIR_SECLABEL_LABEL_BUFLEN:
+ *
+ * Macro providing the maximum length of the virDomainSecLabel
+ * label string.  Note that this value is based on that used
+ * by Labeled NFS.
+ */
+#define VIR_SECLABEL_LABEL_BUFLEN (4096 + 1)
+
+/**
+ * VIR_SECLABEL_MODEL_BUFLEN:
+ *
+ * Macro providing the maximum length of the virDomainSecLabel
+ * model string.
+ */
+#define VIR_SECLABEL_MODEL_BUFLEN (256 + 1)
+
+/**
+ * VIR_SECLABEL_POLICYTYPE_BUFLEN:
+ *
+ * Macro providing the maximum length of the virDomainSecLabel
+ * policy string.
+ */
+#define VIR_SECLABEL_POLICYTYPE_BUFLEN (256 + 1)
+
+/**
+ * virDomainSecLabel:
+ *
+ * a virDomainSecLabel is a structure filled by virDomainGetSecLabel(),
+ * providing the security label and associated attributes for the specified
+ * domain.
+ *
+ */
+typedef struct _virDomainSecLabel {
+    char model[VIR_SECLABEL_MODEL_BUFLEN];              /* name of security labeling model */
+    char label[VIR_SECLABEL_LABEL_BUFLEN];              /* security label string */
+    char policytype[VIR_SECLABEL_POLICYTYPE_BUFLEN];    /* policy type */
+    int enforcing;                                      /* 1 if security policy is being enforced for domain */
+} virDomainSecLabel;
+
+/**
+ * virDomainSecLabelPtr:
+ *
+ * a virDomainSecLabelPtr is a pointer to a virDomainSecLabel.
+ */
+typedef virDomainSecLabel *virDomainSecLabelPtr;
+
+/**
  * virNodeInfoPtr:
  *
  * a virNodeInfo is a structure filled by virNodeGetInfo() and providing
@@ -504,6 +551,8 @@ int                     virDomainSetMaxMemory   (virDomainPtr domain,
 int                     virDomainSetMemory      (virDomainPtr domain,
                                                  unsigned long memory);
 int                     virDomainGetMaxVcpus    (virDomainPtr domain);
+int                     virDomainGetSecLabel	(virDomainPtr domain,
+                                                 virDomainSecLabelPtr seclabel);
 
 /*
  * XML domain description
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index 8e24708..da955c2 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -58,6 +58,7 @@ typedef enum {
     VIR_FROM_STORAGE,   /* Error from storage driver */
     VIR_FROM_NETWORK,   /* Error from network config */
     VIR_FROM_DOMAIN,    /* Error from domain config */
+    VIR_FROM_SECLABEL,  /* Error from security labeling framework */
 } virErrorDomain;
 
 
@@ -148,6 +149,7 @@ typedef enum {
     VIR_WAR_NO_STORAGE, /* failed to start storage */
     VIR_ERR_NO_STORAGE_POOL, /* storage pool not found */
     VIR_ERR_NO_STORAGE_VOL, /* storage pool not found */
+    VIR_ERR_NO_SECLABEL_MODEL, /* security labeling model not found */
 } virErrorNumber;
 
 /**
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f671155..4a200cb 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -18,6 +18,8 @@ src/proxy_internal.c
 src/qemu_conf.c
 src/qemu_driver.c
 src/remote_internal.c
+src/seclabel.c
+src/seclabel_selinux.c
 src/sexpr.c
 src/storage_backend.c
 src/storage_backend_disk.c
diff --git a/python/generator.py b/python/generator.py
index c706b19..b95ac4f 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -332,6 +332,7 @@ skip_function = (
     'virCopyLastError', # Python API is called virGetLastError instead
     'virConnectOpenAuth', # Python C code is manually written
     'virDefaultErrorFunc', # Python virErrorFuncHandler impl calls this from C
+    'virDomainGetSecLabel', # Needs investigation...
 )
 
 
diff --git a/qemud/remote.c b/qemud/remote.c
index 72e064e..c3dc871 100644
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -1248,6 +1248,61 @@ remoteDispatchDomainGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
 }
 
 static int
+remoteDispatchDomainGetSeclabel (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                 struct qemud_client *client,
+                                 remote_message_header *req,
+                                 remote_domain_get_seclabel_args *args,
+                                 remote_domain_get_seclabel_ret *ret)
+{
+    virDomainPtr dom;
+    virDomainSecLabel seclabel;
+    CHECK_CONN(client);
+
+    dom = get_nonnull_domain (client->conn, args->dom);
+    if (dom == NULL) {
+        remoteDispatchError (client, req, "%s", _("domain not found"));
+        return -2;
+    }
+
+    memset (&seclabel, 0, sizeof seclabel);
+
+    if (virDomainGetSecLabel (dom, &seclabel) == -1) {
+        virDomainFree (dom);
+        remoteDispatchError (client, req, "%s", _("unable to get security label"));
+        return -1;
+    }
+
+    ret->label.label_len = strlen(seclabel.label) + 1;
+    if (VIR_ALLOC_N(ret->label.label_val, ret->label.label_len) < 0) {
+        virDomainFree (dom);
+        remoteDispatchError (client, req, "%s", strerror (errno));
+        return -2;
+    }
+    strcpy(ret->label.label_val, seclabel.label);
+
+    ret->model.model_len = strlen(seclabel.model) + 1;
+    if (VIR_ALLOC_N(ret->model.model_val, ret->model.model_len) < 0) {
+        virDomainFree (dom);
+        remoteDispatchError (client, req, "%s", strerror (errno));
+        return -2;
+    }
+    strcpy(ret->model.model_val, seclabel.model);
+
+    ret->policytype.policytype_len = strlen(seclabel.policytype) + 1;
+    if (VIR_ALLOC_N(ret->policytype.policytype_val, ret->policytype.policytype_len) < 0) {
+        virDomainFree (dom);
+        remoteDispatchError (client, req, "%s", strerror (errno));
+        return -2;
+    }
+    strcpy(ret->policytype.policytype_val, seclabel.policytype);
+
+    ret->enforcing = seclabel.enforcing;
+
+    virDomainFree(dom);
+    return 0;
+}
+
+static int
 remoteDispatchDomainGetOsType (struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client,
                                remote_message_header *req,
diff --git a/qemud/remote_dispatch_localvars.h b/qemud/remote_dispatch_localvars.h
index f46b493..fe55109 100644
--- a/qemud/remote_dispatch_localvars.h
+++ b/qemud/remote_dispatch_localvars.h
@@ -89,6 +89,8 @@ remote_domain_get_vcpus_ret lv_remote_domain_get_vcpus_ret;
 remote_domain_get_scheduler_parameters_args lv_remote_domain_get_scheduler_parameters_args;
 remote_domain_get_scheduler_parameters_ret lv_remote_domain_get_scheduler_parameters_ret;
 remote_node_get_info_ret lv_remote_node_get_info_ret;
+remote_domain_get_seclabel_args lv_remote_domain_get_seclabel_args;
+remote_domain_get_seclabel_ret lv_remote_domain_get_seclabel_ret;
 remote_network_lookup_by_name_args lv_remote_network_lookup_by_name_args;
 remote_network_lookup_by_name_ret lv_remote_network_lookup_by_name_ret;
 remote_domain_memory_peek_args lv_remote_domain_memory_peek_args;
diff --git a/qemud/remote_dispatch_proc_switch.h b/qemud/remote_dispatch_proc_switch.h
index 89296d7..52d1ce1 100644
--- a/qemud/remote_dispatch_proc_switch.h
+++ b/qemud/remote_dispatch_proc_switch.h
@@ -179,6 +179,15 @@ case REMOTE_PROC_DOMAIN_GET_SCHEDULER_TYPE:
         ret = (char *) &lv_remote_domain_get_scheduler_type_ret;
         memset (&lv_remote_domain_get_scheduler_type_ret, 0, sizeof lv_remote_domain_get_scheduler_type_ret);
         break;
+case REMOTE_PROC_DOMAIN_GET_SECLABEL:
+        fn = (dispatch_fn) remoteDispatchDomainGetSeclabel;
+        args_filter = (xdrproc_t) xdr_remote_domain_get_seclabel_args;
+        args = (char *) &lv_remote_domain_get_seclabel_args;
+        memset (&lv_remote_domain_get_seclabel_args, 0, sizeof lv_remote_domain_get_seclabel_args);
+        ret_filter = (xdrproc_t) xdr_remote_domain_get_seclabel_ret;
+        ret = (char *) &lv_remote_domain_get_seclabel_ret;
+        memset (&lv_remote_domain_get_seclabel_ret, 0, sizeof lv_remote_domain_get_seclabel_ret);
+        break;
 case REMOTE_PROC_DOMAIN_GET_VCPUS:
         fn = (dispatch_fn) remoteDispatchDomainGetVcpus;
         args_filter = (xdrproc_t) xdr_remote_domain_get_vcpus_args;
diff --git a/qemud/remote_dispatch_prototypes.h b/qemud/remote_dispatch_prototypes.h
index 3f4eb9f..2f38611 100644
--- a/qemud/remote_dispatch_prototypes.h
+++ b/qemud/remote_dispatch_prototypes.h
@@ -25,6 +25,7 @@ static int remoteDispatchDomainGetMaxVcpus (struct qemud_server *server, struct
 static int remoteDispatchDomainGetOsType (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_get_os_type_args *args, remote_domain_get_os_type_ret *ret);
 static int remoteDispatchDomainGetSchedulerParameters (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_get_scheduler_parameters_args *args, remote_domain_get_scheduler_parameters_ret *ret);
 static int remoteDispatchDomainGetSchedulerType (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_get_scheduler_type_args *args, remote_domain_get_scheduler_type_ret *ret);
+static int remoteDispatchDomainGetSeclabel (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_get_seclabel_args *args, remote_domain_get_seclabel_ret *ret);
 static int remoteDispatchDomainGetVcpus (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_get_vcpus_args *args, remote_domain_get_vcpus_ret *ret);
 static int remoteDispatchDomainInterfaceStats (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_interface_stats_args *args, remote_domain_interface_stats_ret *ret);
 static int remoteDispatchDomainLookupById (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_lookup_by_id_args *args, remote_domain_lookup_by_id_ret *ret);
diff --git a/qemud/remote_protocol.c b/qemud/remote_protocol.c
index 33a25e1..f8ccf71 100644
--- a/qemud/remote_protocol.c
+++ b/qemud/remote_protocol.c
@@ -1083,6 +1083,36 @@ xdr_remote_domain_get_max_vcpus_ret (XDR *xdrs, remote_domain_get_max_vcpus_ret
 }
 
 bool_t
+xdr_remote_domain_get_seclabel_args (XDR *xdrs, remote_domain_get_seclabel_args *objp)
+{
+
+         if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_seclabel_ret (XDR *xdrs, remote_domain_get_seclabel_ret *objp)
+{
+        char **objp_cpp1 = (char **) (void *) &objp->label.label_val;
+        char **objp_cpp2 = (char **) (void *) &objp->policytype.policytype_val;
+        char **objp_cpp0 = (char **) (void *) &objp->model.model_val;
+
+         if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->model.model_len, REMOTE_SECLABEL_MODEL_MAX,
+                sizeof (char), (xdrproc_t) xdr_char))
+                 return FALSE;
+         if (!xdr_array (xdrs, objp_cpp1, (u_int *) &objp->label.label_len, REMOTE_SECLABEL_LABEL_MAX,
+                sizeof (char), (xdrproc_t) xdr_char))
+                 return FALSE;
+         if (!xdr_array (xdrs, objp_cpp2, (u_int *) &objp->policytype.policytype_len, REMOTE_SECLABEL_POLICYTYPE_MAX,
+                sizeof (char), (xdrproc_t) xdr_char))
+                 return FALSE;
+         if (!xdr_int (xdrs, &objp->enforcing))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
 xdr_remote_domain_attach_device_args (XDR *xdrs, remote_domain_attach_device_args *objp)
 {
 
diff --git a/qemud/remote_protocol.h b/qemud/remote_protocol.h
index 0bf8b79..9a6b3ac 100644
--- a/qemud/remote_protocol.h
+++ b/qemud/remote_protocol.h
@@ -37,6 +37,9 @@ typedef remote_nonnull_string *remote_string;
 #define REMOTE_AUTH_TYPE_LIST_MAX 20
 #define REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX 65536
 #define REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX 65536
+#define REMOTE_SECLABEL_MODEL_MAX VIR_SECLABEL_MODEL_BUFLEN
+#define REMOTE_SECLABEL_LABEL_MAX VIR_SECLABEL_LABEL_BUFLEN
+#define REMOTE_SECLABEL_POLICYTYPE_MAX VIR_SECLABEL_POLICYTYPE_BUFLEN
 
 typedef char remote_uuid[VIR_UUID_BUFLEN];
 
@@ -589,6 +592,28 @@ struct remote_domain_get_max_vcpus_ret {
 };
 typedef struct remote_domain_get_max_vcpus_ret remote_domain_get_max_vcpus_ret;
 
+struct remote_domain_get_seclabel_args {
+        remote_nonnull_domain dom;
+};
+typedef struct remote_domain_get_seclabel_args remote_domain_get_seclabel_args;
+
+struct remote_domain_get_seclabel_ret {
+        struct {
+                u_int model_len;
+                char *model_val;
+        } model;
+        struct {
+                u_int label_len;
+                char *label_val;
+        } label;
+        struct {
+                u_int policytype_len;
+                char *policytype_val;
+        } policytype;
+        int enforcing;
+};
+typedef struct remote_domain_get_seclabel_ret remote_domain_get_seclabel_ret;
+
 struct remote_domain_attach_device_args {
         remote_nonnull_domain dom;
         remote_nonnull_string xml;
@@ -1189,6 +1214,7 @@ enum remote_procedure {
         REMOTE_PROC_NODE_GET_FREE_MEMORY = 102,
         REMOTE_PROC_DOMAIN_BLOCK_PEEK = 103,
         REMOTE_PROC_DOMAIN_MEMORY_PEEK = 104,
+        REMOTE_PROC_DOMAIN_GET_SECLABEL = 105,
 };
 typedef enum remote_procedure remote_procedure;
 
@@ -1308,6 +1334,8 @@ extern  bool_t xdr_remote_domain_get_vcpus_args (XDR *, remote_domain_get_vcpus_
 extern  bool_t xdr_remote_domain_get_vcpus_ret (XDR *, remote_domain_get_vcpus_ret*);
 extern  bool_t xdr_remote_domain_get_max_vcpus_args (XDR *, remote_domain_get_max_vcpus_args*);
 extern  bool_t xdr_remote_domain_get_max_vcpus_ret (XDR *, remote_domain_get_max_vcpus_ret*);
+extern  bool_t xdr_remote_domain_get_seclabel_args (XDR *, remote_domain_get_seclabel_args*);
+extern  bool_t xdr_remote_domain_get_seclabel_ret (XDR *, remote_domain_get_seclabel_ret*);
 extern  bool_t xdr_remote_domain_attach_device_args (XDR *, remote_domain_attach_device_args*);
 extern  bool_t xdr_remote_domain_detach_device_args (XDR *, remote_domain_detach_device_args*);
 extern  bool_t xdr_remote_domain_get_autostart_args (XDR *, remote_domain_get_autostart_args*);
@@ -1489,6 +1517,8 @@ extern bool_t xdr_remote_domain_get_vcpus_args ();
 extern bool_t xdr_remote_domain_get_vcpus_ret ();
 extern bool_t xdr_remote_domain_get_max_vcpus_args ();
 extern bool_t xdr_remote_domain_get_max_vcpus_ret ();
+extern bool_t xdr_remote_domain_get_seclabel_args ();
+extern bool_t xdr_remote_domain_get_seclabel_ret ();
 extern bool_t xdr_remote_domain_attach_device_args ();
 extern bool_t xdr_remote_domain_detach_device_args ();
 extern bool_t xdr_remote_domain_get_autostart_args ();
diff --git a/qemud/remote_protocol.x b/qemud/remote_protocol.x
index f1bd9ff..6170cd8 100644
--- a/qemud/remote_protocol.x
+++ b/qemud/remote_protocol.x
@@ -110,6 +110,21 @@ const REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX = 65536;
  */
 const REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX = 65536;
 
+/*
+ * Maximum length of a security label model field.
+ */
+const REMOTE_SECLABEL_MODEL_MAX = VIR_SECLABEL_MODEL_BUFLEN;
+
+/*
+ * Maximum length of a security label field.
+ */
+const REMOTE_SECLABEL_LABEL_MAX = VIR_SECLABEL_LABEL_BUFLEN;
+
+/*
+ * Maximum length of a security label policy type field.
+ */
+const REMOTE_SECLABEL_POLICYTYPE_MAX = VIR_SECLABEL_POLICYTYPE_BUFLEN;
+
 /* UUID.  VIR_UUID_BUFLEN definition comes from libvirt.h */
 typedef opaque remote_uuid[VIR_UUID_BUFLEN];
 
@@ -577,6 +592,17 @@ struct remote_domain_get_max_vcpus_ret {
     int num;
 };
 
+struct remote_domain_get_seclabel_args {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_get_seclabel_ret {
+    char model<REMOTE_SECLABEL_MODEL_MAX>;
+    char label<REMOTE_SECLABEL_LABEL_MAX>;
+    char policytype<REMOTE_SECLABEL_POLICYTYPE_MAX>;
+    int enforcing;
+};
+
 struct remote_domain_attach_device_args {
     remote_nonnull_domain dom;
     remote_nonnull_string xml;
@@ -1086,7 +1112,9 @@ enum remote_procedure {
     REMOTE_PROC_NODE_GET_FREE_MEMORY = 102,
 
     REMOTE_PROC_DOMAIN_BLOCK_PEEK = 103,
-    REMOTE_PROC_DOMAIN_MEMORY_PEEK = 104
+    REMOTE_PROC_DOMAIN_MEMORY_PEEK = 104,
+
+    REMOTE_PROC_DOMAIN_GET_SECLABEL = 105
 };
 
 /* Custom RPC structure. */
diff --git a/src/Makefile.am b/src/Makefile.am
index 5a769f8..758463c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -111,7 +111,7 @@ QEMU_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
 
@@ -132,6 +132,12 @@ STORAGE_HELPER_DISK_SOURCES =					\
 		parthelper.c
 
 
+# Security framework and drivers for various models
+SECURITY_DRIVER_SOURCES =					\
+		seclabel.h seclabel.c
+
+SECURITY_DRIVER_SELINUX_SOURCES =				\
+		seclabel_selinux.h seclabel_selinux.c
 
 #########################
 #
@@ -173,6 +179,7 @@ libvirt_la_SOURCES += $(NETWORK_DRIVER_SOURCES)
 endif
 libvirt_la_SOURCES += $(STORAGE_DRIVER_SOURCES)
 libvirt_la_SOURCES += $(STORAGE_DRIVER_FS_SOURCES)
+libvirt_la_SOURCES += $(SECURITY_DRIVER_SOURCES)
 
 if WITH_QEMU
 libvirt_la_SOURCES += $(QEMU_DRIVER_SOURCES)
@@ -193,6 +200,10 @@ endif
 if WITH_STORAGE_DISK
 libvirt_la_SOURCES += $(STORAGE_DRIVER_DISK_SOURCES)
 endif
+
+if HAVE_SELINUX
+libvirt_la_SOURCES += $(SECURITY_DRIVER_SELINUX_SOURCES)
+endif
 endif
 
 # Add all conditional sources just in case...
@@ -208,7 +219,9 @@ EXTRA_DIST +=							\
 		$(STORAGE_DRIVER_FS_SOURCES)			\
 		$(STORAGE_DRIVER_LVM_SOURCES)			\
 		$(STORAGE_DRIVER_ISCSI_SOURCES)			\
-		$(STORAGE_DRIVER_DISK_SOURCES)
+		$(STORAGE_DRIVER_DISK_SOURCES)			\
+		$(SECURITY_DRIVER_SOURCES)			\
+		$(SECURITY_DRIVER_SELINUX_SOURCES)
 
 
 libvirt_la_LIBADD = $(LIBXML_LIBS) $(GNUTLS_LIBS) $(SASL_LIBS) $(SELINUX_LIBS) \
diff --git a/src/domain_conf.c b/src/domain_conf.c
index 2bade8d..5154fac 100644
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -345,6 +345,18 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
     VIR_FREE(def);
 }
 
+void virDomainSecLabelDefFree(virDomainDefPtr def);
+
+void virDomainSecLabelDefFree(virDomainDefPtr def)
+{
+    if (def->seclabel.model)
+        VIR_FREE(def->seclabel.model);
+    if (def->seclabel.label)
+        VIR_FREE(def->seclabel.label);
+    if (def->seclabel.policytype)
+        VIR_FREE(def->seclabel.policytype);
+}
+
 void virDomainDefFree(virDomainDefPtr def)
 {
     unsigned int i;
@@ -403,6 +415,8 @@ void virDomainDefFree(virDomainDefPtr def)
     VIR_FREE(def->cpumask);
     VIR_FREE(def->emulator);
 
+    virDomainSecLabelDefFree(def);
+
     VIR_FREE(def);
 }
 
@@ -1628,6 +1642,61 @@ static int virDomainLifecycleParseXML(virConnectPtr conn,
     return 0;
 }
 
+static int
+virDomainSecLabelDefParseXMLString(virConnectPtr conn,
+                                   const char *str,
+                                   int maxlen,
+                                   const char *name,
+                                   char **to,
+                                   xmlXPathContextPtr ctxt)
+{
+    char *tmp = virXPathString(conn, str, ctxt);
+
+    if (tmp != NULL) {
+        if (strlen(tmp) >= maxlen) {
+            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                 _("\'%s\' longer than %d characters"),
+                                 name, maxlen);
+            return -1;
+        }
+        *to = tmp;
+    } else {
+        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                             _("\'%s\' missing"), name);
+        return -1;
+    }
+    return 0;
+}
+
+static int
+virDomainSecLabelDefParseXML(virConnectPtr conn,
+                             const virDomainDefPtr def,
+                             xmlXPathContextPtr ctxt)
+{
+    if (virXPathNode(conn, "./seclabel", ctxt) == NULL)
+        return 0;
+
+    if (virDomainSecLabelDefParseXMLString(conn, "string(./seclabel/@model)",
+                                          VIR_SECLABEL_MODEL_BUFLEN-1, "model",
+                                          &def->seclabel.model, ctxt) == -1)
+        goto error;
+
+    if (virDomainSecLabelDefParseXMLString(conn, "string(./seclabel/label[1])",
+                                          VIR_SECLABEL_LABEL_BUFLEN-1, "label",
+                                          &def->seclabel.label, ctxt) == -1)
+        goto error;
+
+    if (virDomainSecLabelDefParseXMLString(conn, "string(./seclabel/policytype[1])",
+                                          VIR_SECLABEL_POLICYTYPE_BUFLEN-1, "policytype",
+                                          &def->seclabel.policytype, ctxt) == -1)
+        goto error;
+
+    return 0;
+
+error:
+    virDomainSecLabelDefFree(def);
+    return -1;
+}
 
 virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn,
                                               const virDomainDefPtr def,
@@ -2187,6 +2256,10 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
     }
     VIR_FREE(nodes);
 
+    /* analysis of security label */
+    if (virDomainSecLabelDefParseXML(conn, def, ctxt) == -1)
+        goto error;
+
     return def;
 
 no_memory:
@@ -3179,6 +3252,14 @@ 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);
+        virBufferEscapeString(&buf, "    <policytype>%s</policytype>\n", def->seclabel.policytype);
+        virBufferAddLit(&buf, "  </seclabel>\n");
+    }
+
     virBufferAddLit(&buf, "</domain>\n");
 
     if (virBufferError(&buf))
diff --git a/src/domain_conf.h b/src/domain_conf.h
index 4d193f4..a8b5e01 100644
--- a/src/domain_conf.h
+++ b/src/domain_conf.h
@@ -389,6 +389,15 @@ struct _virDomainOSDef {
     char *bootloaderArgs;
 };
 
+/* Security label configuration for domain */
+typedef struct _virDomainSecLabelDef virDomainSecLabelDef;
+typedef virDomainSecLabelDef *virDomainSecLabelDefPtr;
+struct _virDomainSecLabelDef {
+    char *model;        /* name of security labeling model */
+    char *label;        /* security label string */
+    char *policytype;   /* policy type */
+};
+
 #define VIR_DOMAIN_CPUMASK_LEN 1024
 
 /* Guest VM main configuration */
@@ -446,6 +455,7 @@ struct _virDomainDef {
 
     /* Only 1 */
     virDomainChrDefPtr console;
+    virDomainSecLabelDef seclabel;
 };
 
 /* Guest VM runtime state */
diff --git a/src/driver.h b/src/driver.h
index 0540f80..fd7ebdc 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -182,6 +182,9 @@ typedef int
 typedef int
         (*virDrvDomainGetMaxVcpus)	(virDomainPtr domain);
 typedef int
+        (*virDrvDomainGetSecLabel)	(virDomainPtr domain,
+                                         virDomainSecLabelPtr seclabel);
+typedef int
         (*virDrvDomainAttachDevice)	(virDomainPtr domain,
                                          const char *xml);
 typedef int
@@ -330,6 +333,7 @@ struct _virDriver {
     virDrvDomainPinVcpu		domainPinVcpu;
     virDrvDomainGetVcpus		domainGetVcpus;
     virDrvDomainGetMaxVcpus		domainGetMaxVcpus;
+    virDrvDomainGetSecLabel     domainGetSecLabel;
     virDrvDomainDumpXML		domainDumpXML;
     virDrvListDefinedDomains	listDefinedDomains;
     virDrvNumOfDefinedDomains	numOfDefinedDomains;
diff --git a/src/libvirt.c b/src/libvirt.c
index ca2675a..3b90c37 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -3228,6 +3228,41 @@ virDomainGetMaxVcpus(virDomainPtr domain)
     return -1;
 }
 
+/**
+ * virDomainGetSecLabel:
+ * @domain: a domain object
+ * @vm: VM object (looked up by caller)
+ * @seclabel: pointer to a virDomainSecLabel structure
+ *
+ * Extract security label of an actice domain.
+ *
+ * Returns 0 in case of success, -1 in case of failure, and -2
+ * if the operation is not supported (caller decides if that's
+ * an error).
+ */
+int
+virDomainGetSecLabel(virDomainPtr domain, virDomainSecLabelPtr seclabel)
+{
+    virConnectPtr conn;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return -1;
+    }
+
+    if (seclabel == NULL) {
+        virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return -1;
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainGetSecLabel)
+        return conn->driver->domainGetSecLabel(domain, seclabel);
+
+    virLibConnWarning(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -2;
+}
 
 /**
  * virDomainAttachDevice:
diff --git a/src/libvirt_sym.version b/src/libvirt_sym.version
index 3cc4505..190abda 100644
--- a/src/libvirt_sym.version
+++ b/src/libvirt_sym.version
@@ -81,6 +81,8 @@
 
 	virDomainMigrate;
 
+	virDomainGetSecLabel;
+
 	virNetworkGetConnect;
 	virConnectNumOfNetworks;
 	virConnectListNetworks;
diff --git a/src/lxc_driver.c b/src/lxc_driver.c
index c598d1d..dd76a8a 100644
--- a/src/lxc_driver.c
+++ b/src/lxc_driver.c
@@ -1256,6 +1256,7 @@ static virDriver lxcDriver = {
     NULL, /* domainPinVcpu */
     NULL, /* domainGetVcpus */
     NULL, /* domainGetMaxVcpus */
+    NULL, /* domainGetSecLabel */
     lxcDomainDumpXML, /* domainDumpXML */
     lxcListDefinedDomains, /* listDefinedDomains */
     lxcNumDefinedDomains, /* numOfDefinedDomains */
diff --git a/src/openvz_driver.c b/src/openvz_driver.c
index b82d0df..4e3fa73 100644
--- a/src/openvz_driver.c
+++ b/src/openvz_driver.c
@@ -990,6 +990,7 @@ static virDriver openvzDriver = {
     NULL, /* domainPinVcpu */
     NULL, /* domainGetVcpus */
     openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */
+    NULL, /* domainGetSecLabel */
     openvzDomainDumpXML, /* domainDumpXML */
     openvzListDefinedDomains, /* listDomains */
     openvzNumDefinedDomains, /* numOfDomains */
diff --git a/src/qemu_conf.h b/src/qemu_conf.h
index cfd7d35..db4dbc2 100644
--- a/src/qemu_conf.h
+++ b/src/qemu_conf.h
@@ -31,6 +31,7 @@
 #include "capabilities.h"
 #include "network_conf.h"
 #include "domain_conf.h"
+#include "seclabel.h"
 
 #define qemudDebug(fmt, ...) do {} while(0)
 
@@ -63,6 +64,7 @@ struct qemud_driver {
     char *vncListen;
 
     virCapsPtr caps;
+    virSecLabelDriverPtr secLabelDriver;
 };
 
 
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 904fe00..2a27b93 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -64,6 +64,7 @@
 #include "memory.h"
 #include "uuid.h"
 #include "domain_conf.h"
+#include "seclabel.h"
 
 /* For storing short-lived temporary files. */
 #define TEMPDIR LOCAL_STATE_DIR "/cache/libvirt"
@@ -141,6 +142,30 @@ qemudAutostartConfigs(struct qemud_driver *driver) {
     }
 }
 
+static int
+qemudSecLabelInit(struct qemud_driver *qemud_drv)
+{
+    int ret;
+    virSecLabelDriverPtr seclabel_drv;
+
+    ret = virSecLabelDriverStartup(&seclabel_drv);
+    if (ret == -1) {
+        qemudLog(QEMUD_ERR, _("Failed to start security labeling driver"));
+        return -1;
+    }
+    if (ret == -2)
+        return 0;
+
+    qemud_drv->secLabelDriver = seclabel_drv;
+
+    qemudLog(QEMUD_DEBUG, "Initialized security labeling driver \'%s\' with "
+             "policy type \'%s\' in %s mode.\n", seclabel_drv->name,
+             virSecLabelDriverGetPolicyType(seclabel_drv),
+             virSecLabelDriverGetEnforcing(seclabel_drv) ? "enforcing" : "permissive");
+
+    return 0;
+}
+
 /**
  * qemudStartup:
  *
@@ -199,6 +224,11 @@ qemudStartup(void) {
     if ((qemu_driver->caps = qemudCapsInit()) == NULL)
         goto out_of_memory;
 
+    if (qemudSecLabelInit(qemu_driver) < 0) {
+        qemudShutdown();
+        return -1;
+    }
+
     if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
         qemudShutdown();
         return -1;
@@ -742,6 +772,15 @@ static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
     return -1;
 }
 
+static int qemudDomainSetSecLabel(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm)
+{
+    if (vm->def->seclabel.model != NULL)
+        if (driver->secLabelDriver && driver->secLabelDriver->domainSetLabel)
+            return driver->secLabelDriver->domainSetLabel(conn, driver->secLabelDriver,
+                                                          &vm->def->seclabel);
+    return 0;
+}
+
 static int qemudStartVMDaemon(virConnectPtr conn,
                               struct qemud_driver *driver,
                               virDomainObjPtr vm,
@@ -833,6 +872,16 @@ static int qemudStartVMDaemon(virConnectPtr conn,
         return -1;
     }
 
+    /*
+     * Set up the security label for the domain here, before doing
+     * too much else.
+     */
+    if (qemudDomainSetSecLabel(conn, driver, vm) < 0) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                         _("Failed to set security label"));
+        return -1;
+    }
+
     if (qemudExtractVersionInfo(emulator,
                                 NULL,
                                 &qemuCmdFlags) < 0) {
@@ -2098,7 +2147,47 @@ static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
     return ret;
 }
 
+static int qemudDomainGetSecLabel(virDomainPtr dom, virDomainSecLabelPtr seclabel)
+{
+    struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
+    virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    const char *type;
+
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+        virUUIDFormat(dom->uuid, uuidstr);
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+                         _("no domain with matching uuid '%s'"), uuidstr);
+        return -1;
+    }
+
+    if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
+                         _("unknown virt type in domain definition '%d'"),
+                         vm->def->virtType);
+        return -1;
+    }
+
+    /*
+     * Theoretically, the pid can be replaced during this operation and
+     * return the label of a different process.  If atomicity is needed,
+     * further validation will be required.
+     */
+    if (virDomainIsActive(vm)) {
+        if (driver->secLabelDriver && driver->secLabelDriver->domainGetLabel) {
+            if (driver->secLabelDriver->domainGetLabel(dom->conn, driver->secLabelDriver,
+                                                       vm, seclabel) == -1) {
+                qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
+                                 _("Failed to get security label"));
+                return -1;
+            }
+        }
+    }
+    return 0;
+}
 
+/* TODO: check seclabel restore */
 static int qemudDomainRestore(virConnectPtr conn,
                        const char *path) {
     struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
@@ -3174,6 +3263,7 @@ static virDriver qemuDriver = {
     NULL, /* domainGetVcpus */
 #endif
     qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */
+    qemudDomainGetSecLabel, /* domainGetSecLabel */
     qemudDomainDumpXML, /* domainDumpXML */
     qemudListDefinedDomains, /* listDomains */
     qemudNumDefinedDomains, /* numOfDomains */
diff --git a/src/remote_internal.c b/src/remote_internal.c
index 35b7b4b..bfb71b2 100644
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -1838,6 +1838,58 @@ remoteDomainGetMaxVcpus (virDomainPtr domain)
     return ret.num;
 }
 
+static int
+remoteDomainGetSecLabel (virDomainPtr domain, virDomainSecLabelPtr seclabel)
+{
+    remote_domain_get_seclabel_args args;
+    remote_domain_get_seclabel_ret ret;
+    int rv = 0;
+    GET_PRIVATE (domain->conn, -1);
+
+    make_nonnull_domain (&args.dom, domain);
+    memset (&ret, 0, sizeof ret);
+    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SECLABEL,
+              (xdrproc_t) xdr_remote_domain_get_seclabel_args, (char *)&args,
+              (xdrproc_t) xdr_remote_domain_get_seclabel_ret, (char *)&ret) == -1) {
+        return -1;
+    }
+
+    if (ret.policytype.policytype_val != NULL) {
+        if (strlen (ret.label.label_val) >= sizeof seclabel->label) {
+            errorf (domain->conn, VIR_ERR_RPC, _("security label exceeds maximum: %zd"),
+                    sizeof seclabel->label - 1);
+            rv = -1;
+            goto cleanup;
+        }
+
+        if (strlen (ret.model.model_val) >= sizeof seclabel->model) {
+            errorf (domain->conn, VIR_ERR_RPC, _("security model exceeds maximum: %zd"),
+                    sizeof seclabel->model - 1);
+            rv = -1;
+            goto cleanup;
+        }
+
+        if (strlen (ret.policytype.policytype_val) >= sizeof seclabel->policytype) {
+            errorf (domain->conn, VIR_ERR_RPC, _("security policytype exceeds maximum: %zd"),
+                    sizeof seclabel->policytype - 1);
+            rv = -1;
+            goto cleanup;
+        }
+
+        strcpy (seclabel->label, ret.label.label_val);
+        strcpy (seclabel->model, ret.model.model_val);
+        strcpy (seclabel->policytype, ret.policytype.policytype_val);
+        seclabel->enforcing = ret.enforcing;
+
+    cleanup:
+        free (ret.label.label_val);
+        free (ret.model.model_val);
+        free (ret.policytype.policytype_val);
+    }
+
+    return rv;
+}
+
 static char *
 remoteDomainDumpXML (virDomainPtr domain, int flags)
 {
@@ -4850,6 +4902,7 @@ static virDriver driver = {
     .domainPinVcpu = remoteDomainPinVcpu,
     .domainGetVcpus = remoteDomainGetVcpus,
     .domainGetMaxVcpus = remoteDomainGetMaxVcpus,
+    .domainGetSecLabel = remoteDomainGetSecLabel,
     .domainDumpXML = remoteDomainDumpXML,
     .listDefinedDomains = remoteListDefinedDomains,
     .numOfDefinedDomains = remoteNumOfDefinedDomains,
diff --git a/src/seclabel.c b/src/seclabel.c
new file mode 100644
index 0000000..ffe0c90
--- /dev/null
+++ b/src/seclabel.c
@@ -0,0 +1,130 @@
+/*
+ * 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 "seclabel.h"
+
+#if HAVE_SELINUX
+#include "seclabel_selinux.h"
+#endif
+
+static virSecLabelDriverPtr seclabel_drivers[] = {
+#ifdef HAVE_SELINUX
+    &virSELinuxSecLabelDriver,
+#endif
+};
+
+/*
+ * Probe each security labeling driver: each should perform a test to see if
+ * it should be loaded, e.g. if the currently active host security mechanism
+ * matches.  If the probe succeeds, initialize the driver and return it.
+ *
+ * Returns 0 on success, -1 on error, and -2 on no driver found (caller
+ * to determine if that's an error).
+ */
+int
+virSecLabelDriverStartup(virSecLabelDriverPtr * drv)
+{
+    unsigned int i;
+
+    for (i = 0; i < (sizeof(seclabel_drivers) / sizeof(seclabel_drivers[0])); i++) {
+        virSecLabelDriverPtr tmp = seclabel_drivers[i];
+
+        if (tmp->probe()) {
+            virSecLabelDriverInit(tmp);
+            if (tmp->open(NULL, tmp) == -1) {
+                return -1;
+            } else {
+                *drv = tmp;
+                break;
+            }
+        } else
+            return -2;
+    }
+    return 0;
+}
+
+void
+virSecLabelReportError(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_SECLABEL, code,
+                    VIR_ERR_ERROR, NULL, NULL, NULL, -1, -1, "%s",
+                    errorMessage);
+}
+
+/*
+ * Helpers
+ */
+void
+virSecLabelDriverSetEnforcing(virSecLabelDriverPtr drv, int enforcing)
+{
+    drv->_private.enforcing = enforcing;
+}
+
+int
+virSecLabelDriverGetEnforcing(virSecLabelDriverPtr drv)
+{
+    return drv->_private.enforcing;
+}
+
+void
+virSecLabelDriverInit(virSecLabelDriverPtr drv)
+{
+    memset(&drv->_private, 0, sizeof drv->_private);
+}
+
+int
+virSecLabelDriverSetPolicyType(virConnectPtr conn,
+                               virSecLabelDriverPtr drv,
+                               const char *policytype)
+{
+    if (strlen(policytype) >= VIR_SECLABEL_POLICYTYPE_BUFLEN) {
+        virSecLabelReportError(conn, VIR_ERR_ERROR,
+                               _("%s: policy type \'%s\' is "
+                               "longer than the maximum allowed length of %d"),
+                               __func__, policytype,
+                               VIR_SECLABEL_POLICYTYPE_BUFLEN - 1);
+        return -1;
+    }
+    strcpy(drv->_private.policytype, policytype);
+    return 0;
+}
+
+const char *
+virSecLabelDriverGetPolicyType(virSecLabelDriverPtr drv)
+{
+    return drv->_private.policytype;
+}
+
+void
+virSecLabelDriverSetInitialized(virSecLabelDriverPtr drv)
+{
+    drv->_private.initialized = 1;
+}
+
+const char *
+virSecLabelDriverGetModel(virSecLabelDriverPtr drv)
+{
+    return drv->name;
+}
diff --git a/src/seclabel.h b/src/seclabel.h
new file mode 100644
index 0000000..4dc602f
--- /dev/null
+++ b/src/seclabel.h
@@ -0,0 +1,68 @@
+/*
+ * 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_SECLABEL_H__
+#define __VIR_SECLABEL_H__
+
+#include "internal.h"
+#include "domain_conf.h"
+
+typedef struct _virSecLabelDriver virSecLabelDriver;
+typedef virSecLabelDriver *virSecLabelDriverPtr;
+typedef int (*virSecLabelDriverProbe) (void);
+typedef int (*virSecLabelDriverOpen) (virConnectPtr conn,
+                                      virSecLabelDriverPtr drv);
+typedef int (*virSecLabelDomainGetLabel) (virConnectPtr conn,
+                                          virSecLabelDriverPtr drv,
+                                          virDomainObjPtr vm,
+                                          virDomainSecLabelPtr sec);
+typedef int (*virSecLabelDomainSetLabel) (virConnectPtr conn,
+                                          virSecLabelDriverPtr drv,
+                                          virDomainSecLabelDefPtr secdef);
+
+struct _virSecLabelDriver {
+    const char *name;
+    virSecLabelDriverProbe probe;
+    virSecLabelDriverOpen open;
+    virSecLabelDomainGetLabel domainGetLabel;
+    virSecLabelDomainSetLabel domainSetLabel;
+
+    /*
+     * This is internally managed driver state and should only be accessed
+     * via helpers below.
+     */
+    struct {
+        int enforcing:1, initialized:1;
+        char policytype[VIR_SECLABEL_POLICYTYPE_BUFLEN];
+    } _private;
+};
+
+/* Global methods */
+int virSecLabelDriverStartup(virSecLabelDriverPtr * drv);
+
+void
+virSecLabelReportError(virConnectPtr conn, int code, const char *fmt, ...)
+    ATTRIBUTE_FORMAT(printf, 3, 4);
+
+/* Helpers */
+void virSecLabelDriverSetEnforcing(virSecLabelDriverPtr drv,
+                                   int enforcing);
+int virSecLabelDriverGetEnforcing(virSecLabelDriverPtr drv);
+void virSecLabelDriverInit(virSecLabelDriverPtr drv);
+int virSecLabelDriverSetPolicyType(virConnectPtr conn,
+                                   virSecLabelDriverPtr drv,
+                                   const char *policytype);
+const char *virSecLabelDriverGetPolicyType(virSecLabelDriverPtr drv);
+void virSecLabelDriverSetInitialized(virSecLabelDriverPtr drv);
+const char *virSecLabelDriverGetModel(virSecLabelDriverPtr drv);
+
+#endif /* __VIR_SECLABEL_H__ */
diff --git a/src/seclabel_selinux.c b/src/seclabel_selinux.c
new file mode 100644
index 0000000..4c67a7f
--- /dev/null
+++ b/src/seclabel_selinux.c
@@ -0,0 +1,132 @@
+/*
+ * 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>
+ *
+ * SELinux seclabel driver.
+ */
+#include <config.h>
+#include <selinux/selinux.h>
+
+#include "seclabel.h"
+#include "seclabel_selinux.h"
+
+static int
+SELinuxSecLabelDriverProbe(void)
+{
+    return is_selinux_enabled();
+}
+
+static int
+SELinuxSecLabelDriverOpen(virConnectPtr conn, virSecLabelDriverPtr drv)
+{
+    char *policytype;
+    int enforcing, ret;
+
+    if (selinux_getpolicytype(&policytype) == -1) {
+        virSecLabelReportError(conn, VIR_ERR_ERROR, _("%s: error calling "
+                               "selinux_getpolicytype(): %s"), __func__,
+                               strerror(errno));
+        return -1;
+    }
+
+    virSecLabelDriverSetPolicyType(conn, drv, policytype);
+
+    enforcing = security_getenforce();
+    if (enforcing == -1) {
+        virSecLabelReportError(conn, VIR_ERR_ERROR, _("%s: error calling "
+                               "security_getenforce(): %s"), __func__,
+                               strerror(errno));
+        ret = -1;
+        goto out_free;
+    }
+
+    virSecLabelDriverSetEnforcing(drv, enforcing);
+    ret = 0;
+
+  out_free:
+    free(policytype);
+    return ret;
+}
+
+static int
+SELinuxSecLabelDomainGetLabel(virConnectPtr conn, virSecLabelDriverPtr drv,
+                              virDomainObjPtr vm, virDomainSecLabelPtr sec)
+{
+    security_context_t ctx;
+    const char *p;
+
+    if (getpidcon(vm->pid, &ctx) == -1) {
+        virSecLabelReportError(conn, VIR_ERR_ERROR, _("%s: error calling "
+                               "getpidcon(): %s"), __func__,
+                               strerror(errno));
+        return -1;
+    }
+
+    if (strlen((char *) ctx) >= VIR_SECLABEL_LABEL_BUFLEN) {
+        virSecLabelReportError(conn, VIR_ERR_ERROR,
+                               _("%s: security label exceeds "
+                               "maximum length: %d"), __func__,
+                               VIR_SECLABEL_LABEL_BUFLEN - 1);
+        return -1;
+    }
+
+    strcpy(sec->label, (char *) ctx);
+    free(ctx);
+
+    p = virSecLabelDriverGetModel(drv);
+    if (strlen(p) >= VIR_SECLABEL_MODEL_BUFLEN) {
+        virSecLabelReportError(conn, VIR_ERR_ERROR,
+                               _("%s: security model exceeds "
+                               "maximum length: %d"), __func__,
+                               VIR_SECLABEL_MODEL_BUFLEN - 1);
+        return -1;
+    }
+    strcpy(sec->model, p);
+
+    p = virSecLabelDriverGetPolicyType(drv);
+    if (strlen(p) >= VIR_SECLABEL_POLICYTYPE_BUFLEN) {
+        virSecLabelReportError(conn, VIR_ERR_ERROR,
+                               _("%s: security polictype exceeds "
+                               "maximum length: %d"), __func__,
+                               VIR_SECLABEL_POLICYTYPE_BUFLEN - 1);
+        return -1;
+    }
+    strcpy(sec->policytype, p);
+
+    sec->enforcing = virSecLabelDriverGetEnforcing(drv);
+
+    return 0;
+}
+
+static int
+SELinuxSecLabelDomainSetLabel(virConnectPtr conn, virSecLabelDriverPtr drv,
+                              const virDomainSecLabelDefPtr secdef)
+{
+    /* TODO: verify DOI */
+
+    if (drv) { /* Shut up gcc for now... */ };
+
+    if (setexeccon(secdef->label) == -1) {
+        virSecLabelReportError(conn, VIR_ERR_ERROR,
+                               _("%s: unable to set security context "
+                               "'\%s\': %s"), __func__, secdef->label,
+                               strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+virSecLabelDriver virSELinuxSecLabelDriver = {
+    .name               = "selinux",
+    .probe              = SELinuxSecLabelDriverProbe,
+    .open               = SELinuxSecLabelDriverOpen,
+    .domainGetLabel     = SELinuxSecLabelDomainGetLabel,
+    .domainSetLabel     = SELinuxSecLabelDomainSetLabel,
+};
diff --git a/src/seclabel_selinux.h b/src/seclabel_selinux.h
new file mode 100644
index 0000000..20e575d
--- /dev/null
+++ b/src/seclabel_selinux.h
@@ -0,0 +1,18 @@
+/*
+ * 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_SECLABEL_SELINUX_H__
+#define __VIR_SECLABEL_SELINUX_H__
+
+extern virSecLabelDriver virSELinuxSecLabelDriver;
+
+#endif /* __VIR_SECLABEL_SELINUX_H__ */
diff --git a/src/storage_backend.c b/src/storage_backend.c
index de4efa7..df021d7 100644
--- a/src/storage_backend.c
+++ b/src/storage_backend.c
@@ -316,6 +316,7 @@ virStorageBackendUpdateVolInfoFD(virConnectPtr conn,
     VIR_FREE(vol->target.perms.label);
 
 #if HAVE_SELINUX
+/* XXX: make this a security driver call */
     if (fgetfilecon(fd, &filecon) == -1) {
         if (errno != ENODATA && errno != ENOTSUP) {
             virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
diff --git a/src/test.c b/src/test.c
index aab74e4..d6cfd3c 100644
--- a/src/test.c
+++ b/src/test.c
@@ -1530,6 +1530,7 @@ static virDriver testDriver = {
     NULL, /* domainPinVcpu */
     NULL, /* domainGetVcpus */
     NULL, /* domainGetMaxVcpus */
+    NULL, /* domainGetSecLabel */
     testDomainDumpXML, /* domainDumpXML */
     testListDefinedDomains, /* listDefinedDomains */
     testNumOfDefinedDomains, /* numOfDefinedDomains */
diff --git a/src/virsh.c b/src/virsh.c
index 89aa4fa..4c1208c 100644
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -971,6 +971,7 @@ static const vshCmdOptDef opts_undefine[] = {
     {NULL, 0, 0, NULL}
 };
 
+/* XXX MAC policy for defining & undefining domains ?? */
 static int
 cmdUndefine(vshControl *ctl, const vshCmd *cmd)
 {
@@ -1542,6 +1543,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd)
 {
     virDomainInfo info;
     virDomainPtr dom;
+    virDomainSecLabel seclabel;
     int ret = TRUE, autostart;
     unsigned int id;
     char *str, uuid[VIR_UUID_STRING_BUFLEN];
@@ -1600,6 +1602,20 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd)
                  autostart ? _("enable") : _("disable") );
     }
 
+    memset(&seclabel, 0, sizeof seclabel);
+
+    if (virDomainGetSecLabel(dom, &seclabel) == -1)
+        ret = FALSE;
+    else {
+        /*
+         * Security labels are only valid for active
+         * domains.
+         */
+        if (seclabel.model[0] != '\0')
+            vshPrint(ctl, "%-15s %s (%s/%s/%s)\n", _("Security label:"),
+                     seclabel.label, seclabel.model, seclabel.policytype,
+                     seclabel.enforcing ? "enforcing" : "permissive");
+    }
     virDomainFree(dom);
     return ret;
 }
diff --git a/src/virterror.c b/src/virterror.c
index 21c7339..3b4ce2c 100644
--- a/src/virterror.c
+++ b/src/virterror.c
@@ -310,6 +310,9 @@ virDefaultErrorFunc(virErrorPtr err)
         case VIR_FROM_DOMAIN:
             dom = "Domain Config ";
             break;
+        case VIR_FROM_SECLABEL:
+            dom = "Security Labeling ";
+            break;
 
     }
     if ((err->dom != NULL) && (err->code != VIR_ERR_INVALID_DOMAIN)) {
@@ -719,6 +722,12 @@ __virErrorMsg(virErrorNumber error, const char *info)
                 else
                         errmsg = _("Failed to find a storage driver: %s");
                 break;
+        case VIR_ERR_NO_SECLABEL_MODEL:
+            if (info == NULL)
+                errmsg = _("Security labeling model not found");
+            else
+                errmsg = _("Security labeling model not found: %s");
+            break;
     }
     return (errmsg);
 }
diff --git a/tests/daemon-conf b/tests/daemon-conf
index db1f0d3..5c09315 100755
--- a/tests/daemon-conf
+++ b/tests/daemon-conf
@@ -41,6 +41,9 @@ while :; do
   # Filter out this diagnostic.
   sed '/^Cannot set group when not running as root$/d' err > k && mv k err
 
+  # Filter out this diagnostic, too.
+  sed '/^Initialized security labeling driver/d' err > k && mv k err
+
   printf '%s\n\n' "remoteReadConfigFile: $f: $param_name: $msg" > expected-err
   diff -u expected-err err || fail=1
 

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-21  2:06 [RFC] sVirt v0.10 - initial prototype James Morris
@ 2008-10-21 13:57 ` Daniel J Walsh
  2008-10-21 16:22   ` Daniel P. Berrange
  2008-10-22  9:23   ` James Morris
  2008-10-21 17:17 ` Daniel P. Berrange
  2008-10-30  9:40 ` [libvirt] " Atsushi SAKAI
  2 siblings, 2 replies; 18+ messages in thread
From: Daniel J Walsh @ 2008-10-21 13:57 UTC (permalink / raw)
  To: James Morris
  Cc: libvir-list, Daniel P. Berrange, Daniel Veillard, Stephen Smalley,
	selinux

James Morris wrote:
> This is a request for comments on the initial prototype release of sVirt, 
> a project to add security labeling support to Linux-based virtualization.
> 
> Project page: 
>   http://www.selinuxproject.org/page/SVirt
> 
> Previous libvirt discussions:
> 
>   High-level requirements:
>     https://www.redhat.com/archives/libvir-list/2008-August/msg00255.html
> 
>   XML security labels:
>     https://www.redhat.com/archives/libvir-list/2008-August/msg00740.html
> 
> A patch for libvirt is attached; and also included in a release tarball at 
> http://namei.org/svirt/.  See 'readme.txt' there for more details on 
> building and running the code.
> 
> The purpose of this release is to establish a proof of concept of applying 
> security labels to VMs, and for discussion of the underlying technical 
> approach.
> 
> With this release, it is possible to define a security label for a 
> kvm/qemu domain in its XML configuration ('virsh edit'), launch the domain 
> and have it transition to the specified security label ('virsh start'), 
> then query the security label of the running domain ('virsh dominfo').
> 
> The following changes were made to libvirt:
> 
> 1. Implementing a pluggable security label driver framework;
> 
> 2. Implementing an SELinux security label driver for (1);
> 
> 3. Wiring the security label framework into the Qemu driver;
> 
> 4. Implementing basic libvirt API calls for initializing the driver, 
>    and getting/setting domain security labels;
> 
> 5. Extending the domain XML configuration to include security labels;
> 
> 6. Adding domain security label display/edit/dump support to virsh.
> 
> One of the design principles I've followed with this is to reduce or 
> eliminate configuration wherever possible.  If a variety of security 
> labeling drivers are present, libvirtd automatically detects which one to 
> enable and enables it.  e.g. if SELinux is enabled on the system, the 
> SELinux labeling driver is enabled automatically when livbirtd starts.
> 
> Another is to treat security labels as opaque unless they're actually 
> being used for security purposes (e.g. to launch the domain).  So, virsh 
> and the domain configuration code currently do not need to semantically 
> interpet security labels, just understand their format.  This should suit 
> the initial simple goal of isolated domains, which only requires security 
> labels to be distinct.
> 
> The domain security label configuration format is as follows:
> 
> # virsh dumpxml sys1
> <domain>
>     ....
>   <seclabel model='selinux'>
>     <label>system_u:system_r:virtd_t:s0</label>
>     <policytype>targeted</policytype>
>   </seclabel>
> </domain>
> 
> It's possible to query the security label of a running domain via virsh:
> 
> # virsh dominfo sys1
> Id:             1
> Name:           sys1
> UUID:           fa3c8e06-0877-2a08-06fd-f2479b7bacb4
> OS Type:        hvm
> State:          running
> CPU(s):         1
> CPU time:       11.4s
> Max memory:     524288 kB
> Used memory:    524288 kB
> Autostart:      disable
> Security label: system_u:system_r:virtd_t:s0 (selinux/targeted/enforcing)
> 
> The security label is deterimed via the new virDomainGetSecLabel() API 
> method, which is transported over RPC to the backend driver (qemu in this 
> case), and is entirely independent of the local security model, if any.  
> e.g. this command could be run remotely from an entirely different 
> platform: you just see what's happening on the remote system, as with 
> other attributes of the domain.
> 
> Feedback on the design thus far is sought before proceeding to more 
> comprehensive integration.
> 
> In particular, I'd be interested in any thoughts on the placement of the 
> security labeling driver within libvirt, as this seems to be the most 
> critical architectural issue (I've already refactored this aspect once).  
> 
> Currently, the idea is to attach the security labeling driver to the virt 
> driver, rather than implement it independently as a top-level component as 
> in the case of other types of drivers (e.g. storage).  This is because 
> process-based security labeling is highly dependent on the kind of 
> virtualization in use, and may not make sense at all in some cases (e.g. 
> when using a non-Linux hypervisor, or containers).
> 
> In the case of qemu, a security labeling driver is added to qemud:
> 
> @@ -63,6 +64,7 @@ struct qemud_driver {
>      char *vncListen;
>  
>      virCapsPtr caps;
> +    virSecLabelDriverPtr secLabelDriver;
>  };
> 
> and then initialized during qemud startup from qemudSecLabelInit().  
> 
> During initialization, any available security labeling drivers are probed, 
> and the first one which thinks it should be used is installed. Top-level 
> libvirt API calls are then dispatched to the active security labeling 
> driver via the backend virt driver, as necessary.
> 
> Note that the security labeling framework in this release is always 
> built-in -- it can be made a compile-time option later if desired.
> 
> Requirements not yet addressed include:
> - Labeling of resources and generally comprehensive labeling management
> - Automatic labeling (e.g. for the simple isolation use-case)
> - Integration of labeling support into higher-level management tools such 
>   as virt-manager
> - Integration with the audit subsystem to help with administration and 
>   debugging
> - Domain of interpretation (DOI) checking/translation
> - Python bindings
> 
> As mentioned, the goal at this stage is to get feedback on the underlying 
> design: comments welcome!
> 
> 
> - James
> 
Why do we care about the policy type?  Policy type is a fairly
meaningless object.  If you are trying to figure out if the host machine
is valid to run a virtual machine you should just check whether the type
is valid on the machine,  That way if I define minimum policy with virt
support on one host and targeted policy with virt support on another
machine, both would work.  Finally I think it might be ok for the
administrator to request that this virtual machine would only run on a
machine with SELinux in enforcing mode. For example if you had a fairly
untrusted virtual machine you would want to ensure that the machine was
enforcing SELinux before it got started.

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-21 13:57 ` Daniel J Walsh
@ 2008-10-21 16:22   ` Daniel P. Berrange
  2008-10-21 17:50     ` Daniel J Walsh
                       ` (2 more replies)
  2008-10-22  9:23   ` James Morris
  1 sibling, 3 replies; 18+ messages in thread
From: Daniel P. Berrange @ 2008-10-21 16:22 UTC (permalink / raw)
  To: Daniel J Walsh
  Cc: James Morris, libvir-list, Daniel Veillard, Stephen Smalley,
	selinux

On Tue, Oct 21, 2008 at 09:57:15AM -0400, Daniel J Walsh wrote:
> James Morris wrote:

[snip]

> > The domain security label configuration format is as follows:
> > 
> > # virsh dumpxml sys1
> > <domain>
> >     ....
> >   <seclabel model='selinux'>
> >     <label>system_u:system_r:virtd_t:s0</label>
> >     <policytype>targeted</policytype>
> >   </seclabel>
> > </domain>
> > 
> > It's possible to query the security label of a running domain via virsh:
> > 
> > # virsh dominfo sys1
> > Id:             1
> > Name:           sys1
> > UUID:           fa3c8e06-0877-2a08-06fd-f2479b7bacb4
> > OS Type:        hvm
> > State:          running
> > CPU(s):         1
> > CPU time:       11.4s
> > Max memory:     524288 kB
> > Used memory:    524288 kB
> > Autostart:      disable
> > Security label: system_u:system_r:virtd_t:s0 (selinux/targeted/enforcing)

[snip]

> Why do we care about the policy type?  Policy type is a fairly
> meaningless object.  If you are trying to figure out if the host machine
> is valid to run a virtual machine you should just check whether the type
> is valid on the machine,  That way if I define minimum policy with virt
> support on one host and targeted policy with virt support on another
> machine, both would work.  Finally I think it might be ok for the
> administrator to request that this virtual machine would only run on a
> machine with SELinux in enforcing mode. For example if you had a fairly
> untrusted virtual machine you would want to ensure that the machine was
> enforcing SELinux before it got started.

Who/what should be making such a policy decision though ? Seems like the
management app using libvirt would want to do that - perhaps even making
that decison before defining the existance of the VM on the target machine,
let alone starting it.

When migrating a VM from one host to another an application may also 
want to verify that the same policy is available on both the source
and target hosts. A simple 'targeted' vs 'enforcing'  string is likely
not sufficient in this context. This also feels like host level info,
rather per-VM.

I think the 'policytype' bit of the label may thus better live in the
host capabilities XML document, so you can query it independantly of
any virtual machine

eg perhaps something like

# virsh capabilities 
<capabilities>

  <host>
    <cpu>
      <arch>i686</arch>
    </cpu>
    <secpolicy model='selinux'>
       <type>targetted</type>
       <state>enforcing</state>
    </secpolicy>
  </host>

  .... snip rest of XML...

Is there any meaningful / useful policy version information that can
be included here ? Or policy feature bits

The VM config would thus only need

   <domain>
     ....
     <seclabel model='selinux'>
       <label>system_u:system_r:virtd_t:s0</label>
     </seclabel>
     ...
   </domain>


I should note that the domain XML format is representative of the config
for a particular deployment of a virtual machine onto a host. 

It is not a generic interchange format for 'appliances'. If you were
distributing an appliance, then the virt-image XML format would be used,
and this encodes information on pre-requisites for host capabilities. 

When an appliance is deployed as a virtual domain, the virt-image tool,
validate the virt-image XML pre-requisites, against the host capabilites
XML to determine if the host is suitable.

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 :|

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-21  2:06 [RFC] sVirt v0.10 - initial prototype James Morris
  2008-10-21 13:57 ` Daniel J Walsh
@ 2008-10-21 17:17 ` Daniel P. Berrange
  2008-10-22 10:01   ` James Morris
  2008-10-30  9:40 ` [libvirt] " Atsushi SAKAI
  2 siblings, 1 reply; 18+ messages in thread
From: Daniel P. Berrange @ 2008-10-21 17:17 UTC (permalink / raw)
  To: James Morris
  Cc: libvir-list, Daniel Veillard, Daniel J Walsh, Stephen Smalley,
	selinux

On Tue, Oct 21, 2008 at 01:06:17PM +1100, James Morris wrote:
> With this release, it is possible to define a security label for a 
> kvm/qemu domain in its XML configuration ('virsh edit'), launch the domain 
> and have it transition to the specified security label ('virsh start'), 
> then query the security label of the running domain ('virsh dominfo').
> 
> The following changes were made to libvirt:
> 
> 1. Implementing a pluggable security label driver framework;
> 
> 2. Implementing an SELinux security label driver for (1);
> 
> 3. Wiring the security label framework into the Qemu driver;
> 
> 4. Implementing basic libvirt API calls for initializing the driver, 
>    and getting/setting domain security labels;
> 
> 5. Extending the domain XML configuration to include security labels;
> 
> 6. Adding domain security label display/edit/dump support to virsh.
> 
> One of the design principles I've followed with this is to reduce or 
> eliminate configuration wherever possible.  If a variety of security 
> labeling drivers are present, libvirtd automatically detects which one to 
> enable and enables it.  e.g. if SELinux is enabled on the system, the 
> SELinux labeling driver is enabled automatically when livbirtd starts.
> 
> Another is to treat security labels as opaque unless they're actually 
> being used for security purposes (e.g. to launch the domain).  So, virsh 
> and the domain configuration code currently do not need to semantically 
> interpet security labels, just understand their format.  This should suit 
> the initial simple goal of isolated domains, which only requires security 
> labels to be distinct.
> 
> The domain security label configuration format is as follows:
> 
> # virsh dumpxml sys1
> <domain>
>     ....
>   <seclabel model='selinux'>
>     <label>system_u:system_r:virtd_t:s0</label>
>     <policytype>targeted</policytype>
>   </seclabel>
> </domain> 

As I mentioned in my reply to Dan Walsh's comments, I thing that the
policy type & its state (disabled, permissive, enforcing) is really a
property of the host, rather than the VM, and so should live in the
host capabilities XML document.

> Currently, the idea is to attach the security labeling driver to the virt 
> driver, rather than implement it independently as a top-level component as 
> in the case of other types of drivers (e.g. storage).  This is because 
> process-based security labeling is highly dependent on the kind of 
> virtualization in use, and may not make sense at all in some cases (e.g. 
> when using a non-Linux hypervisor, or containers).

Makes sense - the choice of hypervisor driver in libvirt determines
what security model has to be applied to the storage/network sub-drivers
in libvirt. So, eg if we activate Xen backend, we need to have an XSM
based implementation for the security model of both the Xen driver
and the storage backend.

> 
> In the case of qemu, a security labeling driver is added to qemud:
> 
> @@ -63,6 +64,7 @@ struct qemud_driver {
>      char *vncListen;
>  
>      virCapsPtr caps;
> +    virSecLabelDriverPtr secLabelDriver;
>  };
> 
> and then initialized during qemud startup from qemudSecLabelInit().  
> 
> During initialization, any available security labeling drivers are probed, 
> and the first one which thinks it should be used is installed. Top-level 
> libvirt API calls are then dispatched to the active security labeling 
> driver via the backend virt driver, as necessary.

That all makes sense to me - you'll also likely need to expose the
hypervisor driver's active security driver, to the storage & network
drivers. For that I reckon extending the 'virDriverPtr' struct to
add a internal only method

   virSecLabelDriverPtr (*getSecLabelDriver)(void);

would be a suitable approach. This would avoid the storage/network
drivers needing to know about the internal state of the HV driver.

> Note that the security labeling framework in this release is always 
> built-in -- it can be made a compile-time option later if desired.

As long as we can turn off the specific security model backends
that is sufficient - no need to be able to turn off the entire
security framework within libvirt - assuming of course everything
handles a 'NULL' secLabelDriver.

> Requirements not yet addressed include:
> - Labeling of resources and generally comprehensive labeling management
> - Automatic labeling (e.g. for the simple isolation use-case)
> - Integration of labeling support into higher-level management tools such 
>   as virt-manager
> - Integration with the audit subsystem to help with administration and 
>   debugging
> - Domain of interpretation (DOI) checking/translation
> - Python bindings
> 
> As mentioned, the goal at this stage is to get feedback on the underlying 
> design: comments welcome!

Looking at it from a libvirt architecture POV, i think its all basically
a sane approach. It appears, so far, to be generic enough that we could 
plug into an alternate XSM based impl for the Xen world, or delegate
to whatever APIs something like VMWare / Hyper-V might provide.

> diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
> index 35b80d0..58ded58 100644
> --- a/include/libvirt/libvirt.h
> +++ b/include/libvirt/libvirt.h
> @@ -111,6 +111,53 @@ typedef enum {
>  } virDomainCreateFlags;
>  
>  /**
> + * VIR_SECLABEL_LABEL_BUFLEN:
> + *
> + * Macro providing the maximum length of the virDomainSecLabel
> + * label string.  Note that this value is based on that used
> + * by Labeled NFS.
> + */
> +#define VIR_SECLABEL_LABEL_BUFLEN (4096 + 1)
> +
> +/**
> + * VIR_SECLABEL_MODEL_BUFLEN:
> + *
> + * Macro providing the maximum length of the virDomainSecLabel
> + * model string.
> + */
> +#define VIR_SECLABEL_MODEL_BUFLEN (256 + 1)
> +
> +/**
> + * VIR_SECLABEL_POLICYTYPE_BUFLEN:
> + *
> + * Macro providing the maximum length of the virDomainSecLabel
> + * policy string.
> + */
> +#define VIR_SECLABEL_POLICYTYPE_BUFLEN (256 + 1)
> +
> +/**
> + * virDomainSecLabel:
> + *
> + * a virDomainSecLabel is a structure filled by virDomainGetSecLabel(),
> + * providing the security label and associated attributes for the specified
> + * domain.
> + *
> + */
> +typedef struct _virDomainSecLabel {
> +    char model[VIR_SECLABEL_MODEL_BUFLEN];              /* name of security labeling model */
> +    char label[VIR_SECLABEL_LABEL_BUFLEN];              /* security label string */
> +    char policytype[VIR_SECLABEL_POLICYTYPE_BUFLEN];    /* policy type */
> +    int enforcing;                                      /* 1 if security policy is being enforced for domain */
> +} virDomainSecLabel;

The policytype/model would seem redundant here as per-host attributes ?

I guess since SELinux gained ability to specify that individual security 
domains are permissive, we do arguably still need an explicit flag 
'enforcing' flag here, independantly of the global per-host 'enforcing' 
vs 'permissive' flag.

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 :|

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-21 16:22   ` Daniel P. Berrange
@ 2008-10-21 17:50     ` Daniel J Walsh
  2008-10-22  9:51       ` Daniel P. Berrange
  2008-10-22  9:50     ` James Morris
  2008-10-29 21:51     ` James Morris
  2 siblings, 1 reply; 18+ messages in thread
From: Daniel J Walsh @ 2008-10-21 17:50 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: James Morris, libvir-list, Daniel Veillard, Stephen Smalley,
	selinux

Daniel P. Berrange wrote:
> On Tue, Oct 21, 2008 at 09:57:15AM -0400, Daniel J Walsh wrote:
>> James Morris wrote:
> 
> [snip]
> 
>>> The domain security label configuration format is as follows:
>>>
>>> # virsh dumpxml sys1
>>> <domain>
>>>     ....
>>>   <seclabel model='selinux'>
>>>     <label>system_u:system_r:virtd_t:s0</label>
>>>     <policytype>targeted</policytype>
>>>   </seclabel>
>>> </domain>
>>>
>>> It's possible to query the security label of a running domain via virsh:
>>>
>>> # virsh dominfo sys1
>>> Id:             1
>>> Name:           sys1
>>> UUID:           fa3c8e06-0877-2a08-06fd-f2479b7bacb4
>>> OS Type:        hvm
>>> State:          running
>>> CPU(s):         1
>>> CPU time:       11.4s
>>> Max memory:     524288 kB
>>> Used memory:    524288 kB
>>> Autostart:      disable
>>> Security label: system_u:system_r:virtd_t:s0 (selinux/targeted/enforcing)
> 
> [snip]
> 
>> Why do we care about the policy type?  Policy type is a fairly
>> meaningless object.  If you are trying to figure out if the host machine
>> is valid to run a virtual machine you should just check whether the type
>> is valid on the machine,  That way if I define minimum policy with virt
>> support on one host and targeted policy with virt support on another
>> machine, both would work.  Finally I think it might be ok for the
>> administrator to request that this virtual machine would only run on a
>> machine with SELinux in enforcing mode. For example if you had a fairly
>> untrusted virtual machine you would want to ensure that the machine was
>> enforcing SELinux before it got started.
> 
> Who/what should be making such a policy decision though ? Seems like the
> management app using libvirt would want to do that - perhaps even making
> that decison before defining the existance of the VM on the target machine,
> let alone starting it.
> 
> When migrating a VM from one host to another an application may also 
> want to verify that the same policy is available on both the source
> and target hosts. A simple 'targeted' vs 'enforcing'  string is likely
> not sufficient in this context. This also feels like host level info,
> rather per-VM.
> 
> I think the 'policytype' bit of the label may thus better live in the
> host capabilities XML document, so you can query it independantly of
> any virtual machine
> 
> eg perhaps something like
> 
> # virsh capabilities 
> <capabilities>
> 
>   <host>
>     <cpu>
>       <arch>i686</arch>
>     </cpu>
>     <secpolicy model='selinux'>
>        <type>targetted</type>
>        <state>enforcing</state>
>     </secpolicy>
>   </host>
> 
>   .... snip rest of XML...
> 
> Is there any meaningful / useful policy version information that can
> be included here ? Or policy feature bits
> 
> The VM config would thus only need
> 
>    <domain>
>      ....
>      <seclabel model='selinux'>
>        <label>system_u:system_r:virtd_t:s0</label>
>      </seclabel>
>      ...
>    </domain>
> 
> 
> I should note that the domain XML format is representative of the config
> for a particular deployment of a virtual machine onto a host. 
> 
> It is not a generic interchange format for 'appliances'. If you were
> distributing an appliance, then the virt-image XML format would be used,
> and this encodes information on pre-requisites for host capabilities. 
> 
> When an appliance is deployed as a virtual domain, the virt-image tool,
> validate the virt-image XML pre-requisites, against the host capabilites
> XML to determine if the host is suitable.
> 
> Daniel
Again targeted means nothing.  It is just an arbitrary name given to a
policy package. So I don't see why it should be mentioned anywhere.

I think the existance of the kernel policy which understands what a
system_u:system_r:virtd_t:s0 is what is important.

Again, I could have a three host machines each one with a different
policy package say targeted, mls and overt policy package.  If all three
understand what a system_u:system_r:virtd_t:s0 type is, then all three
could run the image.

Having two machine with a "targeted" policy on them does nothing to
assure that a processs labeled system_u:system_r:virtd_t:s0
 can run.

As far as enforcing mode is concerned, I thought that you could require
that this virtual machine could only run on machines with SELinux in
enforcing mode. so wouldn't that be associated with the virtual machine?

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-21 13:57 ` Daniel J Walsh
  2008-10-21 16:22   ` Daniel P. Berrange
@ 2008-10-22  9:23   ` James Morris
  2008-10-23 12:05     ` Paul Moore
  1 sibling, 1 reply; 18+ messages in thread
From: James Morris @ 2008-10-22  9:23 UTC (permalink / raw)
  To: Daniel J Walsh
  Cc: libvir-list, Daniel P. Berrange, Daniel Veillard, Stephen Smalley,
	selinux

On Tue, 21 Oct 2008, Daniel J Walsh wrote:

> Why do we care about the policy type?  Policy type is a fairly
> meaningless object.  If you are trying to figure out if the host machine
> is valid to run a virtual machine you should just check whether the type
> is valid on the machine,  That way if I define minimum policy with virt
> support on one host and targeted policy with virt support on another
> machine, both would work.  

We need a way to indicate how to interpret the meaning of labels, which 
may vary depending on how policy has been implemented and deployed within 
a specific administrative boundary.  Keep in mind also that this API needs 
to be useable with non-SELinux security schemes, although, in any case, 
just because a label is technically valid on a system, doesn't mean that 
the meaning is understood.  e.g. "virt_image_t:s0" on a targeted system 
could mean something radically different to "virt_image_t:s0" on an MLS 
system, where, say, "s0" might mean "top secret" instead of "nothing".

Perhaps we should call this element "doi" (Domain of Interpretation) 
instead of "policytype", in keeping with existing similar security 
labeling, and not tied in name to the SELinux polictype configuration 
variable.

I thought the SELinux policytype in this case would be a useful starting 
point for the DOI, although the truth is that this needs to be entirely 
administratively managed.  We can't predict where administrative security 
boundaries will be or how the user will represent them.  Possibile DOI 
schemes include domain name, policy package+version names, existing 
kerberos realms etc.

As this will be a long-lasting API, we need to build support for DOI in 
now, and annotate where the DOI should be considered.  e.g.

- A server should only launch a domain if the domain's label is bound to a 
  an appropriate DOI;

- When displaying security labels remotely, the DOI bound to the label 
  should be displayed with the label (or translate the label, if
  appropriate).

For a default value, I suggest we use the string "local", which means that 
the label only has significance on the local system where the domain is 
running.  Anything beyond that needs to be explicitly configured by the 
admin.

> Finally I think it might be ok for the administrator to request that 
> this virtual machine would only run on a machine with SELinux in 
> enforcing mode. For example if you had a fairly untrusted virtual 
> machine you would want to ensure that the machine was enforcing SELinux 
> before it got started.

Ok, so the domain configuration could have an element like:

  <enforce>yes</enforce>

which means that label security policy must be applied.

The security label for the domain would now look like:

  <seclabel model='selinux'>
    <label>system_u:system_r:virtd_t:s0</label>
    <doi>local</doi>
    <enforce>no</enforce>
  </seclabel>



- James
-- 
James Morris
<jmorris@namei.org>

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-21 16:22   ` Daniel P. Berrange
  2008-10-21 17:50     ` Daniel J Walsh
@ 2008-10-22  9:50     ` James Morris
  2008-10-22 10:03       ` Daniel P. Berrange
  2008-10-29 21:51     ` James Morris
  2 siblings, 1 reply; 18+ messages in thread
From: James Morris @ 2008-10-22  9:50 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Daniel J Walsh, libvir-list, Daniel Veillard, Stephen Smalley,
	selinux

On Tue, 21 Oct 2008, Daniel P. Berrange wrote:

> I should note that the domain XML format is representative of the config
> for a particular deployment of a virtual machine onto a host. 
> 
> It is not a generic interchange format for 'appliances'. If you were
> distributing an appliance, then the virt-image XML format would be used,
> and this encodes information on pre-requisites for host capabilities. 
> 
> When an appliance is deployed as a virtual domain, the virt-image tool,
> validate the virt-image XML pre-requisites, against the host capabilites
> XML to determine if the host is suitable.

As you mention in a later email, enforcing mode can be set on a 
per-process (domain) basis, so for the case of domain labeling, the 
current enforcing status needs to be bound to the domain.

In terms of migration and provisioning, we need to consider several issues 
in more detail (some perhaps later), e.g.:

- It should be possible to migrate an "isolated" domain between different 
  types of security models if each supports it (e.g. from Smack to 
  SELinux);

- How do we handle different types of virtualization running on the same 
  host, e.g. qemu domains running inside containers?

- Policy for import and export of domains, including translation of 
  labels when imported.

Initially, though, perhaps just stick with the simplest case of listing 
which security models and DOIs are supported, and I think we should stick 
with 'seclabel' rather than introduce 'secpolicy'.

  <host>
     ...
     <seclabel model='selinux'>
       <doi>engineering.example.com.</doi>
       <!-- any other supported DOIs... -->
       <enforcing>yes</enforcing>
     </seclabel>

     <!-- any other active security labeling models ... -->

  </host>




-- 
James Morris
<jmorris@namei.org>

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-21 17:50     ` Daniel J Walsh
@ 2008-10-22  9:51       ` Daniel P. Berrange
  0 siblings, 0 replies; 18+ messages in thread
From: Daniel P. Berrange @ 2008-10-22  9:51 UTC (permalink / raw)
  To: Daniel J Walsh
  Cc: James Morris, libvir-list, Daniel Veillard, Stephen Smalley,
	selinux

On Tue, Oct 21, 2008 at 01:50:20PM -0400, Daniel J Walsh wrote:
> Daniel P. Berrange wrote:
> > On Tue, Oct 21, 2008 at 09:57:15AM -0400, Daniel J Walsh wrote:
> >> James Morris wrote:
> > I think the 'policytype' bit of the label may thus better live in the
> > host capabilities XML document, so you can query it independantly of
> > any virtual machine
> > 
> > eg perhaps something like
> > 
> > # virsh capabilities 
> > <capabilities>
> > 
> >   <host>
> >     <cpu>
> >       <arch>i686</arch>
> >     </cpu>
> >     <secpolicy model='selinux'>
> >        <type>targetted</type>
> >        <state>enforcing</state>
> >     </secpolicy>
> >   </host>
> > 
> >   .... snip rest of XML...
> > 
> > Is there any meaningful / useful policy version information that can
> > be included here ? Or policy feature bits
> > 
> > The VM config would thus only need
> > 
> >    <domain>
> >      ....
> >      <seclabel model='selinux'>
> >        <label>system_u:system_r:virtd_t:s0</label>
> >      </seclabel>
> >      ...
> >    </domain>
> > 
> > 
> > I should note that the domain XML format is representative of the config
> > for a particular deployment of a virtual machine onto a host. 
> > 
> > It is not a generic interchange format for 'appliances'. If you were
> > distributing an appliance, then the virt-image XML format would be used,
> > and this encodes information on pre-requisites for host capabilities. 
> > 
> > When an appliance is deployed as a virtual domain, the virt-image tool,
> > validate the virt-image XML pre-requisites, against the host capabilites
> > XML to determine if the host is suitable.
> > 
> > Daniel
> Again targeted means nothing.  It is just an arbitrary name given to a
> policy package. So I don't see why it should be mentioned anywhere.
> 
> I think the existance of the kernel policy which understands what a
> system_u:system_r:virtd_t:s0 is what is important.
> 
> Again, I could have a three host machines each one with a different
> policy package say targeted, mls and overt policy package.  If all three
> understand what a system_u:system_r:virtd_t:s0 type is, then all three
> could run the image.

I guess my point was that we need a way to determine whether the policy 
on any machine is suitable for running a VM, before placing the VM on 
that host. In the context of a data center mgmt app we can have 100's or
1000's of possible virtualization enabled hosts. Not all of these
hosts will be providing the same level of functionality / same versions
of software, including selinux policy. 

So before starting a VM, the mgmt app needs to be able to make a reasonably
accurate decision about what host will support the VM's requirements
for SELinux policy capabilities. We can't just pick one at random, try to
start if and see if the kernel complains that 'system_u:system_r:virtd_t:s0'
doesn't exist in its policy.

> Having two machine with a "targeted" policy on them does nothing to
> assure that a processs labeled system_u:system_r:virtd_t:s0
> can run.

It wasn't intended to be a guarentee - its basically metadata to help the
admin / mgmt app pick a suitable virtualization host from amongst their
data center of 100's of machine. 

Maybe exposing the policytype 'targetted' is the wrong thing to be
considering for this purpose. Perhaps we should instead provide an API
to let you query the full list of all defined security domains, roles
and users. Basically enough info to let you validate whether the label
'system_u:system_r:virtd_t:s0' is likely to be supported. NB I use the
word 'likely' here - we don't need an absolute guarentee - we just need
to be able to make a reasonable choice of hosts & if it fails it can be
re-placed elsewhere.

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 :|

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-21 17:17 ` Daniel P. Berrange
@ 2008-10-22 10:01   ` James Morris
  0 siblings, 0 replies; 18+ messages in thread
From: James Morris @ 2008-10-22 10:01 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: libvir-list, Daniel Veillard, Daniel J Walsh, Stephen Smalley,
	selinux

On Tue, 21 Oct 2008, Daniel P. Berrange wrote:

> As I mentioned in my reply to Dan Walsh's comments, I thing that the
> policy type & its state (disabled, permissive, enforcing) is really a
> property of the host, rather than the VM, and so should live in the
> host capabilities XML document.

I think we need to differentiate between what the host is capable of 
supporting (e.g. multiple virt schemes with different security models, or 
even emulating/translating other security models), and what the current 
label on the domain actually is.  In the latter case, we need to bind the 
DOI, enforcing state and security model to the domain security label.

> That all makes sense to me - you'll also likely need to expose the
> hypervisor driver's active security driver, to the storage & network
> drivers. For that I reckon extending the 'virDriverPtr' struct to
> add a internal only method
> 
>    virSecLabelDriverPtr (*getSecLabelDriver)(void);
> 
> would be a suitable approach. This would avoid the storage/network
> drivers needing to know about the internal state of the HV driver.

Ok, I need to investigate this further.


> > +typedef struct _virDomainSecLabel {
> > +    char model[VIR_SECLABEL_MODEL_BUFLEN];              /* name of security labeling model */
> > +    char label[VIR_SECLABEL_LABEL_BUFLEN];              /* security label string */
> > +    char policytype[VIR_SECLABEL_POLICYTYPE_BUFLEN];    /* policy type */
> > +    int enforcing;                                      /* 1 if security policy is being enforced for domain */
> > +} virDomainSecLabel;
> 
> The policytype/model would seem redundant here as per-host attributes ?

As mentioned, I think we need to differentiate host capabilities from 
specific security labeling state for a domain on that host.

> I guess since SELinux gained ability to specify that individual security 
> domains are permissive, we do arguably still need an explicit flag 
> 'enforcing' flag here, independantly of the global per-host 'enforcing' 
> vs 'permissive' flag.

Yep.


- James
-- 
James Morris
<jmorris@namei.org>

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-22  9:50     ` James Morris
@ 2008-10-22 10:03       ` Daniel P. Berrange
  2008-10-22 10:05         ` James Morris
  0 siblings, 1 reply; 18+ messages in thread
From: Daniel P. Berrange @ 2008-10-22 10:03 UTC (permalink / raw)
  To: James Morris
  Cc: Daniel J Walsh, libvir-list, Daniel Veillard, Stephen Smalley,
	selinux

On Wed, Oct 22, 2008 at 08:50:19PM +1100, James Morris wrote:
> On Tue, 21 Oct 2008, Daniel P. Berrange wrote:
> 
> > I should note that the domain XML format is representative of the config
> > for a particular deployment of a virtual machine onto a host. 
> > 
> > It is not a generic interchange format for 'appliances'. If you were
> > distributing an appliance, then the virt-image XML format would be used,
> > and this encodes information on pre-requisites for host capabilities. 
> > 
> > When an appliance is deployed as a virtual domain, the virt-image tool,
> > validate the virt-image XML pre-requisites, against the host capabilites
> > XML to determine if the host is suitable.
> 
> As you mention in a later email, enforcing mode can be set on a 
> per-process (domain) basis, so for the case of domain labeling, the 
> current enforcing status needs to be bound to the domain.
> 
> In terms of migration and provisioning, we need to consider several issues 
> in more detail (some perhaps later), e.g.:
> 
> - It should be possible to migrate an "isolated" domain between different 
>   types of security models if each supports it (e.g. from Smack to 
>   SELinux);
> 
> - How do we handle different types of virtualization running on the same 
>   host, e.g. qemu domains running inside containers?

The data in the host capability XML is interpreted wrt the hypervisor 
connection URI you gave to virConnectPtr.

So if you open two libvirt connections, one with qemu:///system and
one with 'xen:///' on the same physical host, it is expected you will
see alternative views of that host. 

As just one example, if you opened 'qemu:///system' on a Xen enabled
host you'd only see a view of the world that covers the hardware 
available to Domain-0. This can be a subset of the hardware seen by
the hypervisor itself. If you opened 'xen:///' then you'd see the
full view.

So, what this means for security models - if you opened 'qemu:///system'
on a Xen enabled host you'd likely see a SELinux security model, whereas
'xen:///' would likely show you an XSM security model.

That said in normal circumstances we don't expect that people will 
use multiple different virtualization technologies within the context
of a single OS instance. You may however see nested virtualization,
eg, a Fedora 9 KVM host, runs a RHEL-5 xen guest, which runs a 
Windows guest.  There are even patches for KVM to let it expose
SVM hardware virt to the guests.

libvirt does not try to track this nesting explicitly - its viewpoint
is always limited to a single hypervisor connection. The intent is
that libvirt provides enough metadata, to allow an external mgmt
application to build up a complete 'world view' of all its data 
center, correlating guests & hosts, primarily via the UUID.

> - Policy for import and export of domains, including translation of 
>   labels when imported.
> 
> Initially, though, perhaps just stick with the simplest case of listing 
> which security models and DOIs are supported, and I think we should stick 
> with 'seclabel' rather than introduce 'secpolicy'.
> 
>   <host>
>      ...
>      <seclabel model='selinux'>
>        <doi>engineering.example.com.</doi>
>        <!-- any other supported DOIs... -->
>        <enforcing>yes</enforcing>
>      </seclabel>
> 
>      <!-- any other active security labeling models ... -->
> 
>   </host>

I think to start with we probably just assume a single security
labelling model per hypervisor connection. If a single host
happened to have multiple models, I believe each model would
likely be scoped to a specific hypervisor on the host.

Regards,
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 :|

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-22 10:03       ` Daniel P. Berrange
@ 2008-10-22 10:05         ` James Morris
  0 siblings, 0 replies; 18+ messages in thread
From: James Morris @ 2008-10-22 10:05 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Daniel J Walsh, libvir-list, Daniel Veillard, Stephen Smalley,
	selinux

On Wed, 22 Oct 2008, Daniel P. Berrange wrote:


> I think to start with we probably just assume a single security
> labelling model per hypervisor connection. If a single host
> happened to have multiple models, I believe each model would
> likely be scoped to a specific hypervisor on the host.

I would expect that, too.


-- 
James Morris
<jmorris@namei.org>

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-22  9:23   ` James Morris
@ 2008-10-23 12:05     ` Paul Moore
  2008-10-28 21:42       ` James Morris
  0 siblings, 1 reply; 18+ messages in thread
From: Paul Moore @ 2008-10-23 12:05 UTC (permalink / raw)
  To: James Morris
  Cc: Daniel J Walsh, libvir-list, Daniel P. Berrange, Daniel Veillard,
	Stephen Smalley, selinux

On Wednesday 22 October 2008 5:23:45 am James Morris wrote:
> On Tue, 21 Oct 2008, Daniel J Walsh wrote:
> > Why do we care about the policy type?  Policy type is a fairly
> > meaningless object.  If you are trying to figure out if the host
> > machine is valid to run a virtual machine you should just check
> > whether the type is valid on the machine,  That way if I define
> > minimum policy with virt support on one host and targeted policy
> > with virt support on another machine, both would work.
>
> We need a way to indicate how to interpret the meaning of labels,
> which may vary depending on how policy has been implemented and
> deployed within a specific administrative boundary.  Keep in mind
> also that this API needs to be useable with non-SELinux security
> schemes, although, in any case, just because a label is technically
> valid on a system, doesn't mean that the meaning is understood.  e.g.
> "virt_image_t:s0" on a targeted system could mean something radically
> different to "virt_image_t:s0" on an MLS system, where, say, "s0"
> might mean "top secret" instead of "nothing".
>
> Perhaps we should call this element "doi" (Domain of Interpretation)
> instead of "policytype", in keeping with existing similar security
> labeling, and not tied in name to the SELinux polictype configuration
> variable.
>
> I thought the SELinux policytype in this case would be a useful
> starting point for the DOI, although the truth is that this needs to
> be entirely administratively managed.  We can't predict where
> administrative security boundaries will be or how the user will
> represent them.  Possibile DOI schemes include domain name, policy
> package+version names, existing kerberos realms etc.

I like the concept of a DOI field instead of policy type; considering 
the portability of guest images this seems like a good solution based 
on the relative success of DOIs in other distributed applications.

However, may I suggest that instead of representing the DOI as a string 
we use a 32bit integer?  I know that may sound a bit odd, but in the 
networking world most DOI values are represented as integers and when 
security labels are involved they tend to be 32bits.  I understand that 
using a plain integer is much more abstract than a human readable 
string but it should make it easier to leverage existing and future* 
DOI frameworks.

*An informal group/list just formed to start discussing DOI management 
issues such as DOI formats, negotiation and translation.

-- 
paul moore
linux @ hp

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-23 12:05     ` Paul Moore
@ 2008-10-28 21:42       ` James Morris
  2008-10-28 22:17         ` Paul Moore
  0 siblings, 1 reply; 18+ messages in thread
From: James Morris @ 2008-10-28 21:42 UTC (permalink / raw)
  To: Paul Moore
  Cc: Daniel J Walsh, libvir-list, Daniel P. Berrange, Daniel Veillard,
	Stephen Smalley, selinux

On Thu, 23 Oct 2008, Paul Moore wrote:

> However, may I suggest that instead of representing the DOI as a string 
> we use a 32bit integer?  I know that may sound a bit odd, but in the 
> networking world most DOI values are represented as integers and when 
> security labels are involved they tend to be 32bits.  I understand that 
> using a plain integer is much more abstract than a human readable 
> string but it should make it easier to leverage existing and future* 
> DOI frameworks.

I'd prefer to use string, which can be managed freely by the user, and be 
human-readable.  Unlike IP layer networking, we're not constrained by e.g. 
having to fit in the IP options, and can simply convey the DOI as-is.

This will also not prevent users from utilizing integers as the DOI if 
desired.

In the common non-DoD case, people should be able to configure the DOI as 
simply as editing a configuration file to set the DOI to a domain name or 
arbitrary realm name.


> *An informal group/list just formed to start discussing DOI management 
> issues such as DOI formats, negotiation and translation.

URL ?


- James
-- 
James Morris
<jmorris@namei.org>

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-28 21:42       ` James Morris
@ 2008-10-28 22:17         ` Paul Moore
  2008-10-29 14:40           ` David P. Quigley
  0 siblings, 1 reply; 18+ messages in thread
From: Paul Moore @ 2008-10-28 22:17 UTC (permalink / raw)
  To: James Morris
  Cc: Daniel J Walsh, libvir-list, Daniel P. Berrange, Daniel Veillard,
	Stephen Smalley, selinux

On Tuesday 28 October 2008 5:42:17 pm James Morris wrote:
> On Thu, 23 Oct 2008, Paul Moore wrote:
> > However, may I suggest that instead of representing the DOI as a
> > string we use a 32bit integer?  I know that may sound a bit odd,
> > but in the networking world most DOI values are represented as
> > integers and when security labels are involved they tend to be
> > 32bits.  I understand that using a plain integer is much more
> > abstract than a human readable string but it should make it easier
> > to leverage existing and future* DOI frameworks.
>
> I'd prefer to use string, which can be managed freely by the user,
> and be human-readable.  Unlike IP layer networking, we're not
> constrained by e.g. having to fit in the IP options, and can simply
> convey the DOI as-is.

True, we've got plenty of space to play with in the sVirt case as 
opposed to things like labeled networking and labeled NFS.  However, 
that wasn't really my concern.  It is likely that at some point in the 
future we will have some sort of standardized approach to dealing with 
DOIs and right now most of the DOIs in the labeled security space are 
32 bit integers; using a 32 bit value in sVirt has the potential to 
make life much easier down the road.  Granted, if strings are voted as 
the way forward and portability of labeled guests really takes off then 
I'm sure we'll find a way to deal with it; it would just be nice not to 
have to adapt things later on.

> This will also not prevent users from utilizing integers as the DOI
> if desired.

Also true.

> In the common non-DoD case, people should be able to configure the
> DOI as simply as editing a configuration file to set the DOI to a
> domain name or arbitrary realm name.

I don't think DoD/non-DoD has anything to do with it, it is more of a 
management issue and both groups have the same problem.  Is the 
convenience of being able to enter "guests-r-us.com" over "5" in the 
DOI field really worth the disconnect from the traditional 32 bit DOI 
integer?

> > *An informal group/list just formed to start discussing DOI
> > management issues such as DOI formats, negotiation and translation.
>
> URL ?

Viola, http://mail.opensolaris.org/mailman/listinfo/doi-discuss, there 
was one thread in the beginning that got some traffic but it has been 
pretty quiet since then.  I'm pretty sure archives are available at the 
link above.

-- 
paul moore
linux @ hp

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-28 22:17         ` Paul Moore
@ 2008-10-29 14:40           ` David P. Quigley
  0 siblings, 0 replies; 18+ messages in thread
From: David P. Quigley @ 2008-10-29 14:40 UTC (permalink / raw)
  To: Paul Moore
  Cc: James Morris, Daniel J Walsh, libvir-list, Daniel P. Berrange,
	Daniel Veillard, Stephen Smalley, selinux

On Tue, 2008-10-28 at 18:17 -0400, Paul Moore wrote:
> On Tuesday 28 October 2008 5:42:17 pm James Morris wrote:
> > On Thu, 23 Oct 2008, Paul Moore wrote:
> > > However, may I suggest that instead of representing the DOI as a
> > > string we use a 32bit integer?  I know that may sound a bit odd,
> > > but in the networking world most DOI values are represented as
> > > integers and when security labels are involved they tend to be
> > > 32bits.  I understand that using a plain integer is much more
> > > abstract than a human readable string but it should make it easier
> > > to leverage existing and future* DOI frameworks.
> >
> > I'd prefer to use string, which can be managed freely by the user,
> > and be human-readable.  Unlike IP layer networking, we're not
> > constrained by e.g. having to fit in the IP options, and can simply
> > convey the DOI as-is.
> 
> True, we've got plenty of space to play with in the sVirt case as 
> opposed to things like labeled networking and labeled NFS.  However, 
> that wasn't really my concern.  It is likely that at some point in the 
> future we will have some sort of standardized approach to dealing with 
> DOIs and right now most of the DOIs in the labeled security space are 
> 32 bit integers; using a 32 bit value in sVirt has the potential to 
> make life much easier down the road.  Granted, if strings are voted as 
> the way forward and portability of labeled guests really takes off then 
> I'm sure we'll find a way to deal with it; it would just be nice not to 
> have to adapt things later on.

I really don't like the idea of using strings for this. With our u32
scheme we have a way of provisioning off private DOI spaces which is
fairly simple since we can allocate ranges within the int. With strings
if you want to indicate something is private you are going to have to
come up with come convention of adding a prefix or suffix to indicate
that. If you want to do DOI->Name translations we can make sure to
require a valid name for the DOI in the IANA registration for the public
ones and you will have to have something similar to setransd to handle
them for private ones. Either that or build it into your scheme that
when I specify a DOI I specify a name for it as well. You can have DOI
be a complex element containing an int and a string.

> 
> > This will also not prevent users from utilizing integers as the DOI
> > if desired.
> 
> Also true.

However if you go with strings they are completely unusable for labeled
networking and labeled NFS unless they are already a number or we come
up with some sort of translation facility for it. I'd rather see the
translation from int->string than string->int.

> 
> > In the common non-DoD case, people should be able to configure the
> > DOI as simply as editing a configuration file to set the DOI to a
> > domain name or arbitrary realm name.
> 
> I don't think DoD/non-DoD has anything to do with it, it is more of a 
> management issue and both groups have the same problem.  Is the 
> convenience of being able to enter "guests-r-us.com" over "5" in the 
> DOI field really worth the disconnect from the traditional 32 bit DOI 
> integer?

If in the config file the DOI is a complex element with both DOI and
name you can have your cake and eat it to. I see the name element as an
explicit mapping rule of DOI to a string. Also if you intend to have
names like the one above it seems even less correct to use them. When
guests-r-us.com and myguests.com can be running policies with the same
exact semantics then it is even more important to say they both have a
DOI of 5. That way you really know the policy semantics are the same
instead of it being shrouded by the names. It would confuse the hell out
of me as an administrator if they were identical but have two different
names or if I looked at my myguests.com VMs and saw that they were
running the guests-r-us.com DOI.

> 
> > > *An informal group/list just formed to start discussing DOI
> > > management issues such as DOI formats, negotiation and translation.
> >
> > URL ?
> 
> Viola, http://mail.opensolaris.org/mailman/listinfo/doi-discuss, there 
> was one thread in the beginning that got some traffic but it has been 
> pretty quiet since then.  I'm pretty sure archives are available at the 
> link above.
> 


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] sVirt v0.10 - initial prototype
  2008-10-21 16:22   ` Daniel P. Berrange
  2008-10-21 17:50     ` Daniel J Walsh
  2008-10-22  9:50     ` James Morris
@ 2008-10-29 21:51     ` James Morris
  2 siblings, 0 replies; 18+ messages in thread
From: James Morris @ 2008-10-29 21:51 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Daniel J Walsh, libvir-list, Daniel Veillard, Stephen Smalley,
	selinux

On Tue, 21 Oct 2008, Daniel P. Berrange wrote:

> eg perhaps something like
> 
> # virsh capabilities 
> <capabilities>
> 
>   <host>
>     <cpu>
>       <arch>i686</arch>
>     </cpu>
>     <secpolicy model='selinux'>
>        <type>targetted</type>
>        <state>enforcing</state>
>     </secpolicy>
>   </host>
> 
>   .... snip rest of XML...

I don't think the endforcing state for the host will be useful, as this 
can change between API calls, and it really needs to be enforced on the 
host at the time of domain instantiation.

> Is there any meaningful / useful policy version information that can
> be included here ? Or policy feature bits

Possibly, although I think we should leave the configuration of DOI to the 
admin, rather than trying to figure out what might be useful in advance.  
In some cases, the admin may wish to use an RPM package+version string, 
and others, a domain name could indicate that each system is managed 
within an boundary with consistent label semantics.


- James
-- 
James Morris
<jmorris@namei.org>

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [libvirt] [RFC] sVirt v0.10 - initial prototype
  2008-10-21  2:06 [RFC] sVirt v0.10 - initial prototype James Morris
  2008-10-21 13:57 ` Daniel J Walsh
  2008-10-21 17:17 ` Daniel P. Berrange
@ 2008-10-30  9:40 ` Atsushi SAKAI
  2008-10-30 19:18   ` Daniel J Walsh
  2 siblings, 1 reply; 18+ messages in thread
From: Atsushi SAKAI @ 2008-10-30  9:40 UTC (permalink / raw)
  To: James Morris; +Cc: libvir-list, Stephen Smalley, Daniel J Walsh, selinux

Hi, James

I have a question just for interest.

The security context stores like
/etc/selinux/targeted/contexts/files/file_contexts.

But you are storeing the domain security label on libvirt specific XML.
Of course, this is good for libvirt POV.

Is it permitted for SELinux policy POV?


By the way, I want to see the further discussion of the Requirements.
> Requirements not yet addressed include:

Thanks
Atsushi SAKAI



James Morris <jmorris@namei.org> wrote:

[snip]
> The domain security label configuration format is as follows:
> 
> # virsh dumpxml sys1
> <domain>
>     ....
>   <seclabel model='selinux'>
>     <label>system_u:system_r:virtd_t:s0</label>
>     <policytype>targeted</policytype>
>   </seclabel>
> </domain>
> 
> It's possible to query the security label of a running domain via virsh:
> 
> # virsh dominfo sys1
> Id:             1
> Name:           sys1
> UUID:           fa3c8e06-0877-2a08-06fd-f2479b7bacb4
> OS Type:        hvm
> State:          running
> CPU(s):         1
> CPU time:       11.4s
> Max memory:     524288 kB
> Used memory:    524288 kB
> Autostart:      disable
> Security label: system_u:system_r:virtd_t:s0 (selinux/targeted/enforcing)
> 
> The security label is deterimed via the new virDomainGetSecLabel() API 
> method, which is transported over RPC to the backend driver (qemu in this 
> case), and is entirely independent of the local security model, if any.  
> e.g. this command could be run remotely from an entirely different 
> platform: you just see what's happening on the remote system, as with 
> other attributes of the domain.
> 
> Feedback on the design thus far is sought before proceeding to more 
> comprehensive integration.
> 
> In particular, I'd be interested in any thoughts on the placement of the 
> security labeling driver within libvirt, as this seems to be the most 
> critical architectural issue (I've already refactored this aspect once).  
> 
> Currently, the idea is to attach the security labeling driver to the virt 
> driver, rather than implement it independently as a top-level component as 
> in the case of other types of drivers (e.g. storage).  This is because 
> process-based security labeling is highly dependent on the kind of 
> virtualization in use, and may not make sense at all in some cases (e.g. 
> when using a non-Linux hypervisor, or containers).
> 
> In the case of qemu, a security labeling driver is added to qemud:
> 
> @@ -63,6 +64,7 @@ struct qemud_driver {
>      char *vncListen;
>  
>      virCapsPtr caps;
> +    virSecLabelDriverPtr secLabelDriver;
>  };
> 
> and then initialized during qemud startup from qemudSecLabelInit().  
> 
> During initialization, any available security labeling drivers are probed, 
> and the first one which thinks it should be used is installed. Top-level 
> libvirt API calls are then dispatched to the active security labeling 
> driver via the backend virt driver, as necessary.
> 
> Note that the security labeling framework in this release is always 
> built-in -- it can be made a compile-time option later if desired.
> 
> Requirements not yet addressed include:
> - Labeling of resources and generally comprehensive labeling management
> - Automatic labeling (e.g. for the simple isolation use-case)
> - Integration of labeling support into higher-level management tools such 
>   as virt-manager
> - Integration with the audit subsystem to help with administration and 
>   debugging
> - Domain of interpretation (DOI) checking/translation
> - Python bindings
> 
> As mentioned, the goal at this stage is to get feedback on the underlying 
> design: comments welcome!
> 
> 
> - James
> -- 
> James Morris
> <jmorris@namei.org>



--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [libvirt] [RFC] sVirt v0.10 - initial prototype
  2008-10-30  9:40 ` [libvirt] " Atsushi SAKAI
@ 2008-10-30 19:18   ` Daniel J Walsh
  0 siblings, 0 replies; 18+ messages in thread
From: Daniel J Walsh @ 2008-10-30 19:18 UTC (permalink / raw)
  To: Atsushi SAKAI; +Cc: James Morris, libvir-list, Stephen Smalley, selinux

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Atsushi SAKAI wrote:
> Hi, James
> 
> I have a question just for interest.
> 
> The security context stores like
> /etc/selinux/targeted/contexts/files/file_contexts.
> 
> But you are storeing the domain security label on libvirt specific XML.
> Of course, this is good for libvirt POV.
> 
> Is it permitted for SELinux policy POV?
> 
> 
> By the way, I want to see the further discussion of the Requirements.
>> Requirements not yet addressed include:
> 
> Thanks
> Atsushi SAKAI
> 
Both /etc/selinux/targeted/contexts/files/file_contexts and libvirt
specific XML are just indicators of the way the system should be setup.
 The kernel policy is the final arbiter of the policy.  So if the kernel
does not understand virt_image_t in
/etc/selinux/targeted/contexts/files/file_contexts, it will not allow
tools like rpm or restorecon to set it as a file context.  Similarly if
the process label qemu_t is specified in the libvirt xml, and the kernel
policy does not know what a qemu_t is, it will not allow libvirt to
start a processes labeled qemu_t.

> 
> 
> James Morris <jmorris@namei.org> wrote:
> 
> [snip]
>> The domain security label configuration format is as follows:
>>
>> # virsh dumpxml sys1
>> <domain>
>>     ....
>>   <seclabel model='selinux'>
>>     <label>system_u:system_r:virtd_t:s0</label>
>>     <policytype>targeted</policytype>
>>   </seclabel>
>> </domain>
>>
>> It's possible to query the security label of a running domain via virsh:
>>
>> # virsh dominfo sys1
>> Id:             1
>> Name:           sys1
>> UUID:           fa3c8e06-0877-2a08-06fd-f2479b7bacb4
>> OS Type:        hvm
>> State:          running
>> CPU(s):         1
>> CPU time:       11.4s
>> Max memory:     524288 kB
>> Used memory:    524288 kB
>> Autostart:      disable
>> Security label: system_u:system_r:virtd_t:s0 (selinux/targeted/enforcing)
>>
>> The security label is deterimed via the new virDomainGetSecLabel() API 
>> method, which is transported over RPC to the backend driver (qemu in this 
>> case), and is entirely independent of the local security model, if any.  
>> e.g. this command could be run remotely from an entirely different 
>> platform: you just see what's happening on the remote system, as with 
>> other attributes of the domain.
>>
>> Feedback on the design thus far is sought before proceeding to more 
>> comprehensive integration.
>>
>> In particular, I'd be interested in any thoughts on the placement of the 
>> security labeling driver within libvirt, as this seems to be the most 
>> critical architectural issue (I've already refactored this aspect once).  
>>
>> Currently, the idea is to attach the security labeling driver to the virt 
>> driver, rather than implement it independently as a top-level component as 
>> in the case of other types of drivers (e.g. storage).  This is because 
>> process-based security labeling is highly dependent on the kind of 
>> virtualization in use, and may not make sense at all in some cases (e.g. 
>> when using a non-Linux hypervisor, or containers).
>>
>> In the case of qemu, a security labeling driver is added to qemud:
>>
>> @@ -63,6 +64,7 @@ struct qemud_driver {
>>      char *vncListen;
>>  
>>      virCapsPtr caps;
>> +    virSecLabelDriverPtr secLabelDriver;
>>  };
>>
>> and then initialized during qemud startup from qemudSecLabelInit().  
>>
>> During initialization, any available security labeling drivers are probed, 
>> and the first one which thinks it should be used is installed. Top-level 
>> libvirt API calls are then dispatched to the active security labeling 
>> driver via the backend virt driver, as necessary.
>>
>> Note that the security labeling framework in this release is always 
>> built-in -- it can be made a compile-time option later if desired.
>>
>> Requirements not yet addressed include:
>> - Labeling of resources and generally comprehensive labeling management
>> - Automatic labeling (e.g. for the simple isolation use-case)
>> - Integration of labeling support into higher-level management tools such 
>>   as virt-manager
>> - Integration with the audit subsystem to help with administration and 
>>   debugging
>> - Domain of interpretation (DOI) checking/translation
>> - Python bindings
>>
>> As mentioned, the goal at this stage is to get feedback on the underlying 
>> design: comments welcome!
>>
>>
>> - James
>> -- 
>> James Morris
>> <jmorris@namei.org>
> 
> 
> 
> --
> This message was distributed to subscribers of the selinux mailing list.
> If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
> the words "unsubscribe selinux" without quotes as the message.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkkKCHgACgkQrlYvE4MpobO44ACdG8CX5Y6ptaUTd2RtP4rtjaTo
u1sAniwNi1WoYUuxkO3zM9A8hNUGLhTO
=jtTR
-----END PGP SIGNATURE-----

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2008-10-30 19:18 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-21  2:06 [RFC] sVirt v0.10 - initial prototype James Morris
2008-10-21 13:57 ` Daniel J Walsh
2008-10-21 16:22   ` Daniel P. Berrange
2008-10-21 17:50     ` Daniel J Walsh
2008-10-22  9:51       ` Daniel P. Berrange
2008-10-22  9:50     ` James Morris
2008-10-22 10:03       ` Daniel P. Berrange
2008-10-22 10:05         ` James Morris
2008-10-29 21:51     ` James Morris
2008-10-22  9:23   ` James Morris
2008-10-23 12:05     ` Paul Moore
2008-10-28 21:42       ` James Morris
2008-10-28 22:17         ` Paul Moore
2008-10-29 14:40           ` David P. Quigley
2008-10-21 17:17 ` Daniel P. Berrange
2008-10-22 10:01   ` James Morris
2008-10-30  9:40 ` [libvirt] " Atsushi SAKAI
2008-10-30 19:18   ` Daniel J Walsh

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.