Skip to content

Commit 217af7e

Browse files
committed
apparmor: refactor profile rules and attachments
In preparation for moving from a single set of rules and a single attachment to multiple rulesets and attachments separate from the profile refactor attachment information and ruleset info into their own structures. Signed-off-by: John Johansen <[email protected]>
1 parent 3bf3d72 commit 217af7e

File tree

18 files changed

+308
-239
lines changed

18 files changed

+308
-239
lines changed

security/apparmor/apparmorfs.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -611,30 +611,29 @@ static const struct file_operations aa_fs_ns_revision_fops = {
611611
static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,
612612
const char *match_str, size_t match_len)
613613
{
614+
struct aa_ruleset *rules = &profile->rules;
614615
struct aa_perms tmp = { };
615-
struct aa_dfa *dfa;
616616
aa_state_t state = DFA_NOMATCH;
617617

618618
if (profile_unconfined(profile))
619619
return;
620-
if (profile->file.dfa && *match_str == AA_CLASS_FILE) {
621-
dfa = profile->file.dfa;
622-
state = aa_dfa_match_len(dfa,
623-
profile->file.start[AA_CLASS_FILE],
620+
if (rules->file.dfa && *match_str == AA_CLASS_FILE) {
621+
state = aa_dfa_match_len(rules->file.dfa,
622+
rules->file.start[AA_CLASS_FILE],
624623
match_str + 1, match_len - 1);
625624
if (state) {
626625
struct path_cond cond = { };
627626

628-
tmp = *(aa_lookup_fperms(&(profile->file), state, &cond));
627+
tmp = *(aa_lookup_fperms(&(rules->file), state, &cond));
629628
}
630-
} else if (profile->policy.dfa) {
631-
if (!PROFILE_MEDIATES(profile, *match_str))
629+
} else if (rules->policy.dfa) {
630+
if (!RULE_MEDIATES(rules, *match_str))
632631
return; /* no change to current perms */
633-
dfa = profile->policy.dfa;
634-
state = aa_dfa_match_len(dfa, profile->policy.start[0],
632+
state = aa_dfa_match_len(rules->policy.dfa,
633+
rules->policy.start[0],
635634
match_str, match_len);
636635
if (state)
637-
tmp = *aa_lookup_perms(&profile->policy, state);
636+
tmp = *aa_lookup_perms(&rules->policy, state);
638637
}
639638
aa_apply_modes_to_perms(profile, &tmp);
640639
aa_perms_accum_raw(perms, &tmp);
@@ -1093,9 +1092,9 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v)
10931092
struct aa_proxy *proxy = seq->private;
10941093
struct aa_label *label = aa_get_label_rcu(&proxy->label);
10951094
struct aa_profile *profile = labels_profile(label);
1096-
if (profile->attach)
1097-
seq_printf(seq, "%s\n", profile->attach);
1098-
else if (profile->xmatch.dfa)
1095+
if (profile->attach.xmatch_str)
1096+
seq_printf(seq, "%s\n", profile->attach.xmatch_str);
1097+
else if (profile->attach.xmatch.dfa)
10991098
seq_puts(seq, "<unknown>\n");
11001099
else
11011100
seq_printf(seq, "%s\n", profile->base.name);

security/apparmor/capability.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
6464
static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
6565
int cap, int error)
6666
{
67+
struct aa_ruleset *rules = &profile->rules;
6768
struct audit_cache *ent;
6869
int type = AUDIT_APPARMOR_AUTO;
6970

@@ -72,13 +73,13 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
7273
if (likely(!error)) {
7374
/* test if auditing is being forced */
7475
if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
75-
!cap_raised(profile->caps.audit, cap)))
76+
!cap_raised(rules->caps.audit, cap)))
7677
return 0;
7778
type = AUDIT_APPARMOR_AUDIT;
7879
} else if (KILL_MODE(profile) ||
79-
cap_raised(profile->caps.kill, cap)) {
80+
cap_raised(rules->caps.kill, cap)) {
8081
type = AUDIT_APPARMOR_KILL;
81-
} else if (cap_raised(profile->caps.quiet, cap) &&
82+
} else if (cap_raised(rules->caps.quiet, cap) &&
8283
AUDIT_MODE(profile) != AUDIT_NOQUIET &&
8384
AUDIT_MODE(profile) != AUDIT_ALL) {
8485
/* quiet auditing */
@@ -114,10 +115,11 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
114115
static int profile_capable(struct aa_profile *profile, int cap,
115116
unsigned int opts, struct common_audit_data *sa)
116117
{
118+
struct aa_ruleset *rules = &profile->rules;
117119
int error;
118120

119-
if (cap_raised(profile->caps.allow, cap) &&
120-
!cap_raised(profile->caps.denied, cap))
121+
if (cap_raised(rules->caps.allow, cap) &&
122+
!cap_raised(rules->caps.denied, cap))
121123
error = 0;
122124
else
123125
error = -EPERM;

security/apparmor/domain.c

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,20 @@ static inline aa_state_t match_component(struct aa_profile *profile,
8181
struct aa_profile *tp,
8282
bool stack, aa_state_t state)
8383
{
84+
struct aa_ruleset *rules = &profile->rules;
8485
const char *ns_name;
8586

8687
if (stack)
87-
state = aa_dfa_match(profile->file.dfa, state, "&");
88+
state = aa_dfa_match(rules->file.dfa, state, "&");
8889
if (profile->ns == tp->ns)
89-
return aa_dfa_match(profile->file.dfa, state, tp->base.hname);
90+
return aa_dfa_match(rules->file.dfa, state, tp->base.hname);
9091

9192
/* try matching with namespace name and then profile */
9293
ns_name = aa_ns_name(profile->ns, tp->ns, true);
93-
state = aa_dfa_match_len(profile->file.dfa, state, ":", 1);
94-
state = aa_dfa_match(profile->file.dfa, state, ns_name);
95-
state = aa_dfa_match_len(profile->file.dfa, state, ":", 1);
96-
return aa_dfa_match(profile->file.dfa, state, tp->base.hname);
94+
state = aa_dfa_match_len(rules->file.dfa, state, ":", 1);
95+
state = aa_dfa_match(rules->file.dfa, state, ns_name);
96+
state = aa_dfa_match_len(rules->file.dfa, state, ":", 1);
97+
return aa_dfa_match(rules->file.dfa, state, tp->base.hname);
9798
}
9899

99100
/**
@@ -117,6 +118,7 @@ static int label_compound_match(struct aa_profile *profile,
117118
aa_state_t state, bool subns, u32 request,
118119
struct aa_perms *perms)
119120
{
121+
struct aa_ruleset *rules = &profile->rules;
120122
struct aa_profile *tp;
121123
struct label_it i;
122124
struct path_cond cond = { };
@@ -139,12 +141,12 @@ static int label_compound_match(struct aa_profile *profile,
139141
label_for_each_cont(i, label, tp) {
140142
if (!aa_ns_visible(profile->ns, tp->ns, subns))
141143
continue;
142-
state = aa_dfa_match(profile->file.dfa, state, "//&");
144+
state = aa_dfa_match(rules->file.dfa, state, "//&");
143145
state = match_component(profile, tp, false, state);
144146
if (!state)
145147
goto fail;
146148
}
147-
*perms = *(aa_lookup_fperms(&(profile->file), state, &cond));
149+
*perms = *(aa_lookup_fperms(&(rules->file), state, &cond));
148150
aa_apply_modes_to_perms(profile, perms);
149151
if ((perms->allow & request) != request)
150152
return -EACCES;
@@ -177,6 +179,7 @@ static int label_components_match(struct aa_profile *profile,
177179
aa_state_t start, bool subns, u32 request,
178180
struct aa_perms *perms)
179181
{
182+
struct aa_ruleset *rules = &profile->rules;
180183
struct aa_profile *tp;
181184
struct label_it i;
182185
struct aa_perms tmp;
@@ -197,7 +200,7 @@ static int label_components_match(struct aa_profile *profile,
197200
return 0;
198201

199202
next:
200-
tmp = *(aa_lookup_fperms(&(profile->file), state, &cond));
203+
tmp = *(aa_lookup_fperms(&(rules->file), state, &cond));
201204
aa_apply_modes_to_perms(profile, &tmp);
202205
aa_perms_accum(perms, &tmp);
203206
label_for_each_cont(i, label, tp) {
@@ -206,7 +209,7 @@ static int label_components_match(struct aa_profile *profile,
206209
state = match_component(profile, tp, stack, start);
207210
if (!state)
208211
goto fail;
209-
tmp = *(aa_lookup_fperms(&(profile->file), state, &cond));
212+
tmp = *(aa_lookup_fperms(&(rules->file), state, &cond));
210213
aa_apply_modes_to_perms(profile, &tmp);
211214
aa_perms_accum(perms, &tmp);
212215
}
@@ -296,18 +299,19 @@ static int aa_xattrs_match(const struct linux_binprm *bprm,
296299
ssize_t size;
297300
struct dentry *d;
298301
char *value = NULL;
299-
int value_size = 0, ret = profile->xattr_count;
302+
struct aa_attachment *attach = &profile->attach;
303+
int value_size = 0, ret = attach->xattr_count;
300304

301-
if (!bprm || !profile->xattr_count)
305+
if (!bprm || !attach->xattr_count)
302306
return 0;
303307
might_sleep();
304308

305309
/* transition from exec match to xattr set */
306-
state = aa_dfa_outofband_transition(profile->xmatch.dfa, state);
310+
state = aa_dfa_outofband_transition(attach->xmatch.dfa, state);
307311
d = bprm->file->f_path.dentry;
308312

309-
for (i = 0; i < profile->xattr_count; i++) {
310-
size = vfs_getxattr_alloc(&init_user_ns, d, profile->xattrs[i],
313+
for (i = 0; i < attach->xattr_count; i++) {
314+
size = vfs_getxattr_alloc(&init_user_ns, d, attach->xattrs[i],
311315
&value, value_size, GFP_KERNEL);
312316
if (size >= 0) {
313317
u32 index, perm;
@@ -317,20 +321,20 @@ static int aa_xattrs_match(const struct linux_binprm *bprm,
317321
* that not present xattr can be distinguished from a 0
318322
* length value or rule that matches any value
319323
*/
320-
state = aa_dfa_null_transition(profile->xmatch.dfa,
324+
state = aa_dfa_null_transition(attach->xmatch.dfa,
321325
state);
322326
/* Check xattr value */
323-
state = aa_dfa_match_len(profile->xmatch.dfa, state,
327+
state = aa_dfa_match_len(attach->xmatch.dfa, state,
324328
value, size);
325-
index = ACCEPT_TABLE(profile->xmatch.dfa)[state];
326-
perm = profile->xmatch.perms[index].allow;
329+
index = ACCEPT_TABLE(attach->xmatch.dfa)[state];
330+
perm = attach->xmatch.perms[index].allow;
327331
if (!(perm & MAY_EXEC)) {
328332
ret = -EINVAL;
329333
goto out;
330334
}
331335
}
332336
/* transition to next element */
333-
state = aa_dfa_outofband_transition(profile->xmatch.dfa, state);
337+
state = aa_dfa_outofband_transition(attach->xmatch.dfa, state);
334338
if (size < 0) {
335339
/*
336340
* No xattr match, so verify if transition to
@@ -382,6 +386,8 @@ static struct aa_label *find_attach(const struct linux_binprm *bprm,
382386
rcu_read_lock();
383387
restart:
384388
list_for_each_entry_rcu(profile, head, base.list) {
389+
struct aa_attachment *attach = &profile->attach;
390+
385391
if (profile->label.flags & FLAG_NULL &&
386392
&profile->label == ns_unconfined(profile->ns))
387393
continue;
@@ -397,24 +403,24 @@ static struct aa_label *find_attach(const struct linux_binprm *bprm,
397403
* as another profile, signal a conflict and refuse to
398404
* match.
399405
*/
400-
if (profile->xmatch.dfa) {
406+
if (attach->xmatch.dfa) {
401407
unsigned int count;
402408
aa_state_t state;
403409
u32 index, perm;
404410

405-
state = aa_dfa_leftmatch(profile->xmatch.dfa,
406-
profile->xmatch.start[AA_CLASS_XMATCH],
411+
state = aa_dfa_leftmatch(attach->xmatch.dfa,
412+
attach->xmatch.start[AA_CLASS_XMATCH],
407413
name, &count);
408-
index = ACCEPT_TABLE(profile->xmatch.dfa)[state];
409-
perm = profile->xmatch.perms[index].allow;
414+
index = ACCEPT_TABLE(attach->xmatch.dfa)[state];
415+
perm = attach->xmatch.perms[index].allow;
410416
/* any accepting state means a valid match. */
411417
if (perm & MAY_EXEC) {
412418
int ret = 0;
413419

414420
if (count < candidate_len)
415421
continue;
416422

417-
if (bprm && profile->xattr_count) {
423+
if (bprm && attach->xattr_count) {
418424
long rev = READ_ONCE(ns->revision);
419425

420426
if (!aa_get_profile_not0(profile))
@@ -453,7 +459,7 @@ static struct aa_label *find_attach(const struct linux_binprm *bprm,
453459
* xattrs, or a longer match
454460
*/
455461
candidate = profile;
456-
candidate_len = max(count, profile->xmatch_len);
462+
candidate_len = max(count, attach->xmatch_len);
457463
candidate_xattrs = ret;
458464
conflict = false;
459465
}
@@ -497,6 +503,7 @@ static const char *next_name(int xtype, const char *name)
497503
struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
498504
const char **name)
499505
{
506+
struct aa_ruleset *rules = &profile->rules;
500507
struct aa_label *label = NULL;
501508
u32 xtype = xindex & AA_X_TYPE_MASK;
502509
int index = xindex & AA_X_INDEX_MASK;
@@ -507,7 +514,7 @@ struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
507514
/* TODO: move lookup parsing to unpack time so this is a straight
508515
* index into the resultant label
509516
*/
510-
for (*name = profile->file.trans.table[index]; !label && *name;
517+
for (*name = rules->file.trans.table[index]; !label && *name;
511518
*name = next_name(xtype, *name)) {
512519
if (xindex & AA_X_CHILD) {
513520
struct aa_profile *new_profile;
@@ -546,6 +553,7 @@ static struct aa_label *x_to_label(struct aa_profile *profile,
546553
const char **lookupname,
547554
const char **info)
548555
{
556+
struct aa_ruleset *rules = &profile->rules;
549557
struct aa_label *new = NULL;
550558
struct aa_ns *ns = profile->ns;
551559
u32 xtype = xindex & AA_X_TYPE_MASK;
@@ -558,7 +566,7 @@ static struct aa_label *x_to_label(struct aa_profile *profile,
558566
break;
559567
case AA_X_TABLE:
560568
/* TODO: fix when perm mapping done at unload */
561-
stack = profile->file.trans.table[xindex & AA_X_INDEX_MASK];
569+
stack = rules->file.trans.table[xindex & AA_X_INDEX_MASK];
562570
if (*stack != '&') {
563571
/* released by caller */
564572
new = x_table_lookup(profile, xindex, lookupname);
@@ -612,9 +620,10 @@ static struct aa_label *profile_transition(struct aa_profile *profile,
612620
char *buffer, struct path_cond *cond,
613621
bool *secure_exec)
614622
{
623+
struct aa_ruleset *rules = &profile->rules;
615624
struct aa_label *new = NULL;
616625
const char *info = NULL, *name = NULL, *target = NULL;
617-
aa_state_t state = profile->file.start[AA_CLASS_FILE];
626+
aa_state_t state = rules->file.start[AA_CLASS_FILE];
618627
struct aa_perms perms = {};
619628
bool nonewprivs = false;
620629
int error = 0;
@@ -648,7 +657,7 @@ static struct aa_label *profile_transition(struct aa_profile *profile,
648657
}
649658

650659
/* find exec permissions for name */
651-
state = aa_str_perms(&(profile->file), state, name, cond, &perms);
660+
state = aa_str_perms(&(rules->file), state, name, cond, &perms);
652661
if (perms.allow & MAY_EXEC) {
653662
/* exec permission determine how to transition */
654663
new = x_to_label(profile, bprm, name, perms.xindex, &target,
@@ -710,7 +719,8 @@ static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec,
710719
char *buffer, struct path_cond *cond,
711720
bool *secure_exec)
712721
{
713-
aa_state_t state = profile->file.start[AA_CLASS_FILE];
722+
struct aa_ruleset *rules = &profile->rules;
723+
aa_state_t state = rules->file.start[AA_CLASS_FILE];
714724
struct aa_perms perms = {};
715725
const char *xname = NULL, *info = "change_profile onexec";
716726
int error = -EACCES;
@@ -743,7 +753,7 @@ static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec,
743753
}
744754

745755
/* find exec permissions for name */
746-
state = aa_str_perms(&(profile->file), state, xname, cond, &perms);
756+
state = aa_str_perms(&(rules->file), state, xname, cond, &perms);
747757
if (!(perms.allow & AA_MAY_ONEXEC)) {
748758
info = "no change_onexec valid for executable";
749759
goto audit;
@@ -752,7 +762,7 @@ static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec,
752762
* onexec permission is linked to exec with a standard pairing
753763
* exec\0change_profile
754764
*/
755-
state = aa_dfa_null_transition(profile->file.dfa, state);
765+
state = aa_dfa_null_transition(rules->file.dfa, state);
756766
error = change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC,
757767
state, &perms);
758768
if (error) {
@@ -1249,12 +1259,13 @@ static int change_profile_perms_wrapper(const char *op, const char *name,
12491259
struct aa_label *target, bool stack,
12501260
u32 request, struct aa_perms *perms)
12511261
{
1262+
struct aa_ruleset *rules = &profile->rules;
12521263
const char *info = NULL;
12531264
int error = 0;
12541265

12551266
if (!error)
12561267
error = change_profile_perms(profile, target, stack, request,
1257-
profile->file.start[AA_CLASS_FILE],
1268+
rules->file.start[AA_CLASS_FILE],
12581269
perms);
12591270
if (error)
12601271
error = aa_audit_file(profile, perms, op, request, name,

0 commit comments

Comments
 (0)