aboutsummaryrefslogtreecommitdiffstats
path: root/xen/xsm
diff options
context:
space:
mode:
authorDaniel De Graaf <dgdegra@tycho.nsa.gov>2012-02-02 15:23:43 +0000
committerDaniel De Graaf <dgdegra@tycho.nsa.gov>2012-02-02 15:23:43 +0000
commite26bb0662fc0ed8d78742352e090ac82eb7bb95b (patch)
tree3b2c1fa3bac6f73e83ee4b81084eace27bb609ca /xen/xsm
parentcc64b587f5f0545cf9f85c5b748b8bb71bf9fa26 (diff)
downloadxen-e26bb0662fc0ed8d78742352e090ac82eb7bb95b.tar.gz
xen-e26bb0662fc0ed8d78742352e090ac82eb7bb95b.tar.bz2
xen-e26bb0662fc0ed8d78742352e090ac82eb7bb95b.zip
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@tycho.nsa.gov> Committed-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/xsm')
-rw-r--r--xen/xsm/flask/flask_op.c159
-rw-r--r--xen/xsm/flask/include/conditional.h5
-rw-r--r--xen/xsm/flask/ss/services.c75
3 files changed, 203 insertions, 36 deletions
diff --git a/xen/xsm/flask/flask_op.c b/xen/xsm/flask/flask_op.c
index 265a3cf3ac..64d9ec5fd6 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 bd3eb927a7..2fa0a30fe6 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 3b0acf5b02..0189baf760 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;