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

[Xen-devel] [PATCH 2/8] xsm/flask: allow policy booleans to be addressed by name



Booleans are currently only addressable by using a sequence number that
is not easily accessible to tools. Add new FLASK operations to get/set
booleans by name, and to get the name of a boolean given its ID.

Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>
---
 xen/include/public/xsm/flask_op.h   |    5 +-
 xen/xsm/flask/flask_op.c            |  159 ++++++++++++++++++++++++++++++-----
 xen/xsm/flask/include/conditional.h |    5 +-
 xen/xsm/flask/ss/services.c         |   75 +++++++++++++----
 4 files changed, 207 insertions(+), 37 deletions(-)

diff --git a/xen/include/public/xsm/flask_op.h 
b/xen/include/public/xsm/flask_op.h
index e2dd403..416ac08 100644
--- a/xen/include/public/xsm/flask_op.h
+++ b/xen/include/public/xsm/flask_op.h
@@ -47,8 +47,11 @@
 #define FLASK_MEMBER            20
 #define FLASK_ADD_OCONTEXT      21
 #define FLASK_DEL_OCONTEXT      22
+#define FLASK_GETBOOL_NAMED     23
+#define FLASK_GETBOOL2          24
+#define FLASK_SETBOOL_NAMED     25
 
-#define FLASK_LAST              FLASK_DEL_OCONTEXT
+#define FLASK_LAST              FLASK_SETBOOL_NAMED
 
 typedef struct flask_op {
     uint32_t  cmd;
diff --git a/xen/xsm/flask/flask_op.c b/xen/xsm/flask/flask_op.c
index 265a3cf..64d9ec5 100644
--- a/xen/xsm/flask/flask_op.c
+++ b/xen/xsm/flask/flask_op.c
@@ -47,7 +47,10 @@ integer_param("flask_enabled", flask_enabled);
         1UL<<FLASK_SETAVC_THRESHOLD | \
         1UL<<FLASK_MEMBER | \
         1UL<<FLASK_ADD_OCONTEXT | \
-        1UL<<FLASK_DEL_OCONTEXT \
+        1UL<<FLASK_DEL_OCONTEXT | \
+        1UL<<FLASK_GETBOOL_NAMED | \
+        1UL<<FLASK_GETBOOL2 | \
+        1UL<<FLASK_SETBOOL_NAMED \
     )
 
 #define FLASK_COPY_OUT \
@@ -65,7 +68,9 @@ integer_param("flask_enabled", flask_enabled);
         1UL<<FLASK_GETAVC_THRESHOLD | \
         1UL<<FLASK_AVC_HASHSTATS | \
         1UL<<FLASK_AVC_CACHESTATS | \
-        1UL<<FLASK_MEMBER \
+        1UL<<FLASK_MEMBER | \
+        1UL<<FLASK_GETBOOL_NAMED | \
+        1UL<<FLASK_GETBOOL2 \
     )
 
 static DEFINE_SPINLOCK(sel_sem);
@@ -73,6 +78,7 @@ static DEFINE_SPINLOCK(sel_sem);
 /* global data for booleans */
 static int bool_num = 0;
 static int *bool_pending_values = NULL;
+static int flask_security_make_bools(void);
 
 extern int ss_initialized;
 
@@ -573,7 +579,7 @@ static int flask_security_setavc_threshold(char *buf, 
uint32_t count)
 static int flask_security_set_bool(char *buf, uint32_t count)
 {
     int length = -EFAULT;
-    int i, new_value;
+    unsigned int i, new_value;
 
     spin_lock(&sel_sem);
 
@@ -585,10 +591,14 @@ static int flask_security_set_bool(char *buf, uint32_t 
count)
     if ( sscanf(buf, "%d %d", &i, &new_value) != 2 )
         goto out;
 
+    if (!bool_pending_values)
+        flask_security_make_bools();
+
+    if ( i >= bool_num )
+        goto out;
+
     if ( new_value )
-    {
         new_value = 1;
-    }
 
     bool_pending_values[i] = new_value;
     length = count;
@@ -598,6 +608,57 @@ static int flask_security_set_bool(char *buf, uint32_t 
count)
     return length;
 }
 
