[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [ACM] Check a domain's authorization to run.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1185523275 -3600
# Node ID bf512fde6667f213dc5e32239fd567e2b5a6ef37
# Parent  07655ed2fe58ebf883b8a4b5c2dccf15576f4778
[ACM] Check a domain's authorization to run.

A domain is only authorized to run if it has a superset of Simple Type
Enforcement Types in its VM label compared to that of Domain-0, which
itself may not have all STEs available in a policy. This patch adds a
check for this into Xend and the necessary code support into Xen.

Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx>
---
 tools/python/xen/lowlevel/acm/acm.c         |    9 ++--
 tools/python/xen/util/security.py           |   22 +++++++++-
 tools/python/xen/xend/XendDomainInfo.py     |   10 +++-
 xen/acm/acm_chinesewall_hooks.c             |    1 
 xen/acm/acm_core.c                          |   29 -------------
 xen/acm/acm_policy.c                        |    4 +
 xen/acm/acm_simple_type_enforcement_hooks.c |   38 ++++++++++++++++-
 xen/include/acm/acm_core.h                  |    3 -
 xen/include/acm/acm_hooks.h                 |   60 +++++++++++++++++++++-------
 xen/include/public/acm.h                    |    5 +-
 10 files changed, 125 insertions(+), 56 deletions(-)

diff -r 07655ed2fe58 -r bf512fde6667 tools/python/xen/lowlevel/acm/acm.c
--- a/tools/python/xen/lowlevel/acm/acm.c       Thu Jul 26 12:00:32 2007 +0100
+++ b/tools/python/xen/lowlevel/acm/acm.c       Fri Jul 27 09:01:15 2007 +0100
@@ -148,9 +148,10 @@ static PyObject *getdecision(PyObject * 
     char *arg1_name, *arg1, *arg2_name, *arg2, *decision = NULL;
     struct acm_getdecision getdecision;
     int xc_handle, rc;
-
-    if (!PyArg_ParseTuple(args, "ssss", &arg1_name,
-                          &arg1, &arg2_name, &arg2)) {
+    uint32_t hooktype;
+
+    if (!PyArg_ParseTuple(args, "ssssi", &arg1_name,
+                          &arg1, &arg2_name, &arg2, &hooktype)) {
         return NULL;
     }
 
@@ -163,7 +164,7 @@ static PyObject *getdecision(PyObject * 
     (strcmp(arg2_name, "domid") && strcmp(arg2_name, "ssidref")))
         return NULL;
 
-    getdecision.hook = ACMHOOK_sharing;
+    getdecision.hook = hooktype;
     if (!strcmp(arg1_name, "domid")) {
         getdecision.get_decision_by1 = ACM_GETBY_domainid;
         getdecision.id1.domainid = atoi(arg1);
diff -r 07655ed2fe58 -r bf512fde6667 tools/python/xen/util/security.py
--- a/tools/python/xen/util/security.py Thu Jul 26 12:00:32 2007 +0100
+++ b/tools/python/xen/util/security.py Fri Jul 27 09:01:15 2007 +0100
@@ -61,6 +61,10 @@ empty_line_re = re.compile("^\s*$")
 empty_line_re = re.compile("^\s*$")
 binary_name_re = re.compile(".*[chwall|ste|chwall_ste].*\.bin", re.IGNORECASE)
 policy_name_re = re.compile(".*[chwall|ste|chwall_ste].*", re.IGNORECASE)
+
+#decision hooks known to the hypervisor
+ACMHOOK_sharing = 1
+ACMHOOK_authorization = 2
 
 #other global variables
 NULL_SSIDREF = 0
@@ -453,7 +457,8 @@ def get_decision(arg1, arg2):
         err("Invalid id or ssidref type, string or int required")
 
     try:
-        decision = acm.getdecision(arg1[0], arg1[1], arg2[0], arg2[1])
+        decision = acm.getdecision(arg1[0], arg1[1], arg2[0], arg2[1],
+                                   ACMHOOK_sharing)
     except:
         err("Cannot determine decision.")
 
@@ -461,6 +466,21 @@ def get_decision(arg1, arg2):
         return decision
     else:
         err("Cannot determine decision (Invalid parameter).")
+
+
+def has_authorization(ssidref):
+    """ Check if the domain with the given ssidref has authorization to
+        run on this system. To have authoriztion dom0's STE types must
+        be a superset of that of the domain's given through its ssidref.
+    """
+    rc = True
+    dom0_ssidref = int(acm.getssid(0)['ssidref'])
+    decision = acm.getdecision('ssidref', str(dom0_ssidref),
+                               'ssidref', str(ssidref),
+                               ACMHOOK_authorization)
+    if decision == "DENIED":
+        rc = False
+    return rc
 
 
 def hv_chg_policy(bin_pol, del_array, chg_array):
diff -r 07655ed2fe58 -r bf512fde6667 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Thu Jul 26 12:00:32 2007 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Fri Jul 27 09:01:15 2007 +0100
@@ -1460,9 +1460,13 @@ class XendDomainInfo:
         # allocation of 1MB. We free up 2MB here to be on the safe side.
         balloon.free(2*1024) # 2MB should be plenty
 
-        ssidref = security.calc_dom_ssidref_from_info(self.info)
-        if ssidref == 0 and security.on():
-            raise VmError('VM is not properly labeled.')
+        ssidref = 0
+        if security.on():
+            ssidref = security.calc_dom_ssidref_from_info(self.info)
+            if ssidref == 0:
+                raise VmError('VM is not properly labeled.')
+            if security.has_authorization(ssidref) == False:
+                raise VmError("VM is not authorized to run.")
 
         try:
             self.domid = xc.domain_create(
diff -r 07655ed2fe58 -r bf512fde6667 xen/acm/acm_chinesewall_hooks.c
--- a/xen/acm/acm_chinesewall_hooks.c   Thu Jul 26 12:00:32 2007 +0100
+++ b/xen/acm/acm_chinesewall_hooks.c   Fri Jul 27 09:01:15 2007 +0100
@@ -685,6 +685,7 @@ struct acm_operations acm_chinesewall_op
     .fail_grant_setup = NULL,
     /* generic domain-requested decision hooks */
     .sharing = NULL,
+    .authorization = NULL,
 
     .is_default_policy = chwall_is_default_policy,
 };
diff -r 07655ed2fe58 -r bf512fde6667 xen/acm/acm_core.c
--- a/xen/acm/acm_core.c        Thu Jul 26 12:00:32 2007 +0100
+++ b/xen/acm/acm_core.c        Fri Jul 27 09:01:15 2007 +0100
@@ -314,26 +314,7 @@ acm_init(char *policy_start,
     return ret;
 }
 
-int
-acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
-{
-    struct domain *subj = rcu_lock_domain_by_id(id);
-    int ret;
- 
-    if (subj == NULL)
-    {
-        printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id);
-        return ACM_NULL_POINTER_ERROR;
-    }
-
-    ret = acm_init_domain_ssid_new(subj, ssidref);
-
-    rcu_unlock_domain(subj);
-
-    return ret;
-}
-
-int acm_init_domain_ssid_new(struct domain *subj, ssidref_t ssidref)
+int acm_init_domain_ssid(struct domain *subj, ssidref_t ssidref)
 {
     struct acm_ssid_domain *ssid;
     int ret1, ret2;
@@ -373,10 +354,6 @@ int acm_init_domain_ssid_new(struct doma
         acm_free_domain_ssid(ssid);
         return ACM_INIT_SSID_ERROR;
     }
-
-    write_lock(&ssid_list_rwlock);
-    list_add(&ssid->node, &ssid_list);
-    write_unlock(&ssid_list_rwlock);
 
     printkd("%s: assigned domain %x the ssidref=%x.\n",
            __func__, subj->domain_id, ssid->ssidref);
@@ -398,10 +375,6 @@ acm_free_domain_ssid(struct acm_ssid_dom
     if (acm_secondary_ops->free_domain_ssid != NULL)
         acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
     ssid->secondary_ssid = NULL;
-
-    write_lock(&ssid_list_rwlock);
-    list_del(&ssid->node);
-    write_unlock(&ssid_list_rwlock);
 
     xfree(ssid);
     printkd("%s: Freed individual domain ssid (domain=%02x).\n",
diff -r 07655ed2fe58 -r bf512fde6667 xen/acm/acm_policy.c
--- a/xen/acm/acm_policy.c      Thu Jul 26 12:00:32 2007 +0100
+++ b/xen/acm/acm_policy.c      Fri Jul 27 09:01:15 2007 +0100
@@ -438,6 +438,10 @@ acm_get_decision(ssidref_t ssidref1, ssi
         ret = acm_sharing(ssidref1, ssidref2);
         break;
 
+    case ACMHOOK_authorization:
+        ret = acm_authorization(ssidref1, ssidref2);
+        break;
+
     default:
         /* deny */
         break;
diff -r 07655ed2fe58 -r bf512fde6667 xen/acm/acm_simple_type_enforcement_hooks.c
--- a/xen/acm/acm_simple_type_enforcement_hooks.c       Thu Jul 26 12:00:32 
2007 +0100
+++ b/xen/acm/acm_simple_type_enforcement_hooks.c       Fri Jul 27 09:01:15 
2007 +0100
@@ -38,15 +38,16 @@ ssidref_t dom0_ste_ssidref = 0x0001;
 /* local cache structures for STE policy */
 struct ste_binary_policy ste_bin_pol;
 
-static inline int have_common_type (ssidref_t ref1, ssidref_t ref2) {
+static inline int have_common_type (ssidref_t ref1, ssidref_t ref2)
+{
     int i;
 
     if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs &&
          ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs )
     {
         for( i = 0; i< ste_bin_pol.max_types; i++ )
-            if ( ste_bin_pol.ssidrefs[ref1*ste_bin_pol.max_types + i] &&
-                 ste_bin_pol.ssidrefs[ref2*ste_bin_pol.max_types + i])
+            if ( ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] &&
+                 ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i])
             {
                 printkd("%s: common type #%02x.\n", __func__, i);
                 return 1;
@@ -54,6 +55,26 @@ static inline int have_common_type (ssid
     }
     return 0;
 }
+
+static inline int is_superset(ssidref_t ref1, ssidref_t ref2)
+{
+    int i;
+
+    if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs &&
+         ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs )
+    {
+        for( i = 0; i< ste_bin_pol.max_types; i++ )
+            if (!ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] &&
+                 ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i])
+            {
+                return 0;
+            }
+    } else {
+        return 0;
+    }
+    return 1;
+}
+
 
 /* Helper function: return = (subj and obj share a common type) */
 static int share_common_type(struct domain *subj, struct domain *obj)
@@ -609,6 +630,7 @@ ste_pre_domain_create(void *subject_ssid
 {      
     /* check for ssidref in range for policy */
     ssidref_t ste_ssidref;
+
     traceprintk("%s.\n", __func__);
 
     read_lock(&acm_bin_pol_rwlock);
@@ -830,6 +852,15 @@ ste_sharing(ssidref_t ssidref1, ssidref_
         GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1),
         GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2));
     return (hct ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED);
+}
+
+static int
+ste_authorization(ssidref_t ssidref1, ssidref_t ssidref2)
+{
+    int iss = is_superset(
+        GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1),
+        GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2));
+    return (iss ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED);
 }
 
 static int
@@ -867,6 +898,7 @@ struct acm_operations acm_simple_type_en
     .pre_grant_setup        = ste_pre_grant_setup,
     .fail_grant_setup       = NULL,
     .sharing                = ste_sharing,
+    .authorization          = ste_authorization,
 
     .is_default_policy      = ste_is_default_policy,
 };
