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] Update Xen Flask module to policy.24.

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Update Xen Flask module to policy.24.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 19 Aug 2009 07:40:29 -0700
Delivery-date: Wed, 19 Aug 2009 07:42:50 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
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/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/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 Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1250688172 -3600
# Node ID 001a99da12947d3e2caadafc7458e40a8ba92fbf
# Parent  b79da5f5ffe7d1463176a6975e155f92ac3b10af
Update Xen Flask module to policy.24.

This is a back-port of the latest SELinux code to Xen, adjusted
for Xen coding style and interfaces.  Unneeded functionality such
as most object context config data, handle_unknown, MLS field
defaulting, etc has been omitted.

Signed-off-by:  Stephen D. Smalley <sds@xxxxxxxxxxxxx>
Signed-off-by: George S. Coker, II <gscoker@xxxxxxxxxxxxxx>
---
 tools/flask/policy/Makefile      |    2 
 xen/xsm/flask/avc.c              |  264 +++++++++--------
 xen/xsm/flask/flask_op.c         |    2 
 xen/xsm/flask/include/avc_ss.h   |   23 +
 xen/xsm/flask/include/security.h |   14 
 xen/xsm/flask/ss/avtab.c         |  144 ++++++---
 xen/xsm/flask/ss/avtab.h         |   20 -
 xen/xsm/flask/ss/conditional.c   |   23 -
 xen/xsm/flask/ss/conditional.h   |    2 
 xen/xsm/flask/ss/context.h       |   33 +-
 xen/xsm/flask/ss/ebitmap.c       |  231 +++++++--------
 xen/xsm/flask/ss/ebitmap.h       |   94 ++++--
 xen/xsm/flask/ss/hashtab.c       |   10 
 xen/xsm/flask/ss/hashtab.h       |   12 
 xen/xsm/flask/ss/mls.c           |  351 ++++++++--------------
 xen/xsm/flask/ss/mls.h           |    6 
 xen/xsm/flask/ss/policydb.c      |  415 +++++++++++++++++++++++---
 xen/xsm/flask/ss/policydb.h      |   31 +-
 xen/xsm/flask/ss/services.c      |  600 +++++++++++++++++++++++++++------------
 xen/xsm/flask/ss/sidtab.c        |    2 
 xen/xsm/flask/ss/symtab.c        |    8 
 21 files changed, 1496 insertions(+), 791 deletions(-)

diff -r b79da5f5ffe7 -r 001a99da1294 tools/flask/policy/Makefile
--- a/tools/flask/policy/Makefile       Wed Aug 19 14:22:15 2009 +0100
+++ b/tools/flask/policy/Makefile       Wed Aug 19 14:22:52 2009 +0100
@@ -20,7 +20,7 @@
 # By default, checkpolicy will create the highest
 # version policy it supports.  Setting this will
 # override the version.
-OUTPUT_POLICY = 20
+#OUTPUT_POLICY = 20
 
 # Policy Type
 # strict, targeted,
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/avc.c
--- a/xen/xsm/flask/avc.c       Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/avc.c       Wed Aug 19 14:22:52 2009 +0100
@@ -32,12 +32,7 @@
 #include "avc.h"
 #include "avc_ss.h"
 