+static int flask_security_set_bool_name(char *buf, uint32_t count)
+{
+    int rv, num;
+    int i, new_value, commit;
+    int *values = NULL;
+    char *name;
+    
+    name = xmalloc_bytes(count);
+    if ( name == NULL )
+        return -ENOMEM;
+
+    spin_lock(&sel_sem);
+
+    rv = domain_has_security(current->domain, SECURITY__SETBOOL);
+    if ( rv )
+        goto out;
+    
+    rv = -EINVAL;
+    if ( sscanf(buf, "%s %d %d", name, &new_value, &commit) != 3 )
+        goto out;
+
+    i = security_find_bool(name);
+    if ( i < 0 )
+        goto out;
+
+    if ( new_value )
+        new_value = 1;
+
+    if ( commit ) {
+        rv = security_get_bools(&num, NULL, &values);
+        if ( rv != 0 )
+            goto out;
+        values[i] = new_value;
+        if (bool_pending_values)
+            bool_pending_values[i] = new_value;
+        rv = security_set_bools(num, values);
+        xfree(values);
+    } else {
+        if (!bool_pending_values)
+            flask_security_make_bools();
+
+        bool_pending_values[i] = new_value;
+        rv = count;
+    }
+
+ out:
+    xfree(name);
+    spin_unlock(&sel_sem);
+    return rv;
+}
+
 static int flask_security_commit_bools(char *buf, uint32_t count)
 {
     int length = -EFAULT;
@@ -613,7 +674,7 @@ static int flask_security_commit_bools(char *buf, uint32_t 
count)
     if ( sscanf(buf, "%d", &new_value) != 1 )
         goto out;
 
-    if ( new_value )
+    if ( new_value && bool_pending_values )
         security_set_bools(bool_num, bool_pending_values);
     
     length = count;
@@ -623,10 +684,11 @@ static int flask_security_commit_bools(char *buf, 
uint32_t count)
     return length;
 }
 
-static int flask_security_get_bool(char *buf, uint32_t count)
+static int flask_security_get_bool(char *buf, uint32_t count, int named)
 {
     int length;
-    int i, cur_enforcing;
+    int i, cur_enforcing, pend_enforcing;
+    char* name = NULL;
     
     spin_lock(&sel_sem);
     
@@ -641,25 +703,70 @@ static int flask_security_get_bool(char *buf, uint32_t 
count)
         goto out;
     }
 
+    if ( bool_pending_values )
+        pend_enforcing = bool_pending_values[i];
+    else
+        pend_enforcing = cur_enforcing;
+
+    if ( named )
+        name = security_get_bool_name(i);
+    if ( named && !name )
+        goto out;
+
     memset(buf, 0, count);
-    length = snprintf(buf, count, "%d %d", cur_enforcing,
-                      bool_pending_values[i]);
+    if ( named )
+        length = snprintf(buf, count, "%d %d %s", cur_enforcing,
+                          pend_enforcing, name);
+    else
+        length = snprintf(buf, count, "%d %d", cur_enforcing,
+                          pend_enforcing);
 
  out:
+    xfree(name);
     spin_unlock(&sel_sem);
     return length;
 }
 
+static int flask_security_get_bool_name(char *buf, uint32_t count)
+{
+    int rv = -ENOENT;
+    int i, cur_enforcing, pend_enforcing;
+    
+    spin_lock(&sel_sem);
+    
+    i = security_find_bool(buf);
+    if ( i < 0 )
+        goto out;
+
+    cur_enforcing = security_get_bool_value(i);
+    if ( cur_enforcing < 0 )
+    {
+        rv = cur_enforcing;
+        goto out;
+    }
+
+    if ( bool_pending_values )
+        pend_enforcing = bool_pending_values[i];
+    else
+        pend_enforcing = cur_enforcing;
+
+    memset(buf, 0, count);
+    rv = snprintf(buf, count, "%d %d", cur_enforcing, pend_enforcing);
+
+ out:
+    spin_unlock(&sel_sem);
+    return rv;
+}
+
 static int flask_security_make_bools(void)
 {
-    int i, ret = 0;
-    char **names = NULL;
+    int ret = 0;
     int num;
     int *values = NULL;
     
     xfree(bool_pending_values);
     
-    ret = security_get_bools(&num, &names, &values);
+    ret = security_get_bools(&num, NULL, &values);
     if ( ret != 0 )
         goto out;
 
@@ -667,12 +774,6 @@ static int flask_security_make_bools(void)
     bool_pending_values = values;
 
  out:
-    if ( names )
-    {
-        for ( i = 0; i < num; i++ )
-            xfree(names[i]);
-        xfree(names);
-    }    
     return ret;
 }
 
@@ -938,7 +1039,7 @@ long do_flask_op(XEN_GUEST_HANDLE(xsm_op_t) u_flask_op)
 
     case FLASK_GETBOOL:
     {
-        length = flask_security_get_bool(arg, op->size);
+        length = flask_security_get_bool(arg, op->size, 0);
     }
     break;
 
@@ -1010,6 +1111,24 @@ long do_flask_op(XEN_GUEST_HANDLE(xsm_op_t) u_flask_op)
         break;
     }
 
+    case FLASK_GETBOOL_NAMED:
+    {
+        length = flask_security_get_bool_name(arg, op->size);
+    }
+    break;
+
+    case FLASK_GETBOOL2:
+    {
+        length = flask_security_get_bool(arg, op->size, 1);
+    }
+    break;
+
+    case FLASK_SETBOOL_NAMED:
+    {
+        length = flask_security_set_bool_name(arg, op->size);
+    }
+    break;
+
     default:
         length = -ENOSYS;
         break;
