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

[Xen-devel] [PATCH] xsm: add device tree labeling support



This adds support in the hypervisor and policy build toolchain for
Xen/Flask policy version 25, which adds the ability to label ARM device
tree nodes and expands the IOMEM ocontext entries to 64 bits.

Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>
---

Note: Actually using the features added in this patch requires a patch
to the SELinux toolchain (checkpolicy) which has just been sent to that
upstream and xen-devel.

 tools/flask/policy/Makefile       |  22 +++++---
 xen/include/public/xsm/flask_op.h |   9 ++++
 xen/xsm/flask/flask_op.c          |  28 ++++++++++
 xen/xsm/flask/include/security.h  |   9 +++-
 xen/xsm/flask/ss/policydb.c       |  73 +++++++++++++++++++------
 xen/xsm/flask/ss/policydb.h       |   7 +--
 xen/xsm/flask/ss/services.c       | 111 +++++++++++++++++++++++++++++++++++---
 7 files changed, 226 insertions(+), 33 deletions(-)

diff --git a/tools/flask/policy/Makefile b/tools/flask/policy/Makefile
index e564396..3220f6b 100644
--- a/tools/flask/policy/Makefile
+++ b/tools/flask/policy/Makefile
@@ -26,15 +26,13 @@ M4 ?= m4
 #
 ########################################
 
-# Policy version
-# By default, checkpolicy creates the highest version policy it supports. Force
-# the use of version 24 which is the highest that Xen supports, and the first 
to
-# include the Xen policy type (needed for static device policy).
-OUTPUT_POLICY = 24
-
 POLICY_FILENAME = xenpolicy-$(shell $(MAKE) -C $(XEN_ROOT)/xen xenversion 
--no-print-directory)
 POLICY_LOADPATH = /boot
 
+# Minimum and maximum policy versions supported by the hypervisor
+POLICY_VER_MIN = 24
+POLICY_VER_MAX = 25
+
 # policy source layout
 POLDIR := policy
 MODDIR := $(POLDIR)/modules
@@ -64,6 +62,18 @@ MOD_CONF := $(POLDIR)/modules.conf
 
 # checkpolicy can use the #line directives provided by -s for error reporting:
 M4PARAM := -D self_contained_policy -s
+
+# If checkpolicy supports Xen policy versions other than 24 (the first version
+# with support for the Xen policy), it will report them in the output of
+# "checkpolicy -t Xen -V", such as "Xen policy compatibility range: 24 25".
+# Otherwise, the maximum version supported by checkpolicy is 24.
+CHECKPOLICY_VERS_TXT := $(shell $(CHECKPOLICY) -t Xen -V)
+CHECKPOLICY_XEN_MAX = $(if $(findstring 
Xen,$(CHECKPOLICY_VERS_TXT)),$(lastword $(CHECKPOLICY_VERS_TXT)),24)
+
+# The output policy version used will be the highest supported by both the
+# hypervisor and the checkpolicy binary
+OUTPUT_POLICY := $(shell if test $(CHECKPOLICY_XEN_MAX) -gt $(POLICY_VER_MAX); 
then echo $(POLICY_VER_MAX); else echo $(CHECKPOLICY_XEN_MAX); fi)
+
 CHECKPOLICY_PARAM := -t Xen -c $(OUTPUT_POLICY)
 
 # enable MLS if requested.
diff --git a/xen/include/public/xsm/flask_op.h 
b/xen/include/public/xsm/flask_op.h
index f874589..c76359c 100644
--- a/xen/include/public/xsm/flask_op.h
+++ b/xen/include/public/xsm/flask_op.h
@@ -150,6 +150,13 @@ struct xen_flask_relabel {
     uint32_t sid;
 };
 