diff -r 07655ed2fe58 -r bf512fde6667 xen/include/acm/acm_core.h
--- a/xen/include/acm/acm_core.h        Thu Jul 26 12:00:32 2007 +0100
+++ b/xen/include/acm/acm_core.h        Fri Jul 27 09:01:15 2007 +0100
@@ -153,8 +153,7 @@ static inline int acm_array_append_tuple
 }
 
 /* protos */
-int acm_init_domain_ssid(domid_t id, ssidref_t ssidref);
-int acm_init_domain_ssid_new(struct domain *, ssidref_t ssidref);
+int acm_init_domain_ssid(struct domain *, ssidref_t ssidref);
 void acm_free_domain_ssid(struct acm_ssid_domain *ssid);
 int acm_init_binary_policy(u32 policy_code);
 int acm_set_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size);
diff -r 07655ed2fe58 -r bf512fde6667 xen/include/acm/acm_hooks.h
--- a/xen/include/acm/acm_hooks.h       Thu Jul 26 12:00:32 2007 +0100
+++ b/xen/include/acm/acm_hooks.h       Fri Jul 27 09:01:15 2007 +0100
@@ -112,7 +112,10 @@ struct acm_operations {
     int  (*pre_grant_setup)            (domid_t id);
     void (*fail_grant_setup)           (domid_t id);
     /* generic domain-requested decision hooks (can be NULL) */
-    int (*sharing)                     (ssidref_t ssidref1, ssidref_t 
ssidref2);
+    int (*sharing)                     (ssidref_t ssidref1,
+                                        ssidref_t ssidref2);
+    int (*authorization)               (ssidref_t ssidref1,
+                                        ssidref_t ssidref2);
     /* determine whether the default policy is installed */
     int (*is_default_policy)           (void);
 };
