aboutsummaryrefslogtreecommitdiffstats
path: root/xen/xsm
diff options
context:
space:
mode:
authorDaniel De Graaf <dgdegra@tycho.nsa.gov>2012-02-06 05:07:20 -0800
committerDaniel De Graaf <dgdegra@tycho.nsa.gov>2012-02-06 05:07:20 -0800
commit9ea4c2df1542d65001187361bbc968d4f91eda5c (patch)
treefd1094137dd3a0a6653cff2b185fa481906ba08b /xen/xsm
parente012ef393b73d499497d146696cfec5dda28cf89 (diff)
downloadxen-9ea4c2df1542d65001187361bbc968d4f91eda5c.tar.gz
xen-9ea4c2df1542d65001187361bbc968d4f91eda5c.tar.bz2
xen-9ea4c2df1542d65001187361bbc968d4f91eda5c.zip
flask: Update flask_op hypercall structure
Instead of placing string parsing inside the hypervisor, use binary structures like other Xen hypercalls do. 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/avc.c13
-rw-r--r--xen/xsm/flask/flask_op.c1128
-rw-r--r--xen/xsm/flask/include/avc.h3
-rw-r--r--xen/xsm/flask/include/security.h4
-rw-r--r--xen/xsm/flask/ss/services.c11
5 files changed, 330 insertions, 829 deletions
diff --git a/xen/xsm/flask/avc.c b/xen/xsm/flask/avc.c
index 3a60a3a0f3..74f160d89a 100644
--- a/xen/xsm/flask/avc.c
+++ b/xen/xsm/flask/avc.c
@@ -28,6 +28,7 @@
#include <xen/rcupdate.h>
#include <asm/atomic.h>
#include <asm/current.h>
+#include <public/xsm/flask_op.h>
#include "avc.h"
#include "avc_ss.h"
@@ -251,7 +252,7 @@ void __init avc_init(void)
printk("AVC INITIALIZED\n");
}
-int avc_get_hash_stats(char *buf, uint32_t size)
+int avc_get_hash_stats(struct xen_flask_hash_stats *arg)
{
int i, chain_len, max_chain_len, slots_used;
struct avc_node *node;
@@ -279,10 +280,12 @@ int avc_get_hash_stats(char *buf, uint32_t size)
rcu_read_unlock(&avc_rcu_lock);
- return snprintf(buf, size, "entries: %d\nbuckets used: %d/%d\n"
- "longest chain: %d\n",
- atomic_read(&avc_cache.active_nodes),
- slots_used, AVC_CACHE_SLOTS, max_chain_len);
+ arg->entries = atomic_read(&avc_cache.active_nodes);
+ arg->buckets_used = slots_used;
+ arg->buckets_total = AVC_CACHE_SLOTS;
+ arg->max_chain_len = max_chain_len;
+
+ return 0;
}
static void avc_node_free(struct rcu_head *rhead)
diff --git a/xen/xsm/flask/flask_op.c b/xen/xsm/flask/flask_op.c
index 64d9ec5fd6..00a0af2ab6 100644
--- a/xen/xsm/flask/flask_op.c
+++ b/xen/xsm/flask/flask_op.c
@@ -30,48 +30,21 @@ integer_param("flask_enabled", flask_enabled);
#endif
#define MAX_POLICY_SIZE 0x4000000
-#define FLASK_COPY_IN \
- ( \
- 1UL<<FLASK_LOAD | \
- 1UL<<FLASK_SETENFORCE | \
- 1UL<<FLASK_CONTEXT_TO_SID | \
- 1UL<<FLASK_SID_TO_CONTEXT | \
- 1UL<<FLASK_ACCESS | \
- 1UL<<FLASK_CREATE | \
- 1UL<<FLASK_RELABEL | \
- 1UL<<FLASK_USER | \
- 1UL<<FLASK_GETBOOL | \
- 1UL<<FLASK_SETBOOL | \
- 1UL<<FLASK_COMMITBOOLS | \
- 1UL<<FLASK_DISABLE | \
- 1UL<<FLASK_SETAVC_THRESHOLD | \
- 1UL<<FLASK_MEMBER | \
- 1UL<<FLASK_ADD_OCONTEXT | \
- 1UL<<FLASK_DEL_OCONTEXT | \
- 1UL<<FLASK_GETBOOL_NAMED | \
- 1UL<<FLASK_GETBOOL2 | \
- 1UL<<FLASK_SETBOOL_NAMED \
- )
#define FLASK_COPY_OUT \
( \
- 1UL<<FLASK_GETENFORCE | \
1UL<<FLASK_CONTEXT_TO_SID | \
1UL<<FLASK_SID_TO_CONTEXT | \
1UL<<FLASK_ACCESS | \
1UL<<FLASK_CREATE | \
1UL<<FLASK_RELABEL | \
1UL<<FLASK_USER | \
- 1UL<<FLASK_POLICYVERS | \
1UL<<FLASK_GETBOOL | \
- 1UL<<FLASK_MLS | \
- 1UL<<FLASK_GETAVC_THRESHOLD | \
+ 1UL<<FLASK_SETBOOL | \
1UL<<FLASK_AVC_HASHSTATS | \
1UL<<FLASK_AVC_CACHESTATS | \
1UL<<FLASK_MEMBER | \
- 1UL<<FLASK_GETBOOL_NAMED | \
- 1UL<<FLASK_GETBOOL2 \
- )
+ 0)
static DEFINE_SPINLOCK(sel_sem);
@@ -96,412 +69,186 @@ static int domain_has_security(struct domain *d, u32 perms)
perms, NULL);
}
-static int flask_security_user(char *buf, uint32_t size)
-{
- char *page = NULL;
- char *con, *user, *ptr;
- u32 sid, *sids;
- int length;
- char *newcon;
- int i, rc;
- u32 len, nsids;
-
- length = domain_has_security(current->domain, SECURITY__COMPUTE_USER);
- if ( length )
- return length;
-
- length = -ENOMEM;
- con = xmalloc_array(char, size+1);
- if ( !con )
- return length;
- memset(con, 0, size+1);
-
- user = xmalloc_array(char, size+1);
- if ( !user )
- goto out;
- memset(user, 0, size+1);
-
- length = -ENOMEM;
- page = xmalloc_bytes(PAGE_SIZE);
- if ( !page )
- goto out2;
- memset(page, 0, PAGE_SIZE);
-
- length = -EINVAL;
- if ( sscanf(buf, "%s %s", con, user) != 2 )
- goto out2;
-
- length = security_context_to_sid(con, strlen(con)+1, &sid);
- if ( length < 0 )
- goto out2;
-
- length = security_get_user_sids(sid, user, &sids, &nsids);
- if ( length < 0 )
- goto out2;
-
- length = snprintf(page, PAGE_SIZE, "%u", nsids) + 1;
- ptr = page + length;
- for ( i = 0; i < nsids; i++ )
- {
- rc = security_sid_to_context(sids[i], &newcon, &len);
- if ( rc )
- {
- length = rc;
- goto out3;
- }
- if ( (length + len) >= PAGE_SIZE )
- {
- xfree(newcon);
- length = -ERANGE;
- goto out3;
- }
- memcpy(ptr, newcon, len);
- xfree(newcon);
- ptr += len;
- length += len;
- }
-
- if ( length > size )
- {
- printk( "%s: context size (%u) exceeds payload "
- "max\n", __FUNCTION__, length);
- length = -ERANGE;
- goto out3;
- }
-
- memset(buf, 0, size);
- memcpy(buf, page, length);
-
- out3:
- xfree(sids);
- out2:
- if ( page )
- xfree(page);
- xfree(user);
- out:
- xfree(con);
- return length;
-}
-
-static int flask_security_relabel(char *buf, uint32_t size)
+static int flask_copyin_string(XEN_GUEST_HANDLE(char) u_buf, char **buf, uint32_t size)
{
- char *scon, *tcon;
- u32 ssid, tsid, newsid;
- u16 tclass;
- int length;
- char *newcon;
- u32 len;
+ char *tmp = xmalloc_bytes(size + 1);
+ if ( !tmp )
+ return -ENOMEM;
- length = domain_has_security(current->domain, SECURITY__COMPUTE_RELABEL);
- if ( length )
- return length;
-
- length = -ENOMEM;
- scon = xmalloc_array(char, size+1);
- if ( !scon )
- return length;
- memset(scon, 0, size+1);
-
- tcon = xmalloc_array(char, size+1);
- if ( !tcon )
- goto out;
- memset(tcon, 0, size+1);
-
- length = -EINVAL;
- if ( sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3 )
- goto out2;
-
- length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
- if ( length < 0 )
- goto out2;
- length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
- if ( length < 0 )
- goto out2;
-
- length = security_change_sid(ssid, tsid, tclass, &newsid);
- if ( length < 0 )
- goto out2;
-
- length = security_sid_to_context(newsid, &newcon, &len);
- if ( length < 0 )
- goto out2;
-
- if ( len > size )
+ if ( copy_from_guest(tmp, u_buf, size) )
{
- printk( "%s: context size (%u) exceeds payload "
- "max\n", __FUNCTION__, len);
- length = -ERANGE;
- goto out3;
+ xfree(tmp);
+ return -EFAULT;
}
+ tmp[size] = 0;
- memset(buf, 0, size);
- memcpy(buf, newcon, len);
- length = len;
-
- out3:
- xfree(newcon);
- out2:
- xfree(tcon);
- out:
- xfree(scon);
- return length;
+ *buf = tmp;
+ return 0;
}
-static int flask_security_create(char *buf, uint32_t size)
+static int flask_security_user(struct xen_flask_userlist *arg)
{
- char *scon, *tcon;
- u32 ssid, tsid, newsid;
- u16 tclass;
- int length;
- char *newcon;
- u32 len;
+ char *user;
+ u32 *sids;
+ u32 nsids;
+ int rv;
- length = domain_has_security(current->domain, SECURITY__COMPUTE_CREATE);
- if ( length )
- return length;
+ rv = domain_has_security(current->domain, SECURITY__COMPUTE_USER);
+ if ( rv )
+ return rv;
- length = -ENOMEM;
- scon = xmalloc_array(char, size+1);
- if ( !scon )
- return length;
- memset(scon, 0, size+1);
+ rv = flask_copyin_string(arg->u.user, &user, arg->size);
+ if ( rv )
+ return rv;
- tcon = xmalloc_array(char, size+1);
- if ( !tcon )
+ rv = security_get_user_sids(arg->start_sid, user, &sids, &nsids);
+ if ( rv < 0 )
goto out;
- memset(tcon, 0, size+1);
-
- length = -EINVAL;
- if ( sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3 )
- goto out2;
-
- length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
- if ( length < 0 )
- goto out2;
- length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
- if ( length < 0 )
- goto out2;
+ if ( nsids * sizeof(sids[0]) > arg->size )
+ nsids = arg->size / sizeof(sids[0]);
- length = security_transition_sid(ssid, tsid, tclass, &newsid);
- if ( length < 0 )
- goto out2;
+ arg->size = nsids;
- length = security_sid_to_context(newsid, &newcon, &len);
- if ( length < 0 )
- goto out2;
-
- if ( len > size )
- {
- printk( "%s: context size (%u) exceeds payload "
- "max\n", __FUNCTION__, len);
- length = -ERANGE;
- goto out3;
- }
+ if ( copy_to_guest(arg->u.sids, sids, nsids) )
+ rv = -EFAULT;
- memset(buf, 0, size);
- memcpy(buf, newcon, len);
- length = len;
-
- out3:
- xfree(newcon);
- out2:
- xfree(tcon);
+ xfree(sids);
out:
- xfree(scon);
- return length;
+ xfree(user);
+ return rv;
}
-static int flask_security_access(char *buf, uint32_t size)
+static int flask_security_relabel(struct xen_flask_transition *arg)
{
- char *scon, *tcon;
- u32 ssid, tsid;
- u16 tclass;
- u32 req;
- struct av_decision avd;
- int length;
+ int rv;
- length = domain_has_security(current->domain, SECURITY__COMPUTE_AV);
- if ( length )
- return length;
-
- length = -ENOMEM;
- scon = xmalloc_array(char, size+1);
- if (!scon)
- return length;
- memset(scon, 0, size+1);
-
- tcon = xmalloc_array(char, size+1);
- if ( !tcon )
- goto out;
- memset( tcon, 0, size+1 );
-
- length = -EINVAL;
- if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4)
- goto out2;
-
- length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
- if ( length < 0 )
- goto out2;
-
- length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
- if ( length < 0 )
- goto out2;
+ rv = domain_has_security(current->domain, SECURITY__COMPUTE_RELABEL);
+ if ( rv )
+ return rv;
- length = security_compute_av(ssid, tsid, tclass, req, &avd);
- if ( length < 0 )
- goto out2;
+ rv = security_change_sid(arg->ssid, arg->tsid, arg->tclass, &arg->newsid);
- memset(buf, 0, size);
- length = snprintf(buf, size, "%x %x %x %x %u",
- avd.allowed, 0xffffffff,
- avd.auditallow, avd.auditdeny,
- avd.seqno);
-
- out2:
- xfree(tcon);
- out:
- xfree(scon);
- return length;
+ return rv;
}
-static int flask_security_member(char *buf, uint32_t size)
+static int flask_security_create(struct xen_flask_transition *arg)
{
- char *scon, *tcon;
- u32 ssid, tsid, newsid;
- u16 tclass;
- int length;
- char *newcon;
- u32 len;
+ int rv;
- length = domain_has_security(current->domain, SECURITY__COMPUTE_MEMBER);
- if ( length )
- return length;
+ rv = domain_has_security(current->domain, SECURITY__COMPUTE_CREATE);
+ if ( rv )
+ return rv;
- length = -ENOMEM;
- scon = xmalloc_array(char, size+1);
- if ( !scon )
- return length;
- memset(scon, 0, size+1);
+ rv = security_transition_sid(arg->ssid, arg->tsid, arg->tclass, &arg->newsid);
- tcon = xmalloc_array(char, size+1);
- if ( !tcon )
- goto out;
- memset(tcon, 0, size+1);
+ return rv;
+}
- length = -EINVAL;
- if ( sscanf(buf, "%s, %s, %hu", scon, tcon, &tclass) != 3 )
- goto out2;
+static int flask_security_access(struct xen_flask_access *arg)
+{
+ struct av_decision avd;
+ int rv;
- length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
- if ( length < 0 )
- goto out2;
+ rv = domain_has_security(current->domain, SECURITY__COMPUTE_AV);
+ if ( rv )
+ return rv;
- length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
- if ( length < 0 )
- goto out2;
+ rv = security_compute_av(arg->ssid, arg->tsid, arg->tclass, arg->req, &avd);
+ if ( rv < 0 )
+ return rv;
- length = security_member_sid(ssid, tsid, tclass, &newsid);
- if ( length < 0 )
- goto out2;
+ arg->allowed = avd.allowed;
+ arg->audit_allow = avd.auditallow;
+ arg->audit_deny = avd.auditdeny;
+ arg->seqno = avd.seqno;
+
+ return rv;
+}
- length = security_sid_to_context(newsid, &newcon, &len);
- if ( length < 0 )
- goto out2;
+static int flask_security_member(struct xen_flask_transition *arg)
+{
+ int rv;
- if ( len > size )
- {
- printk("%s: context size (%u) exceeds payload "
- "max\n", __FUNCTION__, len);
- length = -ERANGE;
- goto out3;
- }
+ rv = domain_has_security(current->domain, SECURITY__COMPUTE_MEMBER);
+ if ( rv )
+ return rv;
- memset(buf, 0, size);
- memcpy(buf, newcon, len);
- length = len;
+ rv = security_member_sid(arg->ssid, arg->tsid, arg->tclass, &arg->newsid);
- out3:
- xfree(newcon);
- out2:
- xfree(tcon);
- out:
- xfree(scon);
- return length;
+ return rv;
}
-static int flask_security_setenforce(char *buf, uint32_t count)
+static int flask_security_setenforce(struct xen_flask_setenforce *arg)
{
- int length;
- int new_value;
+ int enforce = !!(arg->enforcing);
+ int rv;
- if ( sscanf(buf, "%d", &new_value) != 1 )
- return -EINVAL;
+ if ( enforce == flask_enforcing )
+ return 0;
- if ( new_value != flask_enforcing )
- {
- length = domain_has_security(current->domain, SECURITY__SETENFORCE);
- if ( length )
- goto out;
- flask_enforcing = new_value;
- if ( flask_enforcing )
- avc_ss_reset(0);
- }
- length = count;
+ rv = domain_has_security(current->domain, SECURITY__SETENFORCE);
+ if ( rv )
+ return rv;
- out:
- return length;
+ flask_enforcing = enforce;
+
+ if ( flask_enforcing )
+ avc_ss_reset(0);
+
+ return 0;
}
-static int flask_security_context(char *buf, uint32_t count)
+static int flask_security_context(struct xen_flask_sid_context *arg)
{
- u32 sid;
- int length;
+ int rv;
+ char *buf;
- length = domain_has_security(current->domain, SECURITY__CHECK_CONTEXT);
- if ( length )
- goto out;
+ rv = domain_has_security(current->domain, SECURITY__CHECK_CONTEXT);
+ if ( rv )
+ return rv;
- length = security_context_to_sid(buf, count, &sid);
- if ( length < 0 )
- goto out;
+ rv = flask_copyin_string(arg->context, &buf, arg->size);
+ if ( rv )
+ return rv;
- memset(buf, 0, count);
- length = snprintf(buf, count, "%u", sid);
+ rv = security_context_to_sid(buf, arg->size, &arg->sid);
+ if ( rv < 0 )
+ goto out;
out:
- return length;
+ xfree(buf);
+
+ return rv;
}
-static int flask_security_sid(char *buf, uint32_t count)
+static int flask_security_sid(struct xen_flask_sid_context *arg)
{
+ int rv;
char *context;
- u32 sid;
u32 len;
- int length;
- length = domain_has_security(current->domain, SECURITY__CHECK_CONTEXT);
- if ( length )
- goto out;
+ rv = domain_has_security(current->domain, SECURITY__CHECK_CONTEXT);
+ if ( rv )
+ return rv;
- if ( sscanf(buf, "%u", &sid) != 1 )
- goto out;
+ rv = security_sid_to_context(arg->sid, &context, &len);
+ if ( rv < 0 )
+ return rv;
- length = security_sid_to_context(sid, &context, &len);
- if ( length < 0 )
- goto out;
+ rv = 0;
- if ( len > count )
- return -ERANGE;
+ if ( len > arg->size )
+ rv = -ERANGE;
- memset(buf, 0, count);
- memcpy(buf, context, len);
- length = len;
+ arg->size = len;
+
+ if ( !rv && copy_to_guest(arg->context, context, len) )
+ rv = -EFAULT;
xfree(context);
- out:
- return length;
+ return rv;
}
int flask_disable(void)
@@ -530,229 +277,154 @@ int flask_disable(void)
return 0;
}
-static int flask_security_disable(char *buf, uint32_t count)
-{
- int length;
- int new_value;
-
- length = -EINVAL;
- if ( sscanf(buf, "%d", &new_value) != 1 )
- goto out;
-
- if ( new_value )
- {
- length = flask_disable();
- if ( length < 0 )
- goto out;
- }
-
- length = count;
-
- out:
- return length;
-}
-
-static int flask_security_setavc_threshold(char *buf, uint32_t count)
+static int flask_security_setavc_threshold(struct xen_flask_setavc_threshold *arg)
{
- int ret;
- int new_value;
-
- if ( sscanf(buf, "%u", &new_value) != 1 )
- {
- ret = -EINVAL;
- goto out;
- }
+ int rv = 0;
- if ( new_value != avc_cache_threshold )
+ if ( arg->threshold != avc_cache_threshold )
{
- ret = domain_has_security(current->domain, SECURITY__SETSECPARAM);
- if ( ret )
+ rv = domain_has_security(current->domain, SECURITY__SETSECPARAM);
+ if ( rv )
goto out;
- avc_cache_threshold = new_value;
+ avc_cache_threshold = arg->threshold;
}
- ret = count;
out:
- return ret;
+ return rv;
}
-static int flask_security_set_bool(char *buf, uint32_t count)
+static int flask_security_resolve_bool(struct xen_flask_boolean *arg)
{
- int length = -EFAULT;
- unsigned int i, new_value;
-
- spin_lock(&sel_sem);
-
- length = domain_has_security(current->domain, SECURITY__SETBOOL);
- if ( length )
- goto out;
-
- length = -EINVAL;
- if ( sscanf(buf, "%d %d", &i, &new_value) != 2 )
- goto out;
+ char *name;
+ int rv;
- if (!bool_pending_values)
- flask_security_make_bools();
+ if ( arg->bool_id != -1 )
+ return 0;
- if ( i >= bool_num )
- goto out;
+ rv = flask_copyin_string(arg->name, &name, arg->size);
+ if ( rv )
+ return rv;
- if ( new_value )
- new_value = 1;
+ arg->bool_id = security_find_bool(name);
+ arg->size = 0;
- bool_pending_values[i] = new_value;
- length = count;
+ xfree(name);
- out:
- spin_unlock(&sel_sem);
- return length;
+ return 0;
}
-static int flask_security_set_bool_name(char *buf, uint32_t count)
+static int flask_security_set_bool(struct xen_flask_boolean *arg)
{
- int rv, num;
- int i, new_value, commit;
- int *values = NULL;
- char *name;
-
- name = xmalloc_bytes(count);
- if ( name == NULL )
- return -ENOMEM;
+ int rv;
- spin_lock(&sel_sem);
+ rv = flask_security_resolve_bool(arg);
+ if ( rv )
+ return rv;
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;
+ return rv;
- i = security_find_bool(name);
- if ( i < 0 )
- goto out;
+ spin_lock(&sel_sem);
- if ( new_value )
- new_value = 1;
+ if ( arg->commit )
+ {
+ int num;
+ int *values;
- 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;
+
+ if ( arg->bool_id >= num )
+ {
+ rv = -ENOENT;
+ goto out;
+ }
+ values[arg->bool_id] = !!(arg->new_value);
+
+ arg->enforcing = arg->pending = !!(arg->new_value);
+
+ if ( bool_pending_values )
+ bool_pending_values[arg->bool_id] = !!(arg->new_value);
+
rv = security_set_bools(num, values);
xfree(values);
- } else {
- if (!bool_pending_values)
+ }
+ else
+ {
+ if ( !bool_pending_values )
flask_security_make_bools();
- bool_pending_values[i] = new_value;
- rv = count;
+ if ( arg->bool_id >= bool_num )
+ goto out;
+
+ bool_pending_values[arg->bool_id] = !!(arg->new_value);
+ arg->pending = !!(arg->new_value);
+ arg->enforcing = security_get_bool_value(arg->bool_id);
+
+ rv = 0;
}
out:
- xfree(name);
spin_unlock(&sel_sem);
return rv;
}
-static int flask_security_commit_bools(char *buf, uint32_t count)
+static int flask_security_commit_bools(void)
{
- int length = -EFAULT;
- int new_value;
+ int rv;
spin_lock(&sel_sem);
- length = domain_has_security(current->domain, SECURITY__SETBOOL);
- if ( length )
- goto out;
-
- length = -EINVAL;
- if ( sscanf(buf, "%d", &new_value) != 1 )
+ rv = domain_has_security(current->domain, SECURITY__SETBOOL);
+ if ( rv )
goto out;
- if ( new_value && bool_pending_values )
- security_set_bools(bool_num, bool_pending_values);
+ if ( bool_pending_values )
+ rv = security_set_bools(bool_num, bool_pending_values);
- length = count;
-
out:
spin_unlock(&sel_sem);
- return length;
+ return rv;
}
-static int flask_security_get_bool(char *buf, uint32_t count, int named)
+static int flask_security_get_bool(struct xen_flask_boolean *arg)
{
- int length;
- int i, cur_enforcing, pend_enforcing;
- char* name = NULL;
-
- spin_lock(&sel_sem);
-
- length = -EINVAL;
- if ( sscanf(buf, "%d", &i) != 1 )
- goto out;
+ int rv;
- cur_enforcing = security_get_bool_value(i);
- if ( cur_enforcing < 0 )
- {
- length = cur_enforcing;
- goto out;
- }
+ rv = flask_security_resolve_bool(arg);
+ if ( rv )
+ return rv;
- if ( bool_pending_values )
- pend_enforcing = bool_pending_values[i];
- else
- pend_enforcing = cur_enforcing;
+ spin_lock(&sel_sem);
- if ( named )
- name = security_get_bool_name(i);
- if ( named && !name )
+ rv = security_get_bool_value(arg->bool_id);
+ if ( rv < 0 )
goto out;
- memset(buf, 0, count);
- 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);
+ arg->enforcing = rv;
- out:
- xfree(name);
- spin_unlock(&sel_sem);
- return length;
-}
+ if ( bool_pending_values )
+ arg->pending = bool_pending_values[arg->bool_id];
+ else
+ arg->pending = rv;
-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;
+ rv = 0;
- cur_enforcing = security_get_bool_value(i);
- if ( cur_enforcing < 0 )
+ if ( arg->size )
{
- rv = cur_enforcing;
- goto out;
+ char *nameout = security_get_bool_name(arg->bool_id);
+ size_t nameout_len = strlen(nameout);
+ if ( nameout_len > arg->size )
+ rv = -ERANGE;
+ arg->size = nameout_len;
+
+ if ( !rv && copy_to_guest(arg->name, nameout, nameout_len) )
+ rv = -EFAULT;
+ xfree(nameout);
}
- 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;
@@ -779,380 +451,212 @@ static int flask_security_make_bools(void)
#ifdef FLASK_AVC_STATS
-static int flask_security_avc_cachestats(char *buf, uint32_t count)
+static int flask_security_avc_cachestats(struct xen_flask_cache_stats *arg)
{
- char *page = NULL;
- int len = 0;
- int length = 0;
- int cpu;
struct avc_cache_stats *st;
- page = (char *)xmalloc_bytes(PAGE_SIZE);
- if ( !page )
- return -ENOMEM;
- memset(page, 0, PAGE_SIZE);
+ if ( arg->cpu > nr_cpu_ids )
+ return -ENOENT;
+ if ( !cpu_online(arg->cpu) )
+ return -ENOENT;
- len = snprintf(page, PAGE_SIZE, "lookups hits misses allocations reclaims "
- "frees\n");
- if ( len > count ) {
- length = -EINVAL;
- goto out;
- }
-
- memcpy(buf, page, len);
- buf += len;
- length += len;
- count -= len;
+ st = &per_cpu(avc_cache_stats, arg->cpu);
- for_each_online_cpu ( cpu )
- {
- st = &per_cpu(avc_cache_stats, cpu);
+ arg->lookups = st->lookups;
+ arg->hits = st->hits;
+ arg->misses = st->misses;
+ arg->allocations = st->allocations;
+ arg->reclaims = st->reclaims;
+ arg->frees = st->frees;
- len = snprintf(page, PAGE_SIZE, "%u %u %u %u %u %u\n", st->lookups,
- st->hits, st->misses, st->allocations,
- st->reclaims, st->frees);
- if ( len > count ) {
- length = -EINVAL;
- goto out;
- }
- memcpy(buf, page, len);
- buf += len;
- length += len;
- count -= len;
- }
-
- out:
- xfree(page);
- return length;
+ return 0;
}
#endif
-static int flask_security_load(char *buf, uint32_t count)
+static int flask_security_load(struct xen_flask_load *load)
{
int ret;
- int length;
-
- spin_lock(&sel_sem);
+ void *buf = NULL;
- length = domain_has_security(current->domain, SECURITY__LOAD_POLICY);
- if ( length )
- goto out;
-
- length = security_load_policy(buf, count);
- if ( length )
- goto out;
-
- ret = flask_security_make_bools();
+ ret = domain_has_security(current->domain, SECURITY__LOAD_POLICY);
if ( ret )
- length = ret;
- else
- length = count;
+ return ret;
- out:
- spin_unlock(&sel_sem);
- return length;
-}
-
-static int flask_ocontext_del(char *buf, uint32_t size)
-{
- int len = 0;
- char *ocontext;
- unsigned long low = 0;
- unsigned long high = 0;
-
- len = domain_has_security(current->domain, SECURITY__DEL_OCONTEXT);
- if ( len )
- return len;
+ if ( load->size > MAX_POLICY_SIZE )
+ return -EINVAL;
- if ( (ocontext = xmalloc_bytes(size) ) == NULL )
+ buf = xmalloc_bytes(load->size);
+ if ( !buf )
return -ENOMEM;
- len = sscanf(buf, "%s %lu %lu", ocontext, &low, &high);
- if ( len < 2 )
+ if ( copy_from_guest(buf, load->buffer, load->size) )
{
- len = -EINVAL;
- goto out;
+ ret = -EFAULT;
+ goto out_free;
}
- else if ( len == 2 )
- high = low;
- if ( low > high )
- {
- len = -EINVAL;
+ spin_lock(&sel_sem);
+
+ ret = security_load_policy(buf, load->size);
+ if ( ret )
goto out;
- }
- len = security_ocontext_del(ocontext, low, high);
+ xfree(bool_pending_values);
+ bool_pending_values = NULL;
+ ret = 0;
+
out:
- xfree(ocontext);
- return len;
+ spin_unlock(&sel_sem);
+ out_free:
+ xfree(buf);
+ return ret;
}
-static int flask_ocontext_add(char *buf, uint32_t size)
+static int flask_ocontext_del(struct xen_flask_ocontext *arg)
{
- int len = 0;
- u32 sid = 0;
- unsigned long low = 0;
- unsigned long high = 0;
- char *scontext;
- char *ocontext;
-
- len = domain_has_security(current->domain, SECURITY__ADD_OCONTEXT);
- if ( len )
- return len;
-
- if ( (scontext = xmalloc_bytes(size) ) == NULL )
- return -ENOMEM;
+ int rv;
- if ( (ocontext = xmalloc_bytes(size) ) == NULL )
- {
- xfree(scontext);
- return -ENOMEM;
- }
-
- memset(scontext, 0, size);
- memset(ocontext, 0, size);
+ if ( arg->low > arg->high )
+ return -EINVAL;
- len = sscanf(buf, "%s %s %lu %lu", ocontext, scontext, &low, &high);
- if ( len < 3 )
- {
- len = -EINVAL;
- goto out;
- }
- else if ( len == 3 )
- high = low;
+ rv = domain_has_security(current->domain, SECURITY__DEL_OCONTEXT);
+ if ( rv )
+ return rv;
- if ( low > high )
- {
- len = -EINVAL;
- goto out;
- }
- len = security_context_to_sid(scontext, strlen(scontext)+1, &sid);
- if ( len < 0 )
- {
- len = -EINVAL;
- goto out;
- }
- len = security_ocontext_add(ocontext, low, high, sid);
- out:
- xfree(ocontext);
- xfree(scontext);
- return len;
+ return security_ocontext_del(arg->ocon, arg->low, arg->high);
}
-long do_flask_op(XEN_GUEST_HANDLE(xsm_op_t) u_flask_op)
+static int flask_ocontext_add(struct xen_flask_ocontext *arg)
{
- flask_op_t curop, *op = &curop;
- int rc = 0;
- int length = 0;
- char *arg = NULL;
+ int rv;
- if ( copy_from_guest(op, u_flask_op, 1) )
- return -EFAULT;
-
- if ( op->cmd > FLASK_LAST)
+ if ( arg->low > arg->high )
return -EINVAL;
- if ( op->size > MAX_POLICY_SIZE )
- return -EINVAL;
+ rv = domain_has_security(current->domain, SECURITY__ADD_OCONTEXT);
+ if ( rv )
+ return rv;
- if ( (op->buf == NULL && op->size != 0) ||
- (op->buf != NULL && op->size == 0) )
- return -EINVAL;
+ return security_ocontext_add(arg->ocon, arg->low, arg->high, arg->sid);
+}
- arg = xmalloc_bytes(op->size + 1);
- if ( !arg )
- return -ENOMEM;
+long do_flask_op(XEN_GUEST_HANDLE(xsm_op_t) u_flask_op)
+{
+ xen_flask_op_t op;
+ int rv;
- memset(arg, 0, op->size + 1);
+ if ( copy_from_guest(&op, u_flask_op, 1) )
+ return -EFAULT;
- if ( (FLASK_COPY_IN&(1UL<<op->cmd)) && op->buf != NULL &&
- copy_from_guest(arg, guest_handle_from_ptr(op->buf, char), op->size) )
- {
- rc = -EFAULT;
- goto out;
- }
+ if ( op.interface_version != XEN_FLASK_INTERFACE_VERSION )
+ return -ENOSYS;
- switch ( op->cmd )
+ switch ( op.cmd )
{
-
case FLASK_LOAD:
- {
- length = flask_security_load(arg, op->size);
- }
- break;
-
+ rv = flask_security_load(&op.u.load);
+ break;
+
case FLASK_GETENFORCE:
- {
- length = snprintf(arg, op->size, "%d", flask_enforcing);
- }
- break;
+ rv = flask_enforcing;
+ break;
case FLASK_SETENFORCE:
- {
- length = flask_security_setenforce(arg, op->size);
- }
- break;
+ rv = flask_security_setenforce(&op.u.enforce);
+ break;
case FLASK_CONTEXT_TO_SID:
- {
- length = flask_security_context(arg, op->size);
- }
- break;
+ rv = flask_security_context(&op.u.sid_context);
+ break;
case FLASK_SID_TO_CONTEXT:
- {
- length = flask_security_sid(arg, op->size);
- }
- break;
+ rv = flask_security_sid(&op.u.sid_context);
+ break;
case FLASK_ACCESS:
- {
- length = flask_security_access(arg, op->size);
- }
- break;
+ rv = flask_security_access(&op.u.access);
+ break;
case FLASK_CREATE:
- {
- length = flask_security_create(arg, op->size);
- }
- break;
+ rv = flask_security_create(&op.u.transition);
+ break;
case FLASK_RELABEL:
- {
- length = flask_security_relabel(arg, op->size);
- }
- break;
+ rv = flask_security_relabel(&op.u.transition);
+ break;
case FLASK_USER:
- {
- length = flask_security_user(arg, op->size);
- }
- break;
+ rv = flask_security_user(&op.u.userlist);
+ break;
case FLASK_POLICYVERS:
- {
- length = snprintf(arg, op->size, "%d", POLICYDB_VERSION_MAX);
- }
- break;
+ rv = POLICYDB_VERSION_MAX;
+ break;
case FLASK_GETBOOL:
- {
- length = flask_security_get_bool(arg, op->size, 0);
- }
- break;
+ rv = flask_security_get_bool(&op.u.boolean);
+ break;
case FLASK_SETBOOL:
- {
- length = flask_security_set_bool(arg, op->size);
- }
- break;
+ rv = flask_security_set_bool(&op.u.boolean);
+ break;
case FLASK_COMMITBOOLS:
- {
- length = flask_security_commit_bools(arg, op->size);
- }
- break;
+ rv = flask_security_commit_bools();
+ break;
case FLASK_MLS:
- {
- length = snprintf(arg, op->size, "%d", flask_mls_enabled);
- }
- break;
+ rv = flask_mls_enabled;
+ break;
case FLASK_DISABLE:
- {
- length = flask_security_disable(arg, op->size);
- }
- break;
+ rv = flask_disable();
+ break;
case FLASK_GETAVC_THRESHOLD:
- {
- length = snprintf(arg, op->size, "%d", avc_cache_threshold);
- }
- break;
+ rv = avc_cache_threshold;
+ break;
case FLASK_SETAVC_THRESHOLD:
- {
- length = flask_security_setavc_threshold(arg, op->size);
- }
- break;
+ rv = flask_security_setavc_threshold(&op.u.setavc_threshold);
+ break;
case FLASK_AVC_HASHSTATS:
- {
- length = avc_get_hash_stats(arg, op->size);
- }
- break;
+ rv = avc_get_hash_stats(&op.u.hash_stats);
+ break;
-#ifdef FLASK_AVC_STATS
+#ifdef FLASK_AVC_STATS
case FLASK_AVC_CACHESTATS:
- {
- length = flask_security_avc_cachestats(arg, op->size);
- }
- break;
+ rv = flask_security_avc_cachestats(&op.u.cache_stats);
+ break;
#endif
case FLASK_MEMBER:
- {
- length = flask_security_member(arg, op->size);
- }
- break;
+ rv = flask_security_member(&op.u.transition);
+ break;
case FLASK_ADD_OCONTEXT:
- {
- length = flask_ocontext_add(arg, op->size);
+ rv = flask_ocontext_add(&op.u.ocontext);
break;
- }
case FLASK_DEL_OCONTEXT:
- {
- length = flask_ocontext_del(arg, op->size);
+ rv = flask_ocontext_del(&op.u.ocontext);
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;
-
+ rv = -ENOSYS;
}
- if ( length < 0 )
- {
- rc = length;
+ if ( rv < 0 )
goto out;
- }
-
- if ( (FLASK_COPY_OUT&(1UL<<op->cmd)) && op->buf != NULL &&
- copy_to_guest(guest_handle_from_ptr(op->buf, char), arg, op->size) )
+
+ if ( (FLASK_COPY_OUT&(1UL<<op.cmd)) )
{
- rc = -EFAULT;
- goto out;
+ if ( copy_to_guest(u_flask_op, &op, 1) )
+ rv = -EFAULT;
}
- op->size = length;
- if ( copy_to_guest(u_flask_op, op, 1) )
- rc = -EFAULT;
-
out:
- xfree(arg);
- return rc;
+ return rv;
}
diff --git a/xen/xsm/flask/include/avc.h b/xen/xsm/flask/include/avc.h
index 8fffbb65c0..0f62891154 100644
--- a/xen/xsm/flask/include/avc.h
+++ b/xen/xsm/flask/include/avc.h
@@ -104,7 +104,8 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
u32 ssid, u32 tsid, u16 tclass, u32 perms);
/* Exported to selinuxfs */
-int avc_get_hash_stats(char *buf, uint32_t size);
+struct xen_flask_hash_stats;
+int avc_get_hash_stats(struct xen_flask_hash_stats *arg);
extern unsigned int avc_cache_threshold;
#ifdef FLASK_AVC_STATS
diff --git a/xen/xsm/flask/include/security.h b/xen/xsm/flask/include/security.h
index 67ca6d01ce..348f018fc6 100644
--- a/xen/xsm/flask/include/security.h
+++ b/xen/xsm/flask/include/security.h
@@ -90,8 +90,8 @@ int security_iterate_iomem_sids(unsigned long start, unsigned long end,
int security_iterate_ioport_sids(u32 start, u32 end,
security_iterate_fn fn, void *data);
-int security_ocontext_add(char *ocontext, unsigned long low,
+int security_ocontext_add(u32 ocontext, unsigned long low,
unsigned long high, u32 sid);
-int security_ocontext_del(char *ocontext, unsigned int low, unsigned int high);
+int security_ocontext_del(u32 ocontext, unsigned int low, unsigned int high);
#endif /* _FLASK_SECURITY_H_ */
diff --git a/xen/xsm/flask/ss/services.c b/xen/xsm/flask/ss/services.c
index 0189baf760..363f586a7d 100644
--- a/xen/xsm/flask/ss/services.c
+++ b/xen/xsm/flask/ss/services.c
@@ -2097,17 +2097,14 @@ int determine_ocontext( char *ocontext )
return -1;
}
-int security_ocontext_add( char *ocontext, unsigned long low, unsigned long high
+int security_ocontext_add( u32 ocon, unsigned long low, unsigned long high
,u32 sid )
{
int ret = 0;
- int ocon = 0;
struct ocontext *c;
struct ocontext *prev;
struct ocontext *add;
- if ( (ocon = determine_ocontext(ocontext)) < 0 )
- return -EINVAL;
if ( (add = xmalloc(struct ocontext)) == NULL )
return -ENOMEM;
memset(add, 0, sizeof(struct ocontext));
@@ -2254,15 +2251,11 @@ int security_ocontext_add( char *ocontext, unsigned long low, unsigned long high
return ret;
}
-int security_ocontext_del( char *ocontext, unsigned int low, unsigned int high )
+int security_ocontext_del( u32 ocon, unsigned int low, unsigned int high )
{
int ret = 0;
- int ocon = 0;
struct ocontext *c, *before_c;
- if ( (ocon = determine_ocontext(ocontext)) < 0 )
- return -EINVAL;
-
POLICY_WRLOCK;
switch( ocon )
{