+struct xen_flask_devicetree_label {
+    /* IN */
+    uint32_t sid;
+    uint32_t length;
+    XEN_GUEST_HANDLE(char) path;
+};
+
 struct xen_flask_op {
     uint32_t cmd;
 #define FLASK_LOAD              1
@@ -176,6 +183,7 @@ struct xen_flask_op {
 #define FLASK_DEL_OCONTEXT      22
 #define FLASK_GET_PEER_SID      23
 #define FLASK_RELABEL_DOMAIN    24
+#define FLASK_DEVICETREE_LABEL  25
     uint32_t interface_version; /* XEN_FLASK_INTERFACE_VERSION */
     union {
         struct xen_flask_load load;
@@ -195,6 +203,7 @@ struct xen_flask_op {
         struct xen_flask_ocontext ocontext;
         struct xen_flask_peersid peersid;
         struct xen_flask_relabel relabel;
+        struct xen_flask_devicetree_label devicetree_label;
     } u;
 };
 typedef struct xen_flask_op xen_flask_op_t;
diff --git a/xen/xsm/flask/flask_op.c b/xen/xsm/flask/flask_op.c
index 84c7fec..47aacc1 100644
--- a/xen/xsm/flask/flask_op.c
+++ b/xen/xsm/flask/flask_op.c
@@ -563,6 +563,27 @@ static int flask_security_load(struct xen_flask_load *load)
     return ret;
 }
 
+static int flask_devicetree_label(struct xen_flask_devicetree_label *arg)
+{
+    int rv;
+    char *buf;
+    u32 sid = arg->sid;
+    u32 perm = sid ? SECURITY__ADD_OCONTEXT : SECURITY__DEL_OCONTEXT;
+
+    rv = domain_has_security(current->domain, perm);
+    if ( rv )
+        return rv;
+
+    rv = flask_copyin_string(arg->path, &buf, arg->length, PAGE_SIZE);
+    if ( rv )
+        return rv;
+
+    /* buf is consumed or freed by this function */
+    rv = security_devicetree_setlabel(buf, sid);
+
+    return rv;
+}
+
 #ifndef COMPAT
 
 static int flask_ocontext_del(struct xen_flask_ocontext *arg)
@@ -790,6 +811,10 @@ ret_t do_flask_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) 
u_flask_op)
         rv = flask_relabel_domain(&op.u.relabel);
         break;
 
+    case FLASK_DEVICETREE_LABEL:
+        rv = flask_devicetree_label(&op.u.devicetree_label);
+        break;
+
     default:
         rv = -ENOSYS;
     }
@@ -848,6 +873,9 @@ CHECK_flask_transition;
 #define flask_security_get_bool compat_security_get_bool
 #define flask_security_set_bool compat_security_set_bool
 
+#define xen_flask_devicetree_label compat_flask_devicetree_label
+#define flask_devicetree_label compat_devicetree_label
+
 #define xen_flask_op_t compat_flask_op_t
 #undef ret_t
 #define ret_t int
diff --git a/xen/xsm/flask/include/security.h b/xen/xsm/flask/include/security.h
index d07bae0..9590dd3 100644
--- a/xen/xsm/flask/include/security.h
+++ b/xen/xsm/flask/include/security.h
@@ -30,10 +30,11 @@
 #define POLICYDB_VERSION_POLCAP                22
 #define POLICYDB_VERSION_PERMISSIVE    23
 #define POLICYDB_VERSION_BOUNDARY      24
+#define POLICYDB_VERSION_AARCH          25
 
 /* Range of policy versions we understand*/
 #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_BOUNDARY
+#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_AARCH
 
 enum flask_bootparam_t {
     FLASK_BOOTPARAM_PERMISSIVE,
@@ -82,6 +83,8 @@ int security_ioport_sid(u32 ioport, u32 *out_sid);
 
 int security_device_sid(u32 device, u32 *out_sid);
 
+int security_devicetree_sid(const char *path, u32 *out_sid);
+
 int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
                                                                     u16 
tclass);
 