@@ -148,6 +151,8 @@ static inline int acm_is_policy(char *bu
 { return 0; }
 static inline int acm_sharing(ssidref_t ssidref1, ssidref_t ssidref2)
 { return 0; }
+static inline int acm_authorization(ssidref_t ssidref1, ssidref_t ssidref2)
+{ return 0; }
 static inline int acm_domain_create(struct domain *d, ssidref_t ssidref)
 { return 0; }
 static inline void acm_domain_destroy(struct domain *d)
@@ -157,6 +162,19 @@ static inline void acm_domain_destroy(st
 
 #else
 
+static inline void acm_domain_ssid_onto_list(struct acm_ssid_domain *ssid)
+{
+    write_lock(&ssid_list_rwlock);
+    list_add(&ssid->node, &ssid_list);
+    write_unlock(&ssid_list_rwlock);
+}
+
+static inline void acm_domain_ssid_off_list(struct acm_ssid_domain *ssid)
+{
+    write_lock(&ssid_list_rwlock);
+    list_del(&ssid->node);
+    write_unlock(&ssid_list_rwlock);
+}
 
 static inline int acm_pre_eventchannel_unbound(domid_t id1, domid_t id2)
 {
@@ -241,6 +259,7 @@ static inline void acm_domain_destroy(st
         if (acm_secondary_ops->domain_destroy != NULL)
             acm_secondary_ops->domain_destroy(ssid, d);
         /* free security ssid for the destroyed domain (also if null policy */
+        acm_domain_ssid_off_list(ssid);
         acm_free_domain_ssid((struct acm_ssid_domain *)(ssid));
     }
 }
@@ -250,13 +269,16 @@ static inline int acm_domain_create(stru
 {
     void *subject_ssid = current->domain->ssid;
     domid_t domid = d->domain_id;
-    int rc = 0;
+    int rc;
 
     read_lock(&acm_bin_pol_rwlock);
     /*
        To be called when a domain is created; returns '0' if the
        domain is allowed to be created, != '0' if not.
      */
+    rc = acm_init_domain_ssid(d, ssidref);
+    if (rc != ACM_OK)
+        goto error_out;
 
     if ((acm_primary_ops->domain_create != NULL) &&
         acm_primary_ops->domain_create(subject_ssid, ssidref, domid)) {
@@ -267,18 +289,17 @@ static inline int acm_domain_create(stru
         /* roll-back primary */
         if (acm_primary_ops->domain_destroy != NULL)
             acm_primary_ops->domain_destroy(d->ssid, d);
+        rc = ACM_ACCESS_DENIED;
+    }
+
+    if ( rc == ACM_OK )
+    {
+        acm_domain_ssid_onto_list(d->ssid);
+    } else {
         acm_free_domain_ssid(d->ssid);
-        rc = ACM_ACCESS_DENIED;
-    }
-
-    if (rc == 0) {
-        rc = acm_init_domain_ssid_new(d, ssidref);
-
-        if (rc != ACM_OK) {
-            acm_domain_destroy(d);
-        }
-    }
-
+    }
+
+error_out:
     read_unlock(&acm_bin_pol_rwlock);
     return rc;
 }
@@ -291,6 +312,19 @@ static inline int acm_sharing(ssidref_t 
         return ACM_ACCESS_DENIED;
     else if ((acm_secondary_ops->sharing != NULL) &&
              acm_secondary_ops->sharing(ssidref1, ssidref2)) {
+        return ACM_ACCESS_DENIED;
+    } else
+        return ACM_ACCESS_PERMITTED;
+}
+
+
+static inline int acm_authorization(ssidref_t ssidref1, ssidref_t ssidref2)
+{
+    if ((acm_primary_ops->authorization != NULL) &&
+        acm_primary_ops->authorization(ssidref1, ssidref2))
+        return ACM_ACCESS_DENIED;
+    else if ((acm_secondary_ops->authorization != NULL) &&
+             acm_secondary_ops->authorization(ssidref1, ssidref2)) {
         return ACM_ACCESS_DENIED;
     } else
         return ACM_ACCESS_PERMITTED;
diff -r 07655ed2fe58 -r bf512fde6667 xen/include/public/acm.h
--- a/xen/include/public/acm.h  Thu Jul 26 12:00:32 2007 +0100
+++ b/xen/include/public/acm.h  Fri Jul 27 09:01:15 2007 +0100
@@ -99,8 +99,9 @@ typedef uint32_t ssidref_t;
 typedef uint32_t ssidref_t;
 
 /* hooks that are known to domains */
-#define ACMHOOK_none    0
-#define ACMHOOK_sharing 1
+#define ACMHOOK_none          0
+#define ACMHOOK_sharing       1
+#define ACMHOOK_authorization 2
 
 /* -------security policy relevant type definitions-------- */
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.