Skip to content

Commit 6bdfe2d

Browse files
committed
Merge tag 'apparmor-pr-2023-11-03' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
Pull apparmor updates from John Johansen: "This adds initial support for mediating io_uring and userns creation. Adds a new restriction that tightens the use of change_profile, and a couple of optimizations to reduce performance bottle necks that have been found when retrieving the current task's secid and allocating work buffers. The majority of the patch set continues cleaning up and simplifying the code (fixing comments, removing now dead functions, and macros etc). Finally there are 4 bug fixes, with the regression fix having had a couple months of testing. Features: - optimize retrieving current task secid - add base io_uring mediation - add base userns mediation - improve buffer allocation - allow restricting unprivilege change_profile Cleanups: - Fix kernel doc comments - remove unused declarations - remove unused functions - remove unneeded #ifdef - remove unused macros - mark fns static - cleanup fn with unused return values - cleanup audit data - pass cred through to audit data - refcount the pdb instead of using duplicates - make SK_CTX macro an inline fn - some comment cleanups Bug fixes: - fix regression in mount mediation - fix invalid refenece - use passed in gfp flags - advertise avaiability of extended perms and disconnected.path" * tag 'apparmor-pr-2023-11-03' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor: (39 commits) apparmor: Fix some kernel-doc comments apparmor: Fix one kernel-doc comment apparmor: Fix some kernel-doc comments apparmor: mark new functions static apparmor: Fix regression in mount mediation apparmor: cache buffers on percpu list if there is lock contention apparmor: add io_uring mediation apparmor: add user namespace creation mediation apparmor: allow restricting unprivileged change_profile apparmor: advertise disconnected.path is available apparmor: refcount the pdb apparmor: provide separate audit messages for file and policy checks apparmor: pass cred through to audit info. apparmor: rename audit_data->label to audit_data->subj_label apparmor: combine common_audit_data and apparmor_audit_data apparmor: rename SK_CTX() to aa_sock and make it an inline fn apparmor: Optimize retrieving current task secid apparmor: remove unused functions in policy_ns.c/.h apparmor: remove unneeded #ifdef in decompress_zstd() apparmor: fix invalid reference on profile->disconnected ...
2 parents 136cc1e + 6cede10 commit 6bdfe2d

32 files changed

+1336
-848
lines changed