@@ -96,5 +99,7 @@ int security_iterate_ioport_sids(u32 start, u32 end,
 int security_ocontext_add(u32 ocontext, unsigned long low,
                            unsigned long high, u32 sid);
 
-int security_ocontext_del(u32 ocontext, unsigned int low, unsigned int high);
+int security_ocontext_del(u32 ocontext, unsigned long low, unsigned long high);
+
+int security_devicetree_setlabel(char *path, u32 sid);
 #endif /* _FLASK_SECURITY_H_ */
diff --git a/xen/xsm/flask/ss/policydb.c b/xen/xsm/flask/ss/policydb.c
index b88ea56..c7d29bd 100644
--- a/xen/xsm/flask/ss/policydb.c
+++ b/xen/xsm/flask/ss/policydb.c
@@ -74,55 +74,55 @@ static struct policydb_compat_info policydb_compat[] = {
     {
         .version        = POLICYDB_VERSION_BASE,
         .sym_num        = SYM_NUM - 3,
-        .ocon_num       = OCON_NUM - 1,
+        .ocon_num       = 4,
         .target_type    = TARGET_XEN_OLD,
     },
     {
         .version        = POLICYDB_VERSION_BOOL,
         .sym_num        = SYM_NUM - 2,
-        .ocon_num       = OCON_NUM - 1,
+        .ocon_num       = 4,
         .target_type    = TARGET_XEN_OLD,
     },
     {
         .version        = POLICYDB_VERSION_IPV6,
         .sym_num        = SYM_NUM - 2,
-        .ocon_num       = OCON_NUM,
+        .ocon_num       = 5,
         .target_type    = TARGET_XEN_OLD,
     },
     {
         .version        = POLICYDB_VERSION_NLCLASS,
         .sym_num        = SYM_NUM - 2,
-        .ocon_num       = OCON_NUM,
+        .ocon_num       = 5,
         .target_type    = TARGET_XEN_OLD,
     },
     {
         .version        = POLICYDB_VERSION_MLS,
         .sym_num        = SYM_NUM,
-        .ocon_num       = OCON_NUM,
+        .ocon_num       = 5,
         .target_type    = TARGET_XEN_OLD,
     },
     {
         .version        = POLICYDB_VERSION_AVTAB,
         .sym_num        = SYM_NUM,
-        .ocon_num       = OCON_NUM,
+        .ocon_num       = 5,
         .target_type    = TARGET_XEN_OLD,
     },
     {
        .version        = POLICYDB_VERSION_RANGETRANS,
        .sym_num        = SYM_NUM,
-       .ocon_num       = OCON_NUM,
+       .ocon_num       = 5,
         .target_type    = TARGET_XEN_OLD,
     },
     {
        .version        = POLICYDB_VERSION_POLCAP,
        .sym_num        = SYM_NUM,
-       .ocon_num       = OCON_NUM,
+       .ocon_num       = 5,
         .target_type    = TARGET_XEN_OLD,
     },
     {
        .version        = POLICYDB_VERSION_PERMISSIVE,
        .sym_num        = SYM_NUM,
-       .ocon_num       = OCON_NUM,
+       .ocon_num       = 5,
         .target_type    = TARGET_XEN_OLD,
     },
     {
@@ -134,7 +134,13 @@ static struct policydb_compat_info policydb_compat[] = {
     {
        .version        = POLICYDB_VERSION_BOUNDARY,
        .sym_num        = SYM_NUM,
-       .ocon_num       = OCON_NUM,
+       .ocon_num       = OCON_DEVICE + 1,
+        .target_type    = TARGET_XEN,
+    },
+    {
+       .version        = POLICYDB_VERSION_AARCH,
+       .sym_num        = SYM_NUM,
+       .ocon_num       = OCON_DTREE + 1,
         .target_type    = TARGET_XEN,
     },
 };
@@ -634,7 +640,7 @@ static void ocontext_destroy(struct ocontext *c, int i)
 {
     context_destroy(&c->context[0]);
     context_destroy(&c->context[1]);
-    if ( i == OCON_ISID )
+    if ( i == OCON_ISID || i == OCON_DTREE )
         xfree(c->u.name);
     xfree(c);
 }
@@ -1999,11 +2005,23 @@ int policydb_read(struct policydb *p, void *fp)
                         "Old xen policy does not support iomemcon");
                     goto bad;
                 }
-                rc = next_entry(buf, fp, sizeof(u32) *2);
-                if ( rc < 0 )
-                    goto bad;
-                c->u.iomem.low_iomem = le32_to_cpu(buf[0]);
-                c->u.iomem.high_iomem = le32_to_cpu(buf[1]);
+                if ( p->policyvers >= POLICYDB_VERSION_AARCH )
+                {
+                    u64 b64[2];
+                    rc = next_entry(b64, fp, sizeof(u64) *2);
+                    if ( rc < 0 )
+                        goto bad;
+                    c->u.iomem.low_iomem = le64_to_cpu(b64[0]);
+                    c->u.iomem.high_iomem = le64_to_cpu(b64[1]);
+                }
+                else
+                {
+                    rc = next_entry(buf, fp, sizeof(u32) *2);
+                    if ( rc < 0 )
+                        goto bad;
+                    c->u.iomem.low_iomem = le32_to_cpu(buf[0]);
+                    c->u.iomem.high_iomem = le32_to_cpu(buf[1]);
+                }
                 rc = context_read_and_validate(&c->context[0], p, fp);
                 if ( rc )
                     goto bad;
@@ -2023,6 +2041,29 @@ int policydb_read(struct policydb *p, void *fp)
                 if ( rc )
                     goto bad;
                 break;
+            case OCON_DTREE:
+                if ( p->target_type != TARGET_XEN )
+                {
+                    printk(KERN_ERR
+                        "Old xen policy does not support devicetreecon");
+                    goto bad;
+                }
+                rc = next_entry(buf, fp, sizeof(u32));
+                if ( rc < 0 )
+                    goto bad;
+                len = le32_to_cpu(buf[0]);
+                rc = -ENOMEM;
+                c->u.name = xmalloc_array(char, len + 1);
+                if (!c->u.name)
+                    goto bad;
+                rc = next_entry(c->u.name, fp, len);
+                if ( rc < 0 )
+                    goto bad;
+                c->u.name[len] = 0;
+                rc = context_read_and_validate(&c->context[0], p, fp);
+                if ( rc )
+                    goto bad;
+                break;
             default:
                 printk(KERN_ERR
                        "Flask:  unsupported object context config data\n");
diff --git a/xen/xsm/flask/ss/policydb.h b/xen/xsm/flask/ss/policydb.h
index b176300..30be71a 100644
--- a/xen/xsm/flask/ss/policydb.h
+++ b/xen/xsm/flask/ss/policydb.h
@@ -154,8 +154,8 @@ struct ocontext {
                 u32 high_ioport;
         } ioport;
         struct {
-                u32 low_iomem;
-                u32 high_iomem;
+                u64 low_iomem;
+                u64 high_iomem;
         } iomem;
     } u;
     struct context context[2];    /* security context(s) */
