Skip to content

Commit

Permalink
apparmor: switch from profiles to using labels on contexts
Browse files Browse the repository at this point in the history
Begin the actual switch to using domain labels by storing them on
the context and converting the label to a singular profile where
possible.

Signed-off-by: John Johansen <[email protected]>
  • Loading branch information
John Johansen committed Jun 11, 2017
1 parent f1bd904 commit 637f688
Show file tree
Hide file tree
Showing 20 changed files with 686 additions and 529 deletions.
2 changes: 1 addition & 1 deletion security/apparmor/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o

apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
resource.o secid.o file.o policy_ns.o
resource.o secid.o file.o policy_ns.o label.o
apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o

clean-files := capability_names.h rlim_names.h
Expand Down
128 changes: 70 additions & 58 deletions security/apparmor/apparmorfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,26 +405,26 @@ static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf,
static ssize_t policy_update(u32 mask, const char __user *buf, size_t size,
loff_t *pos, struct aa_ns *ns)
{
ssize_t error;
struct aa_loaddata *data;
struct aa_profile *profile;
struct aa_label *label;
ssize_t error;

profile = begin_current_profile_crit_section();
label = begin_current_label_crit_section();

/* high level check about policy management - fine grained in
* below after unpack
*/
error = aa_may_manage_policy(profile, ns, mask);
error = aa_may_manage_policy(label, ns, mask);
if (error)
return error;

data = aa_simple_write_to_buffer(buf, size, size, pos);
error = PTR_ERR(data);
if (!IS_ERR(data)) {
error = aa_replace_profiles(ns, profile, mask, data);
error = aa_replace_profiles(ns, label, mask, data);
aa_put_loaddata(data);
}
end_current_profile_crit_section(profile);
end_current_label_crit_section(label);

return error;
}
Expand Down Expand Up @@ -468,15 +468,15 @@ static ssize_t profile_remove(struct file *f, const char __user *buf,
size_t size, loff_t *pos)
{
struct aa_loaddata *data;
struct aa_profile *profile;
struct aa_label *label;
ssize_t error;
struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);

profile = begin_current_profile_crit_section();
label = begin_current_label_crit_section();
/* high level check about policy management - fine grained in
* below after unpack
*/
error = aa_may_manage_policy(profile, ns, AA_MAY_REMOVE_POLICY);
error = aa_may_manage_policy(label, ns, AA_MAY_REMOVE_POLICY);
if (error)
goto out;

Expand All @@ -489,11 +489,11 @@ static ssize_t profile_remove(struct file *f, const char __user *buf,
error = PTR_ERR(data);
if (!IS_ERR(data)) {
data->data[size] = 0;
error = aa_remove_profiles(ns, profile, data->data, size);
error = aa_remove_profiles(ns, label, data->data, size);
aa_put_loaddata(data);
}
out:
end_current_profile_crit_section(profile);
end_current_label_crit_section(label);
aa_put_ns(ns);
return error;
}
Expand Down Expand Up @@ -605,7 +605,7 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,
struct aa_dfa *dfa;
unsigned int state = 0;

