mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
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>
This commit is contained in:
1 parent
cc64b587f5
commit
e26bb0662f
4 files changed
+207
-37
No files matched your search
@@ -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;
|
||||
|
||||
+139
-20
@@ -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;
|
||||
|
||||
@@ -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
|
||||
+60
-15
@@ -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;
|
||||
|
||||