@@ -180,7 +180,8 @@ struct ocontext {
 #define OCON_IOPORT  2    /* io ports */
 #define OCON_IOMEM   3    /* io memory */
 #define OCON_DEVICE  4    /* pci devices */
-#define OCON_NUM     5
+#define OCON_DTREE   5    /* device tree nodes */
+#define OCON_NUM     6
 #define OCON_NUM_OLD 7
 
 /* The policy database */
diff --git a/xen/xsm/flask/ss/services.c b/xen/xsm/flask/ss/services.c
index f0e459a..ba2336e 100644
--- a/xen/xsm/flask/ss/services.c
+++ b/xen/xsm/flask/ss/services.c
@@ -1831,6 +1831,41 @@ out:
     return rc;
 }
 
+int security_devicetree_sid(const char *path, u32 *out_sid)
+{
+    struct ocontext *c;
+    int rc = 0;
+
+    POLICY_RDLOCK;
+
+    c = policydb.ocontexts[OCON_DTREE];
+    while ( c )
+    {
+        if ( strcmp(c->u.name, path) == 0 )
+            break;
+        c = c->next;
+    }
+
+    if ( c )
+    {
+        if ( !c->sid[0] )
+        {
+            rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]);
+            if ( rc )
+                goto out;
+        }
+        *out_sid = c->sid[0];
+    }
+    else
+    {
+        *out_sid = SECINITSID_DEVICE;
+    }
+
+out:
+    POLICY_RDUNLOCK;
+    return rc;
+}
+
 int security_find_bool(const char *name)
 {
     int i, rv = -ENOENT;
@@ -2131,7 +2166,7 @@ int security_ocontext_add( u32 ocon, unsigned long low, 
unsigned long high
                 c->u.iomem.high_iomem == high && c->sid[0] == sid)
                 break;
 
-            printk("%s: IO Memory overlap with entry %#x - %#x\n",
+            printk("%s: IO Memory overlap with entry %#lx - %#lx\n",
                    __FUNCTION__, c->u.iomem.low_iomem,
                    c->u.iomem.high_iomem);
             ret = -EEXIST;
@@ -2188,7 +2223,7 @@ int security_ocontext_add( u32 ocon, unsigned long low, 
unsigned long high
     return ret;
 }
 
-int security_ocontext_del( u32 ocon, unsigned int low, unsigned int high )
+int security_ocontext_del( u32 ocon, unsigned long low, unsigned long high )
 {
     int ret = 0;
     struct ocontext *c, *before_c;
@@ -2217,7 +2252,7 @@ int security_ocontext_del( u32 ocon, unsigned int low, 
unsigned int high )
             }
         }
 
-        printk("%s: ocontext not found: pirq %d\n", __FUNCTION__, low);
+        printk("%s: ocontext not found: pirq %ld\n", __FUNCTION__, low);
         ret = -ENOENT;
         break;
 
@@ -2243,7 +2278,7 @@ int security_ocontext_del( u32 ocon, unsigned int low, 
unsigned int high )
             }
         }
 