diff --git a/xen/xsm/flask/include/conditional.h 
b/xen/xsm/flask/include/conditional.h
index bd3eb92..2fa0a30 100644
--- a/xen/xsm/flask/include/conditional.h
+++ b/xen/xsm/flask/include/conditional.h
@@ -17,6 +17,9 @@ int security_get_bools(int *len, char ***names, int **values);
 
 int security_set_bools(int len, int *values);
 
-int security_get_bool_value(int bool);
+int security_find_bool(const char *name);
+
+char *security_get_bool_name(unsigned int bool);
+int security_get_bool_value(unsigned int bool);
 
 #endif
diff --git a/xen/xsm/flask/ss/services.c b/xen/xsm/flask/ss/services.c
index 3b0acf5..0189baf 100644
--- a/xen/xsm/flask/ss/services.c
+++ b/xen/xsm/flask/ss/services.c
@@ -1883,12 +1883,30 @@ out:
     return rc;
 }
 
+int security_find_bool(const char *name)
+{
+    int i, rv = -ENOENT;
+    POLICY_RDLOCK;
+    for ( i = 0; i < policydb.p_bools.nprim; i++ )
+    {
+        if (!strcmp(name, policydb.p_bool_val_to_name[i]))
+        {
+            rv = i;
+            break;
+        }
+    }
+
+    POLICY_RDUNLOCK;
+    return rv;
+}
+
 int security_get_bools(int *len, char ***names, int **values)
 {
     int i, rc = -ENOMEM;
 
     POLICY_RDLOCK;
-    *names = NULL;
+    if ( names )
+        *names = NULL;
     *values = NULL;
 
     *len = policydb.p_bools.nprim;
@@ -1898,10 +1916,12 @@ int security_get_bools(int *len, char ***names, int 
**values)
         goto out;
     }
 
-    *names = (char**)xmalloc_array(char*, *len);
-    if ( !*names )
-        goto err;
-    memset(*names, 0, sizeof(char*) * *len);
+    if ( names ) {
+        *names = (char**)xmalloc_array(char*, *len);
+        if ( !*names )
+            goto err;
+        memset(*names, 0, sizeof(char*) * *len);
+    }
 
     *values = (int*)xmalloc_array(int, *len);
     if ( !*values )
@@ -1911,19 +1931,21 @@ int security_get_bools(int *len, char ***names, int 
**values)
     {
         size_t name_len;
         (*values)[i] = policydb.bool_val_to_struct[i]->state;
-        name_len = strlen(policydb.p_bool_val_to_name[i]) + 1;
-        (*names)[i] = (char*)xmalloc_array(char, name_len);
-        if ( !(*names)[i] )
-            goto err;
-        strlcpy((*names)[i], policydb.p_bool_val_to_name[i], name_len);
-        (*names)[i][name_len - 1] = 0;
+        if ( names ) {
+            name_len = strlen(policydb.p_bool_val_to_name[i]) + 1;
+            (*names)[i] = (char*)xmalloc_array(char, name_len);
+            if ( !(*names)[i] )
+                goto err;
+            strlcpy((*names)[i], policydb.p_bool_val_to_name[i], name_len);
+            (*names)[i][name_len - 1] = 0;
+        }
     }
     rc = 0;
 out:
     POLICY_RDUNLOCK;
     return rc;
 err:
-    if ( *names )
+    if ( names && *names )
     {
         for ( i = 0; i < *len; i++ )
             xfree((*names)[i]);
@@ -1984,17 +2006,17 @@ out:
     return rc;
 }
 
-int security_get_bool_value(int bool)
+int security_get_bool_value(unsigned int bool)
 {
     int rc = 0;
-    int len;
+    unsigned int len;
 
     POLICY_RDLOCK;
 
     len = policydb.p_bools.nprim;
     if ( bool >= len )
     {
-        rc = -EFAULT;
+        rc = -ENOENT;
         goto out;
     }
 
@@ -2004,6 +2026,29 @@ out:
     return rc;
 }
 
+char *security_get_bool_name(unsigned int bool)
+{
+    unsigned int len;
+    char *rv = NULL;
+
+    POLICY_RDLOCK;
+
+    len = policydb.p_bools.nprim;
+    if ( bool >= len )
+    {
+        goto out;
+    }
+
+    len = strlen(policydb.p_bool_val_to_name[bool]) + 1;
+    rv = xmalloc_array(char, len);
+    if ( !rv )
+        goto out;
+    memcpy(rv, policydb.p_bool_val_to_name[bool], len);
+out:
+    POLICY_RDUNLOCK;
+    return rv;
+}
+
 static int security_preserve_bools(struct policydb *p)
 {
     int rc, nbools = 0, *bvalues = NULL, i;
-- 
1.7.7.6


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


 


Rackspace

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