-static const struct av_perm_to_string
-{
-    u16 tclass;
-    u32 value;
-    const char *name;
-} av_perm_to_string[] = {
+static const struct av_perm_to_string av_perm_to_string[] = {
 #define S_(c, v, s) { c, v, s },
 #include "av_perm_to_string.h"
 #undef S_
@@ -57,15 +52,20 @@ static const char *class_to_string[] = {
 #undef TE_
 #undef S_
 
-static const struct av_inherit
-{
-    u16 tclass;
-    const char **common_pts;
-    u32 common_base;
-} av_inherit[] = {
-#define S_(c, i, b) { c, common_##i##_perm_to_string, b },
+static const struct av_inherit av_inherit[] = {
+#define S_(c, i, b) { .tclass = c, .common_pts = common_##i##_perm_to_string, \
+                     .common_base = b },
 #include "av_inherit.h"
 #undef S_
+};
+
+const struct selinux_class_perm selinux_class_perm = {
+       .av_perm_to_string = av_perm_to_string,
+       .av_pts_len = ARRAY_SIZE(av_perm_to_string),
+       .class_to_string = class_to_string,
+       .cts_len = ARRAY_SIZE(class_to_string),
+       .av_inherit = av_inherit,
+       .av_inherit_len = ARRAY_SIZE(av_inherit)
 };
 
 #define AVC_CACHE_SLOTS            512
@@ -86,17 +86,16 @@ struct avc_entry {
     u32            tsid;
     u16            tclass;
     struct av_decision    avd;
-    atomic_t        used;    /* used recently */
 };
 
 struct avc_node {
     struct avc_entry    ae;
-    struct list_head    list;
+    struct hlist_node   list; /* anchored in avc_cache->slots[i] */
     struct rcu_head     rhead;
 };
 
 struct avc_cache {
-    struct list_head    slots[AVC_CACHE_SLOTS];
+    struct hlist_head    slots[AVC_CACHE_SLOTS]; /* head for avc_node->list */
     spinlock_t        slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */
     atomic_t        lru_hint;    /* LRU hint for reclaim scan */
     atomic_t        active_nodes;
@@ -241,7 +240,7 @@ void __init avc_init(void)
 
     for ( i = 0; i < AVC_CACHE_SLOTS; i++ )
     {
-        INIT_LIST_HEAD(&avc_cache.slots[i]);
+        INIT_HLIST_HEAD(&avc_cache.slots[i]);
         spin_lock_init(&avc_cache.slots_lock[i]);
     }
     atomic_set(&avc_cache.active_nodes, 0);
@@ -254,6 +253,7 @@ int avc_get_hash_stats(char *buf, uint32
 {
     int i, chain_len, max_chain_len, slots_used;
     struct avc_node *node;
+    struct hlist_head *head;
 
     rcu_read_lock();
 
@@ -261,11 +261,14 @@ int avc_get_hash_stats(char *buf, uint32
     max_chain_len = 0;
     for ( i = 0; i < AVC_CACHE_SLOTS; i++ )
     {
-        if ( !list_empty(&avc_cache.slots[i]) )
-        {
+        head = &avc_cache.slots[i];
+        if ( !hlist_empty(head) )
+        {
+           struct hlist_node *next;
+
             slots_used++;
             chain_len = 0;
-            list_for_each_entry_rcu(node, &avc_cache.slots[i], list)
+            hlist_for_each_entry_rcu(node, next, head, list)
                 chain_len++;
             if ( chain_len > max_chain_len )
                 max_chain_len = chain_len;
@@ -289,7 +292,7 @@ static void avc_node_free(struct rcu_hea
 
 static void avc_node_delete(struct avc_node *node)
 {
-    list_del_rcu(&node->list);
+    hlist_del_rcu(&node->list);
     call_rcu(&node->rhead, avc_node_free);
     atomic_dec(&avc_cache.active_nodes);
 }
@@ -303,7 +306,7 @@ static void avc_node_kill(struct avc_nod
 
 static void avc_node_replace(struct avc_node *new, struct avc_node *old)
 {
-    list_replace_rcu(&old->list, &new->list);
+    hlist_replace_rcu(&old->list, &new->list);
     call_rcu(&old->rhead, avc_node_free);
     atomic_dec(&avc_cache.active_nodes);
 }
@@ -312,31 +315,34 @@ static inline int avc_reclaim_node(void)
 {
     struct avc_node *node;
     int hvalue, try, ecx;
-       unsigned long flags;
+    unsigned long flags;
+    struct hlist_head *head;
+    struct hlist_node *next;
+    spinlock_t *lock;
 
     for ( try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++ )
     {
         atomic_inc(&avc_cache.lru_hint);
         hvalue =  atomic_read(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1);
-
-               spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flags);
-
-        list_for_each_entry(node, &avc_cache.slots[hvalue], list)
-        {
-            if ( atomic_dec_and_test(&node->ae.used) )
-            {
-                /* Recently Unused */
+        head = &avc_cache.slots[hvalue];
+        lock = &avc_cache.slots_lock[hvalue];
+
+        spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flags);
+        rcu_read_lock();
+        hlist_for_each_entry(node, next, head, list)
+        {
                 avc_node_delete(node);
                 avc_cache_stats_incr(reclaims);
                 ecx++;
                 if ( ecx >= AVC_CACHE_RECLAIM )
                 {
-                                       
spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
-                    goto out;
+                 rcu_read_unlock();
+                 spin_unlock_irqrestore(lock, flags);
+                 goto out;
                 }
-            }
-        }
-               spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
+        }
+        rcu_read_unlock();
+        spin_unlock_irqrestore(lock, flags);
     }    
 out:
     return ecx;
@@ -352,8 +358,7 @@ static struct avc_node *avc_alloc_node(v
 
     memset(node, 0, sizeof(*node));
     INIT_RCU_HEAD(&node->rhead);
-    INIT_LIST_HEAD(&node->list);
-    atomic_set(&node->ae.used, 1);
+    INIT_HLIST_NODE(&node->list);
     avc_cache_stats_incr(allocations);
 
     atomic_inc(&avc_cache.active_nodes);
@@ -364,40 +369,35 @@ out:
     return node;
 }
 
-static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 
tclass, struct avc_entry *ae)
+static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid,
+                              u16 tclass, struct av_decision *avd)
 {
     node->ae.ssid = ssid;
     node->ae.tsid = tsid;
     node->ae.tclass = tclass;
-    memcpy(&node->ae.avd, &ae->avd, sizeof(node->ae.avd));
+    memcpy(&node->ae.avd, avd, sizeof(node->ae.avd));
 }
 
 static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass)
 {
     struct avc_node *node, *ret = NULL;
     int hvalue;
+    struct hlist_head *head;
+    struct hlist_node *next;
 
     hvalue = avc_hash(ssid, tsid, tclass);
-    list_for_each_entry_rcu(node, &avc_cache.slots[hvalue], list)
-    {
-        if ( ssid == node->ae.ssid && tclass == node->ae.tclass && 
-                                                        tsid == node->ae.tsid )
+    head = &avc_cache.slots[hvalue];
+    hlist_for_each_entry_rcu(node, next, head, list)
+    {
+        if ( ssid == node->ae.ssid &&
+            tclass == node->ae.tclass &&
+            tsid == node->ae.tsid )
         {
             ret = node;
             break;
         }
     }
 
-    if ( ret == NULL )
-    {
-        /* cache miss */
-        goto out;
-    }
-
-    /* cache hit */
-    if ( atomic_read(&ret->ae.used) != 1 )
-        atomic_set(&ret->ae.used, 1);
-out:
     return ret;
 }
 
@@ -415,22 +415,18 @@ out:
  * then this function return the avc_node.
  * Otherwise, this function returns NULL.
  */
-static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass, u32 
requested)
+static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass)
 {
     struct avc_node *node;
 
     avc_cache_stats_incr(lookups);
     node = avc_search_node(ssid, tsid, tclass);
 
-    if ( node && ((node->ae.avd.decided & requested) == requested) )
-    {
+    if ( node )
         avc_cache_stats_incr(hits);
-        goto out;
-    }
-
-    node = NULL;
-    avc_cache_stats_incr(misses);
-out:
+    else
+        avc_cache_stats_incr(misses);
+
     return node;
 }
 
@@ -477,34 +473,43 @@ static int avc_latest_notif_update(int s
  * the access vectors into a cache entry, returns
  * avc_node inserted. Otherwise, this function returns NULL.
  */
-static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct 
avc_entry *ae)
+static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass,
+                                   struct av_decision *avd)
 {
     struct avc_node *pos, *node = NULL;
     int hvalue;
-       unsigned long flag;
-
-    if ( avc_latest_notif_update(ae->avd.seqno, 1) )
+    unsigned long flag;
+
+    if ( avc_latest_notif_update(avd->seqno, 1) )
         goto out;
 
     node = avc_alloc_node();
     if ( node )
     {
+        struct hlist_head *head;
+        struct hlist_node *next;
+        spinlock_t *lock;
+
         hvalue = avc_hash(ssid, tsid, tclass);
-        avc_node_populate(node, ssid, tsid, tclass, ae);
-
-               spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag);
-        list_for_each_entry(pos, &avc_cache.slots[hvalue], list)
-        {
-            if ( pos->ae.ssid == ssid && pos->ae.tsid == tsid &&
-                                                    pos->ae.tclass == tclass )
+        avc_node_populate(node, ssid, tsid, tclass, avd);
+
+        head = &avc_cache.slots[hvalue];
+        lock = &avc_cache.slots_lock[hvalue];
+
+        spin_lock_irqsave(lock, flag);
+        hlist_for_each_entry(pos, next, head, list)
+        {
+            if ( pos->ae.ssid == ssid &&
+                 pos->ae.tsid == tsid &&
+                 pos->ae.tclass == tclass )
             {
                 avc_node_replace(node, pos);
                 goto found;
             }
         }
-        list_add_rcu(&node->list, &avc_cache.slots[hvalue]);
+        hlist_add_head_rcu(&node->list, head);
 found:
-               spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flag);
+        spin_unlock_irqrestore(lock, flag);
     }
 out:
     return node;
@@ -622,11 +627,15 @@ static inline int avc_sidcmp(u32 x, u32 
  * otherwise, this function update the AVC entry. The original AVC-entry object
  * will release later by RCU.
  */
-static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 
tclass)
+static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 
tclass,
+                          u32 seqno)
 {
     int hvalue, rc = 0;
-       unsigned long flag;
+    unsigned long flag;
     struct avc_node *pos, *node, *orig = NULL;
+    struct hlist_head *head;
+    struct hlist_node *next;
+    spinlock_t *lock;
     
     node = avc_alloc_node();
     if ( !node )
@@ -636,12 +645,18 @@ static int avc_update_node(u32 event, u3
     }
 
     hvalue = avc_hash(ssid, tsid, tclass);    
-       spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag);
-
-    list_for_each_entry(pos, &avc_cache.slots[hvalue], list)
-    {
-        if ( ssid==pos->ae.ssid && tsid==pos->ae.tsid &&
-                                                        tclass==pos->ae.tclass 
)
+
+    head = &avc_cache.slots[hvalue];
+    lock = &avc_cache.slots_lock[hvalue];
+
+    spin_lock_irqsave(lock, flag);
+
+    hlist_for_each_entry(pos, next, head, list)
+    {
+        if ( ssid == pos->ae.ssid &&
+            tsid == pos->ae.tsid &&
+            tclass == pos->ae.tclass &&
+            seqno == pos->ae.avd.seqno )
         {
             orig = pos;
             break;
@@ -659,7 +674,7 @@ static int avc_update_node(u32 event, u3
      * Copy and replace original node.
      */
 
-    avc_node_populate(node, ssid, tsid, tclass, &orig->ae);
+    avc_node_populate(node, ssid, tsid, tclass, &orig->ae.avd);
 
     switch ( event )
     {
@@ -685,7 +700,7 @@ static int avc_update_node(u32 event, u3
     }
     avc_node_replace(node, orig);
 out_unlock:
-       spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flag);
+    spin_unlock_irqrestore(lock, flag);
 out:
     return rc;
 }
@@ -697,31 +712,40 @@ int avc_ss_reset(u32 seqno)
 int avc_ss_reset(u32 seqno)
 {
     struct avc_callback_node *c;
-    int i, rc = 0;
-       unsigned long flag;
+    int i, rc = 0, tmprc;
+    unsigned long flag;
     struct avc_node *node;
+    struct hlist_head *head;
+    struct hlist_node *next;
+    spinlock_t *lock;
 
     for ( i = 0; i < AVC_CACHE_SLOTS; i++ )
     {
-               spin_lock_irqsave(&avc_cache.slots_lock[i], flag);
-        list_for_each_entry(node, &avc_cache.slots[i], list)
+        head = &avc_cache.slots[i];
+        lock = &avc_cache.slots_lock[i];
+
+        spin_lock_irqsave(lock, flag);
+        rcu_read_lock();
+        hlist_for_each_entry(node, next, head, list)
             avc_node_delete(node);
-               spin_unlock_irqrestore(&avc_cache.slots_lock[i], flag);
+        rcu_read_unlock();
+        spin_unlock_irqrestore(lock, flag);
     }
     
     for ( c = avc_callbacks; c; c = c->next )
     {
         if ( c->events & AVC_CALLBACK_RESET )
         {
-            rc = c->callback(AVC_CALLBACK_RESET,
-                     0, 0, 0, 0, NULL);
-            if ( rc )
-                goto out;
+            tmprc = c->callback(AVC_CALLBACK_RESET,
+                                0, 0, 0, 0, NULL);
+            /* save the first error encountered for the return
+               value and continue processing the callbacks */
+            if ( !rc )
+                rc = tmprc;
         }
     }
 
     avc_latest_notif_update(seqno, 0);
-out:
     return rc;
 }
 
@@ -745,41 +769,47 @@ out:
  * should be released for the auditing.
  */
 int avc_has_perm_noaudit(u32 ssid, u32 tsid, u16 tclass, u32 requested,
-                                                     struct av_decision *avd)
+                         struct av_decision *in_avd)
 {
     struct avc_node *node;
-    struct avc_entry entry, *p_ae;
+    struct av_decision avd_entry, *avd;
     int rc = 0;
     u32 denied;
 
+    BUG_ON(!requested);
+
     rcu_read_lock();
 
-    node = avc_lookup(ssid, tsid, tclass, requested);
+    node = avc_lookup(ssid, tsid, tclass);
     if ( !node )
     {
         rcu_read_unlock();
-        rc = security_compute_av(ssid,tsid,tclass,requested,&entry.avd);
+
+        if ( in_avd )
+            avd = in_avd;
+        else
+            avd = &avd_entry;
+
+        rc = security_compute_av(ssid,tsid,tclass,requested,avd);
         if ( rc )
             goto out;
         rcu_read_lock();
-        node = avc_insert(ssid,tsid,tclass,&entry);
-    }
-
-    p_ae = node ? &node->ae : &entry;
-
-    if ( avd )
-        memcpy(avd, &p_ae->avd, sizeof(*avd));
-
-    denied = requested & ~(p_ae->avd.allowed);
-
-    if ( !requested || denied )
-    {
-        if ( flask_enforcing )
+        node = avc_insert(ssid,tsid,tclass,avd);
+    } else {
+        if ( in_avd )
+            memcpy(in_avd, &node->ae.avd, sizeof(*in_avd));
+        avd = &node->ae.avd;
+    }
+
+    denied = requested & ~(avd->allowed);
+
+    if ( denied )
+    {
+        if ( !flask_enforcing || (avd->flags & AVD_FLAGS_PERMISSIVE) )
+            avc_update_node(AVC_CALLBACK_GRANT,requested,
+                            ssid,tsid,tclass,avd->seqno);
+        else
             rc = -EACCES;
-        else
-            if ( node )
-                avc_update_node(AVC_CALLBACK_GRANT,requested,
-                        ssid,tsid,tclass);
     }
 
     rcu_read_unlock();
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/flask_op.c
--- a/xen/xsm/flask/flask_op.c  Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/flask_op.c  Wed Aug 19 14:22:52 2009 +0100
@@ -346,7 +346,7 @@ static int flask_security_access(char *b
 
     memset(buf, 0, size);
     length = snprintf(buf, size, "%x %x %x %x %u", 
-                                        avd.allowed, avd.decided,
+                                        avd.allowed, 0xffffffff,
                                         avd.auditallow, avd.auditdeny, 
                                         avd.seqno);
                 
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/include/avc_ss.h
--- a/xen/xsm/flask/include/avc_ss.h    Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/include/avc_ss.h    Wed Aug 19 14:22:52 2009 +0100
@@ -10,5 +10,28 @@
 
 int avc_ss_reset(u32 seqno);
 
+struct av_perm_to_string {
+    u16 tclass;
+    u32 value;
+    const char *name;
+};
+
+struct av_inherit {
+    const char **common_pts;
+    u32 common_base;
+    u16 tclass;
+};
+
+struct selinux_class_perm {
+    const struct av_perm_to_string *av_perm_to_string;
+    u32 av_pts_len;
+    u32 cts_len;
+    const char **class_to_string;
+    const struct av_inherit *av_inherit;
+    u32 av_inherit_len;
+};
+
+extern const struct selinux_class_perm selinux_class_perm;
+
 #endif /* _FLASK_AVC_SS_H_ */
 
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/include/security.h
--- a/xen/xsm/flask/include/security.h  Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/include/security.h  Wed Aug 19 14:22:52 2009 +0100
@@ -26,10 +26,14 @@
 #define POLICYDB_VERSION_VALIDATETRANS    19
 #define POLICYDB_VERSION_MLS        19
 #define POLICYDB_VERSION_AVTAB        20
+#define POLICYDB_VERSION_RANGETRANS    21
+#define POLICYDB_VERSION_POLCAP                22
+#define POLICYDB_VERSION_PERMISSIVE    23
+#define POLICYDB_VERSION_BOUNDARY      24
 
 /* Range of policy versions we understand*/
 #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_AVTAB
+#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_BOUNDARY
 
 #ifdef FLASK_BOOTPARAM
 extern int flask_enabled;
@@ -43,11 +47,14 @@ int security_load_policy(void * data, si
 
 struct av_decision {
     u32 allowed;
-    u32 decided;
     u32 auditallow;
     u32 auditdeny;
     u32 seqno;
+    u32 flags;
 };
+
+/* definitions of av_decision.flags */
+#define AVD_FLAGS_PERMISSIVE   0x0001
 
 int security_compute_av(u32 ssid, u32 tsid, u16 tclass, u32 requested,
                                                     struct av_decision *avd);
@@ -61,9 +68,6 @@ int security_sid_to_context(u32 sid, cha
 int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len);
 
 int security_context_to_sid(char *scontext, u32 scontext_len, u32 *out_sid);
-
-int security_context_to_sid_default(char *scontext, u32 scontext_len, 
-                                                    u32 *out_sid, u32 def_sid);
 
 int security_get_user_sids(u32 callsid, char *username, u32 **sids, u32 *nel);
 
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/avtab.c
--- a/xen/xsm/flask/ss/avtab.c  Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/avtab.c  Wed Aug 19 14:22:52 2009 +0100
@@ -12,6 +12,9 @@
  *    This program is free software; you can redistribute it and/or modify
  *      it under the terms of the GNU General Public License as published by
  *    the Free Software Foundation, version 2.
+ *
+ * Updated: Yuichi Nakamura <ynakam@xxxxxxxxxxxxxx>
+ *     Tuned number of hash slots for avtab to reduce memory usage
  */
 
 /* Ported to Xen 3.0, George Coker, <gscoker@xxxxxxxxxxxxxx> */
@@ -25,11 +28,11 @@
 #include "avtab.h"
 #include "policydb.h"
 
-#define AVTAB_HASH(keyp) \
-((keyp->target_class + \
- (keyp->target_type << 2) + \
- (keyp->source_type << 9)) & \
- AVTAB_HASH_MASK)
+static inline int avtab_hash(struct avtab_key *keyp, u16 mask)
+{
+    return ((keyp->target_class + (keyp->target_type << 2) +
+             (keyp->source_type << 9)) & mask);
+}
 
 static struct avtab_node* avtab_insert_node(struct avtab *h, int hvalue,
     struct avtab_node * prev, struct avtab_node * cur, struct avtab_key *key, 
@@ -64,10 +67,10 @@ static int avtab_insert(struct avtab *h,
     struct avtab_node *prev, *cur, *newnode;
     u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
 
-    if ( !h )
+    if ( !h || !h->htable )
         return -EINVAL;
 
-    hvalue = AVTAB_HASH(key);
+    hvalue = avtab_hash(key, h->mask);
     for ( prev = NULL, cur = h->htable[hvalue]; cur;
                                                     prev = cur, cur = 
cur->next)
     {
@@ -105,9 +108,9 @@ struct avtab_node * avtab_insert_nonuniq
     struct avtab_node *prev, *cur, *newnode;
     u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
 
-    if ( !h )
+    if ( !h || !h->htable )
         return NULL;
-    hvalue = AVTAB_HASH(key);
+    hvalue = avtab_hash(key, h->mask);
     for ( prev = NULL, cur = h->htable[hvalue]; cur; 
                                                 prev = cur, cur = cur->next )
     {
@@ -137,10 +140,10 @@ struct avtab_datum *avtab_search(struct 
     struct avtab_node *cur;
     u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
 
-    if ( !h )
+    if ( !h || !h->htable )
         return NULL;
 
-    hvalue = AVTAB_HASH(key);
+    hvalue = avtab_hash(key, h->mask);
     for ( cur = h->htable[hvalue]; cur; cur = cur->next )
     {
         if ( key->source_type == cur->key.source_type &&
@@ -172,10 +175,10 @@ struct avtab_node* avtab_search_node(str
     struct avtab_node *cur;
     u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
 
-    if ( !h )
+    if ( !h || !h->htable )
         return NULL;
 
-    hvalue = AVTAB_HASH(key);
+    hvalue = avtab_hash(key, h->mask);
     for ( cur = h->htable[hvalue]; cur; cur = cur->next )
     {
         if ( key->source_type == cur->key.source_type &&
@@ -235,7 +238,7 @@ void avtab_destroy(struct avtab *h)
     if ( !h || !h->htable )
         return;
 
-    for ( i = 0; i < AVTAB_SIZE; i++ )
+    for ( i = 0; i < h->nslot; i++ )
     {
         cur = h->htable[i];
         while ( cur != NULL )
@@ -248,19 +251,52 @@ void avtab_destroy(struct avtab *h)
     }
     xfree(h->htable);
     h->htable = NULL;
-}
-
+    h->nslot = 0;
+    h->mask = 0;
+}
 
 int avtab_init(struct avtab *h)
 {
+    h->htable = NULL;
+    h->nel = 0;
+    return 0;
+}
+
+int avtab_alloc(struct avtab *h, u32 nrules)
+{
+    u16 mask = 0;
+    u32 shift = 0;
+    u32 work = nrules;
+    u32 nslot = 0;
     int i;
 
-    h->htable = (void *)xmalloc_array(struct avtab_node, AVTAB_SIZE);
+    if ( nrules == 0 )
+        goto avtab_alloc_out;
+
+    while ( work )
+    {
+        work  = work >> 1;
+        shift++;
+       }
+       if ( shift > 2 )
+        shift = shift - 2;
+    nslot = 1 << shift;
+    if ( nslot > MAX_AVTAB_SIZE )
+        nslot = MAX_AVTAB_SIZE;
+    mask = nslot - 1;
+
+    h->htable = xmalloc_array(struct avtab_node *, nslot);
     if ( !h->htable )
         return -ENOMEM;
-    for ( i = 0; i < AVTAB_SIZE; i++ )
+    for ( i = 0; i < nslot; i++ )
         h->htable[i] = NULL;
+
+avtab_alloc_out:
     h->nel = 0;
+    h->nslot = nslot;
+    h->mask = mask;
+    printk(KERN_DEBUG "Flask: %d avtab hash slots, %d rules.\n",
+           h->nslot, nrules);
     return 0;
 }
 
@@ -271,7 +307,7 @@ void avtab_hash_eval(struct avtab *h, ch
 
     slots_used = 0;
     max_chain_len = 0;
-    for ( i = 0; i < AVTAB_SIZE; i++ )
+    for ( i = 0; i < h->nslot; i++ )
     {
         cur = h->htable[i];
         if ( cur )
@@ -290,7 +326,7 @@ void avtab_hash_eval(struct avtab *h, ch
     }
 
     printk(KERN_INFO "%s:  %d entries and %d/%d buckets used, longest "
-           "chain length %d\n", tag, h->nel, slots_used, AVTAB_SIZE,
+           "chain length %d\n", tag, h->nel, slots_used, h->nslot,
                                                                max_chain_len);
 }
 
@@ -303,17 +339,18 @@ static uint16_t spec_order[] = {
     AVTAB_MEMBER
 };
 
-int avtab_read_item(void *fp, u32 vers, struct avtab *a,
+int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
                             int (*insertf)(struct avtab *a, struct avtab_key 
*k,
                                     struct avtab_datum *d, void *p), void *p)
 {
     __le16 buf16[4];
     u16 enabled;
     __le32 buf32[7];
-    u32 items, items2, val;
+    u32 items, items2, val, vers = pol->policyvers;
     struct avtab_key key;
     struct avtab_datum datum;
     int i, rc;
+    unsigned set;
 
     memset(&key, 0, sizeof(struct avtab_key));
     memset(&datum, 0, sizeof(struct avtab_datum));
@@ -323,20 +360,20 @@ int avtab_read_item(void *fp, u32 vers, 
         rc = next_entry(buf32, fp, sizeof(u32));
         if ( rc < 0 )
         {
-            printk(KERN_ERR "security: avtab: truncated entry\n");
+            printk(KERN_ERR "Flask: avtab: truncated entry\n");
             return -1;
         }
         items2 = le32_to_cpu(buf32[0]);
         if ( items2 > ARRAY_SIZE(buf32) )
         {
-            printk(KERN_ERR "security: avtab: entry overflow\n");
+            printk(KERN_ERR "Flask: avtab: entry overflow\n");
             return -1;
 
         }
         rc = next_entry(buf32, fp, sizeof(u32)*items2);
         if ( rc < 0 )
         {
-            printk(KERN_ERR "security: avtab: truncated entry\n");
+            printk(KERN_ERR "Flask: avtab: truncated entry\n");
             return -1;
         }
         items = 0;
@@ -345,21 +382,21 @@ int avtab_read_item(void *fp, u32 vers, 
         key.source_type = (u16)val;
         if ( key.source_type != val )
         {
-            printk("security: avtab: truncated source type\n");
+            printk("Flask: avtab: truncated source type\n");
             return -1;
         }
         val = le32_to_cpu(buf32[items++]);
         key.target_type = (u16)val;
         if ( key.target_type != val )
         {
-            printk("security: avtab: truncated target type\n");
+            printk("Flask: avtab: truncated target type\n");
             return -1;
         }
         val = le32_to_cpu(buf32[items++]);
         key.target_class = (u16)val;
         if ( key.target_class != val )
         {
-            printk("security: avtab: truncated target class\n");
+            printk("Flask: avtab: truncated target class\n");
             return -1;
         }
 
@@ -368,12 +405,12 @@ int avtab_read_item(void *fp, u32 vers, 
 
         if ( !(val & (AVTAB_AV | AVTAB_TYPE)) )
         {
-            printk("security: avtab: null entry\n");
+            printk("Flask: avtab: null entry\n");
             return -1;
         }
         if ( (val & AVTAB_AV) && (val & AVTAB_TYPE) )
         {
-            printk("security: avtab: entry has both access vectors and 
types\n");
+            printk("Flask: avtab: entry has both access vectors and types\n");
             return -1;
         }
 
@@ -390,7 +427,7 @@ int avtab_read_item(void *fp, u32 vers, 
         }
 
         if ( items != items2 ) {
-            printk("security: avtab: entry only had %d items, expected %d\n", 
+            printk("Flask: avtab: entry only had %d items, expected %d\n",
                                                                 items2, items);
             return -1;
         }
@@ -400,7 +437,7 @@ int avtab_read_item(void *fp, u32 vers, 
     rc = next_entry(buf16, fp, sizeof(u16)*4);
     if ( rc < 0 )
     {
-        printk("security: avtab: truncated entry\n");
+        printk("Flask: avtab: truncated entry\n");
         return -1;
     }
 
@@ -410,13 +447,39 @@ int avtab_read_item(void *fp, u32 vers, 
     key.target_class = le16_to_cpu(buf16[items++]);
     key.specified = le16_to_cpu(buf16[items++]);
 
+    if ( !policydb_type_isvalid(pol, key.source_type) ||
+         !policydb_type_isvalid(pol, key.target_type) ||
+         !policydb_class_isvalid(pol, key.target_class) )
+    {
+        printk(KERN_ERR "Flask: avtab: invalid type or class\n");
+        return -1;
+    }
+
+    set = 0;
+    for ( i = 0; i < ARRAY_SIZE(spec_order); i++ )
+    {
+        if ( key.specified & spec_order[i] )
+            set++;
+    }
+    if ( !set || set > 1 )
+    {
+        printk(KERN_ERR "Flask:  avtab:  more than one specifier\n");
+        return -1;
+    }
+
     rc = next_entry(buf32, fp, sizeof(u32));
     if ( rc < 0 )
     {
-        printk("security: avtab: truncated entry\n");
+        printk("Flask: avtab: truncated entry\n");
         return -1;
     }
     datum.data = le32_to_cpu(*buf32);
+    if ( (key.specified & AVTAB_TYPE) &&
+         !policydb_type_isvalid(pol, datum.data) )
+    {
+        printk(KERN_ERR "Flask: avtab: invalid type\n");
+        return -1;
+    }
     return insertf(a, &key, &datum, p);
 }
 
@@ -426,7 +489,7 @@ static int avtab_insertf(struct avtab *a
     return avtab_insert(a, k, d);
 }
 
-int avtab_read(struct avtab *a, void *fp, u32 vers)
+int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
 {
     int rc;
     __le32 buf[1];
@@ -435,25 +498,28 @@ int avtab_read(struct avtab *a, void *fp
     rc = next_entry(buf, fp, sizeof(u32));
     if ( rc < 0 )
     {
-        printk(KERN_ERR "security: avtab: truncated table\n");
+        printk(KERN_ERR "Flask: avtab: truncated table\n");
         goto bad;
     }
     nel = le32_to_cpu(buf[0]);
     if ( !nel )
     {
-        printk(KERN_ERR "security: avtab: table is empty\n");
+        printk(KERN_ERR "Flask: avtab: table is empty\n");
         rc = -EINVAL;
         goto bad;
     }
+    rc = avtab_alloc(a, nel);
+    if ( rc )
+        goto bad;
     for ( i = 0; i < nel; i++ )
     {
-        rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL);
+        rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL);
         if ( rc )
         {
             if ( rc == -ENOMEM )
-                printk(KERN_ERR "security: avtab: out of memory\n");
+                printk(KERN_ERR "Flask: avtab: out of memory\n");
             else if ( rc == -EEXIST )
-                printk(KERN_ERR "security: avtab: duplicate entry\n");
+                printk(KERN_ERR "Flask: avtab: duplicate entry\n");
             else
                 rc = -EINVAL;
             goto bad;
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/avtab.h
--- a/xen/xsm/flask/ss/avtab.h  Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/avtab.h  Wed Aug 19 14:22:52 2009 +0100
@@ -16,6 +16,9 @@
  *    This program is free software; you can redistribute it and/or modify
  *      it under the terms of the GNU General Public License as published by
  *    the Free Software Foundation, version 2.
+ *
+ * Updated: Yuichi Nakamura <ynakam@xxxxxxxxxxxxxx>
+ *     Tuned number of hash slots for avtab to reduce memory usage
  */
 
 /* Ported to Xen 3.0, George Coker, <gscoker@xxxxxxxxxxxxxx> */
@@ -53,19 +56,23 @@ struct avtab {
 struct avtab {
     struct avtab_node **htable;
     u32 nel;    /* number of elements */
+    u32 nslot;      /* number of hash slots */
+    u16 mask;       /* mask to compute hash func */
 };
 
 int avtab_init(struct avtab *);
+int avtab_alloc(struct avtab *, u32);
 struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k);
 void avtab_destroy(struct avtab *h);
 void avtab_hash_eval(struct avtab *h, char *tag);
 
-int avtab_read_item(void *fp, uint32_t vers, struct avtab *a,
+struct policydb;
+int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
             int (*insert)(struct avtab *a, struct avtab_key *k,
                   struct avtab_datum *d, void *p),
             void *p);
 
-int avtab_read(struct avtab *a, void *fp, u32 vers);
+int avtab_read(struct avtab *a, void *fp, struct policydb *pol);
 
 struct avtab_node *avtab_insert_nonunique(struct avtab *h, 
                             struct avtab_key *key, struct avtab_datum *datum);
@@ -75,11 +82,10 @@ struct avtab_node *avtab_search_node_nex
 struct avtab_node *avtab_search_node_next(struct avtab_node *node, 
                                                                 int specified);
 
-#define AVTAB_HASH_BITS 15
-#define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS)
-#define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1)
-
-#define AVTAB_SIZE AVTAB_HASH_BUCKETS
+#define MAX_AVTAB_HASH_BITS 13
+#define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)
+#define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1)
+#define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS
 
 #endif    /* _SS_AVTAB_H_ */
 
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/conditional.c
--- a/xen/xsm/flask/ss/conditional.c    Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/conditional.c    Wed Aug 19 14:22:52 2009 +0100
@@ -101,7 +101,7 @@ int evaluate_cond_node(struct policydb *
     {
         node->cur_state = new_state;
         if ( new_state == -1 )
-            printk(KERN_ERR "security: expression result was undefined - 
disabling all rules.\n");
+            printk(KERN_ERR "Flask: expression result was undefined - 
disabling all rules.\n");
         /* turn the rules on or off */
         for ( cur = node->true_list; cur != NULL; cur = cur->next )
         {
@@ -287,7 +287,7 @@ static int cond_insertf(struct avtab *a,
     {
         if ( avtab_search(&p->te_avtab, k) )
         {
-            printk("security: type rule already exists outside of a "
+            printk("Flask: type rule already exists outside of a "
                                                                 
"conditional.");
             goto err;
         }
@@ -306,7 +306,7 @@ static int cond_insertf(struct avtab *a,
             {
                 if ( avtab_search_node_next(node_ptr, k->specified) )
                 {
-                    printk("security: too many conflicting type rules.");
+                    printk("Flask: too many conflicting type rules.");
                     goto err;
                 }
                 found = 0;
@@ -320,7 +320,7 @@ static int cond_insertf(struct avtab *a,
                 }
                 if ( !found )
                 {
-                    printk("security: conflicting type rules.\n");
+                    printk("Flask: conflicting type rules.\n");
                     goto err;
                 }
             }
@@ -329,7 +329,7 @@ static int cond_insertf(struct avtab *a,
         {
             if ( avtab_search(&p->te_cond_avtab, k) )
             {
-                printk("security: conflicting type rules when adding type rule 
"
+                printk("Flask: conflicting type rules when adding type rule "
                                                                 "for true.\n");
                 goto err;
             }
@@ -339,7 +339,7 @@ static int cond_insertf(struct avtab *a,
     node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
     if ( !node_ptr )
     {
-        printk("security: could not insert rule.");
+        printk("Flask: could not insert rule.");
         goto err;
     }
 
@@ -389,8 +389,7 @@ static int cond_read_av_list(struct poli
     data.tail = NULL;
     for ( i = 0; i < len; i++ )
     {
-        rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, 
cond_insertf,
-                                                                        &data);
+        rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf, &data);
         if ( rc )
             return rc;
     }
@@ -403,13 +402,13 @@ static int expr_isvalid(struct policydb 
 {
     if ( expr->expr_type <= 0 || expr->expr_type > COND_LAST )
     {
-        printk("security: conditional expressions uses unknown operator.\n");
+        printk("Flask: conditional expressions uses unknown operator.\n");
         return 0;
     }
 
     if ( expr->bool > p->p_bools.nprim )
     {
-        printk("security: conditional expressions uses unknown bool.\n");
+        printk("Flask: conditional expressions uses unknown bool.\n");
         return 0;
     }
     return 1;
@@ -488,6 +487,10 @@ int cond_read_list(struct policydb *p, v
         return -1;
 
     len = le32_to_cpu(buf[0]);
+
+    rc = avtab_alloc(&(p->te_cond_avtab), p->te_avtab.nel);
+    if ( rc )
+      goto err;
 
     for ( i = 0; i < len; i++ )
     {
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/conditional.h
--- a/xen/xsm/flask/ss/conditional.h    Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/conditional.h    Wed Aug 19 14:22:52 2009 +0100
@@ -28,7 +28,7 @@ struct cond_expr {
 #define COND_XOR    5 /* bool ^ bool */
 #define COND_EQ        6 /* bool == bool */
 #define COND_NEQ    7 /* bool != bool */
-#define COND_LAST    8
+#define COND_LAST    COND_NEQ
     __u32 expr_type;
     __u32 bool;
     struct cond_expr *next;
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/context.h
--- a/xen/xsm/flask/ss/context.h        Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/context.h        Wed Aug 19 14:22:52 2009 +0100
@@ -42,17 +42,40 @@ static inline int mls_context_cpy(struct
 {
     int rc;
 
-    if (!flask_mls_enabled)
+    if ( !flask_mls_enabled )
         return 0;
 
     dst->range.level[0].sens = src->range.level[0].sens;
     rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
-    if (rc)
+    if ( rc )
         goto out;
 
     dst->range.level[1].sens = src->range.level[1].sens;
     rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat);
-    if (rc)
+    if ( rc )
+        ebitmap_destroy(&dst->range.level[0].cat);
+out:
+    return rc;
+}
+
+/*
+ * Sets both levels in the MLS range of 'dst' to the low level of 'src'.
+ */
+static inline int mls_context_cpy_low(struct context *dst, struct context *src)
+{
+    int rc;
+
+    if ( !flask_mls_enabled )
+        return 0;
+
+    dst->range.level[0].sens = src->range.level[0].sens;
+    rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
+    if ( rc )
+        goto out;
+
+    dst->range.level[1].sens = src->range.level[0].sens;
+    rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[0].cat);
+    if ( rc )
         ebitmap_destroy(&dst->range.level[0].cat);
 out:
     return rc;
@@ -60,7 +83,7 @@ out:
 
 static inline int mls_context_cmp(struct context *c1, struct context *c2)
 {
-    if (!flask_mls_enabled)
+    if ( !flask_mls_enabled )
         return 1;
 
     return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
@@ -71,7 +94,7 @@ static inline int mls_context_cmp(struct
 
 static inline void mls_context_destroy(struct context *c)
 {
-    if (!flask_mls_enabled)
+    if ( !flask_mls_enabled )
         return;
 
     ebitmap_destroy(&c->range.level[0].cat);
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/ebitmap.c
--- a/xen/xsm/flask/ss/ebitmap.c        Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/ebitmap.c        Wed Aug 19 14:22:52 2009 +0100
@@ -3,6 +3,10 @@
  *
  * Author : Stephen Smalley, <sds@xxxxxxxxxxxxxx>
  */
+/*
+ * Updated: KaiGai Kohei <kaigai@xxxxxxxxxxxxx>
+ *      Applied standard bit operations to improve bitmap scanning.
+ */
 
 /* Ported to Xen 3.0, George Coker, <gscoker@xxxxxxxxxxxxxx> */
 
@@ -11,6 +15,7 @@
 #include <xen/xmalloc.h>
 #include <xen/errno.h>
 #include <xen/spinlock.h>
+#include <xen/bitmap.h>
 #include "ebitmap.h"
 #include "policydb.h"
 
@@ -23,7 +28,8 @@ int ebitmap_cmp(struct ebitmap *e1, stru
 
     n1 = e1->node;
     n2 = e2->node;
-    while ( n1 && n2 && (n1->startbit == n2->startbit) && (n1->map == n2->map) 
)
+    while ( n1 && n2 && (n1->startbit == n2->startbit) &&
+            !memcmp(n1->maps, n2->maps, EBITMAP_SIZE / 8))
     {
         n1 = n1->next;
         n2 = n2->next;
@@ -52,7 +58,7 @@ int ebitmap_cpy(struct ebitmap *dst, str
         }
         memset(new, 0, sizeof(*new));
         new->startbit = n->startbit;
-        new->map = n->map;
+        memcpy(new->maps, n->maps, EBITMAP_SIZE / 8);
         new->next = NULL;
         if ( prev )
             prev->next = new;
@@ -69,6 +75,7 @@ int ebitmap_contains(struct ebitmap *e1,
 int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
 {
     struct ebitmap_node *n1, *n2;
+    int i;
 
     if ( e1->highbit < e2->highbit )
         return 0;
@@ -82,8 +89,11 @@ int ebitmap_contains(struct ebitmap *e1,
             n1 = n1->next;
             continue;
         }
-        if ( (n1->map & n2->map) != n2->map )
-            return 0;
+        for ( i = 0; i < EBITMAP_UNIT_NUMS; i++ )
+        {
+            if ( (n1->maps[i] & n2->maps[i]) != n2->maps[i] )
+                return 0;
+        }
 
         n1 = n1->next;
         n2 = n2->next;
@@ -105,13 +115,8 @@ int ebitmap_get_bit(struct ebitmap *e, u
     n = e->node;
     while ( n && (n->startbit <= bit) )
     {
-        if ( (n->startbit + MAPSIZE) > bit )
-        {
-            if ( n->map & (MAPBIT << (bit - n->startbit)) )
-                return 1;
-            else
-                return 0;
-        }
+        if ( (n->startbit + EBITMAP_SIZE) > bit )
+            return ebitmap_node_get_bit(n, bit);
         n = n->next;
     }
 
@@ -126,37 +131,41 @@ int ebitmap_set_bit(struct ebitmap *e, u
     n = e->node;
     while ( n && n->startbit <= bit )
     {
-        if ( (n->startbit + MAPSIZE) > bit )
+        if ( (n->startbit + EBITMAP_SIZE) > bit )
         {
             if ( value )
             {
-                n->map |= (MAPBIT << (bit - n->startbit));
+                ebitmap_node_set_bit(n, bit);
             }
             else
             {
-                n->map &= ~(MAPBIT << (bit - n->startbit));
-                if ( !n->map )
+                unsigned int s;
+
+                ebitmap_node_clr_bit(n, bit);
+
+                s = find_first_bit(n->maps, EBITMAP_SIZE);
+                if ( s < EBITMAP_SIZE )
+                    return 0;
+
+                /* drop this node from the bitmap */
+
+                if ( !n->next )
                 {
-                    /* drop this node from the bitmap */
-
-                    if ( !n->next )
-                    {
-                        /*
-                         * this was the highest map
-                         * within the bitmap
-                         */
-                        if ( prev )
-                            e->highbit = prev->startbit + MAPSIZE;
-                        else
-                            e->highbit = 0;
-                    }
+                    /*
+                     * this was the highest map
+                     * within the bitmap
+                     */
                     if ( prev )
-                        prev->next = n->next;
+                        e->highbit = prev->startbit + EBITMAP_SIZE;
                     else
-                        e->node = n->next;
-
-                    xfree(n);
+                        e->highbit = 0;
                 }
+                if ( prev )
+                    prev->next = n->next;
+                else
+                    e->node = n->next;
+
+                xfree(n);
             }
             return 0;
         }
@@ -172,12 +181,12 @@ int ebitmap_set_bit(struct ebitmap *e, u
         return -ENOMEM;
     memset(new, 0, sizeof(*new));
 
-    new->startbit = bit & ~(MAPSIZE - 1);
-    new->map = (MAPBIT << (bit - new->startbit));
+    new->startbit = bit - (bit % EBITMAP_SIZE);
+    ebitmap_node_set_bit(new, bit);
 
     if ( !n )
         /* this node will be the highest map within the bitmap */
-        e->highbit = new->startbit + MAPSIZE;
+        e->highbit = new->startbit + EBITMAP_SIZE;
 
     if ( prev )
     {
@@ -215,11 +224,11 @@ void ebitmap_destroy(struct ebitmap *e)
 
 int ebitmap_read(struct ebitmap *e, void *fp)
 {
-    int rc;
-    struct ebitmap_node *n, *l;
+    struct ebitmap_node *n = NULL;
+    u32 mapunit, count, startbit, index;
+    u64 map;
     __le32 buf[3];
-    u32 mapsize, count, i;
-    __le64 map;
+    int rc, i;
 
     ebitmap_init(e);
 
@@ -227,99 +236,99 @@ int ebitmap_read(struct ebitmap *e, void
     if ( rc < 0 )
         goto out;
 
-    mapsize = le32_to_cpu(buf[0]);
+    mapunit = le32_to_cpu(buf[0]);
     e->highbit = le32_to_cpu(buf[1]);
     count = le32_to_cpu(buf[2]);
 
-    if ( mapsize != MAPSIZE )
-    {
-        printk(KERN_ERR "security: ebitmap: map size %u does not "
-               "match my size %Zd (high bit was %d)\n", mapsize,
-               MAPSIZE, e->highbit);
+    if ( mapunit != sizeof(u64) * 8 )
+    {
+        printk(KERN_ERR "Flask: ebitmap: map size %u does not "
+               "match my size %Zd (high bit was %d)\n", mapunit,
+               sizeof(u64) * 8, e->highbit);
         goto bad;
     }
+
+    /* round up e->highbit */
+    e->highbit += EBITMAP_SIZE - 1;
+    e->highbit -= (e->highbit % EBITMAP_SIZE);
+
     if ( !e->highbit )
     {
         e->node = NULL;
         goto ok;
     }
-    if ( e->highbit & (MAPSIZE - 1) )
-    {
-        printk(KERN_ERR "security: ebitmap: high bit (%d) is not a "
-               "multiple of the map size (%Zd)\n", e->highbit, MAPSIZE);
-        goto bad;
-    }
-    l = NULL;
+
     for ( i = 0; i < count; i++ )
     {
-        rc = next_entry(buf, fp, sizeof(u32));
+        rc = next_entry(&startbit, fp, sizeof(u32));
         if ( rc < 0 )
         {
-            printk(KERN_ERR "security: ebitmap: truncated map\n");
-            goto bad;
-        }
-        n = xmalloc(struct ebitmap_node);
-        if ( !n )
-        {
-            printk(KERN_ERR "security: ebitmap: out of memory\n");
-            rc = -ENOMEM;
-            goto bad;
-        }
-        memset(n, 0, sizeof(*n));
-
-        n->startbit = le32_to_cpu(buf[0]);
-
-        if ( n->startbit & (MAPSIZE - 1) )
-        {
-            printk(KERN_ERR "security: ebitmap start bit (%d) is "
-                   "not a multiple of the map size (%Zd)\n",
-                   n->startbit, MAPSIZE);
-            goto bad_free;
-        }
-        if ( n->startbit > (e->highbit - MAPSIZE) )
-        {
-            printk(KERN_ERR "security: ebitmap start bit (%d) is "
-                   "beyond the end of the bitmap (%Zd)\n",
-                   n->startbit, (e->highbit - MAPSIZE));
-            goto bad_free;
-        }
+            printk(KERN_ERR "Flask: ebitmap: truncated map\n");
+            goto bad;
+        }
+        startbit = le32_to_cpu(startbit);
+        if ( startbit & (mapunit - 1) )
+        {
+            printk(KERN_ERR "Flask: ebitmap start bit (%d) is "
+                   "not a multiple of the map unit size (%u)\n",
+                   startbit, mapunit);
+            goto bad;
+        }
+        if ( startbit > e->highbit - mapunit )
+        {
+            printk(KERN_ERR "Flask: ebitmap start bit (%d) is "
+                   "beyond the end of the bitmap (%u)\n",
+                   startbit, (e->highbit - mapunit));
+            goto bad;
+        }
+
+        if ( !n || startbit >= n->startbit + EBITMAP_SIZE )
+        {
+            struct ebitmap_node *tmp;
+            tmp = xmalloc(struct ebitmap_node);
+            if ( !tmp )
+            {
+                printk(KERN_ERR
+                       "Flask: ebitmap: out of memory\n");
+                rc = -ENOMEM;
+                goto bad;
+            }
+            memset(tmp, 0, sizeof(*tmp));
+            /* round down */
+            tmp->startbit = startbit - (startbit % EBITMAP_SIZE);
+            if ( n )
+                n->next = tmp;
+            else
+                e->node = tmp;
+            n = tmp;
+        }
+        else if ( startbit <= n->startbit )
+        {
+            printk(KERN_ERR "Flask: ebitmap: start bit %d"
+                   " comes after start bit %d\n",
+                   startbit, n->startbit);
+            goto bad;
+        }
+
         rc = next_entry(&map, fp, sizeof(u64));
         if ( rc < 0 )
         {
-            printk(KERN_ERR "security: ebitmap: truncated map\n");
-            goto bad_free;
-        }
-        n->map = le64_to_cpu(map);
-
-        if ( !n->map )
-        {
-            printk(KERN_ERR "security: ebitmap: null map in "
-                   "ebitmap (startbit %d)\n", n->startbit);
-            goto bad_free;
-        }
-        if ( l )
-        {
-            if ( n->startbit <= l->startbit )
-            {
-                printk(KERN_ERR "security: ebitmap: start "
-                       "bit %d comes after start bit %d\n",
-                       n->startbit, l->startbit);
-                goto bad_free;
-            }
-            l->next = n;
-        }
-        else
-            e->node = n;
-
-        l = n;
-    }
-
+            printk(KERN_ERR "Flask: ebitmap: truncated map\n");
+            goto bad;
+        }
+        map = le64_to_cpu(map);
+
+        index = (startbit - n->startbit) / EBITMAP_UNIT_SIZE;
+        while ( map )
+        {
+            n->maps[index++] = map & (-1UL);
+            map = EBITMAP_SHIFT_UNIT_SIZE(map);
+        }
+    }
 ok:
     rc = 0;
 out:
     return rc;
-bad_free:
-    xfree(n);
 bad:
     if ( !rc )
         rc = -EINVAL;
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/ebitmap.h
--- a/xen/xsm/flask/ss/ebitmap.h        Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/ebitmap.h        Wed Aug 19 14:22:52 2009 +0100
@@ -14,14 +14,20 @@
 #ifndef _SS_EBITMAP_H_
 #define _SS_EBITMAP_H_
 
-#define MAPTYPE u64            /* portion of bitmap in each node */
-#define MAPSIZE (sizeof(MAPTYPE) * 8)    /* number of bits in node bitmap */
-#define MAPBIT  1ULL            /* a bit in the node bitmap */
+#include <xen/bitmap.h>
+
+#define EBITMAP_UNIT_NUMS      ((32 - sizeof(void *) - sizeof(u32))    \
+                                       / sizeof(unsigned long))
+#define EBITMAP_UNIT_SIZE      BITS_PER_LONG
+#define EBITMAP_SIZE           (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE)
+#define EBITMAP_BIT            1ULL
+#define EBITMAP_SHIFT_UNIT_SIZE(x)                                     \
+       (((x) >> EBITMAP_UNIT_SIZE / 2) >> EBITMAP_UNIT_SIZE / 2)
 
 struct ebitmap_node {
-    u32 startbit;        /* starting position in the total bitmap */
-    MAPTYPE map;        /* this node's portion of the bitmap */
     struct ebitmap_node *next;
+    unsigned long maps[EBITMAP_UNIT_NUMS];
+    u32 startbit;
 };
 
 struct ebitmap {
@@ -32,11 +38,18 @@ struct ebitmap {
 #define ebitmap_length(e) ((e)->highbit)
 #define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0)
 
-static inline unsigned int ebitmap_start(struct ebitmap *e,
-                                                 struct ebitmap_node **n)
+static inline unsigned int ebitmap_start_positive(struct ebitmap *e,
+                                                  struct ebitmap_node **n)
 {
-    *n = e->node;
-    return ebitmap_startbit(e);
+    unsigned int ofs;
+
+    for ( *n = e->node; *n; *n = (*n)->next )
+    {
+        ofs = find_first_bit((*n)->maps, EBITMAP_SIZE);
+        if ( ofs < EBITMAP_SIZE )
+            return (*n)->startbit + ofs;
+    }
+    return ebitmap_length(e);
 }
 
 static inline void ebitmap_init(struct ebitmap *e)
@@ -44,29 +57,66 @@ static inline void ebitmap_init(struct e
     memset(e, 0, sizeof(*e));
 }
 
-static inline unsigned int ebitmap_next(struct ebitmap_node **n,
-                                                        unsigned int bit)
+static inline unsigned int ebitmap_next_positive(struct ebitmap *e,
+                                                 struct ebitmap_node **n,
+                                                 unsigned int bit)
 {
-    if ( (bit == ((*n)->startbit + MAPSIZE - 1)) && (*n)->next )
+    unsigned int ofs;
+
+    ofs = find_next_bit((*n)->maps, EBITMAP_SIZE, bit - (*n)->startbit + 1);
+    if ( ofs < EBITMAP_SIZE )
+        return ofs + (*n)->startbit;
+
+    for ( *n = (*n)->next; *n; *n = (*n)->next )
     {
-        *n = (*n)->next;
-        return (*n)->startbit;
+        ofs = find_first_bit((*n)->maps, EBITMAP_SIZE);
+        if ( ofs < EBITMAP_SIZE )
+            return ofs + (*n)->startbit;
     }
-
-    return (bit+1);
+    return ebitmap_length(e);
 }
 
-static inline int ebitmap_node_get_bit(struct ebitmap_node * n,
-                                                        unsigned int bit)
+#define EBITMAP_NODE_INDEX(node, bit)  \
+    (((bit) - (node)->startbit) / EBITMAP_UNIT_SIZE)
+#define EBITMAP_NODE_OFFSET(node, bit) \
+    (((bit) - (node)->startbit) % EBITMAP_UNIT_SIZE)
+
+static inline int ebitmap_node_get_bit(struct ebitmap_node *n,
+                                       unsigned int bit)
 {
-    if ( n->map & (MAPBIT << (bit - n->startbit)) )
+    unsigned int index = EBITMAP_NODE_INDEX(n, bit);
+    unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
+
+    BUG_ON( index >= EBITMAP_UNIT_NUMS );
+    if ( (n->maps[index] & (EBITMAP_BIT << ofs)) )
         return 1;
     return 0;
 }
 
-#define ebitmap_for_each_bit(e, n, bit) \
-    for ( bit = ebitmap_start(e, &n); bit < ebitmap_length(e); \
-                                    bit = ebitmap_next(&n, bit) ) \
+static inline void ebitmap_node_set_bit(struct ebitmap_node *n,
+                                        unsigned int bit)
+{
+    unsigned int index = EBITMAP_NODE_INDEX(n, bit);
+    unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
+
+    BUG_ON(index >= EBITMAP_UNIT_NUMS);
+    n->maps[index] |= (EBITMAP_BIT << ofs);
+}
+
+static inline void ebitmap_node_clr_bit(struct ebitmap_node *n,
+                                        unsigned int bit)
+{
+    unsigned int index = EBITMAP_NODE_INDEX(n, bit);
+    unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
+
+    BUG_ON( index >= EBITMAP_UNIT_NUMS );
+    n->maps[index] &= ~(EBITMAP_BIT << ofs);
+}
+
+#define ebitmap_for_each_positive_bit(e, n, bit)       \
+    for ( bit = ebitmap_start_positive(e, &n);       \
+          bit < ebitmap_length(e);                   \
+          bit = ebitmap_next_positive(e, &n, bit) )   \
 
 int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
 int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/hashtab.c
--- a/xen/xsm/flask/ss/hashtab.c        Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/hashtab.c        Wed Aug 19 14:22:52 2009 +0100
@@ -11,8 +11,10 @@
 #include <xen/errno.h>
 #include "hashtab.h"
 
-struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
-            int (*keycmp)(struct hashtab *h, void *key1, void *key2), u32 size)
+struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h,
+                                                const void *key),
+            int (*keycmp)(struct hashtab *h, const void *key1,
+                         const void *key2), u32 size)
 {
     struct hashtab *p;
     u32 i;
@@ -26,7 +28,7 @@ struct hashtab *hashtab_create(u32 (*has
     p->nel = 0;
     p->hash_value = hash_value;
     p->keycmp = keycmp;
-    p->htable = (void *)xmalloc_array(struct hashtab_node, size);
+    p->htable = xmalloc_array(struct hashtab_node *, size);
     if ( p->htable == NULL )
     {
         xfree(p);
@@ -80,7 +82,7 @@ int hashtab_insert(struct hashtab *h, vo
     return 0;
 }
 
-void *hashtab_search(struct hashtab *h, void *key)
+void *hashtab_search(struct hashtab *h, const void *key)
 {
     u32 hvalue;
     struct hashtab_node *cur;
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/hashtab.h
--- a/xen/xsm/flask/ss/hashtab.h        Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/hashtab.h        Wed Aug 19 14:22:52 2009 +0100
@@ -22,9 +22,9 @@ struct hashtab {
     struct hashtab_node **htable;    /* hash table */
     u32 size;            /* number of slots in hash table */
     u32 nel;            /* number of elements in hash table */
-    u32 (*hash_value)(struct hashtab *h, void *key);
+    u32 (*hash_value)(struct hashtab *h, const void *key);
                     /* hash function */
-    int (*keycmp)(struct hashtab *h, void *key1, void *key2);
+    int (*keycmp)(struct hashtab *h, const void *key1, const void *key2);
                     /* key comparison function */
 };
 
@@ -39,8 +39,10 @@ struct hashtab_info {
  * Returns NULL if insufficent space is available or
  * the new hash table otherwise.
  */
-struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
-            int (*keycmp)(struct hashtab *h, void *key1, void *key2), u32 
size);
+struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h,
+                                                const void *key),
+            int (*keycmp)(struct hashtab *h, const void *key1,
+                         const void *key2), u32 size);
 
 /*
  * Inserts the specified (key, datum) pair into the specified hash table.
@@ -58,7 +60,7 @@ int hashtab_insert(struct hashtab *h, vo
  * Returns NULL if no entry has the specified key or
  * the datum of the entry otherwise.
  */
-void *hashtab_search(struct hashtab *h, void *k);
+void *hashtab_search(struct hashtab *h, const void *k);
 
 /*
  * Destroys the specified hash table.
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/mls.c
--- a/xen/xsm/flask/ss/mls.c    Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/mls.c    Wed Aug 19 14:22:52 2009 +0100
@@ -29,46 +29,49 @@
  */
 int mls_compute_context_len(struct context * context)
 {
-    int i, l, len, range;
+    int i, l, len, head, prev;
+    char *nm;
+    struct ebitmap *e;
     struct ebitmap_node *node;
 
-    if (!flask_mls_enabled)
+    if ( !flask_mls_enabled )
         return 0;
 
     len = 1; /* for the beginning ":" */
     for ( l = 0; l < 2; l++ )
     {
-        range = 0;
-        len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens 
- 1]);
-
-        ebitmap_for_each_bit(&context->range.level[l].cat, node, i)
-        {
-            if ( ebitmap_node_get_bit(node, i) )
+        int index_sens = context->range.level[l].sens;
+        len += strlen(policydb.p_sens_val_to_name[index_sens - 1]);
+
+        /* categories */
+        head = -2;
+        prev = -2;
+        e = &context->range.level[l].cat;
+        ebitmap_for_each_positive_bit(e, node, i)
+        {
+            if ( i - prev > 1 )
             {
-                if ( range )
-                {
-                    range++;
-                    continue;
-                }
-
-                len += strlen(policydb.p_cat_val_to_name[i]) + 1;
-                range++;
+                               /* one or more negative bits are skipped */
+                if ( head != prev )
+                {
+                    nm = policydb.p_cat_val_to_name[prev];
+                    len += strlen(nm) + 1;
+                }
+                nm = policydb.p_cat_val_to_name[i];
+                len += strlen(nm) + 1;
+                head = i;
             }
-            else
-            {
-                if ( range > 1 )
-                    len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
-                range = 0;
-            }
-        }
-        /* Handle case where last category is the end of range */
-        if ( range > 1 )
-            len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
-
+            prev = i;
+        }
+        if ( prev != head )
+        {
+            nm = policydb.p_cat_val_to_name[prev];
+            len += strlen(nm) + 1;
+        }
         if ( l == 0 )
         {
             if ( mls_level_eq(&context->range.level[0], 
-                                                &context->range.level[1]) )
+                              &context->range.level[1]) )
                 break;
             else
                 len++;
@@ -85,8 +88,9 @@ int mls_compute_context_len(struct conte
  */
 void mls_sid_to_context(struct context *context, char **scontext)
 {
-    char *scontextp;
-    int i, l, range, wrote_sep;
+    char *scontextp, *nm;
+    int i, l, head, prev;
+    struct ebitmap *e;
     struct ebitmap_node *node;
 
     if ( !flask_mls_enabled )
@@ -99,64 +103,51 @@ void mls_sid_to_context(struct context *
 
     for ( l = 0; l < 2; l++ )
     {
-        range = 0;
-        wrote_sep = 0;
-        strlcpy(scontextp,
+        memcpy(scontextp,
                 policydb.p_sens_val_to_name[context->range.level[l].sens - 1],
                 
strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]));
-        scontextp += 
strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
+        scontextp += strlen(scontextp);
 
         /* categories */
-        ebitmap_for_each_bit(&context->range.level[l].cat, node, i)
-        {
-            if ( ebitmap_node_get_bit(node, i) )
+        head = -2;
+        prev = -2;
+        e = &context->range.level[l].cat;
+        ebitmap_for_each_positive_bit(e, node, i)
+        {
+            if ( i - prev > 1 )
             {
-                if ( range )
-                {
-                    range++;
-                    continue;
-                }
-
-                if ( !wrote_sep )
-                {
-                    *scontextp++ = ':';
-                    wrote_sep = 1;
-                }
-                else
-                    *scontextp++ = ',';
-                strlcpy(scontextp, policydb.p_cat_val_to_name[i], 
-                    strlen(policydb.p_cat_val_to_name[i]));
-                scontextp += strlen(policydb.p_cat_val_to_name[i]);
-                range++;
-            }
-            else
-            {
-                if ( range > 1 )
-                {
-                    if ( range > 2 )
+                /* one or more negative bits are skipped */
+                if ( prev != head )
+                {
+                    if ( prev - head > 1 )
                         *scontextp++ = '.';
                     else
                         *scontextp++ = ',';
-
-                    strlcpy(scontextp, policydb.p_cat_val_to_name[i - 1],
-                        strlen(policydb.p_cat_val_to_name[i - 1]));
-                    scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
-                }
-                range = 0;
+                    nm = policydb.p_cat_val_to_name[prev];
+                    memcpy(scontextp, nm, strlen(nm));
+                    scontextp += strlen(nm);
+                }
+                if ( prev < 0 )
+                    *scontextp++ = ':';
+                else
+                    *scontextp++ = ',';
+                nm = policydb.p_cat_val_to_name[i];
+                memcpy(scontextp, nm, strlen(nm));
+                scontextp += strlen(nm);
+                head = i;
             }
-        }
-
-        /* Handle case where last category is the end of range */
-        if ( range > 1 )
-        {
-            if ( range > 2 )
+            prev = i;
+        }
+
+        if ( prev != head )
+        {
+            if ( prev - head > 1 )
                 *scontextp++ = '.';
             else
                 *scontextp++ = ',';
-
-            strlcpy(scontextp, policydb.p_cat_val_to_name[i - 1],
-                strlen(policydb.p_cat_val_to_name[i - 1]));
-            scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
+            nm = policydb.p_cat_val_to_name[prev];
+            memcpy(scontextp, nm, strlen(nm));
+            scontextp += strlen(nm);
         }
 
         if ( l == 0 )
@@ -176,54 +167,56 @@ void mls_sid_to_context(struct context *
     return;
 }
 
+int mls_level_isvalid(struct policydb *p, struct mls_level *l)
+{
+    struct level_datum *levdatum;
+    struct ebitmap_node *node;
+    int i;
+
+    if ( !l->sens || l->sens > p->p_levels.nprim )
+        return 0;
+    levdatum = hashtab_search(p->p_levels.table,
+                              p->p_sens_val_to_name[l->sens - 1]);
+    if ( !levdatum )
+        return 0;
+
+    ebitmap_for_each_positive_bit(&l->cat, node, i)
+    {
+        if ( i > p->p_cats.nprim )
+            return 0;
+        if ( !ebitmap_get_bit(&levdatum->level->cat, i) )
+        {
+            /*
+             * Category may not be associated with
+             * sensitivity.
+             */
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+int mls_range_isvalid(struct policydb *p, struct mls_range *r)
+{
+    return ( mls_level_isvalid(p, &r->level[0]) &&
+             mls_level_isvalid(p, &r->level[1]) &&
+             mls_level_dom(&r->level[1], &r->level[0]));
+}
+
 /*
  * Return 1 if the MLS fields in the security context
  * structure `c' are valid.  Return 0 otherwise.
  */
 int mls_context_isvalid(struct policydb *p, struct context *c)
 {
-    struct level_datum *levdatum;
     struct user_datum *usrdatum;
-    struct ebitmap_node *node;
-    int i, l;
 
     if ( !flask_mls_enabled )
         return 1;
 
-    /*
-     * MLS range validity checks: high must dominate low, low level must
-     * be valid (category set <-> sensitivity check), and high level must
-     * be valid (category set <-> sensitivity check)
-     */
-    if ( !mls_level_dom(&c->range.level[1], &c->range.level[0]) )
-        /* High does not dominate low. */
-        return 0;
-
-    for ( l = 0; l < 2; l++ )
-    {
-        if ( !c->range.level[l].sens || c->range.level[l].sens > 
-                                                            p->p_levels.nprim )
-            return 0;
-        levdatum = hashtab_search(p->p_levels.table,
-            p->p_sens_val_to_name[c->range.level[l].sens - 1]);
-        if ( !levdatum )
-            return 0;
-
-        ebitmap_for_each_bit(&c->range.level[l].cat, node, i)
-        {
-            if ( ebitmap_node_get_bit(node, i) )
-            {
-                if ( i > p->p_cats.nprim )
-                    return 0;
-                if ( !ebitmap_get_bit(&levdatum->level->cat, i) )
-                    /*
-                     * Category may not be associated with
-                     * sensitivity in low level.
-                     */
-                    return 0;
-            }
-        }
-    }
+    if ( !mls_range_isvalid(p, &c->range) )
+        return 0;
 
     if ( c->role == OBJECT_R_VAL )
         return 1;
@@ -238,26 +231,6 @@ int mls_context_isvalid(struct policydb 
         return 0; /* user may not be associated with range */
 
     return 1;
-}
-
-/*
- * Copies the MLS range from `src' into `dst'.
- */
-static inline int mls_copy_context(struct context *dst, struct context *src)
-{
-    int l, rc = 0;
-
-    /* Copy the MLS range from the source context */
-    for ( l = 0; l < 2; l++ )
-    {
-        dst->range.level[l].sens = src->range.level[l].sens;
-        rc = ebitmap_cpy(&dst->range.level[l].cat,
-                 &src->range.level[l].cat);
-        if ( rc )
-            break;
-    }
-
-    return rc;
 }
 
 /*
@@ -270,16 +243,11 @@ static inline int mls_copy_context(struc
  * This function modifies the string in place, inserting
  * NULL characters to terminate the MLS fields.
  *
- * If a def_sid is provided and no MLS field is present,
- * copy the MLS field of the associated default context.
- * Used for upgraded to MLS systems where objects may lack
- * MLS fields.
- *
  * Policy read-lock must be held for sidtab lookup.
  *
  */
-int mls_context_to_sid(char oldc, char **scontext, struct context *context,
-                                                struct sidtab *s, u32 def_sid)
+int mls_context_to_sid(char oldc, char **scontext,
+                       struct context *context, struct sidtab *s)
 {
 
     char delim;
@@ -292,23 +260,10 @@ int mls_context_to_sid(char oldc, char *
         return 0;
 
     /*
-     * No MLS component to the security context, try and map to
-     * default if provided.
+     * No MLS component to the security context -> error.
      */
     if ( !oldc )
-    {
-        struct context *defcon;
-
-        if ( def_sid == SECSID_NULL )
-            goto out;
-
-        defcon = sidtab_search(s, def_sid);
-        if ( !defcon )
-            goto out;
-
-        rc = mls_copy_context(context, defcon);
         goto out;
-    }
 
     /* Extract low sensitivity. */
     scontextp = p = *scontext;
@@ -421,26 +376,6 @@ out:
 }
 
 /*
- * Copies the effective MLS range from `src' into `dst'.
- */
-static inline int mls_scopy_context(struct context *dst, struct context *src)
-{
-    int l, rc = 0;
-
-    /* Copy the MLS range from the source context */
-    for ( l = 0; l < 2; l++ )
-    {
-        dst->range.level[l].sens = src->range.level[0].sens;
-        rc = ebitmap_cpy(&dst->range.level[l].cat,
-                 &src->range.level[0].cat);
-        if ( rc )
-            break;
-    }
-
-    return rc;
-}
-
-/*
  * Copies the MLS range `range' into `context'.
  */
 static inline int mls_range_set(struct context *context,
@@ -537,20 +472,17 @@ int mls_convert_context(struct policydb 
         c->range.level[l].sens = levdatum->level->sens;
 
         ebitmap_init(&bitmap);
-        ebitmap_for_each_bit(&c->range.level[l].cat, node, i)
-        {
-            if ( ebitmap_node_get_bit(node, i) )
-            {
-                int rc;
-
-                catdatum = hashtab_search(newp->p_cats.table,
-                             oldp->p_cat_val_to_name[i]);
-                if ( !catdatum )
-                    return -EINVAL;
-                rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
-                if ( rc )
-                    return rc;
-            }
+        ebitmap_for_each_positive_bit(&c->range.level[l].cat, node, i)
+        {
+            int rc;
+
+            catdatum = hashtab_search(newp->p_cats.table,
+                                      oldp->p_cat_val_to_name[i]);
+            if ( !catdatum )
+                return -EINVAL;
+            rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
+            if ( rc )
+                return rc;
         }
         ebitmap_destroy(&c->range.level[l].cat);
         c->range.level[l].cat = bitmap;
@@ -562,48 +494,37 @@ int mls_compute_sid(struct context *scon
 int mls_compute_sid(struct context *scontext, struct context *tcontext,
                         u16 tclass, u32 specified, struct context *newcontext)
 {
+    struct range_trans *rtr;
+
     if ( !flask_mls_enabled )
         return 0;
 
     switch ( specified )
     {
         case AVTAB_TRANSITION:
-            if ( tclass == SECCLASS_DOMAIN )
+            /* Look for a range transition rule. */
+            for (rtr = policydb.range_tr; rtr; rtr = rtr->next)
             {
-                struct range_trans *rangetr;
-                /* Look for a range transition rule. */
-                for ( rangetr = policydb.range_tr; rangetr;
-                                                    rangetr = rangetr->next)
-                {
-                    if ( rangetr->dom == scontext->type &&
-                                        rangetr->type == tcontext->type)
-                    {
-                        /* Set the range from the rule */
-                        return mls_range_set(newcontext, &rangetr->range);
-                    }
+                if (rtr->source_type == scontext->type &&
+                    rtr->target_type == tcontext->type &&
+                    rtr->target_class == tclass)
+                {
+                    /* Set the range from the rule */
+                    return mls_range_set(newcontext,
+                                         &rtr->target_range);
                 }
             }
             /* Fallthrough */
         case AVTAB_CHANGE:
             if ( tclass == SECCLASS_DOMAIN )
                 /* Use the process MLS attributes. */
-                return mls_copy_context(newcontext, scontext);
+                return mls_context_cpy(newcontext, scontext);
             else
+                /* Use the process effective MLS attributes. */
+                return mls_context_cpy_low(newcontext, scontext);
+        case AVTAB_MEMBER:
             /* Use the process effective MLS attributes. */
-            return mls_scopy_context(newcontext, scontext);
-        case AVTAB_MEMBER:
-            /* Only polyinstantiate the MLS attributes if
-               the type is being polyinstantiated */
-            if ( newcontext->type != tcontext->type )
-            {
-                /* Use the process effective MLS attributes. */
-                return mls_scopy_context(newcontext, scontext);
-            }
-            else
-            {
-                /* Use the related object MLS attributes. */
-                return mls_copy_context(newcontext, tcontext);
-            }
+            return mls_context_cpy_low(newcontext, scontext);
         default:
             return -EINVAL;
     }
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/mls.h
--- a/xen/xsm/flask/ss/mls.h    Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/mls.h    Wed Aug 19 14:22:52 2009 +0100
@@ -8,7 +8,7 @@
  *
  *    Support for enhanced MLS infrastructure.
  *
- * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
  */
 
 #ifndef _SS_MLS_H_
@@ -20,9 +20,11 @@ int mls_compute_context_len(struct conte
 int mls_compute_context_len(struct context *context);
 void mls_sid_to_context(struct context *context, char **scontext);
 int mls_context_isvalid(struct policydb *p, struct context *c);
+int mls_range_isvalid(struct policydb *p, struct mls_range *r);
+int mls_level_isvalid(struct policydb *p, struct mls_level *l);
 
 int mls_context_to_sid(char oldc, char **scontext, struct context *context,
-                                               struct sidtab *s, u32 def_sid);
+                       struct sidtab *s);
 
 int mls_convert_context(struct policydb *oldp, struct policydb *newp,
                                                     struct context *context);
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/policydb.c
--- a/xen/xsm/flask/ss/policydb.c       Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/policydb.c       Wed Aug 19 14:22:52 2009 +0100
@@ -100,6 +100,26 @@ static struct policydb_compat_info polic
         .sym_num        = SYM_NUM,
         .ocon_num       = OCON_NUM,
     },
+    {
+       .version        = POLICYDB_VERSION_RANGETRANS,
+       .sym_num        = SYM_NUM,
+       .ocon_num       = OCON_NUM,
+    },
+    {
+       .version        = POLICYDB_VERSION_POLCAP,
+       .sym_num        = SYM_NUM,
+       .ocon_num       = OCON_NUM,
+    },
+    {
+       .version        = POLICYDB_VERSION_PERMISSIVE,
+       .sym_num        = SYM_NUM,
+       .ocon_num       = OCON_NUM,
+    },
+    {
+       .version        = POLICYDB_VERSION_BOUNDARY,
+       .sym_num        = SYM_NUM,
+       .ocon_num       = OCON_NUM,
+    },
 };
 
 static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -187,6 +207,9 @@ static int policydb_init(struct policydb
     rc = cond_policydb_init(p);
     if ( rc )
         goto out_free_avtab;
+
+    ebitmap_init(&p->policycaps);
+    ebitmap_init(&p->permissive_map);
 
 out:
     return rc;
@@ -244,7 +267,9 @@ static int role_index(void *key, void *d
 
     role = datum;
     p = datap;
-    if ( !role->value || role->value > p->p_roles.nprim )
+    if ( !role->value
+         || role->value > p->p_roles.nprim
+         || role->bounds > p->p_roles.nprim )
         return -EINVAL;
     p->p_role_val_to_name[role->value - 1] = key;
     p->role_val_to_struct[role->value - 1] = role;
@@ -261,9 +286,12 @@ static int type_index(void *key, void *d
 
     if ( typdatum->primary )
     {
-        if ( !typdatum->value || typdatum->value > p->p_types.nprim )
+        if ( !typdatum->value
+             || typdatum->value > p->p_types.nprim
+             || typdatum->bounds > p->p_types.nprim )
             return -EINVAL;
         p->p_type_val_to_name[typdatum->value - 1] = key;
+        p->type_val_to_struct[typdatum->value - 1] = typdatum;
     }
 
     return 0;
@@ -276,7 +304,9 @@ static int user_index(void *key, void *d
 
     usrdatum = datum;
     p = datap;
-    if ( !usrdatum->value || usrdatum->value > p->p_users.nprim )
+    if ( !usrdatum->value
+         || usrdatum->value > p->p_users.nprim
+         || usrdatum->bounds > p->p_users.nprim )
         return -EINVAL;
     p->p_user_val_to_name[usrdatum->value - 1] = key;
     p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
@@ -356,7 +386,7 @@ static int policydb_index_classes(struct
         goto out;
 
     p->class_val_to_struct =
-        (void *)xmalloc_array(struct class_datum, p->p_classes.nprim);
+        xmalloc_array(struct class_datum *, p->p_classes.nprim);
     if ( !p->class_val_to_struct )
     {
         rc = -ENOMEM;
@@ -404,14 +434,14 @@ static int policydb_index_others(struct 
 {
     int i, rc = 0;
 
-    printk(KERN_INFO "security:  %d users, %d roles, %d types, %d bools",
+    printk(KERN_INFO "Flask:  %d users, %d roles, %d types, %d bools",
            p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, 
p->p_bools.nprim);
     if ( flask_mls_enabled )
         printk(", %d sens, %d cats", p->p_levels.nprim, p->p_cats.nprim);
 
     printk("\n");
 
-    printk(KERN_INFO "security:  %d classes, %d rules\n",
+    printk(KERN_INFO "Flask:  %d classes, %d rules\n",
            p->p_classes.nprim, p->te_avtab.nel);
 
 #ifdef DEBUG_HASHES
@@ -420,7 +450,7 @@ static int policydb_index_others(struct 
 #endif
 
     p->role_val_to_struct =
-        (void *)xmalloc_array(struct role_datum, p->p_roles.nprim);
+        xmalloc_array(struct role_datum *, p->p_roles.nprim);
     if ( !p->role_val_to_struct )
     {
         rc = -ENOMEM;
@@ -428,8 +458,16 @@ static int policydb_index_others(struct 
     }
 
     p->user_val_to_struct =
-        (void *)xmalloc_array(struct user_datum, p->p_users.nprim);
+        xmalloc_array(struct user_datum *, p->p_users.nprim);
     if ( !p->user_val_to_struct )
+    {
+        rc = -ENOMEM;
+        goto out;
+    }
+
+    p->type_val_to_struct =
+        xmalloc_array(struct type_datum *, p->p_types.nprim);
+    if ( !p->type_val_to_struct )
     {
         rc = -ENOMEM;
         goto out;
@@ -627,6 +665,7 @@ void policydb_destroy(struct policydb *p
     xfree(p->class_val_to_struct);
     xfree(p->role_val_to_struct);
     xfree(p->user_val_to_struct);
+    xfree(p->type_val_to_struct);
 
     avtab_destroy(&p->te_avtab);
 
@@ -639,6 +678,7 @@ void policydb_destroy(struct policydb *p
             c = c->next;
             ocontext_destroy(ctmp,i);
         }
+        p->ocontexts[i] = NULL;
     }
 
     cond_policydb_destroy(p);
@@ -659,14 +699,28 @@ void policydb_destroy(struct policydb *p
 
     for ( rt = p->range_tr; rt; rt = rt -> next )
     {
-        if ( lrt ) xfree(lrt);
+        if ( lrt )
+        {
+            ebitmap_destroy(&lrt->target_range.level[0].cat);
+            ebitmap_destroy(&lrt->target_range.level[1].cat);
+            xfree(lrt);
+        }
         lrt = rt;
     }
-    if ( lrt ) xfree(lrt);
-
-    for ( i = 0; i < p->p_types.nprim; i++ )
-        ebitmap_destroy(&p->type_attr_map[i]);
+    if ( lrt )
+    {
+        ebitmap_destroy(&lrt->target_range.level[0].cat);
+        ebitmap_destroy(&lrt->target_range.level[1].cat);
+        xfree(lrt);
+    }
+
+    if ( p->type_attr_map )
+        for ( i = 0; i < p->p_types.nprim; i++ )
+            ebitmap_destroy(&p->type_attr_map[i]);
     xfree(p->type_attr_map);
+
+    ebitmap_destroy(&p->policycaps);
+    ebitmap_destroy(&p->permissive_map);
 
     return;
 }
@@ -683,7 +737,7 @@ int policydb_load_isids(struct policydb 
     rc = sidtab_init(s);
     if ( rc )
     {
-        printk(KERN_ERR "security:  out of memory on SID table init\n");
+        printk(KERN_ERR "Flask:  out of memory on SID table init\n");
         goto out;
     }
 
@@ -692,14 +746,14 @@ int policydb_load_isids(struct policydb 
     {
         if ( !c->context[0].user )
         {
-            printk(KERN_ERR "security:  SID %s was never "
+            printk(KERN_ERR "Flask:  SID %s was never "
                    "defined.\n", c->u.name);
             rc = -EINVAL;
             goto out;
         }
         if ( sidtab_insert(s, c->sid[0], &c->context[0]) )
         {
-            printk(KERN_ERR "security:  unable to load initial "
+            printk(KERN_ERR "Flask:  unable to load initial "
                    "SID %s.\n", c->u.name);
             rc = -EINVAL;
             goto out;
@@ -707,6 +761,27 @@ int policydb_load_isids(struct policydb 
     }
 out:
     return rc;
+}
+
+int policydb_class_isvalid(struct policydb *p, unsigned int class)
+{
+    if ( !class || class > p->p_classes.nprim )
+        return 0;
+    return 1;
+}
+
+int policydb_role_isvalid(struct policydb *p, unsigned int role)
+{
+    if ( !role || role > p->p_roles.nprim )
+        return 0;
+    return 1;
+}
+
+int policydb_type_isvalid(struct policydb *p, unsigned int type)
+{
+    if ( !type || type > p->p_types.nprim )
+        return 0;
+    return 1;
 }
 
 /*
@@ -772,14 +847,14 @@ static int mls_read_range_helper(struct 
     items = le32_to_cpu(buf[0]);
     if ( items > ARRAY_SIZE(buf) )
     {
-        printk(KERN_ERR "security: mls:  range overflow\n");
+        printk(KERN_ERR "Flask: mls:  range overflow\n");
         rc = -EINVAL;
         goto out;
     }
     rc = next_entry(buf, fp, sizeof(u32) * items);
     if ( rc < 0 )
     {
-        printk(KERN_ERR "security: mls:  truncated range\n");
+        printk(KERN_ERR "Flask: mls:  truncated range\n");
         goto out;
     }
     r->level[0].sens = le32_to_cpu(buf[0]);
@@ -791,7 +866,7 @@ static int mls_read_range_helper(struct 
     rc = ebitmap_read(&r->level[0].cat, fp);
     if ( rc )
     {
-        printk(KERN_ERR "security: mls:  error reading low "
+        printk(KERN_ERR "Flask: mls:  error reading low "
                "categories\n");
         goto out;
     }
@@ -800,7 +875,7 @@ static int mls_read_range_helper(struct 
         rc = ebitmap_read(&r->level[1].cat, fp);
         if ( rc )
         {
-            printk(KERN_ERR "security: mls:  error reading high "
+            printk(KERN_ERR "Flask: mls:  error reading high "
                    "categories\n");
             goto bad_high;
         }
@@ -810,7 +885,7 @@ static int mls_read_range_helper(struct 
         rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
         if ( rc )
         {
-            printk(KERN_ERR "security: mls:  out of memory\n");
+            printk(KERN_ERR "Flask: mls:  out of memory\n");
             goto bad_high;
         }
     }
@@ -836,7 +911,7 @@ static int context_read_and_validate(str
     rc = next_entry(buf, fp, sizeof buf);
     if ( rc < 0 )
     {
-        printk(KERN_ERR "security: context truncated\n");
+        printk(KERN_ERR "Flask: context truncated\n");
         goto out;
     }
     c->user = le32_to_cpu(buf[0]);
@@ -846,7 +921,7 @@ static int context_read_and_validate(str
     {
         if ( mls_read_range_helper(&c->range, fp) )
         {
-            printk(KERN_ERR "security: error reading MLS range of "
+            printk(KERN_ERR "Flask: error reading MLS range of "
                    "context\n");
             rc = -EINVAL;
             goto out;
@@ -855,7 +930,7 @@ static int context_read_and_validate(str
 
     if ( !policydb_context_isvalid(p, c) )
     {
-        printk(KERN_ERR "security:  invalid security context\n");
+        printk(KERN_ERR "Flask:  invalid security context\n");
         context_destroy(c);
         rc = -EINVAL;
     }
@@ -1121,7 +1196,7 @@ static int class_read(struct policydb *p
                             cladatum->comkey);
         if ( !cladatum->comdatum )
         {
-            printk(KERN_ERR "security:  unknown common %s\n",
+            printk(KERN_ERR "Flask:  unknown common %s\n",
                    cladatum->comkey);
             rc = -EINVAL;
             goto bad;
@@ -1166,8 +1241,8 @@ static int role_read(struct policydb *p,
 {
     char *key = NULL;
     struct role_datum *role;
-    int rc;
-    __le32 buf[2];
+    int rc, to_read = 2;
+    __le32 buf[3];
     u32 len;
 
     role = xmalloc(struct role_datum);
@@ -1178,12 +1253,17 @@ static int role_read(struct policydb *p,
     }
     memset(role, 0, sizeof(*role));
 
-    rc = next_entry(buf, fp, sizeof buf);
+    if ( p->policyvers >= POLICYDB_VERSION_BOUNDARY )
+        to_read = 3;
+
+    rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
     if ( rc < 0 )
         goto bad;
 
     len = le32_to_cpu(buf[0]);
     role->value = le32_to_cpu(buf[1]);
+    if ( p->policyvers >= POLICYDB_VERSION_BOUNDARY )
+        role->bounds = le32_to_cpu(buf[2]);
 
     key = xmalloc_array(char, len + 1);
     if ( !key )
@@ -1231,8 +1311,8 @@ static int type_read(struct policydb *p,
 {
     char *key = NULL;
     struct type_datum *typdatum;
-    int rc;
-    __le32 buf[3];
+    int rc, to_read = 3;
+    __le32 buf[4];
     u32 len;
 
     typdatum = xmalloc(struct type_datum);
@@ -1243,13 +1323,30 @@ static int type_read(struct policydb *p,
     }
     memset(typdatum, 0, sizeof(*typdatum));
 
-    rc = next_entry(buf, fp, sizeof buf);
+    if ( p->policyvers >= POLICYDB_VERSION_BOUNDARY )
+        to_read = 4;
+
+    rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
     if ( rc < 0 )
         goto bad;
 
     len = le32_to_cpu(buf[0]);
     typdatum->value = le32_to_cpu(buf[1]);
-    typdatum->primary = le32_to_cpu(buf[2]);
+    if ( p->policyvers >= POLICYDB_VERSION_BOUNDARY )
+    {
+        u32 prop = le32_to_cpu(buf[2]);
+
+        if ( prop & TYPEDATUM_PROPERTY_PRIMARY )
+            typdatum->primary = 1;
+        if ( prop & TYPEDATUM_PROPERTY_ATTRIBUTE )
+            typdatum->attribute = 1;
+
+        typdatum->bounds = le32_to_cpu(buf[3]);
+    }
+    else
+    {
+        typdatum->primary = le32_to_cpu(buf[2]);
+    }
 
     key = xmalloc_array(char, len + 1);
     if ( !key )
@@ -1287,14 +1384,14 @@ static int mls_read_level(struct mls_lev
     rc = next_entry(buf, fp, sizeof buf);
     if ( rc < 0 )
     {
-        printk(KERN_ERR "security: mls: truncated level\n");
+        printk(KERN_ERR "Flask: mls: truncated level\n");
         goto bad;
     }
     lp->sens = le32_to_cpu(buf[0]);
 
     if ( ebitmap_read(&lp->cat, fp) )
     {
-        printk(KERN_ERR "security: mls:  error reading level categories\n");
+        printk(KERN_ERR "Flask: mls:  error reading level categories\n");
         goto bad;
     }
     return 0;
@@ -1307,8 +1404,8 @@ static int user_read(struct policydb *p,
 {
     char *key = NULL;
     struct user_datum *usrdatum;
-    int rc;
-    __le32 buf[2];
+    int rc, to_read = 2;
+    __le32 buf[3];
     u32 len;
 
     usrdatum = xmalloc(struct user_datum);
@@ -1319,12 +1416,17 @@ static int user_read(struct policydb *p,
     }
     memset(usrdatum, 0, sizeof(*usrdatum));
 
-    rc = next_entry(buf, fp, sizeof buf);
+    if ( p->policyvers >= POLICYDB_VERSION_BOUNDARY )
+        to_read = 3;
+
+    rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
     if ( rc < 0 )
         goto bad;
 
     len = le32_to_cpu(buf[0]);
     usrdatum->value = le32_to_cpu(buf[1]);
+    if ( p->policyvers >= POLICYDB_VERSION_BOUNDARY )
+        usrdatum->bounds = le32_to_cpu(buf[2]);
 
     key = xmalloc_array(char, len + 1);
     if ( !key )
@@ -1475,6 +1577,142 @@ static int (*read_f[SYM_NUM]) (struct po
     cat_read,
 };
 
+static int user_bounds_sanity_check(void *key, void *datum, void *datap)
+{
+    struct user_datum *upper, *user;
+    struct policydb *p = datap;
+    int depth = 0;
+
+    upper = user = datum;
+    while (upper->bounds)
+    {
+        struct ebitmap_node *node;
+        unsigned long bit;
+
+        if ( ++depth == POLICYDB_BOUNDS_MAXDEPTH )
+        {
+            printk(KERN_ERR "Flask: user %s: "
+                   "too deep or looped boundary",
+                   (char *) key);
+            return -EINVAL;
+        }
+
+        upper = p->user_val_to_struct[upper->bounds - 1];
+        ebitmap_for_each_positive_bit(&user->roles, node, bit)
+        {
+            if ( ebitmap_get_bit(&upper->roles, bit) )
+                continue;
+
+            printk(KERN_ERR
+                   "Flask: boundary violated policy: "
+                   "user=%s role=%s bounds=%s\n",
+                   p->p_user_val_to_name[user->value - 1],
+                   p->p_role_val_to_name[bit],
+                   p->p_user_val_to_name[upper->value - 1]);
+
+            return -EINVAL;
+        }
+    }
+
+    return 0;
+}
+
+static int role_bounds_sanity_check(void *key, void *datum, void *datap)
+{
+    struct role_datum *upper, *role;
+    struct policydb *p = datap;
+    int depth = 0;
+
+    upper = role = datum;
+    while (upper->bounds)
+    {
+        struct ebitmap_node *node;
+        unsigned long bit;
+
+        if ( ++depth == POLICYDB_BOUNDS_MAXDEPTH )
+        {
+            printk(KERN_ERR "Flask: role %s: "
+                   "too deep or looped bounds\n",
+                   (char *) key);
+            return -EINVAL;
+        }
+
+        upper = p->role_val_to_struct[upper->bounds - 1];
+        ebitmap_for_each_positive_bit(&role->types, node, bit)
+        {
+            if ( ebitmap_get_bit(&upper->types, bit) )
+                continue;
+
+            printk(KERN_ERR
+                   "Flask: boundary violated policy: "
+                   "role=%s type=%s bounds=%s\n",
+                   p->p_role_val_to_name[role->value - 1],
+                   p->p_type_val_to_name[bit],
+                   p->p_role_val_to_name[upper->value - 1]);
+
+            return -EINVAL;
+        }
+    }
+
+    return 0;
+}
+
+static int type_bounds_sanity_check(void *key, void *datum, void *datap)
+{
+    struct type_datum *upper, *type;
+    struct policydb *p = datap;
+    int depth = 0;
+
+    upper = type = datum;
+    while (upper->bounds)
+    {
+        if ( ++depth == POLICYDB_BOUNDS_MAXDEPTH )
+        {
+            printk(KERN_ERR "Flask: type %s: "
+                              "too deep or looped boundary\n",
+                              (char *) key);
+            return -EINVAL;
+        }
+
+        upper = p->type_val_to_struct[upper->bounds - 1];
+        if ( upper->attribute )
+        {
+            printk(KERN_ERR "Flask: type %s: "
+                              "bounded by attribute %s",
+                              (char *) key,
+                              p->p_type_val_to_name[upper->value - 1]);
+            return -EINVAL;
+        }
+    }
+
+    return 0;
+}
+
+static int policydb_bounds_sanity_check(struct policydb *p)
+{
+    int rc;
+
+    if ( p->policyvers < POLICYDB_VERSION_BOUNDARY )
+        return 0;
+
+    rc = hashtab_map(p->p_users.table,
+                     user_bounds_sanity_check, p);
+    if ( rc )
+        return rc;
+
+    rc = hashtab_map(p->p_roles.table,
+                     role_bounds_sanity_check, p);
+    if ( rc )
+        return rc;
+
+    rc = hashtab_map(p->p_types.table,
+                     type_bounds_sanity_check, p);
+    if ( rc )
+        return rc;
+
+    return 0;
+}
+
 extern int ss_initialized;
 
 /*
@@ -1505,7 +1743,7 @@ int policydb_read(struct policydb *p, vo
 
     if ( le32_to_cpu(buf[0]) != POLICYDB_MAGIC )
     {
-        printk(KERN_ERR "security:  policydb magic number 0x%x does "
+        printk(KERN_ERR "Flask:  policydb magic number 0x%x does "
                "not match expected magic number 0x%x\n",
                le32_to_cpu(buf[0]), POLICYDB_MAGIC);
         goto bad;
@@ -1514,7 +1752,7 @@ int policydb_read(struct policydb *p, vo
     len = le32_to_cpu(buf[1]);
     if ( len != strlen(POLICYDB_STRING) )
     {
-        printk(KERN_ERR "security:  policydb string length %d does not "
+        printk(KERN_ERR "Flask:  policydb string length %d does not "
                "match expected length %lu\n",
                len, strlen(POLICYDB_STRING));
         goto bad;
@@ -1522,7 +1760,7 @@ int policydb_read(struct policydb *p, vo
     policydb_str = xmalloc_array(char, len + 1);
     if ( !policydb_str )
     {
-        printk(KERN_ERR "security:  unable to allocate memory for policydb "
+        printk(KERN_ERR "Flask:  unable to allocate memory for policydb "
                "string of length %d\n", len);
         rc = -ENOMEM;
         goto bad;
@@ -1530,14 +1768,14 @@ int policydb_read(struct policydb *p, vo
     rc = next_entry(policydb_str, fp, len);
     if ( rc < 0 )
     {
-        printk(KERN_ERR "security:  truncated policydb string identifier\n");
+        printk(KERN_ERR "Flask:  truncated policydb string identifier\n");
         xfree(policydb_str);
         goto bad;
     }
     policydb_str[len] = 0;
     if ( strcmp(policydb_str, POLICYDB_STRING) )
     {
-        printk(KERN_ERR "security:  policydb string %s does not match "
+        printk(KERN_ERR "Flask:  policydb string %s does not match "
                "my string %s\n", policydb_str, POLICYDB_STRING);
         xfree(policydb_str);
         goto bad;
@@ -1555,7 +1793,7 @@ int policydb_read(struct policydb *p, vo
     if ( p->policyvers < POLICYDB_VERSION_MIN ||
                                         p->policyvers > POLICYDB_VERSION_MAX )
     {
-            printk(KERN_ERR "security:  policydb version %d does not match "
+            printk(KERN_ERR "Flask:  policydb version %d does not match "
                    "my version range %d-%d\n",
                    le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, 
POLICYDB_VERSION_MAX);
             goto bad;
@@ -1589,20 +1827,28 @@ int policydb_read(struct policydb *p, vo
         }
     }
 
+    if ( p->policyvers >= POLICYDB_VERSION_POLCAP &&
+         ebitmap_read(&p->policycaps, fp) != 0 )
+        goto bad;
+
+    if ( p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
+         ebitmap_read(&p->permissive_map, fp) != 0 )
+        goto bad;
+
     info = policydb_lookup_compat(p->policyvers);
     if ( !info )
     {
-        printk(KERN_ERR "security:  unable to find policy compat info "
+        printk(KERN_ERR "Flask:  unable to find policy compat info "
                "for version %d\n", p->policyvers);
         goto bad;
     }
 
     if ( le32_to_cpu(buf[2]) != info->sym_num ||
-                                        le32_to_cpu(buf[3]) != info->ocon_num )
-    {
-        printk(KERN_ERR "security:  policydb table sizes (%d,%d) do "
+         le32_to_cpu(buf[3]) != info->ocon_num )
+    {
+        printk(KERN_ERR "Flask:  policydb table sizes (%d,%d) do "
                "not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
-            le32_to_cpu(buf[3]),
+               le32_to_cpu(buf[3]),
                info->sym_num, info->ocon_num);
         goto bad;
     }
@@ -1624,7 +1870,7 @@ int policydb_read(struct policydb *p, vo
         p->symtab[i].nprim = nprim;
     }
 
-    rc = avtab_read(&p->te_avtab, fp, p->policyvers);
+    rc = avtab_read(&p->te_avtab, fp, p);
     if ( rc )
         goto bad;
 
@@ -1659,6 +1905,13 @@ int policydb_read(struct policydb *p, vo
         tr->role = le32_to_cpu(buf[0]);
         tr->type = le32_to_cpu(buf[1]);
         tr->new_role = le32_to_cpu(buf[2]);
+        if ( !policydb_role_isvalid(p, tr->role) ||
+             !policydb_type_isvalid(p, tr->type) ||
+             !policydb_role_isvalid(p, tr->new_role) )
+        {
+            rc = -EINVAL;
+            goto bad;
+        }
         ltr = tr;
     }
 
@@ -1685,6 +1938,12 @@ int policydb_read(struct policydb *p, vo
             goto bad;
         ra->role = le32_to_cpu(buf[0]);
         ra->new_role = le32_to_cpu(buf[1]);
+        if ( !policydb_role_isvalid(p, ra->role) ||
+             !policydb_role_isvalid(p, ra->new_role) )
+        {
+            rc = -EINVAL;
+            goto bad;
+        }
         lra = ra;
     }
 
@@ -1720,15 +1979,20 @@ int policydb_read(struct policydb *p, vo
             rc = -EINVAL;
             switch ( i )
             {
-                case OCON_ISID:
-                    rc = next_entry(buf, fp, sizeof(u32));
-                    if ( rc < 0 )
-                        goto bad;
-                    c->sid[0] = le32_to_cpu(buf[0]);
-                    rc = context_read_and_validate(&c->context[0], p, fp);
-                    if ( rc )
-                        goto bad;
+            case OCON_ISID:
+                rc = next_entry(buf, fp, sizeof(u32));
+                if ( rc < 0 )
+                    goto bad;
+                c->sid[0] = le32_to_cpu(buf[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");
+                rc = -EINVAL;
+                goto bad;
             }
         }
     }
@@ -1737,9 +2001,16 @@ int policydb_read(struct policydb *p, vo
     if ( rc < 0 )
         goto bad;
     nel = le32_to_cpu(buf[0]);
+    if ( nel )
+    {
+        printk(KERN_ERR "Flask:  unsupported genfs config data\n");
+        rc = -EINVAL;
+        goto bad;
+    }
 
     if ( p->policyvers >= POLICYDB_VERSION_MLS )
     {
+        int new_rangetr = p->policyvers >= POLICYDB_VERSION_RANGETRANS;
         rc = next_entry(buf, fp, sizeof(u32));
         if ( rc < 0 )
             goto bad;
@@ -1761,11 +2032,31 @@ int policydb_read(struct policydb *p, vo
             rc = next_entry(buf, fp, (sizeof(u32) * 2));
             if ( rc < 0 )
                 goto bad;
-            rt->dom = le32_to_cpu(buf[0]);
-            rt->type = le32_to_cpu(buf[1]);
-            rc = mls_read_range_helper(&rt->range, fp);
+            rt->source_type = le32_to_cpu(buf[0]);
+            rt->target_type = le32_to_cpu(buf[1]);
+            if ( new_rangetr )
+            {
+                rc = next_entry(buf, fp, sizeof(u32));
+                if ( rc < 0 )
+                    goto bad;
+                rt->target_class = le32_to_cpu(buf[0]);
+            } else
+                rt->target_class = SECCLASS_DOMAIN;
+            if ( !policydb_type_isvalid(p, rt->source_type) ||
+                 !policydb_type_isvalid(p, rt->target_type) ||
+                 !policydb_class_isvalid(p, rt->target_class) )
+            {
+                rc = -EINVAL;
+                goto bad;
+            }
+            rc = mls_read_range_helper(&rt->target_range, fp);
             if ( rc )
                 goto bad;
+            if ( !mls_range_isvalid(p, &rt->target_range) )
+            {
+                printk(KERN_WARNING "Flask:  rangetrans:  invalid range\n");
+                goto bad;
+            }
             lrt = rt;
         }
     }
@@ -1786,6 +2077,10 @@ int policydb_read(struct policydb *p, vo
         if ( ebitmap_set_bit(&p->type_attr_map[i], i, 1) )
                 goto bad;
     }
+
+    rc = policydb_bounds_sanity_check(p);
+    if ( rc )
+        goto bad;
 
     rc = 0;
 out:
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/policydb.h
--- a/xen/xsm/flask/ss/policydb.h       Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/policydb.h       Wed Aug 19 14:22:52 2009 +0100
@@ -63,6 +63,7 @@ struct class_datum {
 /* Role attributes */
 struct role_datum {
     u32 value;            /* internal role value */
+    u32 bounds;                        /* boundary of role */
     struct ebitmap dominates;    /* set of roles dominated by this role */
     struct ebitmap types;        /* set of authorized types for role */
 };
@@ -83,12 +84,25 @@ struct role_allow {
 /* Type attributes */
 struct type_datum {
     u32 value;        /* internal type value */
+    u32 bounds;                /* boundary of type */
     unsigned char primary;    /* primary name? */
-};
+    unsigned char attribute;/* attribute ?*/
+};
+
+/*
+ * type_datum properties
+ * available at the kernel policy version >= POLICYDB_VERSION_BOUNDARY
+ */
+#define TYPEDATUM_PROPERTY_PRIMARY     0x0001
+#define TYPEDATUM_PROPERTY_ATTRIBUTE   0x0002
+
+/* limitation of boundary depth  */
+#define POLICYDB_BOUNDS_MAXDEPTH       4
 
 /* User attributes */
 struct user_datum {
     u32 value;            /* internal user value */
+    u32 bounds;                        /* bounds of user */
     struct ebitmap roles;        /* set of authorized roles for user */
     struct mls_range range;        /* MLS range (min - max) for user */
     struct mls_level dfltlevel;    /* default login MLS level for user */
@@ -108,9 +122,10 @@ struct cat_datum {
 };
 
 struct range_trans {
-    u32 dom;            /* current process domain */
-    u32 type;            /* program executable type */
-    struct mls_range range;        /* new range */
+    u32 source_type;
+    u32 target_type;
+    u32 target_class;
+    struct mls_range target_range;
     struct range_trans *next;
 };
 
@@ -191,6 +206,7 @@ struct policydb {
     struct class_datum **class_val_to_struct;
     struct role_datum **role_val_to_struct;
     struct user_datum **user_val_to_struct;
+    struct type_datum **type_val_to_struct;
 
     /* type enforcement access vectors and transitions */
     struct avtab te_avtab;
@@ -218,12 +234,19 @@ struct policydb {
     /* type -> attribute reverse mapping */
     struct ebitmap *type_attr_map;
 
+    struct ebitmap policycaps;
+
+    struct ebitmap permissive_map;
+
     unsigned int policyvers;
 };
 
 extern void policydb_destroy(struct policydb *p);
 extern int policydb_load_isids(struct policydb *p, struct sidtab *s);
 extern int policydb_context_isvalid(struct policydb *p, struct context *c);
+extern int policydb_class_isvalid(struct policydb *p, unsigned int class);
+extern int policydb_type_isvalid(struct policydb *p, unsigned int type);
+extern int policydb_role_isvalid(struct policydb *p, unsigned int role);
 extern int policydb_read(struct policydb *p, void *fp);
 
 #define PERM_SYMTAB_SIZE 32
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/services.c
--- a/xen/xsm/flask/ss/services.c       Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/services.c       Wed Aug 19 14:22:52 2009 +0100
@@ -12,8 +12,22 @@
  *
  *     Added conditional policy language extensions
  *
- * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
- * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ * Updated: Hewlett-Packard <paul.moore@xxxxxx>
+ *
+ *      Added support for the policy capability bitmap
+ *
+ * Updated: Chad Sellers <csellers@xxxxxxxxxx>
+ *
+ *  Added validation of kernel classes and permissions
+ *
+ * Updated: KaiGai Kohei <kaigai@xxxxxxxxxxxxx>
+ *
+ *  Added support for bounds domain and audit messaged on masked permissions
+ *
+ * Copyright (C) 2008, 2009 NEC Corporation
+ * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
+ * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
  * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@xxxxxxxxxx>
  *    This program is free software; you can redistribute it and/or modify
  *      it under the terms of the GNU General Public License as published by
@@ -42,9 +56,9 @@ unsigned int policydb_loaded_version;
 
 static DEFINE_RWLOCK(policy_rwlock);
 #define POLICY_RDLOCK read_lock(&policy_rwlock)
-#define POLICY_WRLOCK write_lock_irq(&policy_rwlock)
+#define POLICY_WRLOCK write_lock(&policy_rwlock)
 #define POLICY_RDUNLOCK read_unlock(&policy_rwlock)
-#define POLICY_WRUNLOCK write_unlock_irq(&policy_rwlock)
+#define POLICY_WRUNLOCK write_unlock(&policy_rwlock)
 
 static DEFINE_SPINLOCK(load_sem);
 #define LOAD_LOCK spin_lock(&load_sem)
@@ -65,6 +79,12 @@ static u32 latest_granting = 0;
 /* Forward declaration. */
 static int context_struct_to_string(struct context *context, char **scontext,
                                                             u32 *scontext_len);
+
+static int context_struct_compute_av(struct context *scontext,
+                                    struct context *tcontext,
+                                    u16 tclass,
+                                    u32 requested,
+                                    struct av_decision *avd);
 
 /*
  * Return the boolean value of a constraint expression
@@ -259,12 +279,180 @@ mls_ops:
 }
 
 /*
+ * security_dump_masked_av - dumps masked permissions during
+ * security_compute_av due to RBAC, MLS/Constraint and Type bounds.
+ */
+static int dump_masked_av_helper(void *k, void *d, void *args)
+{
+    struct perm_datum *pdatum = d;
+    char **permission_names = args;
+
+    BUG_ON(pdatum->value < 1 || pdatum->value > 32);
+
+    permission_names[pdatum->value - 1] = (char *)k;
+
+    return 0;
+}
+
+static void security_dump_masked_av(struct context *scontext,
+                                   struct context *tcontext,
+                                   u16 tclass,
+                                   u32 permissions,
+                                   const char *reason)
+{
+    struct common_datum *common_dat;
+    struct class_datum *tclass_dat;
+    char *tclass_name;
+    char *scontext_name = NULL;
+    char *tcontext_name = NULL;
+    char *permission_names[32];
+    int index;
+    u32 length;
+    unsigned char need_comma = 0;
+
+    if ( !permissions )
+        return;
+
+    tclass_name = policydb.p_class_val_to_name[tclass - 1];
+    tclass_dat = policydb.class_val_to_struct[tclass - 1];
+    common_dat = tclass_dat->comdatum;
+
+    /* init permission_names */
+    if ( common_dat &&
+         hashtab_map(common_dat->permissions.table,
+                     dump_masked_av_helper, permission_names) < 0 )
+        goto out;
+
+    if ( hashtab_map(tclass_dat->permissions.table,
+                    dump_masked_av_helper, permission_names) < 0 )
+        goto out;
+
+       /* get scontext/tcontext in text form */
+    if ( context_struct_to_string(scontext,
+                                 &scontext_name, &length) < 0 )
+        goto out;
+
+    if ( context_struct_to_string(tcontext,
+                                 &tcontext_name, &length) < 0 )
+        goto out;
+
+    printk("Flask: op=security_compute_av reason=%s "
+           "scontext=%s tcontext=%s tclass=%s perms=",
+           reason, scontext_name, tcontext_name, tclass_name);
+
+    for ( index = 0; index < 32; index++ )
+    {
+        u32 mask = (1 << index);
+
+        if ( (mask & permissions) == 0 )
+            continue;
+
+        printk("%s%s",
+               need_comma ? "," : "",
+               permission_names[index]
+               ? permission_names[index] : "????");
+        need_comma = 1;
+    }
+    printk("\n");
+out:
+    /* release scontext/tcontext */
+    xfree(tcontext_name);
+    xfree(scontext_name);
+
+    return;
+}
+
+/*
+ * security_boundary_permission - drops violated permissions
+ * on boundary constraint.
+ */
+static void type_attribute_bounds_av(struct context *scontext,
+                                     struct context *tcontext,
+                                     u16 tclass,
+                                     u32 requested,
+                                     struct av_decision *avd)
+{
+    struct context lo_scontext;
+    struct context lo_tcontext;
+    struct av_decision lo_avd;
+    struct type_datum *source
+        = policydb.type_val_to_struct[scontext->type - 1];
+    struct type_datum *target
+        = policydb.type_val_to_struct[tcontext->type - 1];
+    u32 masked = 0;
+
+    if ( source->bounds )
+    {
+        memset(&lo_avd, 0, sizeof(lo_avd));
+
+        memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
+        lo_scontext.type = source->bounds;
+
+        context_struct_compute_av(&lo_scontext,
+                                  tcontext,
+                                  tclass,
+                                  requested,
+                                  &lo_avd);
+        if ( (lo_avd.allowed & avd->allowed) == avd->allowed )
+            return;            /* no masked permission */
+        masked = ~lo_avd.allowed & avd->allowed;
+    }
+
+    if ( target->bounds )
+    {
+        memset(&lo_avd, 0, sizeof(lo_avd));
+
+        memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext));
+        lo_tcontext.type = target->bounds;
+
+        context_struct_compute_av(scontext,
+                                  &lo_tcontext,
+                                  tclass,
+                                  requested,
+                                  &lo_avd);
+        if ( (lo_avd.allowed & avd->allowed) == avd->allowed )
+            return;            /* no masked permission */
+        masked = ~lo_avd.allowed & avd->allowed;
+    }
+
+    if ( source->bounds && target->bounds )
+    {
+        memset(&lo_avd, 0, sizeof(lo_avd));
+        /*
+         * lo_scontext and lo_tcontext are already
+         * set up.
+         */
+
+        context_struct_compute_av(&lo_scontext,
+                                  &lo_tcontext,
+                                  tclass,
+                                  requested,
+                                  &lo_avd);
+        if ( (lo_avd.allowed & avd->allowed) == avd->allowed )
+            return;            /* no masked permission */
+        masked = ~lo_avd.allowed & avd->allowed;
+    }
+
+    if ( masked )
+    {
+        /* mask violated permissions */
+        avd->allowed &= ~masked;
+
+        /* audit masked permissions */
+        security_dump_masked_av(scontext, tcontext,
+                                tclass, masked, "bounds");
+    }
+}
+
+/*
  * Compute access vectors based on a context structure pair for
  * the permissions in a particular class.
  */
 static int context_struct_compute_av(struct context *scontext,
-                            struct context *tcontext, u16 tclass, u32 
requested, 
-                                                        struct av_decision 
*avd)
+                                    struct context *tcontext,
+                                    u16 tclass,
+                                    u32 requested,
+                                    struct av_decision *avd)
 {
     struct constraint_node *constraint;
     struct role_allow *ra;
@@ -275,22 +463,22 @@ static int context_struct_compute_av(str
     struct ebitmap_node *snode, *tnode;
     unsigned int i, j;
 
-    if ( !tclass || tclass > policydb.p_classes.nprim )
-    {
-        printk(KERN_ERR "security_compute_av:  unrecognized class %d\n",
-               tclass);
-        return -EINVAL;
-    }
-    tclass_datum = policydb.class_val_to_struct[tclass - 1];
-
     /*
      * Initialize the access vectors to the default values.
      */
     avd->allowed = 0;
-    avd->decided = 0xffffffff;
     avd->auditallow = 0;
     avd->auditdeny = 0xffffffff;
     avd->seqno = latest_granting;
+    avd->flags = 0;
+
+    /*
+     * We do not presently support policydb.handle_unknown == allow in Xen.
+     */
+    if ( !tclass || tclass > policydb.p_classes.nprim )
+        return -EINVAL;
+
+    tclass_datum = policydb.class_val_to_struct[tclass - 1];
 
     /*
      * If a specific type enforcement rule was defined for
@@ -300,14 +488,10 @@ static int context_struct_compute_av(str
     avkey.specified = AVTAB_AV;
     sattr = &policydb.type_attr_map[scontext->type - 1];
     tattr = &policydb.type_attr_map[tcontext->type - 1];
-    ebitmap_for_each_bit(sattr, snode, i)
-    {
-        if ( !ebitmap_node_get_bit(snode, i) )
-            continue;
-        ebitmap_for_each_bit(tattr, tnode, j)
-        {
-            if ( !ebitmap_node_get_bit(tnode, j) )
-                continue;
+    ebitmap_for_each_positive_bit(sattr, snode, i)
+    {
+        ebitmap_for_each_positive_bit(tattr, tnode, j)
+        {
             avkey.source_type = i + 1;
             avkey.target_type = j + 1;
             for ( node = avtab_search_node(&policydb.te_avtab, &avkey);
@@ -338,7 +522,7 @@ static int context_struct_compute_av(str
         if ( (constraint->permissions & (avd->allowed) ) &&
             !constraint_expr_eval(scontext, tcontext, NULL, constraint->expr))
         {
-            avd->allowed = (avd->allowed) & ~(constraint->permissions);
+           avd->allowed &= ~(constraint->permissions);
         }
         constraint = constraint->next;
     }
@@ -349,23 +533,25 @@ static int context_struct_compute_av(str
      * pair.
      */
     if ( tclass == SECCLASS_DOMAIN &&
-/* removed until future dynamic domain capability
-        (avd->allowed & (DOMAIN__TRANSITION | DOMAIN__DYNTRANSITION)) &&
-*/
-                                            scontext->role != tcontext->role )
-        {
+         (avd->allowed & DOMAIN__TRANSITION) &&
+         scontext->role != tcontext->role )
+    {
         for ( ra = policydb.role_allow; ra; ra = ra->next )
         {
             if ( scontext->role == ra->role && tcontext->role == ra->new_role )
                 break;
         }
-/* removed until future dynamic domain capability    
         if (!ra)
-            avd->allowed = (avd->allowed) & ~(DOMAIN__TRANSITION |
-                                            DOMAIN__DYNTRANSITION);
-*/
-    }
-
+            avd->allowed &= ~DOMAIN__TRANSITION;
+    }
+
+    /*
+     * If the given source and target types have boundary
+     * constraint, lazy checks have to mask any violated
+     * permission and notice it to userspace via audit.
+     */
+    type_attribute_bounds_av(scontext, tcontext,
+                            tclass, requested, avd);
     return 0;
 }
 
@@ -477,7 +663,7 @@ out:
  * if the access vector decisions were computed successfully.
  */
 int security_compute_av(u32 ssid, u32 tsid, u16 tclass, u32 requested,
-                                                    struct av_decision *avd)
+                        struct av_decision *avd)
 {
     struct context *scontext = NULL, *tcontext = NULL;
     int rc = 0;
@@ -485,7 +671,6 @@ int security_compute_av(u32 ssid, u32 ts
     if ( !ss_initialized )
     {
         avd->allowed = 0xffffffff;
-        avd->decided = 0xffffffff;
         avd->auditallow = 0;
         avd->auditdeny = 0xffffffff;
         avd->seqno = latest_granting;
@@ -510,6 +695,10 @@ int security_compute_av(u32 ssid, u32 ts
     }
 
     rc = context_struct_compute_av(scontext, tcontext, tclass, requested, avd);
+
+    /* permissive domain? */
+    if ( ebitmap_get_bit(&policydb.permissive_map, scontext->type) )
+        avd->flags |= AVD_FLAGS_PERMISSIVE;
 out:
     POLICY_RDUNLOCK;
     return rc;
@@ -611,7 +800,18 @@ out:
 
 }
 
-static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 
*sid, u32 def_sid)
+/**
+ * security_context_to_sid - Obtain a SID for a given security context.
+ * @scontext: security context
+ * @scontext_len: length in bytes
+ * @sid: security identifier, SID
+ *
+ * Obtains a SID associated with the security context that
+ * has the string representation specified by @scontext.
+ * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
+ * memory is available, or 0 on success.
+ */
+int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
 {
     char *scontext2;
     struct context context;
@@ -701,12 +901,12 @@ static int security_context_to_sid_core(
     *p++ = 0;
 
     typdatum = hashtab_search(policydb.p_types.table, scontextp);
-    if ( !typdatum )
+    if ( !typdatum || typdatum->attribute )
         goto out_unlock;
 
     context.type = typdatum->value;
 
-    rc = mls_context_to_sid(oldc, &p, &context, &sidtab, def_sid);
+    rc = mls_context_to_sid(oldc, &p, &context, &sidtab);
     if ( rc )
         goto out_unlock;
 
@@ -730,45 +930,6 @@ out_unlock:
     xfree(scontext2);
 out:
     return rc;
-}
-
-/**
- * security_context_to_sid - Obtain a SID for a given security context.
- * @scontext: security context
- * @scontext_len: length in bytes
- * @sid: security identifier, SID
- *
- * Obtains a SID associated with the security context that
- * has the string representation specified by @scontext.
- * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
- * memory is available, or 0 on success.
- */
-int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
-{
-    return security_context_to_sid_core(scontext, scontext_len,
-                                                            sid, SECSID_NULL);
-}
-
-/**
- * security_context_to_sid_default - Obtain a SID for a given security context,
- * falling back to specified default if needed.
- *
- * @scontext: security context
- * @scontext_len: length in bytes
- * @sid: security identifier, SID
- * @def_sid: default SID to assign on errror
- *
- * Obtains a SID associated with the security context that
- * has the string representation specified by @scontext.
- * The default SID is passed to the MLS layer to be used to allow
- * kernel labeling of the MLS field if the MLS field is not present
- * (for upgrading to MLS without full relabel).
- * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
- * memory is available, or 0 on success.
- */
-int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 
*sid, u32 def_sid)
-{
-    return security_context_to_sid_core(scontext, scontext_len, sid, def_sid);
 }
 
 static int compute_sid_handle_invalid_context(
@@ -1001,88 +1162,128 @@ int security_change_sid(u32 ssid, u32 ts
 }
 
 /*
- * Verify that each permission that is defined under the
- * existing policy is still defined with the same value
- * in the new policy.
- */
-static int validate_perm(void *key, void *datum, void *p)
-{
-    struct hashtab *h;
-    struct perm_datum *perdatum, *perdatum2;
-    int rc = 0;
-
-    h = p;
-    perdatum = datum;
-
-    perdatum2 = hashtab_search(h, key);
-    if ( !perdatum2 )
-    {
-        printk(KERN_ERR "security:  permission %s disappeared", (char *)key);
-        rc = -ENOENT;
-        goto out;
-    }
-    if ( perdatum->value != perdatum2->value )
-    {
-        printk(KERN_ERR "security:  the value of permission %s changed",
-                                                                (char *)key);
-        rc = -EINVAL;
-    }
-out:
-    return rc;
-}
-
-/*
- * Verify that each class that is defined under the
- * existing policy is still defined with the same
- * attributes in the new policy.
- */
-static int validate_class(void *key, void *datum, void *p)
-{
-    struct policydb *newp;
-    struct class_datum *cladatum, *cladatum2;
-    int rc;
-
-    newp = p;
-    cladatum = datum;
-
-    cladatum2 = hashtab_search(newp->p_classes.table, key);
-    if ( !cladatum2 )
-    {
-        printk(KERN_ERR "security:  class %s disappeared\n", (char *)key);
-        rc = -ENOENT;
-        goto out;
-    }
-    if (cladatum->value != cladatum2->value) {
-        printk(KERN_ERR "security:  the value of class %s changed\n",
-                                                                (char *)key);
-        rc = -EINVAL;
-        goto out;
-    }
-    if ( (cladatum->comdatum && !cladatum2->comdatum) ||
-                                (!cladatum->comdatum && cladatum2->comdatum) )
-    {
-        printk(KERN_ERR "security:  the inherits clause for the access "
-               "vector definition for class %s changed\n", (char *)key);
-        rc = -EINVAL;
-        goto out;
-    }
-    if ( cladatum->comdatum )
-    {
-        rc = hashtab_map(cladatum->comdatum->permissions.table, validate_perm,
-                                     cladatum2->comdatum->permissions.table);
-        if ( rc )
-        {
-            printk(" in the access vector definition for class %s\n", 
-                                                                (char *)key);
-            goto out;
-        }
-    }
-    rc = hashtab_map(cladatum->permissions.table, validate_perm,
-                                                cladatum2->permissions.table);
-    if ( rc )
-        printk(" in access vector definition for class %s\n", (char *)key);
-out:
-    return rc;
+ * Verify that each kernel class that is defined in the
+ * policy is correct
+ */
+static int validate_classes(struct policydb *p)
+{
+    int i, j;
+    struct class_datum *cladatum;
+    struct perm_datum *perdatum;
+    u32 nprim, tmp, common_pts_len, perm_val, pol_val;
+    u16 class_val;
+    const struct selinux_class_perm *kdefs = &selinux_class_perm;
+    const char *def_class, *def_perm, *pol_class;
+    struct symtab *perms;
+
+    for ( i = 1; i < kdefs->cts_len; i++ )
+    {
+        def_class = kdefs->class_to_string[i];
+        if ( !def_class )
+            continue;
+        if ( i > p->p_classes.nprim )
+        {
+            printk(KERN_INFO
+                   "Flask:  class %s not defined in policy\n",
+                   def_class);
+            return -EINVAL;
+        }
+        pol_class = p->p_class_val_to_name[i-1];
+        if ( strcmp(pol_class, def_class) )
+        {
+            printk(KERN_ERR
+                   "Flask:  class %d is incorrect, found %s but should be 
%s\n",
+                   i, pol_class, def_class);
+            return -EINVAL;
+        }
+    }
+    for ( i = 0; i < kdefs->av_pts_len; i++ )
+    {
+        class_val = kdefs->av_perm_to_string[i].tclass;
+        perm_val = kdefs->av_perm_to_string[i].value;
+        def_perm = kdefs->av_perm_to_string[i].name;
+        if ( class_val > p->p_classes.nprim )
+            continue;
+        pol_class = p->p_class_val_to_name[class_val-1];
+        cladatum = hashtab_search(p->p_classes.table, pol_class);
+        BUG_ON( !cladatum );
+        perms = &cladatum->permissions;
+        nprim = 1 << (perms->nprim - 1);
+        if ( perm_val > nprim )
+        {
+            printk(KERN_INFO
+                   "Flask:  permission %s in class %s not defined in policy\n",
+                   def_perm, pol_class);
+            return -EINVAL;
+        }
+        perdatum = hashtab_search(perms->table, def_perm);
+        if ( perdatum == NULL )
+        {
+            printk(KERN_ERR
+                   "Flask:  permission %s in class %s not found in policy\n",
+                   def_perm, pol_class);
+            return -EINVAL;
+        }
+        pol_val = 1 << (perdatum->value - 1);
+        if ( pol_val != perm_val )
+        {
+            printk(KERN_ERR
+                   "Flask:  permission %s in class %s has incorrect value\n",
+                   def_perm, pol_class);
+            return -EINVAL;
+        }
+    }
+    for ( i = 0; i < kdefs->av_inherit_len; i++ )
+    {
+        class_val = kdefs->av_inherit[i].tclass;
+        if ( class_val > p->p_classes.nprim )
+            continue;
+        pol_class = p->p_class_val_to_name[class_val-1];
+        cladatum = hashtab_search(p->p_classes.table, pol_class);
+        BUG_ON( !cladatum );
+        if ( !cladatum->comdatum )
+        {
+            printk(KERN_ERR
+            "Flask:  class %s should have an inherits clause but does not\n",
+                   pol_class);
+            return -EINVAL;
+        }
+        tmp = kdefs->av_inherit[i].common_base;
+        common_pts_len = 0;
+        while ( !(tmp & 0x01) )
+        {
+            common_pts_len++;
+            tmp >>= 1;
+        }
+        perms = &cladatum->comdatum->permissions;
+        for ( j = 0; j < common_pts_len; j++ )
+        {
+            def_perm = kdefs->av_inherit[i].common_pts[j];
+            if ( j >= perms->nprim )
+            {
+                printk(KERN_INFO
+                "Flask:  permission %s in class %s not defined in policy\n",
+                       def_perm, pol_class);
+                return -EINVAL;
+            }
+            perdatum = hashtab_search(perms->table, def_perm);
+            if ( perdatum == NULL )
+            {
+                printk(KERN_ERR
+                       "Flask:  permission %s in class %s not found in 
policy\n",
+                       def_perm, pol_class);
+                return -EINVAL;
+            }
+            if ( perdatum->value != j + 1 )
+            {
+                printk(KERN_ERR
+                      "Flask:  permission %s in class %s has incorrect 
value\n",
+                       def_perm, pol_class);
+                return -EINVAL;
+            }
+        }
+    }
+    return 0;
 }
 
 /* Clone the SID into the new SID table. */
@@ -1105,7 +1306,7 @@ static inline int convert_context_handle
         u32 len;
 
         context_struct_to_string(context, &s, &len);
-        printk(KERN_ERR "security:  context %s is invalid\n", s);
+        printk(KERN_ERR "Flask:  context %s is invalid\n", s);
         xfree(s);
     }
     return rc;
@@ -1184,12 +1385,12 @@ bad:
 bad:
     context_struct_to_string(&oldc, &s, &len);
     context_destroy(&oldc);
-    printk(KERN_ERR "security:  invalidating context %s\n", s);
+    printk(KERN_ERR "Flask:  invalidating context %s\n", s);
     xfree(s);
     goto out;
 }
 
-extern void flask_complete_init(void);
+static int security_preserve_bools(struct policydb *p);
 
 /**
  * security_load_policy - Load a security policy configuration.
@@ -1225,6 +1426,14 @@ int security_load_policy(void *data, siz
             policydb_destroy(&policydb);
             return -EINVAL;
         }
+        if ( validate_classes(&policydb) )
+        {
+            printk(KERN_ERR
+                   "Flask:  the definition of a class is incorrect\n");
+            sidtab_destroy(&sidtab);
+            policydb_destroy(&policydb);
+            return -EINVAL;
+        }
         policydb_loaded_version = policydb.policyvers;
         ss_initialized = 1;
         seqno = ++latest_granting;
@@ -1245,12 +1454,19 @@ int security_load_policy(void *data, siz
 
     sidtab_init(&newsidtab);
 
-    /* Verify that the existing classes did not change. */
-    if ( hashtab_map(policydb.p_classes.table, validate_class, &newpolicydb) )
-    {
-        printk(KERN_ERR "security:  the definition of an existing "
-                                                            "class changed\n");
+    /* Verify that the kernel defined classes are correct. */
+    if ( validate_classes(&newpolicydb) )
+    {
+        printk(KERN_ERR
+               "Flask:  the definition of a class is incorrect\n");
         rc = -EINVAL;
+        goto err;
+    }
+
+    rc = security_preserve_bools(&newpolicydb);
+    if ( rc )
+    {
+        printk(KERN_ERR "Flask:  unable to preserve booleans\n");
         goto err;
     }
 
@@ -1517,15 +1733,11 @@ int security_get_user_sids(u32 fromsid, 
     }
     memset(mysids, 0, maxnel*sizeof(*mysids));
 
-    ebitmap_for_each_bit(&user->roles, rnode, i)
-    {
-        if ( !ebitmap_node_get_bit(rnode, i) )
-            continue;
+    ebitmap_for_each_positive_bit(&user->roles, rnode, i)
+    {
         role = policydb.role_val_to_struct[i];
         usercon.role = i+1;
-        ebitmap_for_each_bit(&role->types, tnode, j) {
-            if ( !ebitmap_node_get_bit(tnode, j) )
-                continue;
+        ebitmap_for_each_positive_bit(&role->types, tnode, j) {
             usercon.type = j+1;
 
             if ( mls_setup_user_range(fromcon, user, &usercon) )
@@ -1640,7 +1852,7 @@ int security_set_bools(int len, int *val
         goto out;
     }
 
-    printk(KERN_INFO "security: committed booleans { ");
+    printk(KERN_INFO "Flask: committed booleans { ");
     for ( i = 0; i < len; i++ )
     {
         if ( values[i] )
@@ -1695,3 +1907,37 @@ out:
     POLICY_RDUNLOCK;
     return rc;
 }
+
+static int security_preserve_bools(struct policydb *p)
+{
+    int rc, nbools = 0, *bvalues = NULL, i;
+    char **bnames = NULL;
+    struct cond_bool_datum *booldatum;
+    struct cond_node *cur;
+
+    rc = security_get_bools(&nbools, &bnames, &bvalues);
+    if ( rc )
+        goto out;
+    for ( i = 0; i < nbools; i++ )
+    {
+        booldatum = hashtab_search(p->p_bools.table, bnames[i]);
+        if ( booldatum )
+            booldatum->state = bvalues[i];
+    }
+    for ( cur = p->cond_list; cur; cur = cur->next )
+    {
+        rc = evaluate_cond_node(p, cur);
+        if ( rc )
+            goto out;
+    }
+
+out:
+    if ( bnames )
+    {
+        for ( i = 0; i < nbools; i++ )
+            xfree(bnames[i]);
+    }
+    xfree(bnames);
+    xfree(bvalues);
+    return rc;
+}
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/sidtab.c
--- a/xen/xsm/flask/ss/sidtab.c Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/sidtab.c Wed Aug 19 14:22:52 2009 +0100
@@ -24,7 +24,7 @@ int sidtab_init(struct sidtab *s)
 {
     int i;
 
-    s->htable = (void *)xmalloc_array(struct sidtab_node, SIDTAB_SIZE);
+    s->htable = xmalloc_array(struct sidtab_node *, SIDTAB_SIZE);
     if ( !s->htable )
         return -ENOMEM;
     for ( i = 0; i < SIDTAB_SIZE; i++ )
diff -r b79da5f5ffe7 -r 001a99da1294 xen/xsm/flask/ss/symtab.c
--- a/xen/xsm/flask/ss/symtab.c Wed Aug 19 14:22:15 2009 +0100
+++ b/xen/xsm/flask/ss/symtab.c Wed Aug 19 14:22:52 2009 +0100
@@ -12,9 +12,9 @@
 #include <xen/errno.h>
 #include "symtab.h"
 
-static unsigned int symhash(struct hashtab *h, void *key)
+static unsigned int symhash(struct hashtab *h, const void *key)
 {
-    char *p, *keyp;
+    const char *p, *keyp;
     unsigned int size;
     unsigned int val;
 
@@ -26,9 +26,9 @@ static unsigned int symhash(struct hasht
     return val & (h->size - 1);
 }
 
-static int symcmp(struct hashtab *h, void *key1, void *key2)
+static int symcmp(struct hashtab *h, const void *key1, const void *key2)
 {
-    char *keyp1, *keyp2;
+    const char *keyp1, *keyp2;
 
     keyp1 = key1;
     keyp2 = key2;

_______________________________________________
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] Update Xen Flask module to policy.24., Xen patchbot-unstable <=