Skip to content

Commit 2e12c5f

Browse files
committed
apparmor: add additional flags to extended permission.
This is a step towards merging the file and policy state machines. With the switch to extended permissions the state machine's ACCEPT2 table became unused freeing it up to store state specific flags. The first flags to be stored are FLAG_OWNER and FLAG other which paves the way towards merging the file and policydb perms into a single permission table. Currently Lookups based on the objects ownership conditional will still need separate fns, this will be address in a following patch. Signed-off-by: John Johansen <john.johansen@canonical.com>
1 parent de4754c commit 2e12c5f

File tree

7 files changed

+54
-21
lines changed

7 files changed

+54
-21
lines changed

security/apparmor/apparmorfs.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,8 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,
626626
if (state) {
627627
struct path_cond cond = { };
628628

629-
tmp = *(aa_lookup_fperms(rules->file, state, &cond));
629+
tmp = *(aa_lookup_condperms(current_fsuid(),
630+
rules->file, state, &cond));
630631
}
631632
} else if (rules->policy->dfa) {
632633
if (!RULE_MEDIATES(rules, *match_str))
@@ -2365,7 +2366,7 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = {
23652366
AA_SFS_FILE_BOOLEAN("set_load", 1),
23662367
/* number of out of band transitions supported */
23672368
AA_SFS_FILE_U64("outofband", MAX_OOB_SUPPORTED),
2368-
AA_SFS_FILE_U64("permstable32_version", 1),
2369+
AA_SFS_FILE_U64("permstable32_version", 3),
23692370
AA_SFS_FILE_STRING("permstable32", PERMS32STR),
23702371
AA_SFS_FILE_U64("state32", 1),
23712372
AA_SFS_DIR("unconfined_restrictions", aa_sfs_entry_unconfined),

security/apparmor/domain.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ static int label_compound_match(struct aa_profile *profile,
154154
if (!state)
155155
goto fail;
156156
}
157-
*perms = *(aa_lookup_fperms(rules->file, state, &cond));
157+
*perms = *(aa_lookup_condperms(current_fsuid(), rules->file, state,
158+
&cond));
158159
aa_apply_modes_to_perms(profile, perms);
159160
if ((perms->allow & request) != request)
160161
return -EACCES;
@@ -209,7 +210,8 @@ static int label_components_match(struct aa_profile *profile,
209210
return 0;
210211

211212
next:
212-
tmp = *(aa_lookup_fperms(rules->file, state, &cond));
213+
tmp = *(aa_lookup_condperms(current_fsuid(), rules->file, state,
214+
&cond));
213215
aa_apply_modes_to_perms(profile, &tmp);
214216
aa_perms_accum(perms, &tmp);
215217
label_for_each_cont(i, label, tp) {
@@ -218,7 +220,8 @@ static int label_components_match(struct aa_profile *profile,
218220
state = match_component(profile, tp, stack, start);
219221
if (!state)
220222
goto fail;
221-
tmp = *(aa_lookup_fperms(rules->file, state, &cond));
223+
tmp = *(aa_lookup_condperms(current_fsuid(), rules->file, state,
224+
&cond));
222225
aa_apply_modes_to_perms(profile, &tmp);
223226
aa_perms_accum(perms, &tmp);
224227
}

security/apparmor/file.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -169,26 +169,30 @@ static int path_name(const char *op, const struct cred *subj_cred,
169169
struct aa_perms default_perms = {};
170170
/**
171171
* aa_lookup_fperms - convert dfa compressed perms to internal perms
172-
* @file_rules: the aa_policydb to lookup perms for (NOT NULL)
172+
* @subj_uid: uid to use for subject owner test
173+
* @rules: the aa_policydb to lookup perms for (NOT NULL)
173174
* @state: state in dfa
174175
* @cond: conditions to consider (NOT NULL)
175176
*
176177
* TODO: convert from dfa + state to permission entry
177178
*
178179
* Returns: a pointer to a file permission set
179180
*/
180-
struct aa_perms *aa_lookup_fperms(struct aa_policydb *file_rules,
181-
aa_state_t state, struct path_cond *cond)
181+
struct aa_perms *aa_lookup_condperms(kuid_t subj_uid, struct aa_policydb *rules,
182+
aa_state_t state, struct path_cond *cond)
182183
{
183-
unsigned int index = ACCEPT_TABLE(file_rules->dfa)[state];
184+
unsigned int index = ACCEPT_TABLE(rules->dfa)[state];
184185

185-
if (!(file_rules->perms))
186+
if (!(rules->perms))
186187
return &default_perms;
187188

188-
if (uid_eq(current_fsuid(), cond->uid))
189-
return &(file_rules->perms[index]);
189+
if ((ACCEPT_TABLE2(rules->dfa)[state] & ACCEPT_FLAG_OWNER)) {
190+
if (uid_eq(subj_uid, cond->uid))
191+
return &(rules->perms[index]);
192+
return &(rules->perms[index + 1]);
193+
}
190194

191-
return &(file_rules->perms[index + 1]);
195+
return &(rules->perms[index]);
192196
}
193197

194198
/**
@@ -207,7 +211,8 @@ aa_state_t aa_str_perms(struct aa_policydb *file_rules, aa_state_t start,
207211
{
208212
aa_state_t state;
209213
state = aa_dfa_match(file_rules->dfa, start, name);
210-
*perms = *(aa_lookup_fperms(file_rules, state, cond));
214+
*perms = *(aa_lookup_condperms(current_fsuid(), file_rules, state,
215+
cond));
211216

212217
return state;
213218
}

security/apparmor/include/file.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,9 @@ int aa_audit_file(const struct cred *cred,
7777
const char *target, struct aa_label *tlabel, kuid_t ouid,
7878
const char *info, int error);
7979

80-
struct aa_perms *aa_lookup_fperms(struct aa_policydb *file_rules,
81-
aa_state_t state, struct path_cond *cond);
80+
struct aa_perms *aa_lookup_condperms(kuid_t subj_uid,
81+
struct aa_policydb *file_rules,
82+
aa_state_t state, struct path_cond *cond);
8283
aa_state_t aa_str_perms(struct aa_policydb *file_rules, aa_state_t start,
8384
const char *name, struct path_cond *cond,
8485
struct aa_perms *perms);

security/apparmor/include/policy.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ extern const char *const aa_profile_mode_names[];
5959

6060
#define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2)
6161

62+
/* flags in the dfa accept2 table */
63+
enum dfa_accept_flags {
64+
ACCEPT_FLAG_OWNER = 1,
65+
};
66+
6267
/*
6368
* FIXME: currently need a clean way to replace and remove profiles as a
6469
* set. It should be done at the namespace level.
@@ -124,6 +129,7 @@ static inline void aa_put_pdb(struct aa_policydb *pdb)
124129
kref_put(&pdb->count, aa_pdb_free_kref);
125130
}
126131

132+
/* lookup perm that doesn't have and object conditional */
127133
static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy,
128134
aa_state_t state)
129135
{
@@ -135,7 +141,6 @@ static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy,
135141
return &(policy->perms[index]);
136142
}
137143

138-
139144
/* struct aa_data - generic data structure
140145
* key: name for retrieving this data
141146
* size: size of data in bytes

security/apparmor/policy_compat.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,10 @@ static void remap_dfa_accept(struct aa_dfa *dfa, unsigned int factor)
286286

287287
AA_BUG(!dfa);
288288

289-
for (state = 0; state < state_count; state++)
289+
for (state = 0; state < state_count; state++) {
290290
ACCEPT_TABLE(dfa)[state] = state * factor;
291-
kvfree(dfa->tables[YYTD_ID_ACCEPT2]);
292-
dfa->tables[YYTD_ID_ACCEPT2] = NULL;
291+
ACCEPT_TABLE2(dfa)[state] = factor > 1 ? ACCEPT_FLAG_OWNER : 0;
292+
}
293293
}
294294

295295
/* TODO: merge different dfa mappings into single map_policy fn */

security/apparmor/policy_unpack.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,7 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy,
716716
void *pos = e->pos;
717717
int i, flags, error = -EPROTO;
718718
ssize_t size;
719+
u32 version = 0;
719720

720721
pdb = aa_alloc_pdb(GFP_KERNEL);
721722
if (!pdb)
@@ -733,6 +734,9 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy,
733734
if (pdb->perms) {
734735
/* perms table present accept is index */
735736
flags = TO_ACCEPT1_FLAG(YYTD_DATA32);
737+
if (aa_unpack_u32(e, &version, "permsv") && version > 2)
738+
/* accept2 used for dfa flags */
739+
flags |= TO_ACCEPT2_FLAG(YYTD_DATA32);
736740
} else {
737741
/* packed perms in accept1 and accept2 */
738742
flags = TO_ACCEPT1_FLAG(YYTD_DATA32) |
@@ -770,6 +774,20 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy,
770774
}
771775
}
772776

777+
if (pdb->perms && version <= 2) {
778+
/* add dfa flags table missing in v2 */
779+
u32 noents = pdb->dfa->tables[YYTD_ID_ACCEPT]->td_lolen;
780+
u16 tdflags = pdb->dfa->tables[YYTD_ID_ACCEPT]->td_flags;
781+
size_t tsize = table_size(noents, tdflags);
782+
783+
pdb->dfa->tables[YYTD_ID_ACCEPT2] = kvzalloc(tsize, GFP_KERNEL);
784+
if (!pdb->dfa->tables[YYTD_ID_ACCEPT2]) {
785+
*info = "failed to alloc dfa flags table";
786+
goto out;
787+
}
788+
pdb->dfa->tables[YYTD_ID_ACCEPT2]->td_lolen = noents;
789+
pdb->dfa->tables[YYTD_ID_ACCEPT2]->td_flags = tdflags;
790+
}
773791
/*
774792
* Unfortunately due to a bug in earlier userspaces, a
775793
* transition table may be present even when the dfa is
@@ -785,7 +803,7 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy,
785803

786804
/* TODO: move compat mapping here, requires dfa merging first */
787805
/* TODO: move verify here, it has to be done after compat mappings */
788-
806+
out:
789807
*policy = pdb;
790808
return 0;
791809

0 commit comments

Comments
 (0)