Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 211684
b: refs/heads/master
c: cee74f4
h: refs/heads/master
v: v3
  • Loading branch information
Eric Paris authored and James Morris committed Oct 20, 2010
1 parent b328356 commit 4d1a597
Show file tree
Hide file tree
Showing 13 changed files with 1,257 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 00d85c83ac52e2c1a66397f1abc589f80c543425
refs/heads/master: cee74f47a6baba0ac457e87687fdcf0abd599f0a
2 changes: 1 addition & 1 deletion trunk/security/selinux/include/classmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct security_class_mapping secclass_map[] = {
{ "compute_av", "compute_create", "compute_member",
"check_context", "load_policy", "compute_relabel",
"compute_user", "setenforce", "setbool", "setsecparam",
"setcheckreqprot", NULL } },
"setcheckreqprot", "read_policy", NULL } },
{ "process",
{ "fork", "transition", "sigchld", "sigkill",
"sigstop", "signull", "signal", "ptrace", "getsched", "setsched",
Expand Down
2 changes: 2 additions & 0 deletions trunk/security/selinux/include/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ extern int selinux_policycap_openperm;
int security_mls_enabled(void);

int security_load_policy(void *data, size_t len);
int security_read_policy(void **data, ssize_t *len);
size_t security_policydb_len(void);

int security_policycap_supported(unsigned int req_cap);

Expand Down
95 changes: 95 additions & 0 deletions trunk/security/selinux/selinuxfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ static int *bool_pending_values;
static struct dentry *class_dir;
static unsigned long last_class_ino;

static char policy_opened;

/* global data for policy capabilities */
static struct dentry *policycap_dir;

Expand Down Expand Up @@ -111,6 +113,7 @@ enum sel_inos {
SEL_REJECT_UNKNOWN, /* export unknown reject handling to userspace */
SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */
SEL_STATUS, /* export current status using mmap() */
SEL_POLICY, /* allow userspace to read the in kernel policy */
SEL_INO_NEXT, /* The next inode number to use */
};

Expand Down Expand Up @@ -351,6 +354,97 @@ static const struct file_operations sel_mls_ops = {
.llseek = generic_file_llseek,
};

struct policy_load_memory {
size_t len;
void *data;
};

static int sel_open_policy(struct inode *inode, struct file *filp)
{
struct policy_load_memory *plm = NULL;
int rc;

BUG_ON(filp->private_data);

mutex_lock(&sel_mutex);

rc = task_has_security(current, SECURITY__READ_POLICY);
if (rc)
goto err;

rc = -EBUSY;
if (policy_opened)
goto err;

rc = -ENOMEM;
plm = kzalloc(sizeof(*plm), GFP_KERNEL);
if (!plm)
goto err;

if (i_size_read(inode) != security_policydb_len()) {
mutex_lock(&inode->i_mutex);
i_size_write(inode, security_policydb_len());
mutex_unlock(&inode->i_mutex);
}

rc = security_read_policy(&plm->data, &plm->len);
if (rc)
goto err;

policy_opened = 1;

filp->private_data = plm;

mutex_unlock(&sel_mutex);

return 0;
err:
mutex_unlock(&sel_mutex);

if (plm)
vfree(plm->data);
kfree(plm);
return rc;
}

static int sel_release_policy(struct inode *inode, struct file *filp)
{
struct policy_load_memory *plm = filp->private_data;

BUG_ON(!plm);

policy_opened = 0;

vfree(plm->data);
kfree(plm);

return 0;
}

static ssize_t sel_read_policy(struct file *filp, char __user *buf,
size_t count, loff_t *ppos)
{
struct policy_load_memory *plm = filp->private_data;
int ret;

mutex_lock(&sel_mutex);

ret = task_has_security(current, SECURITY__READ_POLICY);
if (ret)
goto out;

ret = simple_read_from_buffer(buf, count, ppos, plm->data, plm->len);
out:
mutex_unlock(&sel_mutex);
return ret;
}

static const struct file_operations sel_policy_ops = {
.open = sel_open_policy,
.read = sel_read_policy,
.release = sel_release_policy,
};

static ssize_t sel_write_load(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)

Expand Down Expand Up @@ -1668,6 +1762,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
[SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
[SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
[SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO},
[SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUSR},
/* last one */ {""}
};
ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
Expand Down
42 changes: 42 additions & 0 deletions trunk/security/selinux/ss/avtab.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,48 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
goto out;
}

int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp)
{
__le16 buf16[4];
__le32 buf32[1];
int rc;

buf16[0] = cpu_to_le16(cur->key.source_type);
buf16[1] = cpu_to_le16(cur->key.target_type);
buf16[2] = cpu_to_le16(cur->key.target_class);
buf16[3] = cpu_to_le16(cur->key.specified);
rc = put_entry(buf16, sizeof(u16), 4, fp);
if (rc)
return rc;
buf32[0] = cpu_to_le32(cur->datum.data);
rc = put_entry(buf32, sizeof(u32), 1, fp);
if (rc)
return rc;
return 0;
}

int avtab_write(struct policydb *p, struct avtab *a, void *fp)
{
unsigned int i;
int rc = 0;
struct avtab_node *cur;
__le32 buf[1];

buf[0] = cpu_to_le32(a->nel);
rc = put_entry(buf, sizeof(u32), 1, fp);
if (rc)
return rc;

for (i = 0; i < a->nslot; i++) {
for (cur = a->htable[i]; cur; cur = cur->next) {
rc = avtab_write_item(p, cur, fp);
if (rc)
return rc;
}
}

return rc;
}
void avtab_cache_init(void)
{
avtab_node_cachep = kmem_cache_create("avtab_node",
Expand Down
2 changes: 2 additions & 0 deletions trunk/security/selinux/ss/avtab.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
void *p);

int avtab_read(struct avtab *a, void *fp, struct policydb *pol);
int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp);
int avtab_write(struct policydb *p, struct avtab *a, void *fp);

struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key,
struct avtab_datum *datum);
Expand Down
123 changes: 123 additions & 0 deletions trunk/security/selinux/ss/conditional.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,129 @@ int cond_read_list(struct policydb *p, void *fp)
return rc;
}