-        printk("%s: ocontext not found: ioport %#x - %#x\n", __FUNCTION__,
+        printk("%s: ocontext not found: ioport %#lx - %#lx\n", __FUNCTION__,
                 low, high);
         ret = -ENOENT;
         break;
@@ -2270,7 +2305,7 @@ int security_ocontext_del( u32 ocon, unsigned int low, 
unsigned int high )
             }
         }
 
-        printk("%s: ocontext not found: iomem %#x - %#x\n", __FUNCTION__,
+        printk("%s: ocontext not found: iomem %#lx - %#lx\n", __FUNCTION__,
                 low, high);
         ret = -ENOENT;
         break;
@@ -2296,7 +2331,7 @@ int security_ocontext_del( u32 ocon, unsigned int low, 
unsigned int high )
             }
         }
 
-        printk("%s: ocontext not found: pcidevice %#x\n", __FUNCTION__, low);
+        printk("%s: ocontext not found: pcidevice %#lx\n", __FUNCTION__, low);
         ret = -ENOENT;
         break;
 
@@ -2308,3 +2343,67 @@ int security_ocontext_del( u32 ocon, unsigned int low, 
unsigned int high )
     POLICY_WRUNLOCK;
     return ret;
 }
+
+int security_devicetree_setlabel(char *path, u32 sid)
+{
+    int ret = 0;
+    struct ocontext *c;
+    struct ocontext **pcurr;
+    struct ocontext *add = NULL;
+
+    if ( sid )
+    {
+        add = xzalloc(struct ocontext);
+        if ( add == NULL )
+        {
+            xfree(path);
+            return -ENOMEM;
+        }
+        add->sid[0] = sid;
+        add->u.name = path;
+    }
+    else
+    {
+        ret = -ENOENT;
+    }
+
+    POLICY_WRLOCK;
+
+    pcurr = &policydb.ocontexts[OCON_DTREE];
+    c = *pcurr;
+    while ( c )
+    {
+        if ( strcmp(c->u.name, path) == 0 )
+        {
+            if ( sid )
+            {
+                ret = -EEXIST;
+                break;
+            }
+            else
+            {
+                *pcurr = c->next;
+                xfree(c->u.name);
+                xfree(c);
+                ret = 0;
+                break;
+            }
+        }
+        pcurr = &c->next;
+        c = *pcurr;
+    }
+
+    if ( add && ret == 0 )
+    {
+        add->next = policydb.ocontexts[OCON_DTREE];
+        policydb.ocontexts[OCON_DTREE] = add;
+        add = NULL;
+        path = NULL;
+    }
+
+    POLICY_WRUNLOCK;
+
+    xfree(add);
+    xfree(path);
+    return ret;
+}
-- 
2.1.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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