if (unconfined(profile))
if (profile_unconfined(profile))
return;
if (profile->file.dfa && *match_str == AA_CLASS_FILE) {
dfa = profile->file.dfa;
Expand Down Expand Up @@ -655,7 +655,7 @@ static ssize_t query_data(char *buf, size_t buf_len,
{
char *out;
const char *key;
struct aa_profile *profile, *curr;
struct aa_label *label, *curr;
struct aa_data *data;
u32 bytes, blocks;
__le32 outle32;
Expand All @@ -672,11 +672,11 @@ static ssize_t query_data(char *buf, size_t buf_len,
if (buf_len < sizeof(bytes) + sizeof(blocks))
return -EINVAL; /* not enough space */

curr = begin_current_profile_crit_section();
profile = aa_fqlookupn_profile(curr, query, strnlen(query, query_len));
end_current_profile_crit_section(curr);
if (!profile)
return -ENOENT;
curr = begin_current_label_crit_section();
label = aa_label_parse(curr, query, GFP_KERNEL, false, false);
end_current_label_crit_section(curr);
if (IS_ERR(label))
return PTR_ERR(label);

/* We are going to leave space for two numbers. The first is the total
* number of bytes we are writing after the first number. This is so
Expand All @@ -690,13 +690,16 @@ static ssize_t query_data(char *buf, size_t buf_len,
out = buf + sizeof(bytes) + sizeof(blocks);

blocks = 0;
if (profile->data) {
data = rhashtable_lookup_fast(profile->data, &key,
profile->data->p);
if (labels_profile(label)->data) {
data = rhashtable_lookup_fast(labels_profile(label)->data, &key,
labels_profile(label)->data->p);

if (data) {
if (out + sizeof(outle32) + data->size > buf + buf_len)
if (out + sizeof(outle32) + data->size >
buf + buf_len) {
aa_put_label(label);
return -EINVAL; /* not enough space */
}
outle32 = __cpu_to_le32(data->size);
memcpy(out, &outle32, sizeof(outle32));
out += sizeof(outle32);
Expand All @@ -705,7 +708,7 @@ static ssize_t query_data(char *buf, size_t buf_len,
blocks++;
}
}
aa_put_profile(profile);
aa_put_label(label);

outle32 = __cpu_to_le32(out - buf - sizeof(bytes));
memcpy(buf, &outle32, sizeof(outle32));
Expand Down Expand Up @@ -738,7 +741,7 @@ static ssize_t query_data(char *buf, size_t buf_len,
static ssize_t query_label(char *buf, size_t buf_len,
char *query, size_t query_len, bool view_only)
{
struct aa_profile *profile, *curr;
struct aa_label *label, *curr;
char *label_name, *match_str;
size_t label_name_len, match_len;
struct aa_perms perms;
Expand All @@ -760,14 +763,14 @@ static ssize_t query_label(char *buf, size_t buf_len,
match_str = label_name + label_name_len + 1;
match_len = query_len - label_name_len - 1;

curr = begin_current_profile_crit_section();
profile = aa_fqlookupn_profile(curr, label_name, label_name_len);
end_current_profile_crit_section(curr);
if (!profile)
return -ENOENT;
curr = begin_current_label_crit_section();
label = aa_label_parse(curr, label_name, GFP_KERNEL, false, false);
end_current_label_crit_section(curr);
if (IS_ERR(label))
return PTR_ERR(label);

perms = allperms;
profile_query_cb(profile, &perms, match_str, match_len);
profile_query_cb(labels_profile(label), &perms, match_str, match_len);

return scnprintf(buf, buf_len,
"allow 0x%08x\ndeny 0x%08x\naudit 0x%08x\nquiet 0x%08x\n",
Expand Down Expand Up @@ -1026,50 +1029,54 @@ static int seq_profile_release(struct inode *inode, struct file *file)
static int seq_profile_name_show(struct seq_file *seq, void *v)
{
struct aa_proxy *proxy = seq->private;
struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
struct aa_label *label = aa_get_label_rcu(&proxy->label);
struct aa_profile *profile = labels_profile(label);
seq_printf(seq, "%s\n", profile->base.name);
aa_put_profile(profile);
aa_put_label(label);

return 0;
}

static int seq_profile_mode_show(struct seq_file *seq, void *v)
{
struct aa_proxy *proxy = seq->private;
struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
struct aa_label *label = aa_get_label_rcu(&proxy->label);
struct aa_profile *profile = labels_profile(label);
seq_printf(seq, "%s\n", aa_profile_mode_names[profile->mode]);
aa_put_profile(profile);
aa_put_label(label);

return 0;
}

static int seq_profile_attach_show(struct seq_file *seq, void *v)
{
struct aa_proxy *proxy = seq->private;
struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
struct aa_label *label = aa_get_label_rcu(&proxy->label);
struct aa_profile *profile = labels_profile(label);
if (profile->attach)
seq_printf(seq, "%s\n", profile->attach);
else if (profile->xmatch)
seq_puts(seq, "<unknown>\n");
else
seq_printf(seq, "%s\n", profile->base.name);
aa_put_profile(profile);
aa_put_label(label);

return 0;
}

static int seq_profile_hash_show(struct seq_file *seq, void *v)
{
struct aa_proxy *proxy = seq->private;
struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
struct aa_label *label = aa_get_label_rcu(&proxy->label);
struct aa_profile *profile = labels_profile(label);
unsigned int i, size = aa_hash_size();

if (profile->hash) {
for (i = 0; i < size; i++)
seq_printf(seq, "%.2x", profile->hash[i]);
seq_putc(seq, '\n');
}
aa_put_profile(profile);
aa_put_label(label);

return 0;
}
Expand Down Expand Up @@ -1101,22 +1108,22 @@ static const struct file_operations seq_ns_ ##NAME ##_fops = { \

static int seq_ns_level_show(struct seq_file *seq, void *v)
{
struct aa_profile *profile;
struct aa_label *label;

profile = begin_current_profile_crit_section();
seq_printf(seq, "%d\n", profile->ns->level);
end_current_profile_crit_section(profile);
label = begin_current_label_crit_section();
seq_printf(seq, "%d\n", labels_ns(label)->level);
end_current_label_crit_section(label);

return 0;
}

static int seq_ns_name_show(struct seq_file *seq, void *v)
{
struct aa_profile *profile;
struct aa_label *label = begin_current_label_crit_section();

profile = begin_current_profile_crit_section();
seq_printf(seq, "%s\n", aa_ns_name(profile->ns, profile->ns, true));
end_current_profile_crit_section(profile);
seq_printf(seq, "%s\n", aa_ns_name(labels_ns(label),
labels_ns(label), true));
end_current_label_crit_section(label);

return 0;
}
Expand Down Expand Up @@ -1380,7 +1387,7 @@ static struct dentry *create_profile_file(struct dentry *dir, const char *name,
struct aa_profile *profile,
const struct file_operations *fops)
{
struct aa_proxy *proxy = aa_get_proxy(profile->proxy);
struct aa_proxy *proxy = aa_get_proxy(profile->label.proxy);
struct dentry *dent;

dent = aafs_create_file(name, S_IFREG | 0444, dir, proxy, fops);
Expand Down Expand Up @@ -1541,9 +1548,12 @@ static int ns_mkdir_op(struct inode *dir, struct dentry *dentry, umode_t mode)
{
struct aa_ns *ns, *parent;
/* TODO: improve permission check */
struct aa_profile *profile = begin_current_profile_crit_section();
int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY);
end_current_profile_crit_section(profile);
struct aa_label *label;
int error;

label = begin_current_label_crit_section();
error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY);
end_current_label_crit_section(label);
if (error)
return error;

Expand Down Expand Up @@ -1587,13 +1597,16 @@ static int ns_rmdir_op(struct inode *dir, struct dentry *dentry)
{
struct aa_ns *ns, *parent;
/* TODO: improve permission check */
struct aa_profile *profile = begin_current_profile_crit_section();
int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY);
end_current_profile_crit_section(profile);
struct aa_label *label;
int error;

label = begin_current_label_crit_section();
error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY);
end_current_label_crit_section(label);
if (error)
return error;

parent = aa_get_ns(dir->i_private);
parent = aa_get_ns(dir->i_private);
/* rmdir calls the generic securityfs functions to remove files
* from the apparmor dir. It is up to the apparmor ns locking
* to avoid races.
Expand Down Expand Up @@ -1999,10 +2012,9 @@ static int seq_show_profile(struct seq_file *f, void *p)
struct aa_profile *profile = (struct aa_profile *)p;
struct aa_ns *root = f->private;

if (profile->ns != root)
seq_printf(f, ":%s://", aa_ns_name(root, profile->ns, true));
seq_printf(f, "%s (%s)\n", profile->base.hname,
aa_profile_mode_names[profile->mode]);
aa_label_seq_xprint(f, root, &profile->label,
FLAG_SHOW_MODE | FLAG_VIEW_SUBNS, GFP_KERNEL);
seq_putc(f, '\n');

return 0;
}
Expand Down
27 changes: 18 additions & 9 deletions security/apparmor/audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,24 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
audit_log_format(ab, " error=%d", aad(sa)->error);
}

if (aad(sa)->profile) {
struct aa_profile *profile = aad(sa)->profile;
if (profile->ns != root_ns) {
audit_log_format(ab, " namespace=");
audit_log_untrustedstring(ab, profile->ns->base.hname);
if (aad(sa)->label) {
struct aa_label *label = aad(sa)->label;

if (label_isprofile(label)) {
struct aa_profile *profile = labels_profile(label);

if (profile->ns != root_ns) {
audit_log_format(ab, " namespace=");
audit_log_untrustedstring(ab,
profile->ns->base.hname);
}
audit_log_format(ab, " profile=");
audit_log_untrustedstring(ab, profile->base.hname);
} else {
audit_log_format(ab, " label=");
aa_label_xaudit(ab, root_ns, label, FLAG_VIEW_SUBNS,
GFP_ATOMIC);
}
audit_log_format(ab, " profile=");
audit_log_untrustedstring(ab, profile->base.hname);
}

if (aad(sa)->name) {
Expand Down Expand Up @@ -139,8 +149,7 @@ int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
type = AUDIT_APPARMOR_KILL;

if (!unconfined(profile))
aad(sa)->profile = profile;
aad(sa)->label = &profile->label;

aa_audit_msg(type, sa, cb);

Expand Down
Loading

0 comments on commit 637f688

Please sign in to comment.