WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [ACM] Check a domain's authorization to run.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 27 Jul 2007 03:22:57 -0700
Delivery-date: Fri, 27 Jul 2007 03:21:03 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [ACM] Check a domain's authorization to run., Xen patchbot-unstable <=