int cond_write_bool(void *vkey, void *datum, void *ptr)
{
char *key = vkey;
struct cond_bool_datum *booldatum = datum;
struct policy_data *pd = ptr;
void *fp = pd->fp;
__le32 buf[3];
u32 len;
int rc;

len = strlen(key);
buf[0] = cpu_to_le32(booldatum->value);
buf[1] = cpu_to_le32(booldatum->state);
buf[2] = cpu_to_le32(len);
rc = put_entry(buf, sizeof(u32), 3, fp);
if (rc)
return rc;
rc = put_entry(key, 1, len, fp);
if (rc)
return rc;
return 0;
}

/*
* cond_write_cond_av_list doesn't write out the av_list nodes.
* Instead it writes out the key/value pairs from the avtab. This
* is necessary because there is no way to uniquely identifying rules
* in the avtab so it is not possible to associate individual rules
* in the avtab with a conditional without saving them as part of
* the conditional. This means that the avtab with the conditional
* rules will not be saved but will be rebuilt on policy load.
*/
static int cond_write_av_list(struct policydb *p,
struct cond_av_list *list, struct policy_file *fp)
{
__le32 buf[1];
struct cond_av_list *cur_list;
u32 len;
int rc;

len = 0;
for (cur_list = list; cur_list != NULL; cur_list = cur_list->next)
len++;

buf[0] = cpu_to_le32(len);
rc = put_entry(buf, sizeof(u32), 1, fp);
if (rc)
return rc;

if (len == 0)
return 0;

for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
rc = avtab_write_item(p, cur_list->node, fp);
if (rc)
return rc;
}

return 0;
}

int cond_write_node(struct policydb *p, struct cond_node *node,
struct policy_file *fp)
{
struct cond_expr *cur_expr;
__le32 buf[2];
int rc;
u32 len = 0;

buf[0] = cpu_to_le32(node->cur_state);
rc = put_entry(buf, sizeof(u32), 1, fp);
if (rc)
return rc;

for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next)
len++;

buf[0] = cpu_to_le32(len);
rc = put_entry(buf, sizeof(u32), 1, fp);
if (rc)
return rc;

for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) {
buf[0] = cpu_to_le32(cur_expr->expr_type);
buf[1] = cpu_to_le32(cur_expr->bool);
rc = put_entry(buf, sizeof(u32), 2, fp);
if (rc)
return rc;
}

rc = cond_write_av_list(p, node->true_list, fp);
if (rc)
return rc;
rc = cond_write_av_list(p, node->false_list, fp);
if (rc)
return rc;

return 0;
}

int cond_write_list(struct policydb *p, struct cond_node *list, void *fp)
{
struct cond_node *cur;
u32 len;
__le32 buf[1];
int rc;

len = 0;
for (cur = list; cur != NULL; cur = cur->next)
len++;
buf[0] = cpu_to_le32(len);
rc = put_entry(buf, sizeof(u32), 1, fp);
if (rc)
return rc;

for (cur = list; cur != NULL; cur = cur->next) {
rc = cond_write_node(p, cur, fp);
if (rc)
return rc;
}

return 0;
}
/* Determine whether additional permissions are granted by the conditional
* av table, and if so, add them to the result
*/
Expand Down
2 changes: 2 additions & 0 deletions trunk/security/selinux/ss/conditional.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ int cond_index_bool(void *key, void *datum, void *datap);

int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp);
int cond_read_list(struct policydb *p, void *fp);
int cond_write_bool(void *key, void *datum, void *ptr);
int cond_write_list(struct policydb *p, struct cond_node *list, void *fp);

void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd);

Expand Down
Loading

0 comments on commit 4d1a597

Please sign in to comment.