security/apparmor/apparmorfs.c

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ static ssize_t policy_update(u32 mask, const char __user *buf, size_t size,
423423
/* high level check about policy management - fine grained in
424424
* below after unpack
425425
*/
426-
error = aa_may_manage_policy(label, ns, mask);
426+
error = aa_may_manage_policy(current_cred(), label, ns, mask);
427427
if (error)
428428
goto end_section;
429429

@@ -486,7 +486,8 @@ static ssize_t profile_remove(struct file *f, const char __user *buf,
486486
/* high level check about policy management - fine grained in
487487
* below after unpack
488488
*/
489-
error = aa_may_manage_policy(label, ns, AA_MAY_REMOVE_POLICY);
489+
error = aa_may_manage_policy(current_cred(), label, ns,
490+
AA_MAY_REMOVE_POLICY);
490491
if (error)
491492
goto out;
492493

@@ -618,23 +619,23 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,
618619

619620
if (profile_unconfined(profile))
620621
return;
621-
if (rules->file.dfa && *match_str == AA_CLASS_FILE) {
622-
state = aa_dfa_match_len(rules->file.dfa,
623-
rules->file.start[AA_CLASS_FILE],
622+
if (rules->file->dfa && *match_str == AA_CLASS_FILE) {
623+
state = aa_dfa_match_len(rules->file->dfa,
624+
rules->file->start[AA_CLASS_FILE],
624625
match_str + 1, match_len - 1);
625626
if (state) {
626627
struct path_cond cond = { };
627628

628-
tmp = *(aa_lookup_fperms(&(rules->file), state, &cond));
629+
tmp = *(aa_lookup_fperms(rules->file, state, &cond));
629630
}
630-
} else if (rules->policy.dfa) {
631+
} else if (rules->policy->dfa) {
631632
if (!RULE_MEDIATES(rules, *match_str))
632633
return; /* no change to current perms */
633-
state = aa_dfa_match_len(rules->policy.dfa,
634-
rules->policy.start[0],
634+
state = aa_dfa_match_len(rules->policy->dfa,
635+
rules->policy->start[0],
635636
match_str, match_len);
636637
if (state)
637-
tmp = *aa_lookup_perms(&rules->policy, state);
638+
tmp = *aa_lookup_perms(rules->policy, state);
638639
}
639640
aa_apply_modes_to_perms(profile, &tmp);
640641
aa_perms_accum_raw(perms, &tmp);
@@ -1095,7 +1096,7 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v)
10951096
struct aa_profile *profile = labels_profile(label);
10961097
if (profile->attach.xmatch_str)
10971098
seq_printf(seq, "%s\n", profile->attach.xmatch_str);
1098-
else if (profile->attach.xmatch.dfa)
1099+
else if (profile->attach.xmatch->dfa)
10991100
seq_puts(seq, "<unknown>\n");
11001101
else
11011102
seq_printf(seq, "%s\n", profile->base.name);
@@ -1314,7 +1315,6 @@ SEQ_RAWDATA_FOPS(compressed_size);
13141315

13151316
static int decompress_zstd(char *src, size_t slen, char *dst, size_t dlen)
13161317
{
1317-
#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY
13181318
if (slen < dlen) {
13191319
const size_t wksp_len = zstd_dctx_workspace_bound();
13201320
zstd_dctx *ctx;
@@ -1341,7 +1341,6 @@ static int decompress_zstd(char *src, size_t slen, char *dst, size_t dlen)
13411341
kvfree(wksp);
13421342
return ret;
13431343
}
1344-
#endif
13451344

13461345
if (dlen < slen)
13471346
return -EINVAL;
@@ -1806,7 +1805,8 @@ static int ns_mkdir_op(struct mnt_idmap *idmap, struct inode *dir,
18061805
int error;
18071806

18081807
label = begin_current_label_crit_section();
1809-
error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY);
1808+
error = aa_may_manage_policy(current_cred(), label, NULL,
1809+
AA_MAY_LOAD_POLICY);
18101810
end_current_label_crit_section(label);
18111811
if (error)
18121812
return error;
@@ -1855,7 +1855,8 @@ static int ns_rmdir_op(struct inode *dir, struct dentry *dentry)
18551855
int error;
18561856

18571857
label = begin_current_label_crit_section();
1858-
error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY);
1858+
error = aa_may_manage_policy(current_cred(), label, NULL,
1859+
AA_MAY_LOAD_POLICY);
18591860
end_current_label_crit_section(label);
18601861
if (error)
18611862
return error;
@@ -2339,10 +2340,16 @@ static struct aa_sfs_entry aa_sfs_entry_domain[] = {
23392340
AA_SFS_FILE_BOOLEAN("post_nnp_subset", 1),
23402341
AA_SFS_FILE_BOOLEAN("computed_longest_left", 1),
23412342
AA_SFS_DIR("attach_conditions", aa_sfs_entry_attach),
2343+
AA_SFS_FILE_BOOLEAN("disconnected.path", 1),
23422344
AA_SFS_FILE_STRING("version", "1.2"),
23432345
{ }
23442346
};
23452347

2348+
static struct aa_sfs_entry aa_sfs_entry_unconfined[] = {
2349+
AA_SFS_FILE_BOOLEAN("change_profile", 1),
2350+
{ }
2351+
};
2352+
23462353
static struct aa_sfs_entry aa_sfs_entry_versions[] = {
23472354
AA_SFS_FILE_BOOLEAN("v5", 1),
23482355
AA_SFS_FILE_BOOLEAN("v6", 1),
@@ -2352,11 +2359,15 @@ static struct aa_sfs_entry aa_sfs_entry_versions[] = {
23522359
{ }
23532360
};
23542361

2362+
#define PERMS32STR "allow deny subtree cond kill complain prompt audit quiet hide xindex tag label"
23552363
static struct aa_sfs_entry aa_sfs_entry_policy[] = {
23562364
AA_SFS_DIR("versions", aa_sfs_entry_versions),
23572365
AA_SFS_FILE_BOOLEAN("set_load", 1),
23582366
/* number of out of band transitions supported */
23592367
AA_SFS_FILE_U64("outofband", MAX_OOB_SUPPORTED),
2368+
AA_SFS_FILE_U64("permstable32_version", 1),
2369+
AA_SFS_FILE_STRING("permstable32", PERMS32STR),
2370+
AA_SFS_DIR("unconfined_restrictions", aa_sfs_entry_unconfined),
23602371
{ }
23612372
};
23622373

@@ -2368,6 +2379,7 @@ static struct aa_sfs_entry aa_sfs_entry_mount[] = {
23682379
static struct aa_sfs_entry aa_sfs_entry_ns[] = {
23692380
AA_SFS_FILE_BOOLEAN("profile", 1),
23702381
AA_SFS_FILE_BOOLEAN("pivot_root", 0),
2382+
AA_SFS_FILE_STRING("mask", "userns_create"),
23712383
{ }
23722384
};
23732385

@@ -2382,6 +2394,12 @@ static struct aa_sfs_entry aa_sfs_entry_query[] = {
23822394
AA_SFS_DIR("label", aa_sfs_entry_query_label),
23832395
{ }
23842396
};
2397+
2398+
static struct aa_sfs_entry aa_sfs_entry_io_uring[] = {
2399+
AA_SFS_FILE_STRING("mask", "sqpoll override_creds"),
2400+
{ }
2401+
};
2402+
23852403
static struct aa_sfs_entry aa_sfs_entry_features[] = {
23862404
AA_SFS_DIR("policy", aa_sfs_entry_policy),
23872405
AA_SFS_DIR("domain", aa_sfs_entry_domain),
@@ -2395,6 +2413,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
23952413
AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace),
23962414
AA_SFS_DIR("signal", aa_sfs_entry_signal),
23972415
AA_SFS_DIR("query", aa_sfs_entry_query),
2416+
AA_SFS_DIR("io_uring", aa_sfs_entry_io_uring),
23982417
{ }
23992418
};
24002419

security/apparmor/audit.c

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ static const char *const aa_class_names[] = {
5858
"io_uring",
5959
"module",
6060
"lsm",
61-
"unknown",
62-
"unknown",
61+
"namespace",
62+
"io_uring",
6363
"unknown",
6464
"unknown",
6565
"unknown",
@@ -85,37 +85,36 @@ static const char *const aa_class_names[] = {
8585
/**
8686
* audit_pre() - core AppArmor function.
8787
* @ab: audit buffer to fill (NOT NULL)
88-
* @ca: audit structure containing data to audit (NOT NULL)
88+
* @va: audit structure containing data to audit (NOT NULL)
8989
*
90-
* Record common AppArmor audit data from @sa
90+
* Record common AppArmor audit data from @va
9191
*/
92-
static void audit_pre(struct audit_buffer *ab, void *ca)
92+
static void audit_pre(struct audit_buffer *ab, void *va)
9393
{
94-
struct common_audit_data *sa = ca;
94+
struct apparmor_audit_data *ad = aad_of_va(va);
9595

9696
if (aa_g_audit_header) {
9797
audit_log_format(ab, "apparmor=\"%s\"",
98-
aa_audit_type[aad(sa)->type]);
98+
aa_audit_type[ad->type]);
9999
}
100100

101-
if (aad(sa)->op) {
102-
audit_log_format(ab, " operation=\"%s\"", aad(sa)->op);
103-
}
101+
if (ad->op)
102+
audit_log_format(ab, " operation=\"%s\"", ad->op);
104103

105-
if (aad(sa)->class)
104+
if (ad->class)
106105
audit_log_format(ab, " class=\"%s\"",
107-
aad(sa)->class <= AA_CLASS_LAST ?
108-
aa_class_names[aad(sa)->class] :
106+
ad->class <= AA_CLASS_LAST ?
107+
aa_class_names[ad->class] :
109108
"unknown");
110109

111-
if (aad(sa)->info) {
112-
audit_log_format(ab, " info=\"%s\"", aad(sa)->info);
113-
if (aad(sa)->error)
114-
audit_log_format(ab, " error=%d", aad(sa)->error);
110+
if (ad->info) {
111+
audit_log_format(ab, " info=\"%s\"", ad->info);
112+
if (ad->error)
113+
audit_log_format(ab, " error=%d", ad->error);
115114
}
116115

117-
if (aad(sa)->label) {
118-
struct aa_label *label = aad(sa)->label;
116+
if (ad->subj_label) {
117+
struct aa_label *label = ad->subj_label;
119118

120119
if (label_isprofile(label)) {
121120
struct aa_profile *profile = labels_profile(label);
@@ -134,42 +133,44 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
134133
}
135134
}
136135

137-
if (aad(sa)->name) {
136+
if (ad->name) {
138137
audit_log_format(ab, " name=");
139-
audit_log_untrustedstring(ab, aad(sa)->name);
138+
audit_log_untrustedstring(ab, ad->name);
140139
}
141140
}
142141

143142
/**
144143
* aa_audit_msg - Log a message to the audit subsystem
145-
* @sa: audit event structure (NOT NULL)
144+
* @type: audit type for the message
145+
* @ad: audit event structure (NOT NULL)
146146
* @cb: optional callback fn for type specific fields (MAYBE NULL)
147147
*/
148-
void aa_audit_msg(int type, struct common_audit_data *sa,
148+
void aa_audit_msg(int type, struct apparmor_audit_data *ad,
149149
void (*cb) (struct audit_buffer *, void *))
150150
{
151-
aad(sa)->type = type;
152-
common_lsm_audit(sa, audit_pre, cb);
151+
ad->type = type;
152+
common_lsm_audit(&ad->common, audit_pre, cb);
153153
}
154154

155155
/**
156156
* aa_audit - Log a profile based audit event to the audit subsystem
157157
* @type: audit type for the message
158158
* @profile: profile to check against (NOT NULL)
159-
* @sa: audit event (NOT NULL)
159+
* @ad: audit event (NOT NULL)
160160
* @cb: optional callback fn for type specific fields (MAYBE NULL)
161161
*
162162
* Handle default message switching based off of audit mode flags
163163
*
164164
* Returns: error on failure
165165
*/
166-
int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
166+
int aa_audit(int type, struct aa_profile *profile,
167+
struct apparmor_audit_data *ad,
167168
void (*cb) (struct audit_buffer *, void *))
168169
{
169170
AA_BUG(!profile);
170171

171172
if (type == AUDIT_APPARMOR_AUTO) {
172-
if (likely(!aad(sa)->error)) {
173+
if (likely(!ad->error)) {
173174
if (AUDIT_MODE(profile) != AUDIT_ALL)
174175
return 0;
175176
type = AUDIT_APPARMOR_AUDIT;
@@ -181,24 +182,24 @@ int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
181182
if (AUDIT_MODE(profile) == AUDIT_QUIET ||
182183
(type == AUDIT_APPARMOR_DENIED &&
183184
AUDIT_MODE(profile) == AUDIT_QUIET_DENIED))
184-
return aad(sa)->error;
185+
return ad->error;
185186

186187
if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
187188
type = AUDIT_APPARMOR_KILL;
188189

189-
aad(sa)->label = &profile->label;
190+
ad->subj_label = &profile->label;
190191

191-
aa_audit_msg(type, sa, cb);
192+
aa_audit_msg(type, ad, cb);
192193

193-
if (aad(sa)->type == AUDIT_APPARMOR_KILL)
194+
if (ad->type == AUDIT_APPARMOR_KILL)
194195
(void)send_sig_info(SIGKILL, NULL,
195-
sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ?
196-
sa->u.tsk : current);
196+
ad->common.type == LSM_AUDIT_DATA_TASK &&
197+
ad->common.u.tsk ? ad->common.u.tsk : current);
197198

198-
if (aad(sa)->type == AUDIT_APPARMOR_ALLOWED)
199-
return complain_error(aad(sa)->error);
199+
if (ad->type == AUDIT_APPARMOR_ALLOWED)
200+
return complain_error(ad->error);
200201

201-
return aad(sa)->error;
202+
return ad->error;
202203
}
203204

204205
struct aa_audit_rule {

0 commit comments

Comments
 (0)