Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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
...

+1333 -845
+34 -15
security/apparmor/apparmorfs.c
··· 423 423 /* high level check about policy management - fine grained in 424 424 * below after unpack 425 425 */ 426 - error = aa_may_manage_policy(label, ns, mask); 426 + error = aa_may_manage_policy(current_cred(), label, ns, mask); 427 427 if (error) 428 428 goto end_section; 429 429 ··· 486 486 /* high level check about policy management - fine grained in 487 487 * below after unpack 488 488 */ 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); 490 491 if (error) 491 492 goto out; 492 493 ··· 619 618 620 619 if (profile_unconfined(profile)) 621 620 return; 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], 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], 625 624 match_str + 1, match_len - 1); 626 625 if (state) { 627 626 struct path_cond cond = { }; 628 627 629 - tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); 628 + tmp = *(aa_lookup_fperms(rules->file, state, &cond)); 630 629 } 631 - } else if (rules->policy.dfa) { 630 + } else if (rules->policy->dfa) { 632 631 if (!RULE_MEDIATES(rules, *match_str)) 633 632 return; /* no change to current perms */ 634 - state = aa_dfa_match_len(rules->policy.dfa, 635 - rules->policy.start[0], 633 + state = aa_dfa_match_len(rules->policy->dfa, 634 + rules->policy->start[0], 636 635 match_str, match_len); 637 636 if (state) 638 - tmp = *aa_lookup_perms(&rules->policy, state); 637 + tmp = *aa_lookup_perms(rules->policy, state); 639 638 } 640 639 aa_apply_modes_to_perms(profile, &tmp); 641 640 aa_perms_accum_raw(perms, &tmp); ··· 1096 1095 struct aa_profile *profile = labels_profile(label); 1097 1096 if (profile->attach.xmatch_str) 1098 1097 seq_printf(seq, "%s\n", profile->attach.xmatch_str); 1099 - else if (profile->attach.xmatch.dfa) 1098 + else if (profile->attach.xmatch->dfa) 1100 1099 seq_puts(seq, "<unknown>\n"); 1101 1100 else 1102 1101 seq_printf(seq, "%s\n", profile->base.name); ··· 1315 1314 1316 1315 static int decompress_zstd(char *src, size_t slen, char *dst, size_t dlen) 1317 1316 { 1318 - #ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY 1319 1317 if (slen < dlen) { 1320 1318 const size_t wksp_len = zstd_dctx_workspace_bound(); 1321 1319 zstd_dctx *ctx; ··· 1341 1341 kvfree(wksp); 1342 1342 return ret; 1343 1343 } 1344 - #endif 1345 1344 1346 1345 if (dlen < slen) 1347 1346 return -EINVAL; ··· 1805 1806 int error; 1806 1807 1807 1808 label = begin_current_label_crit_section(); 1808 - error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY); 1809 + error = aa_may_manage_policy(current_cred(), label, NULL, 1810 + AA_MAY_LOAD_POLICY); 1809 1811 end_current_label_crit_section(label); 1810 1812 if (error) 1811 1813 return error; ··· 1855 1855 int error; 1856 1856 1857 1857 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); 1859 1860 end_current_label_crit_section(label); 1860 1861 if (error) 1861 1862 return error; ··· 2340 2339 AA_SFS_FILE_BOOLEAN("post_nnp_subset", 1), 2341 2340 AA_SFS_FILE_BOOLEAN("computed_longest_left", 1), 2342 2341 AA_SFS_DIR("attach_conditions", aa_sfs_entry_attach), 2342 + AA_SFS_FILE_BOOLEAN("disconnected.path", 1), 2343 2343 AA_SFS_FILE_STRING("version", "1.2"), 2344 + { } 2345 + }; 2346 + 2347 + static struct aa_sfs_entry aa_sfs_entry_unconfined[] = { 2348 + AA_SFS_FILE_BOOLEAN("change_profile", 1), 2344 2349 { } 2345 2350 }; 2346 2351 ··· 2359 2352 { } 2360 2353 }; 2361 2354 2355 + #define PERMS32STR "allow deny subtree cond kill complain prompt audit quiet hide xindex tag label" 2362 2356 static struct aa_sfs_entry aa_sfs_entry_policy[] = { 2363 2357 AA_SFS_DIR("versions", aa_sfs_entry_versions), 2364 2358 AA_SFS_FILE_BOOLEAN("set_load", 1), 2365 2359 /* number of out of band transitions supported */ 2366 2360 AA_SFS_FILE_U64("outofband", MAX_OOB_SUPPORTED), 2361 + AA_SFS_FILE_U64("permstable32_version", 1), 2362 + AA_SFS_FILE_STRING("permstable32", PERMS32STR), 2363 + AA_SFS_DIR("unconfined_restrictions", aa_sfs_entry_unconfined), 2367 2364 { } 2368 2365 }; 2369 2366 ··· 2379 2368 static struct aa_sfs_entry aa_sfs_entry_ns[] = { 2380 2369 AA_SFS_FILE_BOOLEAN("profile", 1), 2381 2370 AA_SFS_FILE_BOOLEAN("pivot_root", 0), 2371 + AA_SFS_FILE_STRING("mask", "userns_create"), 2382 2372 { } 2383 2373 }; 2384 2374 ··· 2394 2382 AA_SFS_DIR("label", aa_sfs_entry_query_label), 2395 2383 { } 2396 2384 }; 2385 + 2386 + static struct aa_sfs_entry aa_sfs_entry_io_uring[] = { 2387 + AA_SFS_FILE_STRING("mask", "sqpoll override_creds"), 2388 + { } 2389 + }; 2390 + 2397 2391 static struct aa_sfs_entry aa_sfs_entry_features[] = { 2398 2392 AA_SFS_DIR("policy", aa_sfs_entry_policy), 2399 2393 AA_SFS_DIR("domain", aa_sfs_entry_domain), ··· 2413 2395 AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace), 2414 2396 AA_SFS_DIR("signal", aa_sfs_entry_signal), 2415 2397 AA_SFS_DIR("query", aa_sfs_entry_query), 2398 + AA_SFS_DIR("io_uring", aa_sfs_entry_io_uring), 2416 2399 { } 2417 2400 }; 2418 2401
+38 -37
security/apparmor/audit.c
··· 58 58 "io_uring", 59 59 "module", 60 60 "lsm", 61 - "unknown", 62 - "unknown", 61 + "namespace", 62 + "io_uring", 63 63 "unknown", 64 64 "unknown", 65 65 "unknown", ··· 85 85 /** 86 86 * audit_pre() - core AppArmor function. 87 87 * @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) 89 89 * 90 - * Record common AppArmor audit data from @sa 90 + * Record common AppArmor audit data from @va 91 91 */ 92 - static void audit_pre(struct audit_buffer *ab, void *ca) 92 + static void audit_pre(struct audit_buffer *ab, void *va) 93 93 { 94 - struct common_audit_data *sa = ca; 94 + struct apparmor_audit_data *ad = aad_of_va(va); 95 95 96 96 if (aa_g_audit_header) { 97 97 audit_log_format(ab, "apparmor=\"%s\"", 98 - aa_audit_type[aad(sa)->type]); 98 + aa_audit_type[ad->type]); 99 99 } 100 100 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); 104 103 105 - if (aad(sa)->class) 104 + if (ad->class) 106 105 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] : 109 108 "unknown"); 110 109 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); 115 114 } 116 115 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; 119 118 120 119 if (label_isprofile(label)) { 121 120 struct aa_profile *profile = labels_profile(label); ··· 133 134 } 134 135 } 135 136 136 - if (aad(sa)->name) { 137 + if (ad->name) { 137 138 audit_log_format(ab, " name="); 138 - audit_log_untrustedstring(ab, aad(sa)->name); 139 + audit_log_untrustedstring(ab, ad->name); 139 140 } 140 141 } 141 142 142 143 /** 143 144 * aa_audit_msg - Log a message to the audit subsystem 144 - * @sa: audit event structure (NOT NULL) 145 + * @type: audit type for the message 146 + * @ad: audit event structure (NOT NULL) 145 147 * @cb: optional callback fn for type specific fields (MAYBE NULL) 146 148 */ 147 - void aa_audit_msg(int type, struct common_audit_data *sa, 149 + void aa_audit_msg(int type, struct apparmor_audit_data *ad, 148 150 void (*cb) (struct audit_buffer *, void *)) 149 151 { 150 - aad(sa)->type = type; 151 - common_lsm_audit(sa, audit_pre, cb); 152 + ad->type = type; 153 + common_lsm_audit(&ad->common, audit_pre, cb); 152 154 } 153 155 154 156 /** 155 157 * aa_audit - Log a profile based audit event to the audit subsystem 156 158 * @type: audit type for the message 157 159 * @profile: profile to check against (NOT NULL) 158 - * @sa: audit event (NOT NULL) 160 + * @ad: audit event (NOT NULL) 159 161 * @cb: optional callback fn for type specific fields (MAYBE NULL) 160 162 * 161 163 * Handle default message switching based off of audit mode flags 162 164 * 163 165 * Returns: error on failure 164 166 */ 165 - int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa, 167 + int aa_audit(int type, struct aa_profile *profile, 168 + struct apparmor_audit_data *ad, 166 169 void (*cb) (struct audit_buffer *, void *)) 167 170 { 168 171 AA_BUG(!profile); 169 172 170 173 if (type == AUDIT_APPARMOR_AUTO) { 171 - if (likely(!aad(sa)->error)) { 174 + if (likely(!ad->error)) { 172 175 if (AUDIT_MODE(profile) != AUDIT_ALL) 173 176 return 0; 174 177 type = AUDIT_APPARMOR_AUDIT; ··· 182 181 if (AUDIT_MODE(profile) == AUDIT_QUIET || 183 182 (type == AUDIT_APPARMOR_DENIED && 184 183 AUDIT_MODE(profile) == AUDIT_QUIET_DENIED)) 185 - return aad(sa)->error; 184 + return ad->error; 186 185 187 186 if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) 188 187 type = AUDIT_APPARMOR_KILL; 189 188 190 - aad(sa)->label = &profile->label; 189 + ad->subj_label = &profile->label; 191 190 192 - aa_audit_msg(type, sa, cb); 191 + aa_audit_msg(type, ad, cb); 193 192 194 - if (aad(sa)->type == AUDIT_APPARMOR_KILL) 193 + if (ad->type == AUDIT_APPARMOR_KILL) 195 194 (void)send_sig_info(SIGKILL, NULL, 196 - sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ? 197 - sa->u.tsk : current); 195 + ad->common.type == LSM_AUDIT_DATA_TASK && 196 + ad->common.u.tsk ? ad->common.u.tsk : current); 198 197 199 - if (aad(sa)->type == AUDIT_APPARMOR_ALLOWED) 200 - return complain_error(aad(sa)->error); 198 + if (ad->type == AUDIT_APPARMOR_ALLOWED) 199 + return complain_error(ad->error); 201 200 202 - return aad(sa)->error; 201 + return ad->error; 203 202 } 204 203 205 204 struct aa_audit_rule {
+18 -15
security/apparmor/capability.c
··· 38 38 39 39 /** 40 40 * audit_cb - call back for capability components of audit struct 41 - * @ab - audit buffer (NOT NULL) 42 - * @va - audit struct to audit data from (NOT NULL) 41 + * @ab: audit buffer (NOT NULL) 42 + * @va: audit struct to audit data from (NOT NULL) 43 43 */ 44 44 static void audit_cb(struct audit_buffer *ab, void *va) 45 45 { ··· 51 51 52 52 /** 53 53 * audit_caps - audit a capability 54 - * @sa: audit data 54 + * @ad: audit data 55 55 * @profile: profile being tested for confinement (NOT NULL) 56 56 * @cap: capability tested 57 57 * @error: error code returned by test ··· 59 59 * Do auditing of capability and handle, audit/complain/kill modes switching 60 60 * and duplicate message elimination. 61 61 * 62 - * Returns: 0 or sa->error on success, error code on failure 62 + * Returns: 0 or ad->error on success, error code on failure 63 63 */ 64 - static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, 64 + static int audit_caps(struct apparmor_audit_data *ad, struct aa_profile *profile, 65 65 int cap, int error) 66 66 { 67 67 struct aa_ruleset *rules = list_first_entry(&profile->rules, ··· 69 69 struct audit_cache *ent; 70 70 int type = AUDIT_APPARMOR_AUTO; 71 71 72 - aad(sa)->error = error; 72 + ad->error = error; 73 73 74 74 if (likely(!error)) { 75 75 /* test if auditing is being forced */ ··· 101 101 } 102 102 put_cpu_var(audit_cache); 103 103 104 - return aa_audit(type, profile, sa, audit_cb); 104 + return aa_audit(type, profile, ad, audit_cb); 105 105 } 106 106 107 107 /** ··· 109 109 * @profile: profile being enforced (NOT NULL, NOT unconfined) 110 110 * @cap: capability to test if allowed 111 111 * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated 112 - * @sa: audit data (MAY BE NULL indicating no auditing) 112 + * @ad: audit data (MAY BE NULL indicating no auditing) 113 113 * 114 114 * Returns: 0 if allowed else -EPERM 115 115 */ 116 116 static int profile_capable(struct aa_profile *profile, int cap, 117 - unsigned int opts, struct common_audit_data *sa) 117 + unsigned int opts, struct apparmor_audit_data *ad) 118 118 { 119 119 struct aa_ruleset *rules = list_first_entry(&profile->rules, 120 120 typeof(*rules), list); ··· 132 132 /* audit the cap request in complain mode but note that it 133 133 * should be optional. 134 134 */ 135 - aad(sa)->info = "optional: no audit"; 135 + ad->info = "optional: no audit"; 136 136 } 137 137 138 - return audit_caps(sa, profile, cap, error); 138 + return audit_caps(ad, profile, cap, error); 139 139 } 140 140 141 141 /** 142 142 * aa_capable - test permission to use capability 143 + * @subj_cred: cred we are testing capability against 143 144 * @label: label being tested for capability (NOT NULL) 144 145 * @cap: capability to be tested 145 146 * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated ··· 149 148 * 150 149 * Returns: 0 on success, or else an error code. 151 150 */ 152 - int aa_capable(struct aa_label *label, int cap, unsigned int opts) 151 + int aa_capable(const struct cred *subj_cred, struct aa_label *label, 152 + int cap, unsigned int opts) 153 153 { 154 154 struct aa_profile *profile; 155 155 int error = 0; 156 - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, AA_CLASS_CAP, OP_CAPABLE); 156 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_CAP, AA_CLASS_CAP, OP_CAPABLE); 157 157 158 - sa.u.cap = cap; 158 + ad.subj_cred = subj_cred; 159 + ad.common.u.cap = cap; 159 160 error = fn_for_each_confined(label, profile, 160 - profile_capable(profile, cap, opts, &sa)); 161 + profile_capable(profile, cap, opts, &ad)); 161 162 162 163 return error; 163 164 }
+125 -68
security/apparmor/domain.c
··· 31 31 32 32 /** 33 33 * may_change_ptraced_domain - check if can change profile on ptraced task 34 + * @to_cred: cred of task changing domain 34 35 * @to_label: profile to change to (NOT NULL) 35 36 * @info: message if there is an error 36 37 * ··· 40 39 * 41 40 * Returns: %0 or error if change not allowed 42 41 */ 43 - static int may_change_ptraced_domain(struct aa_label *to_label, 42 + static int may_change_ptraced_domain(const struct cred *to_cred, 43 + struct aa_label *to_label, 44 44 const char **info) 45 45 { 46 46 struct task_struct *tracer; 47 47 struct aa_label *tracerl = NULL; 48 + const struct cred *tracer_cred = NULL; 49 + 48 50 int error = 0; 49 51 50 52 rcu_read_lock(); 51 53 tracer = ptrace_parent(current); 52 - if (tracer) 54 + if (tracer) { 53 55 /* released below */ 54 56 tracerl = aa_get_task_label(tracer); 55 - 57 + tracer_cred = get_task_cred(tracer); 58 + } 56 59 /* not ptraced */ 57 60 if (!tracer || unconfined(tracerl)) 58 61 goto out; 59 62 60 - error = aa_may_ptrace(tracerl, to_label, PTRACE_MODE_ATTACH); 63 + error = aa_may_ptrace(tracer_cred, tracerl, to_cred, to_label, 64 + PTRACE_MODE_ATTACH); 61 65 62 66 out: 63 67 rcu_read_unlock(); 64 68 aa_put_label(tracerl); 69 + put_cred(tracer_cred); 65 70 66 71 if (error) 67 72 *info = "ptrace prevents transition"; ··· 77 70 /**** TODO: dedup to aa_label_match - needs perm and dfa, merging 78 71 * specifically this is an exact copy of aa_label_match except 79 72 * aa_compute_perms is replaced with aa_compute_fperms 80 - * and policy.dfa with file.dfa 73 + * and policy->dfa with file->dfa 81 74 ****/ 82 75 /* match a profile and its associated ns component if needed 83 76 * Assumes visibility test has already been done. ··· 93 86 const char *ns_name; 94 87 95 88 if (stack) 96 - state = aa_dfa_match(rules->file.dfa, state, "&"); 89 + state = aa_dfa_match(rules->file->dfa, state, "&"); 97 90 if (profile->ns == tp->ns) 98 - return aa_dfa_match(rules->file.dfa, state, tp->base.hname); 91 + return aa_dfa_match(rules->file->dfa, state, tp->base.hname); 99 92 100 93 /* try matching with namespace name and then profile */ 101 94 ns_name = aa_ns_name(profile->ns, tp->ns, true); 102 - state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); 103 - state = aa_dfa_match(rules->file.dfa, state, ns_name); 104 - state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); 105 - return aa_dfa_match(rules->file.dfa, state, tp->base.hname); 95 + state = aa_dfa_match_len(rules->file->dfa, state, ":", 1); 96 + state = aa_dfa_match(rules->file->dfa, state, ns_name); 97 + state = aa_dfa_match_len(rules->file->dfa, state, ":", 1); 98 + return aa_dfa_match(rules->file->dfa, state, tp->base.hname); 106 99 } 107 100 108 101 /** ··· 150 143 label_for_each_cont(i, label, tp) { 151 144 if (!aa_ns_visible(profile->ns, tp->ns, subns)) 152 145 continue; 153 - state = aa_dfa_match(rules->file.dfa, state, "//&"); 146 + state = aa_dfa_match(rules->file->dfa, state, "//&"); 154 147 state = match_component(profile, tp, false, state); 155 148 if (!state) 156 149 goto fail; 157 150 } 158 - *perms = *(aa_lookup_fperms(&(rules->file), state, &cond)); 151 + *perms = *(aa_lookup_fperms(rules->file, state, &cond)); 159 152 aa_apply_modes_to_perms(profile, perms); 160 153 if ((perms->allow & request) != request) 161 154 return -EACCES; ··· 210 203 return 0; 211 204 212 205 next: 213 - tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); 206 + tmp = *(aa_lookup_fperms(rules->file, state, &cond)); 214 207 aa_apply_modes_to_perms(profile, &tmp); 215 208 aa_perms_accum(perms, &tmp); 216 209 label_for_each_cont(i, label, tp) { ··· 219 212 state = match_component(profile, tp, stack, start); 220 213 if (!state) 221 214 goto fail; 222 - tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); 215 + tmp = *(aa_lookup_fperms(rules->file, state, &cond)); 223 216 aa_apply_modes_to_perms(profile, &tmp); 224 217 aa_perms_accum(perms, &tmp); 225 218 } ··· 272 265 * @stack: whether this is a stacking request 273 266 * @request: requested perms 274 267 * @start: state to start matching in 268 + * @perms: Returns computed perms (NOT NULL) 275 269 * 276 270 * 277 271 * Returns: permission set ··· 317 309 might_sleep(); 318 310 319 311 /* transition from exec match to xattr set */ 320 - state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); 312 + state = aa_dfa_outofband_transition(attach->xmatch->dfa, state); 321 313 d = bprm->file->f_path.dentry; 322 314 323 315 for (i = 0; i < attach->xattr_count; i++) { ··· 331 323 * that not present xattr can be distinguished from a 0 332 324 * length value or rule that matches any value 333 325 */ 334 - state = aa_dfa_null_transition(attach->xmatch.dfa, 326 + state = aa_dfa_null_transition(attach->xmatch->dfa, 335 327 state); 336 328 /* Check xattr value */ 337 - state = aa_dfa_match_len(attach->xmatch.dfa, state, 329 + state = aa_dfa_match_len(attach->xmatch->dfa, state, 338 330 value, size); 339 - index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; 340 - perm = attach->xmatch.perms[index].allow; 331 + index = ACCEPT_TABLE(attach->xmatch->dfa)[state]; 332 + perm = attach->xmatch->perms[index].allow; 341 333 if (!(perm & MAY_EXEC)) { 342 334 ret = -EINVAL; 343 335 goto out; 344 336 } 345 337 } 346 338 /* transition to next element */ 347 - state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); 339 + state = aa_dfa_outofband_transition(attach->xmatch->dfa, state); 348 340 if (size < 0) { 349 341 /* 350 342 * No xattr match, so verify if transition to ··· 367 359 368 360 /** 369 361 * find_attach - do attachment search for unconfined processes 370 - * @bprm - binprm structure of transitioning task 362 + * @bprm: binprm structure of transitioning task 371 363 * @ns: the current namespace (NOT NULL) 372 - * @head - profile list to walk (NOT NULL) 373 - * @name - to match against (NOT NULL) 374 - * @info - info message if there was an error (NOT NULL) 364 + * @head: profile list to walk (NOT NULL) 365 + * @name: to match against (NOT NULL) 366 + * @info: info message if there was an error (NOT NULL) 375 367 * 376 368 * Do a linear search on the profiles in the list. There is a matching 377 369 * preference where an exact match is preferred over a name which uses ··· 413 405 * as another profile, signal a conflict and refuse to 414 406 * match. 415 407 */ 416 - if (attach->xmatch.dfa) { 408 + if (attach->xmatch->dfa) { 417 409 unsigned int count; 418 410 aa_state_t state; 419 411 u32 index, perm; 420 412 421 - state = aa_dfa_leftmatch(attach->xmatch.dfa, 422 - attach->xmatch.start[AA_CLASS_XMATCH], 413 + state = aa_dfa_leftmatch(attach->xmatch->dfa, 414 + attach->xmatch->start[AA_CLASS_XMATCH], 423 415 name, &count); 424 - index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; 425 - perm = attach->xmatch.perms[index].allow; 416 + index = ACCEPT_TABLE(attach->xmatch->dfa)[state]; 417 + perm = attach->xmatch->perms[index].allow; 426 418 /* any accepting state means a valid match. */ 427 419 if (perm & MAY_EXEC) { 428 420 int ret = 0; ··· 525 517 /* TODO: move lookup parsing to unpack time so this is a straight 526 518 * index into the resultant label 527 519 */ 528 - for (*name = rules->file.trans.table[index]; !label && *name; 520 + for (*name = rules->file->trans.table[index]; !label && *name; 529 521 *name = next_name(xtype, *name)) { 530 522 if (xindex & AA_X_CHILD) { 531 523 struct aa_profile *new_profile; ··· 553 545 * @name: name to lookup (NOT NULL) 554 546 * @xindex: index into x transition table 555 547 * @lookupname: returns: name used in lookup if one was specified (NOT NULL) 548 + * @info: info message if there was an error (NOT NULL) 556 549 * 557 550 * find label for a transition index 558 551 * ··· 579 570 break; 580 571 case AA_X_TABLE: 581 572 /* TODO: fix when perm mapping done at unload */ 582 - stack = rules->file.trans.table[xindex & AA_X_INDEX_MASK]; 573 + stack = rules->file->trans.table[xindex & AA_X_INDEX_MASK]; 583 574 if (*stack != '&') { 584 575 /* released by caller */ 585 576 new = x_table_lookup(profile, xindex, lookupname); ··· 628 619 return new; 629 620 } 630 621 631 - static struct aa_label *profile_transition(struct aa_profile *profile, 622 + static struct aa_label *profile_transition(const struct cred *subj_cred, 623 + struct aa_profile *profile, 632 624 const struct linux_binprm *bprm, 633 625 char *buffer, struct path_cond *cond, 634 626 bool *secure_exec) ··· 638 628 typeof(*rules), list); 639 629 struct aa_label *new = NULL; 640 630 const char *info = NULL, *name = NULL, *target = NULL; 641 - aa_state_t state = rules->file.start[AA_CLASS_FILE]; 631 + aa_state_t state = rules->file->start[AA_CLASS_FILE]; 642 632 struct aa_perms perms = {}; 643 633 bool nonewprivs = false; 644 634 int error = 0; ··· 672 662 } 673 663 674 664 /* find exec permissions for name */ 675 - state = aa_str_perms(&(rules->file), state, name, cond, &perms); 665 + state = aa_str_perms(rules->file, state, name, cond, &perms); 676 666 if (perms.allow & MAY_EXEC) { 677 667 /* exec permission determine how to transition */ 678 668 new = x_to_label(profile, bprm, name, perms.xindex, &target, ··· 719 709 } 720 710 721 711 audit: 722 - aa_audit_file(profile, &perms, OP_EXEC, MAY_EXEC, name, target, new, 712 + aa_audit_file(subj_cred, profile, &perms, OP_EXEC, MAY_EXEC, name, 713 + target, new, 723 714 cond->uid, info, error); 724 715 if (!new || nonewprivs) { 725 716 aa_put_label(new); ··· 730 719 return new; 731 720 } 732 721 733 - static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec, 722 + static int profile_onexec(const struct cred *subj_cred, 723 + struct aa_profile *profile, struct aa_label *onexec, 734 724 bool stack, const struct linux_binprm *bprm, 735 725 char *buffer, struct path_cond *cond, 736 726 bool *secure_exec) 737 727 { 738 728 struct aa_ruleset *rules = list_first_entry(&profile->rules, 739 729 typeof(*rules), list); 740 - aa_state_t state = rules->file.start[AA_CLASS_FILE]; 730 + aa_state_t state = rules->file->start[AA_CLASS_FILE]; 741 731 struct aa_perms perms = {}; 742 732 const char *xname = NULL, *info = "change_profile onexec"; 743 733 int error = -EACCES; ··· 771 759 } 772 760 773 761 /* find exec permissions for name */ 774 - state = aa_str_perms(&(rules->file), state, xname, cond, &perms); 762 + state = aa_str_perms(rules->file, state, xname, cond, &perms); 775 763 if (!(perms.allow & AA_MAY_ONEXEC)) { 776 764 info = "no change_onexec valid for executable"; 777 765 goto audit; ··· 780 768 * onexec permission is linked to exec with a standard pairing 781 769 * exec\0change_profile 782 770 */ 783 - state = aa_dfa_null_transition(rules->file.dfa, state); 771 + state = aa_dfa_null_transition(rules->file->dfa, state); 784 772 error = change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC, 785 773 state, &perms); 786 774 if (error) { ··· 799 787 } 800 788 801 789 audit: 802 - return aa_audit_file(profile, &perms, OP_EXEC, AA_MAY_ONEXEC, xname, 790 + return aa_audit_file(subj_cred, profile, &perms, OP_EXEC, 791 + AA_MAY_ONEXEC, xname, 803 792 NULL, onexec, cond->uid, info, error); 804 793 } 805 794 806 795 /* ensure none ns domain transitions are correctly applied with onexec */ 807 796 808 - static struct aa_label *handle_onexec(struct aa_label *label, 797 + static struct aa_label *handle_onexec(const struct cred *subj_cred, 798 + struct aa_label *label, 809 799 struct aa_label *onexec, bool stack, 810 800 const struct linux_binprm *bprm, 811 801 char *buffer, struct path_cond *cond, ··· 824 810 825 811 if (!stack) { 826 812 error = fn_for_each_in_ns(label, profile, 827 - profile_onexec(profile, onexec, stack, 813 + profile_onexec(subj_cred, profile, onexec, stack, 828 814 bprm, buffer, cond, unsafe)); 829 815 if (error) 830 816 return ERR_PTR(error); 831 817 new = fn_label_build_in_ns(label, profile, GFP_KERNEL, 832 818 aa_get_newest_label(onexec), 833 - profile_transition(profile, bprm, buffer, 819 + profile_transition(subj_cred, profile, bprm, 820 + buffer, 834 821 cond, unsafe)); 835 822 836 823 } else { 837 824 /* TODO: determine how much we want to loosen this */ 838 825 error = fn_for_each_in_ns(label, profile, 839 - profile_onexec(profile, onexec, stack, bprm, 826 + profile_onexec(subj_cred, profile, onexec, stack, bprm, 840 827 buffer, cond, unsafe)); 841 828 if (error) 842 829 return ERR_PTR(error); 843 830 new = fn_label_build_in_ns(label, profile, GFP_KERNEL, 844 831 aa_label_merge(&profile->label, onexec, 845 832 GFP_KERNEL), 846 - profile_transition(profile, bprm, buffer, 833 + profile_transition(subj_cred, profile, bprm, 834 + buffer, 847 835 cond, unsafe)); 848 836 } 849 837 ··· 854 838 855 839 /* TODO: get rid of GLOBAL_ROOT_UID */ 856 840 error = fn_for_each_in_ns(label, profile, 857 - aa_audit_file(profile, &nullperms, OP_CHANGE_ONEXEC, 841 + aa_audit_file(subj_cred, profile, &nullperms, 842 + OP_CHANGE_ONEXEC, 858 843 AA_MAY_ONEXEC, bprm->filename, NULL, 859 844 onexec, GLOBAL_ROOT_UID, 860 845 "failed to build target label", -ENOMEM)); ··· 874 857 { 875 858 struct aa_task_ctx *ctx; 876 859 struct aa_label *label, *new = NULL; 860 + const struct cred *subj_cred; 877 861 struct aa_profile *profile; 878 862 char *buffer = NULL; 879 863 const char *info = NULL; ··· 887 869 file_inode(bprm->file)->i_mode 888 870 }; 889 871 872 + subj_cred = current_cred(); 890 873 ctx = task_ctx(current); 891 874 AA_BUG(!cred_label(bprm->cred)); 892 875 AA_BUG(!ctx); ··· 914 895 915 896 /* Test for onexec first as onexec override other x transitions. */ 916 897 if (ctx->onexec) 917 - new = handle_onexec(label, ctx->onexec, ctx->token, 898 + new = handle_onexec(subj_cred, label, ctx->onexec, ctx->token, 918 899 bprm, buffer, &cond, &unsafe); 919 900 else 920 901 new = fn_label_build(label, profile, GFP_KERNEL, 921 - profile_transition(profile, bprm, buffer, 902 + profile_transition(subj_cred, profile, bprm, 903 + buffer, 922 904 &cond, &unsafe)); 923 905 924 906 AA_BUG(!new); ··· 954 934 955 935 if (bprm->unsafe & (LSM_UNSAFE_PTRACE)) { 956 936 /* TODO: test needs to be profile of label to new */ 957 - error = may_change_ptraced_domain(new, &info); 937 + error = may_change_ptraced_domain(bprm->cred, new, &info); 958 938 if (error) 959 939 goto audit; 960 940 } ··· 991 971 992 972 audit: 993 973 error = fn_for_each(label, profile, 994 - aa_audit_file(profile, &nullperms, OP_EXEC, MAY_EXEC, 974 + aa_audit_file(current_cred(), profile, &nullperms, 975 + OP_EXEC, MAY_EXEC, 995 976 bprm->filename, NULL, new, 996 977 vfsuid_into_kuid(vfsuid), info, error)); 997 978 aa_put_label(new); ··· 1008 987 * 1009 988 * Returns: label for hat transition OR ERR_PTR. Does NOT return NULL 1010 989 */ 1011 - static struct aa_label *build_change_hat(struct aa_profile *profile, 990 + static struct aa_label *build_change_hat(const struct cred *subj_cred, 991 + struct aa_profile *profile, 1012 992 const char *name, bool sibling) 1013 993 { 1014 994 struct aa_profile *root, *hat = NULL; ··· 1041 1019 aa_put_profile(root); 1042 1020 1043 1021 audit: 1044 - aa_audit_file(profile, &nullperms, OP_CHANGE_HAT, AA_MAY_CHANGEHAT, 1022 + aa_audit_file(subj_cred, profile, &nullperms, OP_CHANGE_HAT, 1023 + AA_MAY_CHANGEHAT, 1045 1024 name, hat ? hat->base.hname : NULL, 1046 1025 hat ? &hat->label : NULL, GLOBAL_ROOT_UID, info, 1047 1026 error); ··· 1058 1035 * 1059 1036 * Returns: label for hat transition or ERR_PTR. Does not return NULL 1060 1037 */ 1061 - static struct aa_label *change_hat(struct aa_label *label, const char *hats[], 1038 + static struct aa_label *change_hat(const struct cred *subj_cred, 1039 + struct aa_label *label, const char *hats[], 1062 1040 int count, int flags) 1063 1041 { 1064 1042 struct aa_profile *profile, *root, *hat = NULL; ··· 1135 1111 */ 1136 1112 /* TODO: get rid of GLOBAL_ROOT_UID */ 1137 1113 if (count > 1 || COMPLAIN_MODE(profile)) { 1138 - aa_audit_file(profile, &nullperms, OP_CHANGE_HAT, 1114 + aa_audit_file(subj_cred, profile, &nullperms, 1115 + OP_CHANGE_HAT, 1139 1116 AA_MAY_CHANGEHAT, name, NULL, NULL, 1140 1117 GLOBAL_ROOT_UID, info, error); 1141 1118 } ··· 1145 1120 1146 1121 build: 1147 1122 new = fn_label_build_in_ns(label, profile, GFP_KERNEL, 1148 - build_change_hat(profile, name, sibling), 1123 + build_change_hat(subj_cred, profile, name, 1124 + sibling), 1149 1125 aa_get_label(&profile->label)); 1150 1126 if (!new) { 1151 1127 info = "label build failed"; ··· 1176 1150 */ 1177 1151 int aa_change_hat(const char *hats[], int count, u64 token, int flags) 1178 1152 { 1179 - const struct cred *cred; 1153 + const struct cred *subj_cred; 1180 1154 struct aa_task_ctx *ctx = task_ctx(current); 1181 1155 struct aa_label *label, *previous, *new = NULL, *target = NULL; 1182 1156 struct aa_profile *profile; ··· 1185 1159 int error = 0; 1186 1160 1187 1161 /* released below */ 1188 - cred = get_current_cred(); 1189 - label = aa_get_newest_cred_label(cred); 1162 + subj_cred = get_current_cred(); 1163 + label = aa_get_newest_cred_label(subj_cred); 1190 1164 previous = aa_get_newest_label(ctx->previous); 1191 1165 1192 1166 /* ··· 1206 1180 } 1207 1181 1208 1182 if (count) { 1209 - new = change_hat(label, hats, count, flags); 1183 + new = change_hat(subj_cred, label, hats, count, flags); 1210 1184 AA_BUG(!new); 1211 1185 if (IS_ERR(new)) { 1212 1186 error = PTR_ERR(new); ··· 1215 1189 goto out; 1216 1190 } 1217 1191 1218 - error = may_change_ptraced_domain(new, &info); 1192 + /* target cred is the same as current except new label */ 1193 + error = may_change_ptraced_domain(subj_cred, new, &info); 1219 1194 if (error) 1220 1195 goto fail; 1221 1196 ··· 1269 1242 aa_put_label(new); 1270 1243 aa_put_label(previous); 1271 1244 aa_put_label(label); 1272 - put_cred(cred); 1245 + put_cred(subj_cred); 1273 1246 1274 1247 return error; 1275 1248 ··· 1279 1252 1280 1253 fail: 1281 1254 fn_for_each_in_ns(label, profile, 1282 - aa_audit_file(profile, &perms, OP_CHANGE_HAT, 1255 + aa_audit_file(subj_cred, profile, &perms, OP_CHANGE_HAT, 1283 1256 AA_MAY_CHANGEHAT, NULL, NULL, target, 1284 1257 GLOBAL_ROOT_UID, info, error)); 1285 1258 ··· 1288 1261 1289 1262 1290 1263 static int change_profile_perms_wrapper(const char *op, const char *name, 1264 + const struct cred *subj_cred, 1291 1265 struct aa_profile *profile, 1292 1266 struct aa_label *target, bool stack, 1293 1267 u32 request, struct aa_perms *perms) ··· 1300 1272 1301 1273 if (!error) 1302 1274 error = change_profile_perms(profile, target, stack, request, 1303 - rules->file.start[AA_CLASS_FILE], 1275 + rules->file->start[AA_CLASS_FILE], 1304 1276 perms); 1305 1277 if (error) 1306 - error = aa_audit_file(profile, perms, op, request, name, 1278 + error = aa_audit_file(subj_cred, profile, perms, op, request, 1279 + name, 1307 1280 NULL, target, GLOBAL_ROOT_UID, info, 1308 1281 error); 1309 1282 1310 1283 return error; 1311 1284 } 1285 + 1286 + const char *stack_msg = "change_profile unprivileged unconfined converted to stacking"; 1312 1287 1313 1288 /** 1314 1289 * aa_change_profile - perform a one-way profile transition ··· 1335 1304 const char *auditname = fqname; /* retain leading & if stack */ 1336 1305 bool stack = flags & AA_CHANGE_STACK; 1337 1306 struct aa_task_ctx *ctx = task_ctx(current); 1307 + const struct cred *subj_cred = get_current_cred(); 1338 1308 int error = 0; 1339 1309 char *op; 1340 1310 u32 request; ··· 1370 1338 op = OP_STACK; 1371 1339 else 1372 1340 op = OP_CHANGE_PROFILE; 1341 + } 1342 + 1343 + /* This should move to a per profile test. Requires pushing build 1344 + * into callback 1345 + */ 1346 + if (!stack && unconfined(label) && 1347 + label == &labels_ns(label)->unconfined->label && 1348 + aa_unprivileged_unconfined_restricted && 1349 + /* TODO: refactor so this check is a fn */ 1350 + cap_capable(current_cred(), &init_user_ns, CAP_MAC_OVERRIDE, 1351 + CAP_OPT_NOAUDIT)) { 1352 + /* regardless of the request in this case apparmor 1353 + * stacks against unconfined so admin set policy can't be 1354 + * by-passed 1355 + */ 1356 + stack = true; 1357 + perms.audit = request; 1358 + (void) fn_for_each_in_ns(label, profile, 1359 + aa_audit_file(subj_cred, profile, &perms, op, 1360 + request, auditname, NULL, target, 1361 + GLOBAL_ROOT_UID, stack_msg, 0)); 1362 + perms.audit = 0; 1373 1363 } 1374 1364 1375 1365 if (*fqname == '&') { ··· 1435 1381 */ 1436 1382 error = fn_for_each_in_ns(label, profile, 1437 1383 change_profile_perms_wrapper(op, auditname, 1384 + subj_cred, 1438 1385 profile, target, stack, 1439 1386 request, &perms)); 1440 1387 if (error) ··· 1446 1391 1447 1392 check: 1448 1393 /* check if tracing task is allowed to trace target domain */ 1449 - error = may_change_ptraced_domain(target, &info); 1394 + error = may_change_ptraced_domain(subj_cred, target, &info); 1450 1395 if (error && !fn_for_each_in_ns(label, profile, 1451 1396 COMPLAIN_MODE(profile))) 1452 1397 goto audit; ··· 1501 1446 } 1502 1447 1503 1448 /* full transition will be built in exec path */ 1504 - error = aa_set_current_onexec(target, stack); 1449 + aa_set_current_onexec(target, stack); 1505 1450 } 1506 1451 1507 1452 audit: 1508 1453 error = fn_for_each_in_ns(label, profile, 1509 - aa_audit_file(profile, &perms, op, request, auditname, 1454 + aa_audit_file(subj_cred, 1455 + profile, &perms, op, request, auditname, 1510 1456 NULL, new ? new : target, 1511 1457 GLOBAL_ROOT_UID, info, error)); 1512 1458 ··· 1515 1459 aa_put_label(new); 1516 1460 aa_put_label(target); 1517 1461 aa_put_label(label); 1462 + put_cred(subj_cred); 1518 1463 1519 1464 return error; 1520 1465 }
+129 -84
security/apparmor/file.c
··· 44 44 static void file_audit_cb(struct audit_buffer *ab, void *va) 45 45 { 46 46 struct common_audit_data *sa = va; 47 - kuid_t fsuid = current_fsuid(); 47 + struct apparmor_audit_data *ad = aad(sa); 48 + kuid_t fsuid = ad->subj_cred ? ad->subj_cred->fsuid : current_fsuid(); 48 49 char str[10]; 49 50 50 - if (aad(sa)->request & AA_AUDIT_FILE_MASK) { 51 + if (ad->request & AA_AUDIT_FILE_MASK) { 51 52 aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs, 52 - map_mask_to_chr_mask(aad(sa)->request)); 53 + map_mask_to_chr_mask(ad->request)); 53 54 audit_log_format(ab, " requested_mask=\"%s\"", str); 54 55 } 55 - if (aad(sa)->denied & AA_AUDIT_FILE_MASK) { 56 + if (ad->denied & AA_AUDIT_FILE_MASK) { 56 57 aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs, 57 - map_mask_to_chr_mask(aad(sa)->denied)); 58 + map_mask_to_chr_mask(ad->denied)); 58 59 audit_log_format(ab, " denied_mask=\"%s\"", str); 59 60 } 60 - if (aad(sa)->request & AA_AUDIT_FILE_MASK) { 61 + if (ad->request & AA_AUDIT_FILE_MASK) { 61 62 audit_log_format(ab, " fsuid=%d", 62 63 from_kuid(&init_user_ns, fsuid)); 63 64 audit_log_format(ab, " ouid=%d", 64 - from_kuid(&init_user_ns, aad(sa)->fs.ouid)); 65 + from_kuid(&init_user_ns, ad->fs.ouid)); 65 66 } 66 67 67 - if (aad(sa)->peer) { 68 + if (ad->peer) { 68 69 audit_log_format(ab, " target="); 69 - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 70 + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, 70 71 FLAG_VIEW_SUBNS, GFP_KERNEL); 71 - } else if (aad(sa)->fs.target) { 72 + } else if (ad->fs.target) { 72 73 audit_log_format(ab, " target="); 73 - audit_log_untrustedstring(ab, aad(sa)->fs.target); 74 + audit_log_untrustedstring(ab, ad->fs.target); 74 75 } 75 76 } 76 77 77 78 /** 78 79 * aa_audit_file - handle the auditing of file operations 80 + * @subj_cred: cred of the subject 79 81 * @profile: the profile being enforced (NOT NULL) 80 82 * @perms: the permissions computed for the request (NOT NULL) 81 83 * @op: operation being mediated ··· 91 89 * 92 90 * Returns: %0 or error on failure 93 91 */ 94 - int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, 92 + int aa_audit_file(const struct cred *subj_cred, 93 + struct aa_profile *profile, struct aa_perms *perms, 95 94 const char *op, u32 request, const char *name, 96 95 const char *target, struct aa_label *tlabel, 97 96 kuid_t ouid, const char *info, int error) 98 97 { 99 98 int type = AUDIT_APPARMOR_AUTO; 100 - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, AA_CLASS_FILE, op); 99 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_TASK, AA_CLASS_FILE, op); 101 100 102 - sa.u.tsk = NULL; 103 - aad(&sa)->request = request; 104 - aad(&sa)->name = name; 105 - aad(&sa)->fs.target = target; 106 - aad(&sa)->peer = tlabel; 107 - aad(&sa)->fs.ouid = ouid; 108 - aad(&sa)->info = info; 109 - aad(&sa)->error = error; 110 - sa.u.tsk = NULL; 101 + ad.subj_cred = subj_cred; 102 + ad.request = request; 103 + ad.name = name; 104 + ad.fs.target = target; 105 + ad.peer = tlabel; 106 + ad.fs.ouid = ouid; 107 + ad.info = info; 108 + ad.error = error; 109 + ad.common.u.tsk = NULL; 111 110 112 - if (likely(!aad(&sa)->error)) { 111 + if (likely(!ad.error)) { 113 112 u32 mask = perms->audit; 114 113 115 114 if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL)) 116 115 mask = 0xffff; 117 116 118 117 /* mask off perms that are not being force audited */ 119 - aad(&sa)->request &= mask; 118 + ad.request &= mask; 120 119 121 - if (likely(!aad(&sa)->request)) 120 + if (likely(!ad.request)) 122 121 return 0; 123 122 type = AUDIT_APPARMOR_AUDIT; 124 123 } else { 125 124 /* only report permissions that were denied */ 126 - aad(&sa)->request = aad(&sa)->request & ~perms->allow; 127 - AA_BUG(!aad(&sa)->request); 125 + ad.request = ad.request & ~perms->allow; 126 + AA_BUG(!ad.request); 128 127 129 - if (aad(&sa)->request & perms->kill) 128 + if (ad.request & perms->kill) 130 129 type = AUDIT_APPARMOR_KILL; 131 130 132 131 /* quiet known rejects, assumes quiet and kill do not overlap */ 133 - if ((aad(&sa)->request & perms->quiet) && 132 + if ((ad.request & perms->quiet) && 134 133 AUDIT_MODE(profile) != AUDIT_NOQUIET && 135 134 AUDIT_MODE(profile) != AUDIT_ALL) 136 - aad(&sa)->request &= ~perms->quiet; 135 + ad.request &= ~perms->quiet; 137 136 138 - if (!aad(&sa)->request) 139 - return aad(&sa)->error; 137 + if (!ad.request) 138 + return ad.error; 140 139 } 141 140 142 - aad(&sa)->denied = aad(&sa)->request & ~perms->allow; 143 - return aa_audit(type, profile, &sa, file_audit_cb); 141 + ad.denied = ad.request & ~perms->allow; 142 + return aa_audit(type, profile, &ad, file_audit_cb); 144 143 } 145 144 146 - static int path_name(const char *op, struct aa_label *label, 145 + /** 146 + * is_deleted - test if a file has been completely unlinked 147 + * @dentry: dentry of file to test for deletion (NOT NULL) 148 + * 149 + * Returns: true if deleted else false 150 + */ 151 + static inline bool is_deleted(struct dentry *dentry) 152 + { 153 + if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0) 154 + return true; 155 + return false; 156 + } 157 + 158 + static int path_name(const char *op, const struct cred *subj_cred, 159 + struct aa_label *label, 147 160 const struct path *path, int flags, char *buffer, 148 161 const char **name, struct path_cond *cond, u32 request) 149 162 { ··· 170 153 labels_profile(label)->disconnected); 171 154 if (error) { 172 155 fn_for_each_confined(label, profile, 173 - aa_audit_file(profile, &nullperms, op, request, *name, 156 + aa_audit_file(subj_cred, 157 + profile, &nullperms, op, request, *name, 174 158 NULL, NULL, cond->uid, info, error)); 175 159 return error; 176 160 } ··· 182 164 struct aa_perms default_perms = {}; 183 165 /** 184 166 * aa_lookup_fperms - convert dfa compressed perms to internal perms 185 - * @dfa: dfa to lookup perms for (NOT NULL) 167 + * @file_rules: the aa_policydb to lookup perms for (NOT NULL) 186 168 * @state: state in dfa 187 169 * @cond: conditions to consider (NOT NULL) 188 170 * ··· 206 188 207 189 /** 208 190 * aa_str_perms - find permission that match @name 209 - * @dfa: to match against (MAYBE NULL) 210 - * @state: state to start matching in 191 + * @file_rules: the aa_policydb to match against (NOT NULL) 192 + * @start: state to start matching in 211 193 * @name: string to match against dfa (NOT NULL) 212 194 * @cond: conditions to consider for permission set computation (NOT NULL) 213 195 * @perms: Returns - the permissions found when matching @name ··· 225 207 return state; 226 208 } 227 209 228 - static int __aa_path_perm(const char *op, struct aa_profile *profile, 229 - const char *name, u32 request, 230 - struct path_cond *cond, int flags, 210 + static int __aa_path_perm(const char *op, const struct cred *subj_cred, 211 + struct aa_profile *profile, const char *name, 212 + u32 request, struct path_cond *cond, int flags, 231 213 struct aa_perms *perms) 232 214 { 233 215 struct aa_ruleset *rules = list_first_entry(&profile->rules, ··· 236 218 237 219 if (profile_unconfined(profile)) 238 220 return 0; 239 - aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], 221 + aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE], 240 222 name, cond, perms); 241 223 if (request & ~perms->allow) 242 224 e = -EACCES; 243 - return aa_audit_file(profile, perms, op, request, name, NULL, NULL, 225 + return aa_audit_file(subj_cred, 226 + profile, perms, op, request, name, NULL, NULL, 244 227 cond->uid, NULL, e); 245 228 } 246 229 247 230 248 - static int profile_path_perm(const char *op, struct aa_profile *profile, 231 + static int profile_path_perm(const char *op, const struct cred *subj_cred, 232 + struct aa_profile *profile, 249 233 const struct path *path, char *buffer, u32 request, 250 234 struct path_cond *cond, int flags, 251 235 struct aa_perms *perms) ··· 258 238 if (profile_unconfined(profile)) 259 239 return 0; 260 240 261 - error = path_name(op, &profile->label, path, 241 + error = path_name(op, subj_cred, &profile->label, path, 262 242 flags | profile->path_flags, buffer, &name, cond, 263 243 request); 264 244 if (error) 265 245 return error; 266 - return __aa_path_perm(op, profile, name, request, cond, flags, 267 - perms); 246 + return __aa_path_perm(op, subj_cred, profile, name, request, cond, 247 + flags, perms); 268 248 } 269 249 270 250 /** 271 251 * aa_path_perm - do permissions check & audit for @path 272 252 * @op: operation being checked 253 + * @subj_cred: subject cred 273 254 * @label: profile being enforced (NOT NULL) 274 255 * @path: path to check permissions of (NOT NULL) 275 256 * @flags: any additional path flags beyond what the profile specifies ··· 279 258 * 280 259 * Returns: %0 else error if access denied or other error 281 260 */ 282 - int aa_path_perm(const char *op, struct aa_label *label, 261 + int aa_path_perm(const char *op, const struct cred *subj_cred, 262 + struct aa_label *label, 283 263 const struct path *path, int flags, u32 request, 284 264 struct path_cond *cond) 285 265 { ··· 295 273 if (!buffer) 296 274 return -ENOMEM; 297 275 error = fn_for_each_confined(label, profile, 298 - profile_path_perm(op, profile, path, buffer, request, 299 - cond, flags, &perms)); 276 + profile_path_perm(op, subj_cred, profile, path, buffer, 277 + request, cond, flags, &perms)); 300 278 301 279 aa_put_buffer(buffer); 302 280 ··· 323 301 return true; 324 302 } 325 303 326 - static int profile_path_link(struct aa_profile *profile, 304 + static int profile_path_link(const struct cred *subj_cred, 305 + struct aa_profile *profile, 327 306 const struct path *link, char *buffer, 328 307 const struct path *target, char *buffer2, 329 308 struct path_cond *cond) ··· 338 315 aa_state_t state; 339 316 int error; 340 317 341 - error = path_name(OP_LINK, &profile->label, link, profile->path_flags, 318 + error = path_name(OP_LINK, subj_cred, &profile->label, link, 319 + profile->path_flags, 342 320 buffer, &lname, cond, AA_MAY_LINK); 343 321 if (error) 344 322 goto audit; 345 323 346 324 /* buffer2 freed below, tname is pointer in buffer2 */ 347 - error = path_name(OP_LINK, &profile->label, target, profile->path_flags, 325 + error = path_name(OP_LINK, subj_cred, &profile->label, target, 326 + profile->path_flags, 348 327 buffer2, &tname, cond, AA_MAY_LINK); 349 328 if (error) 350 329 goto audit; 351 330 352 331 error = -EACCES; 353 332 /* aa_str_perms - handles the case of the dfa being NULL */ 354 - state = aa_str_perms(&(rules->file), 355 - rules->file.start[AA_CLASS_FILE], lname, 333 + state = aa_str_perms(rules->file, 334 + rules->file->start[AA_CLASS_FILE], lname, 356 335 cond, &lperms); 357 336 358 337 if (!(lperms.allow & AA_MAY_LINK)) 359 338 goto audit; 360 339 361 340 /* test to see if target can be paired with link */ 362 - state = aa_dfa_null_transition(rules->file.dfa, state); 363 - aa_str_perms(&(rules->file), state, tname, cond, &perms); 341 + state = aa_dfa_null_transition(rules->file->dfa, state); 342 + aa_str_perms(rules->file, state, tname, cond, &perms); 364 343 365 344 /* force audit/quiet masks for link are stored in the second entry 366 345 * in the link pair. ··· 384 359 /* Do link perm subset test requiring allowed permission on link are 385 360 * a subset of the allowed permissions on target. 386 361 */ 387 - aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], 362 + aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE], 388 363 tname, cond, &perms); 389 364 390 365 /* AA_MAY_LINK is not considered in the subset test */ ··· 406 381 error = 0; 407 382 408 383 audit: 409 - return aa_audit_file(profile, &lperms, OP_LINK, request, lname, tname, 384 + return aa_audit_file(subj_cred, 385 + profile, &lperms, OP_LINK, request, lname, tname, 410 386 NULL, cond->uid, info, error); 411 387 } 412 388 413 389 /** 414 390 * aa_path_link - Handle hard link permission check 391 + * @subj_cred: subject cred 415 392 * @label: the label being enforced (NOT NULL) 416 393 * @old_dentry: the target dentry (NOT NULL) 417 394 * @new_dir: directory the new link will be created in (NOT NULL) ··· 430 403 * 431 404 * Returns: %0 if allowed else error 432 405 */ 433 - int aa_path_link(struct aa_label *label, struct dentry *old_dentry, 406 + int aa_path_link(const struct cred *subj_cred, 407 + struct aa_label *label, struct dentry *old_dentry, 434 408 const struct path *new_dir, struct dentry *new_dentry) 435 409 { 436 410 struct path link = { .mnt = new_dir->mnt, .dentry = new_dentry }; ··· 452 424 goto out; 453 425 454 426 error = fn_for_each_confined(label, profile, 455 - profile_path_link(profile, &link, buffer, &target, 456 - buffer2, &cond)); 427 + profile_path_link(subj_cred, profile, &link, buffer, 428 + &target, buffer2, &cond)); 457 429 out: 458 430 aa_put_buffer(buffer); 459 431 aa_put_buffer(buffer2); ··· 481 453 spin_unlock(&fctx->lock); 482 454 } 483 455 484 - static int __file_path_perm(const char *op, struct aa_label *label, 456 + static int __file_path_perm(const char *op, const struct cred *subj_cred, 457 + struct aa_label *label, 485 458 struct aa_label *flabel, struct file *file, 486 459 u32 request, u32 denied, bool in_atomic) 487 460 { ··· 509 480 510 481 /* check every profile in task label not in current cache */ 511 482 error = fn_for_each_not_in_set(flabel, label, profile, 512 - profile_path_perm(op, profile, &file->f_path, buffer, 483 + profile_path_perm(op, subj_cred, profile, 484 + &file->f_path, buffer, 513 485 request, &cond, flags, &perms)); 514 486 if (denied && !error) { 515 487 /* ··· 523 493 */ 524 494 if (label == flabel) 525 495 error = fn_for_each(label, profile, 526 - profile_path_perm(op, profile, &file->f_path, 496 + profile_path_perm(op, subj_cred, 497 + profile, &file->f_path, 527 498 buffer, request, &cond, flags, 528 499 &perms)); 529 500 else 530 501 error = fn_for_each_not_in_set(label, flabel, profile, 531 - profile_path_perm(op, profile, &file->f_path, 502 + profile_path_perm(op, subj_cred, 503 + profile, &file->f_path, 532 504 buffer, request, &cond, flags, 533 505 &perms)); 534 506 } ··· 542 510 return error; 543 511 } 544 512 545 - static int __file_sock_perm(const char *op, struct aa_label *label, 513 + static int __file_sock_perm(const char *op, const struct cred *subj_cred, 514 + struct aa_label *label, 546 515 struct aa_label *flabel, struct file *file, 547 516 u32 request, u32 denied) 548 517 { ··· 557 524 return 0; 558 525 559 526 /* TODO: improve to skip profiles cached in flabel */ 560 - error = aa_sock_file_perm(label, op, request, sock); 527 + error = aa_sock_file_perm(subj_cred, label, op, request, sock); 561 528 if (denied) { 562 529 /* TODO: improve to skip profiles checked above */ 563 530 /* check every profile in file label to is cached */ 564 - last_error(error, aa_sock_file_perm(flabel, op, request, sock)); 531 + last_error(error, aa_sock_file_perm(subj_cred, flabel, op, 532 + request, sock)); 565 533 } 566 534 if (!error) 567 535 update_file_ctx(file_ctx(file), label, request); ··· 573 539 /** 574 540 * aa_file_perm - do permission revalidation check & audit for @file 575 541 * @op: operation being checked 542 + * @subj_cred: subject cred 576 543 * @label: label being enforced (NOT NULL) 577 544 * @file: file to revalidate access permissions on (NOT NULL) 578 545 * @request: requested permissions ··· 581 546 * 582 547 * Returns: %0 if access allowed else error 583 548 */ 584 - int aa_file_perm(const char *op, struct aa_label *label, struct file *file, 549 + int aa_file_perm(const char *op, const struct cred *subj_cred, 550 + struct aa_label *label, struct file *file, 585 551 u32 request, bool in_atomic) 586 552 { 587 553 struct aa_file_ctx *fctx; ··· 618 582 /* TODO: label cross check */ 619 583 620 584 if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry)) 621 - error = __file_path_perm(op, label, flabel, file, request, 622 - denied, in_atomic); 585 + error = __file_path_perm(op, subj_cred, label, flabel, file, 586 + request, denied, in_atomic); 623 587 624 588 else if (S_ISSOCK(file_inode(file)->i_mode)) 625 - error = __file_sock_perm(op, label, flabel, file, request, 626 - denied); 589 + error = __file_sock_perm(op, subj_cred, label, flabel, file, 590 + request, denied); 627 591 aa_put_label(flabel); 628 592 629 593 done: 630 594 return error; 631 595 } 632 596 633 - static void revalidate_tty(struct aa_label *label) 597 + static void revalidate_tty(const struct cred *subj_cred, struct aa_label *label) 634 598 { 635 599 struct tty_struct *tty; 636 600 int drop_tty = 0; ··· 648 612 struct tty_file_private, list); 649 613 file = file_priv->file; 650 614 651 - if (aa_file_perm(OP_INHERIT, label, file, MAY_READ | MAY_WRITE, 652 - IN_ATOMIC)) 615 + if (aa_file_perm(OP_INHERIT, subj_cred, label, file, 616 + MAY_READ | MAY_WRITE, IN_ATOMIC)) 653 617 drop_tty = 1; 654 618 } 655 619 spin_unlock(&tty->files_lock); ··· 659 623 no_tty(); 660 624 } 661 625 626 + struct cred_label { 627 + const struct cred *cred; 628 + struct aa_label *label; 629 + }; 630 + 662 631 static int match_file(const void *p, struct file *file, unsigned int fd) 663 632 { 664 - struct aa_label *label = (struct aa_label *)p; 633 + struct cred_label *cl = (struct cred_label *)p; 665 634 666 - if (aa_file_perm(OP_INHERIT, label, file, aa_map_file_to_perms(file), 667 - IN_ATOMIC)) 635 + if (aa_file_perm(OP_INHERIT, cl->cred, cl->label, file, 636 + aa_map_file_to_perms(file), IN_ATOMIC)) 668 637 return fd + 1; 669 638 return 0; 670 639 } ··· 679 638 void aa_inherit_files(const struct cred *cred, struct files_struct *files) 680 639 { 681 640 struct aa_label *label = aa_get_newest_cred_label(cred); 641 + struct cred_label cl = { 642 + .cred = cred, 643 + .label = label, 644 + }; 682 645 struct file *devnull = NULL; 683 646 unsigned int n; 684 647 685 - revalidate_tty(label); 648 + revalidate_tty(cred, label); 686 649 687 650 /* Revalidate access to inherited open files. */ 688 - n = iterate_fd(files, 0, match_file, label); 651 + n = iterate_fd(files, 0, match_file, &cl); 689 652 if (!n) /* none found? */ 690 653 goto out; 691 654 ··· 699 654 /* replace all the matching ones with this */ 700 655 do { 701 656 replace_fd(n - 1, devnull, 0); 702 - } while ((n = iterate_fd(files, n, match_file, label)) != 0); 657 + } while ((n = iterate_fd(files, n, match_file, &cl)) != 0); 703 658 if (devnull) 704 659 fput(devnull); 705 660 out:
+2 -1
security/apparmor/include/apparmor.h
··· 30 30 #define AA_CLASS_NET 14 31 31 #define AA_CLASS_LABEL 16 32 32 #define AA_CLASS_POSIX_MQUEUE 17 33 - #define AA_CLASS_IO_URING 18 34 33 #define AA_CLASS_MODULE 19 35 34 #define AA_CLASS_DISPLAY_LSM 20 35 + #define AA_CLASS_NS 21 36 + #define AA_CLASS_IO_URING 22 36 37 37 38 #define AA_CLASS_X 31 38 39 #define AA_CLASS_DBUS 32
+26 -16
security/apparmor/include/audit.h
··· 103 103 #define OP_PROF_LOAD "profile_load" 104 104 #define OP_PROF_RM "profile_remove" 105 105 106 + #define OP_USERNS_CREATE "userns_create" 107 + 108 + #define OP_URING_OVERRIDE "uring_override" 109 + #define OP_URING_SQPOLL "uring_sqpoll" 106 110 107 111 struct apparmor_audit_data { 108 112 int error; 109 113 int type; 110 114 u16 class; 111 115 const char *op; 112 - struct aa_label *label; 116 + const struct cred *subj_cred; 117 + struct aa_label *subj_label; 113 118 const char *name; 114 119 const char *info; 115 120 u32 request; ··· 156 151 const char *data; 157 152 unsigned long flags; 158 153 } mnt; 154 + struct { 155 + struct aa_label *target; 156 + } uring; 159 157 }; 158 + 159 + struct common_audit_data common; 160 160 }; 161 161 162 162 /* macros for dealing with apparmor_audit_data structure */ 163 - #define aad(SA) ((SA)->apparmor_audit_data) 163 + #define aad(SA) (container_of(SA, struct apparmor_audit_data, common)) 164 + #define aad_of_va(VA) aad((struct common_audit_data *)(VA)) 165 + 164 166 #define DEFINE_AUDIT_DATA(NAME, T, C, X) \ 165 167 /* TODO: cleanup audit init so we don't need _aad = {0,} */ \ 166 - struct apparmor_audit_data NAME ## _aad = { \ 168 + struct apparmor_audit_data NAME = { \ 167 169 .class = (C), \ 168 170 .op = (X), \ 169 - }; \ 170 - struct common_audit_data NAME = \ 171 - { \ 172 - .type = (T), \ 173 - .u.tsk = NULL, \ 174 - }; \ 175 - NAME.apparmor_audit_data = &(NAME ## _aad) 171 + .common.type = (T), \ 172 + .common.u.tsk = NULL, \ 173 + .common.apparmor_audit_data = &NAME, \ 174 + }; 176 175 177 - void aa_audit_msg(int type, struct common_audit_data *sa, 176 + void aa_audit_msg(int type, struct apparmor_audit_data *ad, 178 177 void (*cb) (struct audit_buffer *, void *)); 179 - int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa, 178 + int aa_audit(int type, struct aa_profile *profile, 179 + struct apparmor_audit_data *ad, 180 180 void (*cb) (struct audit_buffer *, void *)); 181 181 182 - #define aa_audit_error(ERROR, SA, CB) \ 182 + #define aa_audit_error(ERROR, AD, CB) \ 183 183 ({ \ 184 - aad((SA))->error = (ERROR); \ 185 - aa_audit_msg(AUDIT_APPARMOR_ERROR, (SA), (CB)); \ 186 - aad((SA))->error; \ 184 + (AD)->error = (ERROR); \ 185 + aa_audit_msg(AUDIT_APPARMOR_ERROR, (AD), (CB)); \ 186 + (AD)->error; \ 187 187 }) 188 188 189 189
+2 -1
security/apparmor/include/capability.h
··· 36 36 37 37 extern struct aa_sfs_entry aa_sfs_entry_caps[]; 38 38 39 - int aa_capable(struct aa_label *label, int cap, unsigned int opts); 39 + int aa_capable(const struct cred *subj_cred, struct aa_label *label, 40 + int cap, unsigned int opts); 40 41 41 42 static inline void aa_free_cap_rules(struct aa_caps *caps) 42 43 {
+10 -44
security/apparmor/include/file.h
··· 45 45 u32 allow; 46 46 }; 47 47 48 - /** 49 - * aa_alloc_file_ctx - allocate file_ctx 50 - * @label: initial label of task creating the file 51 - * @gfp: gfp flags for allocation 52 - * 53 - * Returns: file_ctx or NULL on failure 54 - */ 55 - static inline struct aa_file_ctx *aa_alloc_file_ctx(struct aa_label *label, 56 - gfp_t gfp) 57 - { 58 - struct aa_file_ctx *ctx; 59 - 60 - ctx = kzalloc(sizeof(struct aa_file_ctx), gfp); 61 - if (ctx) { 62 - spin_lock_init(&ctx->lock); 63 - rcu_assign_pointer(ctx->label, aa_get_label(label)); 64 - } 65 - return ctx; 66 - } 67 - 68 - /** 69 - * aa_free_file_ctx - free a file_ctx 70 - * @ctx: file_ctx to free (MAYBE_NULL) 71 - */ 72 - static inline void aa_free_file_ctx(struct aa_file_ctx *ctx) 73 - { 74 - if (ctx) { 75 - aa_put_label(rcu_access_pointer(ctx->label)); 76 - kfree_sensitive(ctx); 77 - } 78 - } 79 - 80 - static inline struct aa_label *aa_get_file_label(struct aa_file_ctx *ctx) 81 - { 82 - return aa_get_label_rcu(&ctx->label); 83 - } 84 - 85 48 /* 86 49 * The xindex is broken into 3 parts 87 50 * - index - an index into either the exec name table or the variable table ··· 71 108 72 109 #define COMBINED_PERM_MASK(X) ((X).allow | (X).audit | (X).quiet | (X).kill) 73 110 74 - int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, 111 + int aa_audit_file(const struct cred *cred, 112 + struct aa_profile *profile, struct aa_perms *perms, 75 113 const char *op, u32 request, const char *name, 76 114 const char *target, struct aa_label *tlabel, kuid_t ouid, 77 115 const char *info, int error); ··· 83 119 const char *name, struct path_cond *cond, 84 120 struct aa_perms *perms); 85 121 86 - int aa_path_perm(const char *op, struct aa_label *label, 87 - const struct path *path, int flags, u32 request, 88 - struct path_cond *cond); 122 + int aa_path_perm(const char *op, const struct cred *subj_cred, 123 + struct aa_label *label, const struct path *path, 124 + int flags, u32 request, struct path_cond *cond); 89 125 90 - int aa_path_link(struct aa_label *label, struct dentry *old_dentry, 91 - const struct path *new_dir, struct dentry *new_dentry); 126 + int aa_path_link(const struct cred *subj_cred, struct aa_label *label, 127 + struct dentry *old_dentry, const struct path *new_dir, 128 + struct dentry *new_dentry); 92 129 93 - int aa_file_perm(const char *op, struct aa_label *label, struct file *file, 130 + int aa_file_perm(const char *op, const struct cred *subj_cred, 131 + struct aa_label *label, struct file *file, 94 132 u32 request, bool in_atomic); 95 133 96 134 void aa_inherit_files(const struct cred *cred, struct files_struct *files);
+3 -1
security/apparmor/include/ipc.h
··· 13 13 14 14 #include <linux/sched.h> 15 15 16 - int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig); 16 + int aa_may_signal(const struct cred *subj_cred, struct aa_label *sender, 17 + const struct cred *target_cred, struct aa_label *target, 18 + int sig); 17 19 18 20 #endif /* __AA_IPC_H */
+2
security/apparmor/include/lib.h
··· 16 16 17 17 #include "match.h" 18 18 19 + extern struct aa_dfa *stacksplitdfa; 20 + 19 21 /* 20 22 * DEBUG remains global (no per profile flag) since it is mostly used in sysctl 21 23 * which is not related to profile accesses.
-6
security/apparmor/include/match.h
··· 102 102 struct table_header *tables[YYTD_ID_TSIZE]; 103 103 }; 104 104 105 - extern struct aa_dfa *nulldfa; 106 - extern struct aa_dfa *stacksplitdfa; 107 - 108 105 #define byte_to_byte(X) (X) 109 106 110 107 #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX) \ ··· 118 121 { 119 122 return ALIGN(sizeof(struct table_header) + len * el_size, 8); 120 123 } 121 - 122 - int aa_setup_dfa_engine(void); 123 - void aa_teardown_dfa_engine(void); 124 124 125 125 #define aa_state_t unsigned int 126 126
+18 -8
security/apparmor/include/mount.h
··· 25 25 26 26 #define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN) 27 27 28 - int aa_remount(struct aa_label *label, const struct path *path, 28 + int aa_remount(const struct cred *subj_cred, 29 + struct aa_label *label, const struct path *path, 29 30 unsigned long flags, void *data); 30 31 31 - int aa_bind_mount(struct aa_label *label, const struct path *path, 32 + int aa_bind_mount(const struct cred *subj_cred, 33 + struct aa_label *label, const struct path *path, 32 34 const char *old_name, unsigned long flags); 33 35 34 36 35 - int aa_mount_change_type(struct aa_label *label, const struct path *path, 37 + int aa_mount_change_type(const struct cred *subj_cred, 38 + struct aa_label *label, const struct path *path, 36 39 unsigned long flags); 37 40 38 - int aa_move_mount(struct aa_label *label, const struct path *path, 39 - const char *old_name); 41 + int aa_move_mount_old(const struct cred *subj_cred, 42 + struct aa_label *label, const struct path *path, 43 + const char *old_name); 44 + int aa_move_mount(const struct cred *subj_cred, 45 + struct aa_label *label, const struct path *from_path, 46 + const struct path *to_path); 40 47 41 - int aa_new_mount(struct aa_label *label, const char *dev_name, 48 + int aa_new_mount(const struct cred *subj_cred, 49 + struct aa_label *label, const char *dev_name, 42 50 const struct path *path, const char *type, unsigned long flags, 43 51 void *data); 44 52 45 - int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags); 53 + int aa_umount(const struct cred *subj_cred, 54 + struct aa_label *label, struct vfsmount *mnt, int flags); 46 55 47 - int aa_pivotroot(struct aa_label *label, const struct path *old_path, 56 + int aa_pivotroot(const struct cred *subj_cred, 57 + struct aa_label *label, const struct path *old_path, 48 58 const struct path *new_path); 49 59 50 60 #endif /* __AA_MOUNT_H */
+16 -9
security/apparmor/include/net.h
··· 52 52 }; 53 53 54 54 #define SK_CTX(X) ((X)->sk_security) 55 - #define SOCK_ctx(X) SOCK_INODE(X)->i_security 55 + static inline struct aa_sk_ctx *aa_sock(const struct sock *sk) 56 + { 57 + return sk->sk_security; 58 + } 59 + 56 60 #define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \ 57 61 struct lsm_network_audit NAME ## _net = { .sk = (SK), \ 58 62 .family = (F)}; \ ··· 65 61 LSM_AUDIT_DATA_NONE, \ 66 62 AA_CLASS_NET, \ 67 63 OP); \ 68 - NAME.u.net = &(NAME ## _net); \ 69 - aad(&NAME)->net.type = (T); \ 70 - aad(&NAME)->net.protocol = (P) 64 + NAME.common.u.net = &(NAME ## _net); \ 65 + NAME.net.type = (T); \ 66 + NAME.net.protocol = (P) 71 67 72 68 #define DEFINE_AUDIT_SK(NAME, OP, SK) \ 73 69 DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \ ··· 94 90 extern struct aa_sfs_entry aa_sfs_entry_network[]; 95 91 96 92 void audit_net_cb(struct audit_buffer *ab, void *va); 97 - int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, 93 + int aa_profile_af_perm(struct aa_profile *profile, 94 + struct apparmor_audit_data *ad, 98 95 u32 request, u16 family, int type); 99 - int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, 96 + int aa_af_perm(const struct cred *subj_cred, struct aa_label *label, 97 + const char *op, u32 request, u16 family, 100 98 int type, int protocol); 101 99 static inline int aa_profile_af_sk_perm(struct aa_profile *profile, 102 - struct common_audit_data *sa, 100 + struct apparmor_audit_data *ad, 103 101 u32 request, 104 102 struct sock *sk) 105 103 { 106 - return aa_profile_af_perm(profile, sa, request, sk->sk_family, 104 + return aa_profile_af_perm(profile, ad, request, sk->sk_family, 107 105 sk->sk_type); 108 106 } 109 107 int aa_sk_perm(const char *op, u32 request, struct sock *sk); 110 108 111 - int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, 109 + int aa_sock_file_perm(const struct cred *subj_cred, struct aa_label *label, 110 + const char *op, u32 request, 112 111 struct socket *sock); 113 112 114 113 int apparmor_secmark_check(struct aa_label *label, char *op, u32 request,
+5 -2
security/apparmor/include/perms.h
··· 48 48 49 49 #define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */ 50 50 51 + #define AA_MAY_CREATE_SQPOLL AA_MAY_CREATE 52 + #define AA_MAY_OVERRIDE_CRED AA_MAY_APPEND 53 + #define AA_URING_PERM_MASK (AA_MAY_OVERRIDE_CRED | AA_MAY_CREATE_SQPOLL) 51 54 52 55 #define PERMS_CHRS_MASK (MAY_READ | MAY_WRITE | AA_MAY_CREATE | \ 53 56 AA_MAY_DELETE | AA_MAY_LINK | AA_MAY_LOCK | \ ··· 215 212 int type, u32 request, struct aa_perms *perms); 216 213 int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, 217 214 u32 request, int type, u32 *deny, 218 - struct common_audit_data *sa); 215 + struct apparmor_audit_data *ad); 219 216 int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, 220 - u32 request, struct common_audit_data *sa, 217 + u32 request, struct apparmor_audit_data *ad, 221 218 void (*cb)(struct audit_buffer *, void *)); 222 219 #endif /* __AA_PERM_H */
+45 -25
security/apparmor/include/policy.h
··· 34 34 struct aa_ns; 35 35 36 36 extern int unprivileged_userns_apparmor_policy; 37 + extern int aa_unprivileged_unconfined_restricted; 37 38 38 39 extern const char *const aa_profile_mode_names[]; 39 40 #define APPARMOR_MODE_NAMES_MAX_INDEX 4 ··· 75 74 76 75 77 76 /* struct aa_policydb - match engine for a policy 77 + * count: refcount for the pdb 78 78 * dfa: dfa pattern match 79 79 * perms: table of permissions 80 80 * strs: table of strings, index by x 81 81 * start: set of start states for the different classes of data 82 82 */ 83 83 struct aa_policydb { 84 + struct kref count; 84 85 struct aa_dfa *dfa; 85 86 struct { 86 87 struct aa_perms *perms; ··· 92 89 aa_state_t start[AA_CLASS_LAST + 1]; 93 90 }; 94 91 95 - static inline void aa_destroy_policydb(struct aa_policydb *policy) 96 - { 97 - aa_put_dfa(policy->dfa); 98 - if (policy->perms) 99 - kvfree(policy->perms); 100 - aa_free_str_table(&policy->trans); 92 + extern struct aa_policydb *nullpdb; 101 93 94 + struct aa_policydb *aa_alloc_pdb(gfp_t gfp); 95 + void aa_pdb_free_kref(struct kref *kref); 96 + 97 + /** 98 + * aa_get_pdb - increment refcount on @pdb 99 + * @pdb: policydb (MAYBE NULL) 100 + * 101 + * Returns: pointer to @pdb if @pdb is NULL will return NULL 102 + * Requires: @pdb must be held with valid refcount when called 103 + */ 104 + static inline struct aa_policydb *aa_get_pdb(struct aa_policydb *pdb) 105 + { 106 + if (pdb) 107 + kref_get(&(pdb->count)); 108 + 109 + return pdb; 110 + } 111 + 112 + /** 113 + * aa_put_pdb - put a pdb refcount 114 + * @pdb: pdb to put refcount (MAYBE NULL) 115 + * 116 + * Requires: if @pdb != NULL that a valid refcount be held 117 + */ 118 + static inline void aa_put_pdb(struct aa_policydb *pdb) 119 + { 120 + if (pdb) 121 + kref_put(&pdb->count, aa_pdb_free_kref); 102 122 } 103 123 104 124 static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy, ··· 165 139 int size; 166 140 167 141 /* TODO: merge policy and file */ 168 - struct aa_policydb policy; 169 - struct aa_policydb file; 142 + struct aa_policydb *policy; 143 + struct aa_policydb *file; 170 144 struct aa_caps caps; 171 145 172 146 struct aa_rlimit rlimits; ··· 185 159 */ 186 160 struct aa_attachment { 187 161 const char *xmatch_str; 188 - struct aa_policydb xmatch; 162 + struct aa_policydb *xmatch; 189 163 unsigned int xmatch_len; 190 164 int xattr_count; 191 165 char **xattrs; ··· 253 227 #define profiles_ns(P) ((P)->ns) 254 228 #define name_is_shared(A, B) ((A)->hname && (A)->hname == (B)->hname) 255 229 256 - void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); 257 - 258 - 259 - void aa_free_proxy_kref(struct kref *kref); 260 230 struct aa_ruleset *aa_alloc_ruleset(gfp_t gfp); 261 231 struct aa_profile *aa_alloc_profile(const char *name, struct aa_proxy *proxy, 262 232 gfp_t gfp); ··· 261 239 struct aa_profile *aa_new_learning_profile(struct aa_profile *parent, bool hat, 262 240 const char *base, gfp_t gfp); 263 241 void aa_free_profile(struct aa_profile *profile); 264 - void aa_free_profile_kref(struct kref *kref); 265 242 struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name); 266 243 struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname, 267 244 size_t n); 268 245 struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name); 269 246 struct aa_profile *aa_fqlookupn_profile(struct aa_label *base, 270 247 const char *fqname, size_t n); 271 - struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name); 272 248 273 249 ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_label *label, 274 250 u32 mask, struct aa_loaddata *udata); 275 251 ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_label *label, 276 252 char *name, size_t size); 277 253 void __aa_profile_list_release(struct list_head *head); 278 - 279 - #define PROF_ADD 1 280 - #define PROF_REPLACE 0 281 254 282 255 #define profile_unconfined(X) ((X)->mode == APPARMOR_UNCONFINED) 283 256 ··· 293 276 unsigned char class) 294 277 { 295 278 if (class <= AA_CLASS_LAST) 296 - return rules->policy.start[class]; 279 + return rules->policy->start[class]; 297 280 else 298 - return aa_dfa_match_len(rules->policy.dfa, 299 - rules->policy.start[0], &class, 1); 281 + return aa_dfa_match_len(rules->policy->dfa, 282 + rules->policy->start[0], &class, 1); 300 283 } 301 284 302 285 static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) ··· 306 289 307 290 if (!state) 308 291 return DFA_NOMATCH; 309 - return aa_dfa_match_len(rules->policy.dfa, state, (char *) &be_af, 2); 292 + return aa_dfa_match_len(rules->policy->dfa, state, (char *) &be_af, 2); 310 293 } 311 294 312 295 static inline aa_state_t ANY_RULE_MEDIATES(struct list_head *head, ··· 387 370 return profile->audit; 388 371 } 389 372 390 - bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns); 391 - bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns); 392 - int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, 373 + bool aa_policy_view_capable(const struct cred *subj_cred, 374 + struct aa_label *label, struct aa_ns *ns); 375 + bool aa_policy_admin_capable(const struct cred *subj_cred, 376 + struct aa_label *label, struct aa_ns *ns); 377 + int aa_may_manage_policy(const struct cred *subj_cred, 378 + struct aa_label *label, struct aa_ns *ns, 393 379 u32 mask); 394 380 bool aa_current_policy_view_capable(struct aa_ns *ns); 395 381 bool aa_current_policy_admin_capable(struct aa_ns *ns);
-14
security/apparmor/include/policy_ns.h
··· 86 86 void aa_free_ns(struct aa_ns *ns); 87 87 int aa_alloc_root_ns(void); 88 88 void aa_free_root_ns(void); 89 - void aa_free_ns_kref(struct kref *kref); 90 89 91 - struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name); 92 - struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n); 93 90 struct aa_ns *__aa_lookupn_ns(struct aa_ns *view, const char *hname, size_t n); 94 91 struct aa_ns *aa_lookupn_ns(struct aa_ns *view, const char *name, size_t n); 95 92 struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name, ··· 146 149 const char *name) 147 150 { 148 151 return __aa_findn_ns(head, name, strlen(name)); 149 - } 150 - 151 - static inline struct aa_ns *__aa_lookup_ns(struct aa_ns *base, 152 - const char *hname) 153 - { 154 - return __aa_lookupn_ns(base, hname, strlen(hname)); 155 - } 156 - 157 - static inline struct aa_ns *aa_lookup_ns(struct aa_ns *view, const char *name) 158 - { 159 - return aa_lookupn_ns(view, name, strlen(name)); 160 152 } 161 153 162 154 #endif /* AA_NAMESPACE_H */
+2 -1
security/apparmor/include/resource.h
··· 33 33 extern struct aa_sfs_entry aa_sfs_entry_rlimit[]; 34 34 35 35 int aa_map_resource(int resource); 36 - int aa_task_setrlimit(struct aa_label *label, struct task_struct *task, 36 + int aa_task_setrlimit(const struct cred *subj_cred, struct aa_label *label, 37 + struct task_struct *task, 37 38 unsigned int resource, struct rlimit *new_rlim); 38 39 39 40 void __aa_transition_rlimits(struct aa_label *old, struct aa_label *new);
+9 -2
security/apparmor/include/task.h
··· 30 30 }; 31 31 32 32 int aa_replace_current_label(struct aa_label *label); 33 - int aa_set_current_onexec(struct aa_label *label, bool stack); 33 + void aa_set_current_onexec(struct aa_label *label, bool stack); 34 34 int aa_set_current_hat(struct aa_label *label, u64 token); 35 35 int aa_restore_previous_label(u64 cookie); 36 36 struct aa_label *aa_get_task_label(struct task_struct *task); ··· 91 91 "segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \ 92 92 "xcpu xfsz vtalrm prof winch io pwr sys emt lost" 93 93 94 - int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, 94 + int aa_may_ptrace(const struct cred *tracer_cred, struct aa_label *tracer, 95 + const struct cred *tracee_cred, struct aa_label *tracee, 95 96 u32 request); 96 97 98 + 99 + 100 + #define AA_USERNS_CREATE 8 101 + 102 + int aa_profile_ns_perm(struct aa_profile *profile, 103 + struct apparmor_audit_data *ad, u32 request); 97 104 98 105 #endif /* __AA_TASK_H */
+30 -23
security/apparmor/ipc.c
··· 52 52 static void audit_signal_cb(struct audit_buffer *ab, void *va) 53 53 { 54 54 struct common_audit_data *sa = va; 55 + struct apparmor_audit_data *ad = aad(sa); 55 56 56 - if (aad(sa)->request & AA_SIGNAL_PERM_MASK) { 57 + if (ad->request & AA_SIGNAL_PERM_MASK) { 57 58 audit_log_format(ab, " requested_mask=\"%s\"", 58 - audit_signal_mask(aad(sa)->request)); 59 - if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) { 59 + audit_signal_mask(ad->request)); 60 + if (ad->denied & AA_SIGNAL_PERM_MASK) { 60 61 audit_log_format(ab, " denied_mask=\"%s\"", 61 - audit_signal_mask(aad(sa)->denied)); 62 + audit_signal_mask(ad->denied)); 62 63 } 63 64 } 64 - if (aad(sa)->signal == SIGUNKNOWN) 65 + if (ad->signal == SIGUNKNOWN) 65 66 audit_log_format(ab, "signal=unknown(%d)", 66 - aad(sa)->unmappedsig); 67 - else if (aad(sa)->signal < MAXMAPPED_SIGNAME) 68 - audit_log_format(ab, " signal=%s", sig_names[aad(sa)->signal]); 67 + ad->unmappedsig); 68 + else if (ad->signal < MAXMAPPED_SIGNAME) 69 + audit_log_format(ab, " signal=%s", sig_names[ad->signal]); 69 70 else 70 71 audit_log_format(ab, " signal=rtmin+%d", 71 - aad(sa)->signal - SIGRT_BASE); 72 + ad->signal - SIGRT_BASE); 72 73 audit_log_format(ab, " peer="); 73 - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 74 + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, 74 75 FLAGS_NONE, GFP_ATOMIC); 75 76 } 76 77 77 - static int profile_signal_perm(struct aa_profile *profile, 78 + static int profile_signal_perm(const struct cred *cred, 79 + struct aa_profile *profile, 78 80 struct aa_label *peer, u32 request, 79 - struct common_audit_data *sa) 81 + struct apparmor_audit_data *ad) 80 82 { 81 83 struct aa_ruleset *rules = list_first_entry(&profile->rules, 82 84 typeof(*rules), list); ··· 89 87 !ANY_RULE_MEDIATES(&profile->rules, AA_CLASS_SIGNAL)) 90 88 return 0; 91 89 92 - aad(sa)->peer = peer; 90 + ad->subj_cred = cred; 91 + ad->peer = peer; 93 92 /* TODO: secondary cache check <profile, profile, perm> */ 94 - state = aa_dfa_next(rules->policy.dfa, 95 - rules->policy.start[AA_CLASS_SIGNAL], 96 - aad(sa)->signal); 93 + state = aa_dfa_next(rules->policy->dfa, 94 + rules->policy->start[AA_CLASS_SIGNAL], 95 + ad->signal); 97 96 aa_label_match(profile, rules, peer, state, false, request, &perms); 98 97 aa_apply_modes_to_perms(profile, &perms); 99 - return aa_check_perms(profile, &perms, request, sa, audit_signal_cb); 98 + return aa_check_perms(profile, &perms, request, ad, audit_signal_cb); 100 99 } 101 100 102 - int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig) 101 + int aa_may_signal(const struct cred *subj_cred, struct aa_label *sender, 102 + const struct cred *target_cred, struct aa_label *target, 103 + int sig) 103 104 { 104 105 struct aa_profile *profile; 105 - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_SIGNAL, OP_SIGNAL); 106 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_SIGNAL, OP_SIGNAL); 106 107 107 - aad(&sa)->signal = map_signal_num(sig); 108 - aad(&sa)->unmappedsig = sig; 108 + ad.signal = map_signal_num(sig); 109 + ad.unmappedsig = sig; 109 110 return xcheck_labels(sender, target, profile, 110 - profile_signal_perm(profile, target, MAY_WRITE, &sa), 111 - profile_signal_perm(profile, sender, MAY_READ, &sa)); 111 + profile_signal_perm(subj_cred, profile, target, 112 + MAY_WRITE, &ad), 113 + profile_signal_perm(target_cred, profile, sender, 114 + MAY_READ, &ad)); 112 115 }
+23 -21
security/apparmor/label.c
··· 154 154 155 155 /** 156 156 * vec_cmp - label comparison for set ordering 157 - * @a: label to compare (NOT NULL) 158 - * @vec: vector of profiles to compare (NOT NULL) 159 - * @n: length of @vec 157 + * @a: aa_profile to compare (NOT NULL) 158 + * @an: length of @a 159 + * @b: aa_profile to compare (NOT NULL) 160 + * @bn: length of @b 160 161 * 161 - * Returns: <0 if a < vec 162 - * ==0 if a == vec 163 - * >0 if a > vec 162 + * Returns: <0 if @a < @b 163 + * ==0 if @a == @b 164 + * >0 if @a > @b 164 165 */ 165 166 static int vec_cmp(struct aa_profile **a, int an, struct aa_profile **b, int bn) 166 167 { ··· 257 256 * aa_vec_unique - canonical sort and unique a list of profiles 258 257 * @n: number of refcounted profiles in the list (@n > 0) 259 258 * @vec: list of profiles to sort and merge 259 + * @flags: null terminator flags of @vec 260 260 * 261 261 * Returns: the number of duplicates eliminated == references put 262 262 * ··· 586 584 587 585 /** 588 586 * __label_remove - remove @label from the label set 589 - * @l: label to remove 587 + * @label: label to remove 590 588 * @new: label to redirect to 591 589 * 592 590 * Requires: labels_set(@label)->lock write_lock ··· 919 917 920 918 /** 921 919 * aa_label_insert - insert label @label into @ls or return existing label 922 - * @ls - labelset to insert @label into 923 - * @label - label to insert 920 + * @ls: labelset to insert @label into 921 + * @label: label to insert 924 922 * 925 923 * Requires: caller to hold a valid ref on @label 926 924 * ··· 1206 1204 1207 1205 /** 1208 1206 * aa_label_merge - attempt to insert new merged label of @a and @b 1209 - * @ls: set of labels to insert label into (NOT NULL) 1210 1207 * @a: label to merge with @b (NOT NULL) 1211 1208 * @b: label to merge with @a (NOT NULL) 1212 1209 * @gfp: memory allocation type ··· 1270 1269 const char *ns_name; 1271 1270 1272 1271 if (profile->ns == tp->ns) 1273 - return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); 1272 + return aa_dfa_match(rules->policy->dfa, state, tp->base.hname); 1274 1273 1275 1274 /* try matching with namespace name and then profile */ 1276 1275 ns_name = aa_ns_name(profile->ns, tp->ns, true); 1277 - state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1); 1278 - state = aa_dfa_match(rules->policy.dfa, state, ns_name); 1279 - state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1); 1280 - return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); 1276 + state = aa_dfa_match_len(rules->policy->dfa, state, ":", 1); 1277 + state = aa_dfa_match(rules->policy->dfa, state, ns_name); 1278 + state = aa_dfa_match_len(rules->policy->dfa, state, ":", 1); 1279 + return aa_dfa_match(rules->policy->dfa, state, tp->base.hname); 1281 1280 } 1282 1281 1283 1282 /** 1284 1283 * label_compound_match - find perms for full compound label 1285 1284 * @profile: profile to find perms for 1285 + * @rules: ruleset to search 1286 1286 * @label: label to check access permissions for 1287 - * @start: state to start match in 1287 + * @state: state to start match in 1288 1288 * @subns: whether to do permission checks on components in a subns 1289 1289 * @request: permissions to request 1290 1290 * @perms: perms struct to set ··· 1323 1321 label_for_each_cont(i, label, tp) { 1324 1322 if (!aa_ns_visible(profile->ns, tp->ns, subns)) 1325 1323 continue; 1326 - state = aa_dfa_match(rules->policy.dfa, state, "//&"); 1324 + state = aa_dfa_match(rules->policy->dfa, state, "//&"); 1327 1325 state = match_component(profile, rules, tp, state); 1328 1326 if (!state) 1329 1327 goto fail; 1330 1328 } 1331 - *perms = *aa_lookup_perms(&rules->policy, state); 1329 + *perms = *aa_lookup_perms(rules->policy, state); 1332 1330 aa_apply_modes_to_perms(profile, perms); 1333 1331 if ((perms->allow & request) != request) 1334 1332 return -EACCES; ··· 1381 1379 return 0; 1382 1380 1383 1381 next: 1384 - tmp = *aa_lookup_perms(&rules->policy, state); 1382 + tmp = *aa_lookup_perms(rules->policy, state); 1385 1383 aa_apply_modes_to_perms(profile, &tmp); 1386 1384 aa_perms_accum(perms, &tmp); 1387 1385 label_for_each_cont(i, label, tp) { ··· 1390 1388 state = match_component(profile, rules, tp, start); 1391 1389 if (!state) 1392 1390 goto fail; 1393 - tmp = *aa_lookup_perms(&rules->policy, state); 1391 + tmp = *aa_lookup_perms(rules->policy, state); 1394 1392 aa_apply_modes_to_perms(profile, &tmp); 1395 1393 aa_perms_accum(perms, &tmp); 1396 1394 } ··· 2039 2037 2040 2038 /** 2041 2039 * __label_update - insert updated version of @label into labelset 2042 - * @label - the label to update/replace 2040 + * @label: the label to update/replace 2043 2041 * 2044 2042 * Returns: new label that is up to date 2045 2043 * else NULL on failure
+27 -27
security/apparmor/lib.c
··· 27 27 28 28 /** 29 29 * aa_free_str_table - free entries str table 30 - * @str: the string table to free (MAYBE NULL) 30 + * @t: the string table to free (MAYBE NULL) 31 31 */ 32 32 void aa_free_str_table(struct aa_str_table *t) 33 33 { ··· 85 85 /** 86 86 * skipn_spaces - Removes leading whitespace from @str. 87 87 * @str: The string to be stripped. 88 + * @n: length of str to parse, will stop at \0 if encountered before n 88 89 * 89 90 * Returns a pointer to the first non-whitespace character in @str. 90 91 * if all whitespace will return NULL ··· 144 143 void aa_info_message(const char *str) 145 144 { 146 145 if (audit_enabled) { 147 - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); 146 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); 148 147 149 - aad(&sa)->info = str; 150 - aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); 148 + ad.info = str; 149 + aa_audit_msg(AUDIT_APPARMOR_STATUS, &ad, NULL); 151 150 } 152 151 printk(KERN_INFO "AppArmor: %s\n", str); 153 152 } ··· 282 281 static void aa_audit_perms_cb(struct audit_buffer *ab, void *va) 283 282 { 284 283 struct common_audit_data *sa = va; 284 + struct apparmor_audit_data *ad = aad(sa); 285 285 286 - if (aad(sa)->request) { 286 + if (ad->request) { 287 287 audit_log_format(ab, " requested_mask="); 288 - aa_audit_perm_mask(ab, aad(sa)->request, aa_file_perm_chrs, 288 + aa_audit_perm_mask(ab, ad->request, aa_file_perm_chrs, 289 289 PERMS_CHRS_MASK, aa_file_perm_names, 290 290 PERMS_NAMES_MASK); 291 291 } 292 - if (aad(sa)->denied) { 292 + if (ad->denied) { 293 293 audit_log_format(ab, "denied_mask="); 294 - aa_audit_perm_mask(ab, aad(sa)->denied, aa_file_perm_chrs, 294 + aa_audit_perm_mask(ab, ad->denied, aa_file_perm_chrs, 295 295 PERMS_CHRS_MASK, aa_file_perm_names, 296 296 PERMS_NAMES_MASK); 297 297 } 298 298 audit_log_format(ab, " peer="); 299 - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 299 + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, 300 300 FLAGS_NONE, GFP_ATOMIC); 301 301 } 302 302 ··· 341 339 /* TODO: doesn't yet handle extended types */ 342 340 aa_state_t state; 343 341 344 - state = aa_dfa_next(rules->policy.dfa, 345 - rules->policy.start[AA_CLASS_LABEL], 342 + state = aa_dfa_next(rules->policy->dfa, 343 + rules->policy->start[AA_CLASS_LABEL], 346 344 type); 347 345 aa_label_match(profile, rules, label, state, false, request, perms); 348 346 } ··· 351 349 /* currently unused */ 352 350 int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, 353 351 u32 request, int type, u32 *deny, 354 - struct common_audit_data *sa) 352 + struct apparmor_audit_data *ad) 355 353 { 356 354 struct aa_ruleset *rules = list_first_entry(&profile->rules, 357 355 typeof(*rules), list); 358 356 struct aa_perms perms; 359 357 360 - aad(sa)->label = &profile->label; 361 - aad(sa)->peer = &target->label; 362 - aad(sa)->request = request; 358 + ad->peer = &target->label; 359 + ad->request = request; 363 360 364 361 aa_profile_match_label(profile, rules, &target->label, type, request, 365 362 &perms); 366 363 aa_apply_modes_to_perms(profile, &perms); 367 364 *deny |= request & perms.deny; 368 - return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb); 365 + return aa_check_perms(profile, &perms, request, ad, aa_audit_perms_cb); 369 366 } 370 367 371 368 /** ··· 372 371 * @profile: profile being checked 373 372 * @perms: perms computed for the request 374 373 * @request: requested perms 375 - * @deny: Returns: explicit deny set 376 - * @sa: initialized audit structure (MAY BE NULL if not auditing) 374 + * @ad: initialized audit structure (MAY BE NULL if not auditing) 377 375 * @cb: callback fn for type specific fields (MAY BE NULL) 378 376 * 379 377 * Returns: 0 if permission else error code ··· 385 385 * with a positive value. 386 386 */ 387 387 int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, 388 - u32 request, struct common_audit_data *sa, 388 + u32 request, struct apparmor_audit_data *ad, 389 389 void (*cb)(struct audit_buffer *, void *)) 390 390 { 391 391 int type, error; ··· 394 394 if (likely(!denied)) { 395 395 /* mask off perms that are not being force audited */ 396 396 request &= perms->audit; 397 - if (!request || !sa) 397 + if (!request || !ad) 398 398 return 0; 399 399 400 400 type = AUDIT_APPARMOR_AUDIT; ··· 413 413 error = -ENOENT; 414 414 415 415 denied &= ~perms->quiet; 416 - if (!sa || !denied) 416 + if (!ad || !denied) 417 417 return error; 418 418 } 419 419 420 - if (sa) { 421 - aad(sa)->label = &profile->label; 422 - aad(sa)->request = request; 423 - aad(sa)->denied = denied; 424 - aad(sa)->error = error; 425 - aa_audit_msg(type, sa, cb); 420 + if (ad) { 421 + ad->subj_label = &profile->label; 422 + ad->request = request; 423 + ad->denied = denied; 424 + ad->error = error; 425 + aa_audit_msg(type, ad, cb); 426 426 } 427 427 428 428 if (type == AUDIT_APPARMOR_ALLOWED)
+356 -58
security/apparmor/lsm.c
··· 49 49 DECLARE_FLEX_ARRAY(char, buffer); 50 50 }; 51 51 52 + struct aa_local_cache { 53 + unsigned int hold; 54 + unsigned int count; 55 + struct list_head head; 56 + }; 57 + 52 58 #define RESERVE_COUNT 2 53 59 static int reserve_count = RESERVE_COUNT; 54 60 static int buffer_count; 55 61 56 62 static LIST_HEAD(aa_global_buffers); 57 63 static DEFINE_SPINLOCK(aa_buffers_lock); 64 + static DEFINE_PER_CPU(struct aa_local_cache, aa_local_buffers); 58 65 59 66 /* 60 67 * LSM hook functions ··· 123 116 unsigned int mode) 124 117 { 125 118 struct aa_label *tracer, *tracee; 119 + const struct cred *cred; 126 120 int error; 127 121 122 + cred = get_task_cred(child); 123 + tracee = cred_label(cred); /* ref count on cred */ 128 124 tracer = __begin_current_label_crit_section(); 129 - tracee = aa_get_task_label(child); 130 - error = aa_may_ptrace(tracer, tracee, 125 + error = aa_may_ptrace(current_cred(), tracer, cred, tracee, 131 126 (mode & PTRACE_MODE_READ) ? AA_PTRACE_READ 132 127 : AA_PTRACE_TRACE); 133 - aa_put_label(tracee); 134 128 __end_current_label_crit_section(tracer); 129 + put_cred(cred); 135 130 136 131 return error; 137 132 } ··· 141 132 static int apparmor_ptrace_traceme(struct task_struct *parent) 142 133 { 143 134 struct aa_label *tracer, *tracee; 135 + const struct cred *cred; 144 136 int error; 145 137 146 138 tracee = __begin_current_label_crit_section(); 147 - tracer = aa_get_task_label(parent); 148 - error = aa_may_ptrace(tracer, tracee, AA_PTRACE_TRACE); 149 - aa_put_label(tracer); 139 + cred = get_task_cred(parent); 140 + tracer = cred_label(cred); /* ref count on cred */ 141 + error = aa_may_ptrace(cred, tracer, current_cred(), tracee, 142 + AA_PTRACE_TRACE); 143 + put_cred(cred); 150 144 __end_current_label_crit_section(tracee); 151 145 152 146 return error; ··· 200 188 201 189 label = aa_get_newest_cred_label(cred); 202 190 if (!unconfined(label)) 203 - error = aa_capable(label, cap, opts); 191 + error = aa_capable(cred, label, cap, opts); 204 192 aa_put_label(label); 205 193 206 194 return error; ··· 223 211 224 212 label = __begin_current_label_crit_section(); 225 213 if (!unconfined(label)) 226 - error = aa_path_perm(op, label, path, 0, mask, cond); 214 + error = aa_path_perm(op, current_cred(), label, path, 0, mask, 215 + cond); 227 216 __end_current_label_crit_section(label); 228 217 229 218 return error; ··· 370 357 371 358 label = begin_current_label_crit_section(); 372 359 if (!unconfined(label)) 373 - error = aa_path_link(label, old_dentry, new_dir, new_dentry); 360 + error = aa_path_link(current_cred(), label, old_dentry, new_dir, 361 + new_dentry); 374 362 end_current_label_crit_section(label); 375 363 376 364 return error; ··· 410 396 vfsuid = i_uid_into_vfsuid(idmap, d_backing_inode(old_dentry)); 411 397 cond_exchange.uid = vfsuid_into_kuid(vfsuid); 412 398 413 - error = aa_path_perm(OP_RENAME_SRC, label, &new_path, 0, 399 + error = aa_path_perm(OP_RENAME_SRC, current_cred(), 400 + label, &new_path, 0, 414 401 MAY_READ | AA_MAY_GETATTR | MAY_WRITE | 415 402 AA_MAY_SETATTR | AA_MAY_DELETE, 416 403 &cond_exchange); 417 404 if (!error) 418 - error = aa_path_perm(OP_RENAME_DEST, label, &old_path, 405 + error = aa_path_perm(OP_RENAME_DEST, current_cred(), 406 + label, &old_path, 419 407 0, MAY_WRITE | AA_MAY_SETATTR | 420 408 AA_MAY_CREATE, &cond_exchange); 421 409 } 422 410 423 411 if (!error) 424 - error = aa_path_perm(OP_RENAME_SRC, label, &old_path, 0, 412 + error = aa_path_perm(OP_RENAME_SRC, current_cred(), 413 + label, &old_path, 0, 425 414 MAY_READ | AA_MAY_GETATTR | MAY_WRITE | 426 415 AA_MAY_SETATTR | AA_MAY_DELETE, 427 416 &cond); 428 417 if (!error) 429 - error = aa_path_perm(OP_RENAME_DEST, label, &new_path, 418 + error = aa_path_perm(OP_RENAME_DEST, current_cred(), 419 + label, &new_path, 430 420 0, MAY_WRITE | AA_MAY_SETATTR | 431 421 AA_MAY_CREATE, &cond); 432 422 ··· 485 467 vfsuid = i_uid_into_vfsuid(idmap, inode); 486 468 cond.uid = vfsuid_into_kuid(vfsuid); 487 469 488 - error = aa_path_perm(OP_OPEN, label, &file->f_path, 0, 470 + error = aa_path_perm(OP_OPEN, file->f_cred, 471 + label, &file->f_path, 0, 489 472 aa_map_file_to_perms(file), &cond); 490 473 /* todo cache full allowed permissions set and state */ 491 474 fctx->allow = aa_map_file_to_perms(file); ··· 526 507 return -EACCES; 527 508 528 509 label = __begin_current_label_crit_section(); 529 - error = aa_file_perm(op, label, file, mask, in_atomic); 510 + error = aa_file_perm(op, current_cred(), label, file, mask, in_atomic); 530 511 __end_current_label_crit_section(label); 531 512 532 513 return error; ··· 589 570 false); 590 571 } 591 572 573 + #ifdef CONFIG_IO_URING 574 + static const char *audit_uring_mask(u32 mask) 575 + { 576 + if (mask & AA_MAY_CREATE_SQPOLL) 577 + return "sqpoll"; 578 + if (mask & AA_MAY_OVERRIDE_CRED) 579 + return "override_creds"; 580 + return ""; 581 + } 582 + 583 + static void audit_uring_cb(struct audit_buffer *ab, void *va) 584 + { 585 + struct apparmor_audit_data *ad = aad_of_va(va); 586 + 587 + if (ad->request & AA_URING_PERM_MASK) { 588 + audit_log_format(ab, " requested=\"%s\"", 589 + audit_uring_mask(ad->request)); 590 + if (ad->denied & AA_URING_PERM_MASK) { 591 + audit_log_format(ab, " denied=\"%s\"", 592 + audit_uring_mask(ad->denied)); 593 + } 594 + } 595 + if (ad->uring.target) { 596 + audit_log_format(ab, " tcontext="); 597 + aa_label_xaudit(ab, labels_ns(ad->subj_label), 598 + ad->uring.target, 599 + FLAGS_NONE, GFP_ATOMIC); 600 + } 601 + } 602 + 603 + static int profile_uring(struct aa_profile *profile, u32 request, 604 + struct aa_label *new, int cap, 605 + struct apparmor_audit_data *ad) 606 + { 607 + unsigned int state; 608 + struct aa_ruleset *rules; 609 + int error = 0; 610 + 611 + AA_BUG(!profile); 612 + 613 + rules = list_first_entry(&profile->rules, typeof(*rules), list); 614 + state = RULE_MEDIATES(rules, AA_CLASS_IO_URING); 615 + if (state) { 616 + struct aa_perms perms = { }; 617 + 618 + if (new) { 619 + aa_label_match(profile, rules, new, state, 620 + false, request, &perms); 621 + } else { 622 + perms = *aa_lookup_perms(rules->policy, state); 623 + } 624 + aa_apply_modes_to_perms(profile, &perms); 625 + error = aa_check_perms(profile, &perms, request, ad, 626 + audit_uring_cb); 627 + } 628 + 629 + return error; 630 + } 631 + 632 + /** 633 + * apparmor_uring_override_creds - check the requested cred override 634 + * @new: the target creds 635 + * 636 + * Check to see if the current task is allowed to override it's credentials 637 + * to service an io_uring operation. 638 + */ 639 + static int apparmor_uring_override_creds(const struct cred *new) 640 + { 641 + struct aa_profile *profile; 642 + struct aa_label *label; 643 + int error; 644 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_IO_URING, 645 + OP_URING_OVERRIDE); 646 + 647 + ad.uring.target = cred_label(new); 648 + label = __begin_current_label_crit_section(); 649 + error = fn_for_each(label, profile, 650 + profile_uring(profile, AA_MAY_OVERRIDE_CRED, 651 + cred_label(new), CAP_SYS_ADMIN, &ad)); 652 + __end_current_label_crit_section(label); 653 + 654 + return error; 655 + } 656 + 657 + /** 658 + * apparmor_uring_sqpoll - check if a io_uring polling thread can be created 659 + * 660 + * Check to see if the current task is allowed to create a new io_uring 661 + * kernel polling thread. 662 + */ 663 + static int apparmor_uring_sqpoll(void) 664 + { 665 + struct aa_profile *profile; 666 + struct aa_label *label; 667 + int error; 668 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_IO_URING, 669 + OP_URING_SQPOLL); 670 + 671 + label = __begin_current_label_crit_section(); 672 + error = fn_for_each(label, profile, 673 + profile_uring(profile, AA_MAY_CREATE_SQPOLL, 674 + NULL, CAP_SYS_ADMIN, &ad)); 675 + __end_current_label_crit_section(label); 676 + 677 + return error; 678 + } 679 + #endif /* CONFIG_IO_URING */ 680 + 592 681 static int apparmor_sb_mount(const char *dev_name, const struct path *path, 593 682 const char *type, unsigned long flags, void *data) 594 683 { ··· 712 585 label = __begin_current_label_crit_section(); 713 586 if (!unconfined(label)) { 714 587 if (flags & MS_REMOUNT) 715 - error = aa_remount(label, path, flags, data); 588 + error = aa_remount(current_cred(), label, path, flags, 589 + data); 716 590 else if (flags & MS_BIND) 717 - error = aa_bind_mount(label, path, dev_name, flags); 591 + error = aa_bind_mount(current_cred(), label, path, 592 + dev_name, flags); 718 593 else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | 719 594 MS_UNBINDABLE)) 720 - error = aa_mount_change_type(label, path, flags); 595 + error = aa_mount_change_type(current_cred(), label, 596 + path, flags); 721 597 else if (flags & MS_MOVE) 722 - error = aa_move_mount(label, path, dev_name); 598 + error = aa_move_mount_old(current_cred(), label, path, 599 + dev_name); 723 600 else 724 - error = aa_new_mount(label, dev_name, path, type, 725 - flags, data); 601 + error = aa_new_mount(current_cred(), label, dev_name, 602 + path, type, flags, data); 726 603 } 604 + __end_current_label_crit_section(label); 605 + 606 + return error; 607 + } 608 + 609 + static int apparmor_move_mount(const struct path *from_path, 610 + const struct path *to_path) 611 + { 612 + struct aa_label *label; 613 + int error = 0; 614 + 615 + label = __begin_current_label_crit_section(); 616 + if (!unconfined(label)) 617 + error = aa_move_mount(current_cred(), label, from_path, 618 + to_path); 727 619 __end_current_label_crit_section(label); 728 620 729 621 return error; ··· 755 609 756 610 label = __begin_current_label_crit_section(); 757 611 if (!unconfined(label)) 758 - error = aa_umount(label, mnt, flags); 612 + error = aa_umount(current_cred(), label, mnt, flags); 759 613 __end_current_label_crit_section(label); 760 614 761 615 return error; ··· 769 623 770 624 label = aa_get_current_label(); 771 625 if (!unconfined(label)) 772 - error = aa_pivotroot(label, old_path, new_path); 626 + error = aa_pivotroot(current_cred(), label, old_path, new_path); 773 627 aa_put_label(label); 774 628 775 629 return error; ··· 808 662 char *command, *largs = NULL, *args = value; 809 663 size_t arg_size; 810 664 int error; 811 - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, 665 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, 812 666 OP_SETPROCATTR); 813 667 814 668 if (size == 0) ··· 868 722 return error; 869 723 870 724 fail: 871 - aad(&sa)->label = begin_current_label_crit_section(); 872 - aad(&sa)->info = name; 873 - aad(&sa)->error = error = -EINVAL; 874 - aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL); 875 - end_current_label_crit_section(aad(&sa)->label); 725 + ad.subj_label = begin_current_label_crit_section(); 726 + ad.info = name; 727 + ad.error = error = -EINVAL; 728 + aa_audit_msg(AUDIT_APPARMOR_DENIED, &ad, NULL); 729 + end_current_label_crit_section(ad.subj_label); 876 730 goto out; 877 731 } 878 732 ··· 912 766 913 767 static void apparmor_current_getsecid_subj(u32 *secid) 914 768 { 915 - struct aa_label *label = aa_get_current_label(); 769 + struct aa_label *label = __begin_current_label_crit_section(); 916 770 *secid = label->secid; 917 - aa_put_label(label); 771 + __end_current_label_crit_section(label); 918 772 } 919 773 920 774 static void apparmor_task_getsecid_obj(struct task_struct *p, u32 *secid) ··· 931 785 int error = 0; 932 786 933 787 if (!unconfined(label)) 934 - error = aa_task_setrlimit(label, task, resource, new_rlim); 788 + error = aa_task_setrlimit(current_cred(), label, task, 789 + resource, new_rlim); 935 790 __end_current_label_crit_section(label); 936 791 937 792 return error; ··· 941 794 static int apparmor_task_kill(struct task_struct *target, struct kernel_siginfo *info, 942 795 int sig, const struct cred *cred) 943 796 { 797 + const struct cred *tc; 944 798 struct aa_label *cl, *tl; 945 799 int error; 946 800 801 + tc = get_task_cred(target); 802 + tl = aa_get_newest_cred_label(tc); 947 803 if (cred) { 948 804 /* 949 805 * Dealing with USB IO specific behavior 950 806 */ 951 807 cl = aa_get_newest_cred_label(cred); 952 - tl = aa_get_task_label(target); 953 - error = aa_may_signal(cl, tl, sig); 808 + error = aa_may_signal(cred, cl, tc, tl, sig); 954 809 aa_put_label(cl); 955 - aa_put_label(tl); 956 810 return error; 811 + } else { 812 + cl = __begin_current_label_crit_section(); 813 + error = aa_may_signal(current_cred(), cl, tc, tl, sig); 814 + __end_current_label_crit_section(cl); 957 815 } 958 - 959 - cl = __begin_current_label_crit_section(); 960 - tl = aa_get_task_label(target); 961 - error = aa_may_signal(cl, tl, sig); 962 816 aa_put_label(tl); 963 - __end_current_label_crit_section(cl); 817 + put_cred(tc); 818 + 819 + return error; 820 + } 821 + 822 + static int apparmor_userns_create(const struct cred *cred) 823 + { 824 + struct aa_label *label; 825 + struct aa_profile *profile; 826 + int error = 0; 827 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_TASK, AA_CLASS_NS, 828 + OP_USERNS_CREATE); 829 + 830 + ad.subj_cred = current_cred(); 831 + 832 + label = begin_current_label_crit_section(); 833 + if (!unconfined(label)) { 834 + error = fn_for_each(label, profile, 835 + aa_profile_ns_perm(profile, &ad, 836 + AA_USERNS_CREATE)); 837 + } 838 + end_current_label_crit_section(label); 964 839 965 840 return error; 966 841 } ··· 998 829 if (!ctx) 999 830 return -ENOMEM; 1000 831 1001 - SK_CTX(sk) = ctx; 832 + sk->sk_security = ctx; 1002 833 1003 834 return 0; 1004 835 } ··· 1008 839 */ 1009 840 static void apparmor_sk_free_security(struct sock *sk) 1010 841 { 1011 - struct aa_sk_ctx *ctx = SK_CTX(sk); 842 + struct aa_sk_ctx *ctx = aa_sock(sk); 1012 843 1013 - SK_CTX(sk) = NULL; 844 + sk->sk_security = NULL; 1014 845 aa_put_label(ctx->label); 1015 846 aa_put_label(ctx->peer); 1016 847 kfree(ctx); ··· 1022 853 static void apparmor_sk_clone_security(const struct sock *sk, 1023 854 struct sock *newsk) 1024 855 { 1025 - struct aa_sk_ctx *ctx = SK_CTX(sk); 1026 - struct aa_sk_ctx *new = SK_CTX(newsk); 856 + struct aa_sk_ctx *ctx = aa_sock(sk); 857 + struct aa_sk_ctx *new = aa_sock(newsk); 1027 858 1028 859 if (new->label) 1029 860 aa_put_label(new->label); ··· 1048 879 if (!(kern || unconfined(label))) 1049 880 error = af_select(family, 1050 881 create_perm(label, family, type, protocol), 1051 - aa_af_perm(label, OP_CREATE, AA_MAY_CREATE, 882 + aa_af_perm(current_cred(), label, 883 + OP_CREATE, AA_MAY_CREATE, 1052 884 family, type, protocol)); 1053 885 end_current_label_crit_section(label); 1054 886 ··· 1077 907 label = aa_get_current_label(); 1078 908 1079 909 if (sock->sk) { 1080 - struct aa_sk_ctx *ctx = SK_CTX(sock->sk); 910 + struct aa_sk_ctx *ctx = aa_sock(sock->sk); 1081 911 1082 912 aa_put_label(ctx->label); 1083 913 ctx->label = aa_get_label(label); ··· 1262 1092 */ 1263 1093 static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 1264 1094 { 1265 - struct aa_sk_ctx *ctx = SK_CTX(sk); 1095 + struct aa_sk_ctx *ctx = aa_sock(sk); 1266 1096 1267 1097 if (!skb->secmark) 1268 1098 return 0; ··· 1275 1105 1276 1106 static struct aa_label *sk_peer_label(struct sock *sk) 1277 1107 { 1278 - struct aa_sk_ctx *ctx = SK_CTX(sk); 1108 + struct aa_sk_ctx *ctx = aa_sock(sk); 1279 1109 1280 1110 if (ctx->peer) 1281 1111 return ctx->peer; ··· 1356 1186 */ 1357 1187 static void apparmor_sock_graft(struct sock *sk, struct socket *parent) 1358 1188 { 1359 - struct aa_sk_ctx *ctx = SK_CTX(sk); 1189 + struct aa_sk_ctx *ctx = aa_sock(sk); 1360 1190 1361 1191 if (!ctx->label) 1362 1192 ctx->label = aa_get_current_label(); ··· 1366 1196 static int apparmor_inet_conn_request(const struct sock *sk, struct sk_buff *skb, 1367 1197 struct request_sock *req) 1368 1198 { 1369 - struct aa_sk_ctx *ctx = SK_CTX(sk); 1199 + struct aa_sk_ctx *ctx = aa_sock(sk); 1370 1200 1371 1201 if (!skb->secmark) 1372 1202 return 0; ··· 1391 1221 LSM_HOOK_INIT(capget, apparmor_capget), 1392 1222 LSM_HOOK_INIT(capable, apparmor_capable), 1393 1223 1224 + LSM_HOOK_INIT(move_mount, apparmor_move_mount), 1394 1225 LSM_HOOK_INIT(sb_mount, apparmor_sb_mount), 1395 1226 LSM_HOOK_INIT(sb_umount, apparmor_sb_umount), 1396 1227 LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot), ··· 1465 1294 LSM_HOOK_INIT(task_getsecid_obj, apparmor_task_getsecid_obj), 1466 1295 LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit), 1467 1296 LSM_HOOK_INIT(task_kill, apparmor_task_kill), 1297 + LSM_HOOK_INIT(userns_create, apparmor_userns_create), 1468 1298 1469 1299 #ifdef CONFIG_AUDIT 1470 1300 LSM_HOOK_INIT(audit_rule_init, aa_audit_rule_init), ··· 1477 1305 LSM_HOOK_INIT(secid_to_secctx, apparmor_secid_to_secctx), 1478 1306 LSM_HOOK_INIT(secctx_to_secid, apparmor_secctx_to_secid), 1479 1307 LSM_HOOK_INIT(release_secctx, apparmor_release_secctx), 1308 + 1309 + #ifdef CONFIG_IO_URING 1310 + LSM_HOOK_INIT(uring_override_creds, apparmor_uring_override_creds), 1311 + LSM_HOOK_INIT(uring_sqpoll, apparmor_uring_sqpoll), 1312 + #endif 1480 1313 }; 1481 1314 1482 1315 /* ··· 1812 1635 char *aa_get_buffer(bool in_atomic) 1813 1636 { 1814 1637 union aa_buffer *aa_buf; 1638 + struct aa_local_cache *cache; 1815 1639 bool try_again = true; 1816 1640 gfp_t flags = (GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN); 1817 1641 1642 + /* use per cpu cached buffers first */ 1643 + cache = get_cpu_ptr(&aa_local_buffers); 1644 + if (!list_empty(&cache->head)) { 1645 + aa_buf = list_first_entry(&cache->head, union aa_buffer, list); 1646 + list_del(&aa_buf->list); 1647 + cache->hold--; 1648 + cache->count--; 1649 + put_cpu_ptr(&aa_local_buffers); 1650 + return &aa_buf->buffer[0]; 1651 + } 1652 + put_cpu_ptr(&aa_local_buffers); 1653 + 1654 + if (!spin_trylock(&aa_buffers_lock)) { 1655 + cache = get_cpu_ptr(&aa_local_buffers); 1656 + cache->hold += 1; 1657 + put_cpu_ptr(&aa_local_buffers); 1658 + spin_lock(&aa_buffers_lock); 1659 + } else { 1660 + cache = get_cpu_ptr(&aa_local_buffers); 1661 + put_cpu_ptr(&aa_local_buffers); 1662 + } 1818 1663 retry: 1819 - spin_lock(&aa_buffers_lock); 1820 1664 if (buffer_count > reserve_count || 1821 1665 (in_atomic && !list_empty(&aa_global_buffers))) { 1822 1666 aa_buf = list_first_entry(&aa_global_buffers, union aa_buffer, ··· 1863 1665 if (!aa_buf) { 1864 1666 if (try_again) { 1865 1667 try_again = false; 1668 + spin_lock(&aa_buffers_lock); 1866 1669 goto retry; 1867 1670 } 1868 1671 pr_warn_once("AppArmor: Failed to allocate a memory buffer.\n"); ··· 1875 1676 void aa_put_buffer(char *buf) 1876 1677 { 1877 1678 union aa_buffer *aa_buf; 1679 + struct aa_local_cache *cache; 1878 1680 1879 1681 if (!buf) 1880 1682 return; 1881 1683 aa_buf = container_of(buf, union aa_buffer, buffer[0]); 1882 1684 1883 - spin_lock(&aa_buffers_lock); 1884 - list_add(&aa_buf->list, &aa_global_buffers); 1885 - buffer_count++; 1886 - spin_unlock(&aa_buffers_lock); 1685 + cache = get_cpu_ptr(&aa_local_buffers); 1686 + if (!cache->hold) { 1687 + put_cpu_ptr(&aa_local_buffers); 1688 + 1689 + if (spin_trylock(&aa_buffers_lock)) { 1690 + /* put back on global list */ 1691 + list_add(&aa_buf->list, &aa_global_buffers); 1692 + buffer_count++; 1693 + spin_unlock(&aa_buffers_lock); 1694 + cache = get_cpu_ptr(&aa_local_buffers); 1695 + put_cpu_ptr(&aa_local_buffers); 1696 + return; 1697 + } 1698 + /* contention on global list, fallback to percpu */ 1699 + cache = get_cpu_ptr(&aa_local_buffers); 1700 + cache->hold += 1; 1701 + } 1702 + 1703 + /* cache in percpu list */ 1704 + list_add(&aa_buf->list, &cache->head); 1705 + cache->count++; 1706 + put_cpu_ptr(&aa_local_buffers); 1887 1707 } 1888 1708 1889 1709 /* ··· 1945 1727 int i, num; 1946 1728 1947 1729 /* 1730 + * per cpu set of cached allocated buffers used to help reduce 1731 + * lock contention 1732 + */ 1733 + for_each_possible_cpu(i) { 1734 + per_cpu(aa_local_buffers, i).hold = 0; 1735 + per_cpu(aa_local_buffers, i).count = 0; 1736 + INIT_LIST_HEAD(&per_cpu(aa_local_buffers, i).head); 1737 + } 1738 + /* 1948 1739 * A function may require two buffers at once. Usually the buffers are 1949 1740 * used for a short period of time and are shared. On UP kernel buffers 1950 1741 * two should be enough, with more CPUs it is possible that more ··· 1992 1765 } 1993 1766 1994 1767 static struct ctl_table apparmor_sysctl_table[] = { 1768 + #ifdef CONFIG_USER_NS 1995 1769 { 1996 1770 .procname = "unprivileged_userns_apparmor_policy", 1997 1771 .data = &unprivileged_userns_apparmor_policy, ··· 2000 1772 .mode = 0600, 2001 1773 .proc_handler = apparmor_dointvec, 2002 1774 }, 1775 + #endif /* CONFIG_USER_NS */ 2003 1776 { 2004 1777 .procname = "apparmor_display_secid_mode", 2005 1778 .data = &apparmor_display_secid_mode, ··· 2008 1779 .mode = 0600, 2009 1780 .proc_handler = apparmor_dointvec, 2010 1781 }, 2011 - 1782 + { 1783 + .procname = "apparmor_restrict_unprivileged_unconfined", 1784 + .data = &aa_unprivileged_unconfined_restricted, 1785 + .maxlen = sizeof(int), 1786 + .mode = 0600, 1787 + .proc_handler = apparmor_dointvec, 1788 + }, 2012 1789 { } 2013 1790 }; 2014 1791 ··· 2044 1809 if (sk == NULL) 2045 1810 return NF_ACCEPT; 2046 1811 2047 - ctx = SK_CTX(sk); 1812 + ctx = aa_sock(sk); 2048 1813 if (!apparmor_secmark_check(ctx->label, OP_SENDMSG, AA_MAY_SEND, 2049 1814 skb->secmark, sk)) 2050 1815 return NF_ACCEPT; ··· 2102 1867 } 2103 1868 __initcall(apparmor_nf_ip_init); 2104 1869 #endif 1870 + 1871 + static char nulldfa_src[] = { 1872 + #include "nulldfa.in" 1873 + }; 1874 + struct aa_dfa *nulldfa; 1875 + 1876 + static char stacksplitdfa_src[] = { 1877 + #include "stacksplitdfa.in" 1878 + }; 1879 + struct aa_dfa *stacksplitdfa; 1880 + struct aa_policydb *nullpdb; 1881 + 1882 + static int __init aa_setup_dfa_engine(void) 1883 + { 1884 + int error = -ENOMEM; 1885 + 1886 + nullpdb = aa_alloc_pdb(GFP_KERNEL); 1887 + if (!nullpdb) 1888 + return -ENOMEM; 1889 + 1890 + nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src), 1891 + TO_ACCEPT1_FLAG(YYTD_DATA32) | 1892 + TO_ACCEPT2_FLAG(YYTD_DATA32)); 1893 + if (IS_ERR(nulldfa)) { 1894 + error = PTR_ERR(nulldfa); 1895 + goto fail; 1896 + } 1897 + nullpdb->dfa = aa_get_dfa(nulldfa); 1898 + nullpdb->perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL); 1899 + if (!nullpdb->perms) 1900 + goto fail; 1901 + nullpdb->size = 2; 1902 + 1903 + stacksplitdfa = aa_dfa_unpack(stacksplitdfa_src, 1904 + sizeof(stacksplitdfa_src), 1905 + TO_ACCEPT1_FLAG(YYTD_DATA32) | 1906 + TO_ACCEPT2_FLAG(YYTD_DATA32)); 1907 + if (IS_ERR(stacksplitdfa)) { 1908 + error = PTR_ERR(stacksplitdfa); 1909 + goto fail; 1910 + } 1911 + 1912 + return 0; 1913 + 1914 + fail: 1915 + aa_put_pdb(nullpdb); 1916 + aa_put_dfa(nulldfa); 1917 + nullpdb = NULL; 1918 + nulldfa = NULL; 1919 + stacksplitdfa = NULL; 1920 + 1921 + return error; 1922 + } 1923 + 1924 + static void __init aa_teardown_dfa_engine(void) 1925 + { 1926 + aa_put_dfa(stacksplitdfa); 1927 + aa_put_dfa(nulldfa); 1928 + aa_put_pdb(nullpdb); 1929 + nullpdb = NULL; 1930 + stacksplitdfa = NULL; 1931 + nulldfa = NULL; 1932 + } 2105 1933 2106 1934 static int __init apparmor_init(void) 2107 1935 {
+2 -46
security/apparmor/match.c
··· 21 21 22 22 #define base_idx(X) ((X) & 0xffffff) 23 23 24 - static char nulldfa_src[] = { 25 - #include "nulldfa.in" 26 - }; 27 - struct aa_dfa *nulldfa; 28 - 29 - static char stacksplitdfa_src[] = { 30 - #include "stacksplitdfa.in" 31 - }; 32 - struct aa_dfa *stacksplitdfa; 33 - 34 - int __init aa_setup_dfa_engine(void) 35 - { 36 - int error; 37 - 38 - nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src), 39 - TO_ACCEPT1_FLAG(YYTD_DATA32) | 40 - TO_ACCEPT2_FLAG(YYTD_DATA32)); 41 - if (IS_ERR(nulldfa)) { 42 - error = PTR_ERR(nulldfa); 43 - nulldfa = NULL; 44 - return error; 45 - } 46 - 47 - stacksplitdfa = aa_dfa_unpack(stacksplitdfa_src, 48 - sizeof(stacksplitdfa_src), 49 - TO_ACCEPT1_FLAG(YYTD_DATA32) | 50 - TO_ACCEPT2_FLAG(YYTD_DATA32)); 51 - if (IS_ERR(stacksplitdfa)) { 52 - aa_put_dfa(nulldfa); 53 - nulldfa = NULL; 54 - error = PTR_ERR(stacksplitdfa); 55 - stacksplitdfa = NULL; 56 - return error; 57 - } 58 - 59 - return 0; 60 - } 61 - 62 - void __init aa_teardown_dfa_engine(void) 63 - { 64 - aa_put_dfa(stacksplitdfa); 65 - aa_put_dfa(nulldfa); 66 - } 67 - 68 24 /** 69 25 * unpack_table - unpack a dfa table (one of accept, default, base, next check) 70 26 * @blob: data to unpack (NOT NULL) ··· 92 136 93 137 /** 94 138 * verify_table_headers - verify that the tables headers are as expected 95 - * @tables - array of dfa tables to check (NOT NULL) 139 + * @tables: array of dfa tables to check (NOT NULL) 96 140 * @flags: flags controlling what type of accept table are acceptable 97 141 * 98 142 * Assumes dfa has gone through the first pass verification done by unpacking ··· 239 283 240 284 /** 241 285 * aa_dfa_free_kref - free aa_dfa by kref (called by aa_put_dfa) 242 - * @kr: kref callback for freeing of a dfa (NOT NULL) 286 + * @kref: kref callback for freeing of a dfa (NOT NULL) 243 287 */ 244 288 void aa_dfa_free_kref(struct kref *kref) 245 289 {
+111 -75
security/apparmor/mount.c
··· 86 86 static void audit_cb(struct audit_buffer *ab, void *va) 87 87 { 88 88 struct common_audit_data *sa = va; 89 + struct apparmor_audit_data *ad = aad(sa); 89 90 90 - if (aad(sa)->mnt.type) { 91 + if (ad->mnt.type) { 91 92 audit_log_format(ab, " fstype="); 92 - audit_log_untrustedstring(ab, aad(sa)->mnt.type); 93 + audit_log_untrustedstring(ab, ad->mnt.type); 93 94 } 94 - if (aad(sa)->mnt.src_name) { 95 + if (ad->mnt.src_name) { 95 96 audit_log_format(ab, " srcname="); 96 - audit_log_untrustedstring(ab, aad(sa)->mnt.src_name); 97 + audit_log_untrustedstring(ab, ad->mnt.src_name); 97 98 } 98 - if (aad(sa)->mnt.trans) { 99 + if (ad->mnt.trans) { 99 100 audit_log_format(ab, " trans="); 100 - audit_log_untrustedstring(ab, aad(sa)->mnt.trans); 101 + audit_log_untrustedstring(ab, ad->mnt.trans); 101 102 } 102 - if (aad(sa)->mnt.flags) { 103 + if (ad->mnt.flags) { 103 104 audit_log_format(ab, " flags=\""); 104 - audit_mnt_flags(ab, aad(sa)->mnt.flags); 105 + audit_mnt_flags(ab, ad->mnt.flags); 105 106 audit_log_format(ab, "\""); 106 107 } 107 - if (aad(sa)->mnt.data) { 108 + if (ad->mnt.data) { 108 109 audit_log_format(ab, " options="); 109 - audit_log_untrustedstring(ab, aad(sa)->mnt.data); 110 + audit_log_untrustedstring(ab, ad->mnt.data); 110 111 } 111 112 } 112 113 113 114 /** 114 115 * audit_mount - handle the auditing of mount operations 116 + * @subj_cred: cred of the subject 115 117 * @profile: the profile being enforced (NOT NULL) 116 118 * @op: operation being mediated (NOT NULL) 117 119 * @name: name of object being mediated (MAYBE NULL) ··· 129 127 * 130 128 * Returns: %0 or error on failure 131 129 */ 132 - static int audit_mount(struct aa_profile *profile, const char *op, 130 + static int audit_mount(const struct cred *subj_cred, 131 + struct aa_profile *profile, const char *op, 133 132 const char *name, const char *src_name, 134 133 const char *type, const char *trans, 135 134 unsigned long flags, const void *data, u32 request, 136 135 struct aa_perms *perms, const char *info, int error) 137 136 { 138 137 int audit_type = AUDIT_APPARMOR_AUTO; 139 - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_MOUNT, op); 138 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_MOUNT, op); 140 139 141 140 if (likely(!error)) { 142 141 u32 mask = perms->audit; ··· 168 165 return error; 169 166 } 170 167 171 - aad(&sa)->name = name; 172 - aad(&sa)->mnt.src_name = src_name; 173 - aad(&sa)->mnt.type = type; 174 - aad(&sa)->mnt.trans = trans; 175 - aad(&sa)->mnt.flags = flags; 168 + ad.subj_cred = subj_cred; 169 + ad.name = name; 170 + ad.mnt.src_name = src_name; 171 + ad.mnt.type = type; 172 + ad.mnt.trans = trans; 173 + ad.mnt.flags = flags; 176 174 if (data && (perms->audit & AA_AUDIT_DATA)) 177 - aad(&sa)->mnt.data = data; 178 - aad(&sa)->info = info; 179 - aad(&sa)->error = error; 175 + ad.mnt.data = data; 176 + ad.info = info; 177 + ad.error = error; 180 178 181 - return aa_audit(audit_type, profile, &sa, audit_cb); 179 + return aa_audit(audit_type, profile, &ad, audit_cb); 182 180 } 183 181 184 182 /** ··· 287 283 288 284 /** 289 285 * match_mnt_path_str - handle path matching for mount 286 + * @subj_cred: cred of confined subject 290 287 * @profile: the confining profile 291 288 * @mntpath: for the mntpnt (NOT NULL) 292 289 * @buffer: buffer to be used to lookup mntpath ··· 300 295 * 301 296 * Returns: 0 on success else error 302 297 */ 303 - static int match_mnt_path_str(struct aa_profile *profile, 298 + static int match_mnt_path_str(const struct cred *subj_cred, 299 + struct aa_profile *profile, 304 300 const struct path *mntpath, char *buffer, 305 301 const char *devname, const char *type, 306 302 unsigned long flags, void *data, bool binary, ··· 332 326 } 333 327 334 328 error = -EACCES; 335 - pos = do_match_mnt(&rules->policy, 336 - rules->policy.start[AA_CLASS_MOUNT], 329 + pos = do_match_mnt(rules->policy, 330 + rules->policy->start[AA_CLASS_MOUNT], 337 331 mntpnt, devname, type, flags, data, binary, &perms); 338 332 if (pos) { 339 333 info = mnt_info_table[pos]; ··· 342 336 error = 0; 343 337 344 338 audit: 345 - return audit_mount(profile, OP_MOUNT, mntpnt, devname, type, NULL, 339 + return audit_mount(subj_cred, profile, OP_MOUNT, mntpnt, devname, 340 + type, NULL, 346 341 flags, data, AA_MAY_MOUNT, &perms, info, error); 347 342 } 348 343 349 344 /** 350 345 * match_mnt - handle path matching for mount 346 + * @subj_cred: cred of the subject 351 347 * @profile: the confining profile 352 348 * @path: for the mntpnt (NOT NULL) 353 349 * @buffer: buffer to be used to lookup mntpath ··· 362 354 * 363 355 * Returns: 0 on success else error 364 356 */ 365 - static int match_mnt(struct aa_profile *profile, const struct path *path, 357 + static int match_mnt(const struct cred *subj_cred, 358 + struct aa_profile *profile, const struct path *path, 366 359 char *buffer, const struct path *devpath, char *devbuffer, 367 360 const char *type, unsigned long flags, void *data, 368 361 bool binary) ··· 387 378 devname = ERR_PTR(error); 388 379 } 389 380 390 - return match_mnt_path_str(profile, path, buffer, devname, type, flags, 391 - data, binary, info); 381 + return match_mnt_path_str(subj_cred, profile, path, buffer, devname, 382 + type, flags, data, binary, info); 392 383 } 393 384 394 - int aa_remount(struct aa_label *label, const struct path *path, 385 + int aa_remount(const struct cred *subj_cred, 386 + struct aa_label *label, const struct path *path, 395 387 unsigned long flags, void *data) 396 388 { 397 389 struct aa_profile *profile; ··· 409 399 if (!buffer) 410 400 return -ENOMEM; 411 401 error = fn_for_each_confined(label, profile, 412 - match_mnt(profile, path, buffer, NULL, NULL, NULL, 402 + match_mnt(subj_cred, profile, path, buffer, NULL, 403 + NULL, NULL, 413 404 flags, data, binary)); 414 405 aa_put_buffer(buffer); 415 406 416 407 return error; 417 408 } 418 409 419 - int aa_bind_mount(struct aa_label *label, const struct path *path, 410 + int aa_bind_mount(const struct cred *subj_cred, 411 + struct aa_label *label, const struct path *path, 420 412 const char *dev_name, unsigned long flags) 421 413 { 422 414 struct aa_profile *profile; ··· 445 433 goto out; 446 434 447 435 error = fn_for_each_confined(label, profile, 448 - match_mnt(profile, path, buffer, &old_path, old_buffer, 449 - NULL, flags, NULL, false)); 436 + match_mnt(subj_cred, profile, path, buffer, &old_path, 437 + old_buffer, NULL, flags, NULL, false)); 450 438 out: 451 439 aa_put_buffer(buffer); 452 440 aa_put_buffer(old_buffer); ··· 455 443 return error; 456 444 } 457 445 458 - int aa_mount_change_type(struct aa_label *label, const struct path *path, 446 + int aa_mount_change_type(const struct cred *subj_cred, 447 + struct aa_label *label, const struct path *path, 459 448 unsigned long flags) 460 449 { 461 450 struct aa_profile *profile; ··· 474 461 if (!buffer) 475 462 return -ENOMEM; 476 463 error = fn_for_each_confined(label, profile, 477 - match_mnt(profile, path, buffer, NULL, NULL, NULL, 464 + match_mnt(subj_cred, profile, path, buffer, NULL, 465 + NULL, NULL, 478 466 flags, NULL, false)); 479 467 aa_put_buffer(buffer); 480 468 481 469 return error; 482 470 } 483 471 484 - int aa_move_mount(struct aa_label *label, const struct path *path, 485 - const char *orig_name) 472 + int aa_move_mount(const struct cred *subj_cred, 473 + struct aa_label *label, const struct path *from_path, 474 + const struct path *to_path) 486 475 { 487 476 struct aa_profile *profile; 488 - char *buffer = NULL, *old_buffer = NULL; 489 - struct path old_path; 477 + char *to_buffer = NULL, *from_buffer = NULL; 490 478 int error; 491 479 492 480 AA_BUG(!label); 493 - AA_BUG(!path); 481 + AA_BUG(!from_path); 482 + AA_BUG(!to_path); 483 + 484 + to_buffer = aa_get_buffer(false); 485 + from_buffer = aa_get_buffer(false); 486 + error = -ENOMEM; 487 + if (!to_buffer || !from_buffer) 488 + goto out; 489 + error = fn_for_each_confined(label, profile, 490 + match_mnt(subj_cred, profile, to_path, to_buffer, 491 + from_path, from_buffer, 492 + NULL, MS_MOVE, NULL, false)); 493 + out: 494 + aa_put_buffer(to_buffer); 495 + aa_put_buffer(from_buffer); 496 + 497 + return error; 498 + } 499 + 500 + int aa_move_mount_old(const struct cred *subj_cred, struct aa_label *label, 501 + const struct path *path, const char *orig_name) 502 + { 503 + struct path old_path; 504 + int error; 494 505 495 506 if (!orig_name || !*orig_name) 496 507 return -EINVAL; 497 - 498 508 error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path); 499 509 if (error) 500 510 return error; 501 511 502 - buffer = aa_get_buffer(false); 503 - old_buffer = aa_get_buffer(false); 504 - error = -ENOMEM; 505 - if (!buffer || !old_buffer) 506 - goto out; 507 - error = fn_for_each_confined(label, profile, 508 - match_mnt(profile, path, buffer, &old_path, old_buffer, 509 - NULL, MS_MOVE, NULL, false)); 510 - out: 511 - aa_put_buffer(buffer); 512 - aa_put_buffer(old_buffer); 512 + error = aa_move_mount(subj_cred, label, &old_path, path); 513 513 path_put(&old_path); 514 514 515 515 return error; 516 516 } 517 517 518 - int aa_new_mount(struct aa_label *label, const char *dev_name, 519 - const struct path *path, const char *type, unsigned long flags, 520 - void *data) 518 + int aa_new_mount(const struct cred *subj_cred, struct aa_label *label, 519 + const char *dev_name, const struct path *path, 520 + const char *type, unsigned long flags, void *data) 521 521 { 522 522 struct aa_profile *profile; 523 523 char *buffer = NULL, *dev_buffer = NULL; ··· 575 549 goto out; 576 550 } 577 551 error = fn_for_each_confined(label, profile, 578 - match_mnt(profile, path, buffer, dev_path, dev_buffer, 552 + match_mnt(subj_cred, profile, path, buffer, 553 + dev_path, dev_buffer, 579 554 type, flags, data, binary)); 580 555 } else { 581 556 error = fn_for_each_confined(label, profile, 582 - match_mnt_path_str(profile, path, buffer, dev_name, 583 - type, flags, data, binary, NULL)); 557 + match_mnt_path_str(subj_cred, profile, path, 558 + buffer, dev_name, 559 + type, flags, data, binary, NULL)); 584 560 } 585 561 586 562 out: ··· 594 566 return error; 595 567 } 596 568 597 - static int profile_umount(struct aa_profile *profile, const struct path *path, 569 + static int profile_umount(const struct cred *subj_cred, 570 + struct aa_profile *profile, const struct path *path, 598 571 char *buffer) 599 572 { 600 573 struct aa_ruleset *rules = list_first_entry(&profile->rules, ··· 616 587 if (error) 617 588 goto audit; 618 589 619 - state = aa_dfa_match(rules->policy.dfa, 620 - rules->policy.start[AA_CLASS_MOUNT], 590 + state = aa_dfa_match(rules->policy->dfa, 591 + rules->policy->start[AA_CLASS_MOUNT], 621 592 name); 622 - perms = *aa_lookup_perms(&rules->policy, state); 593 + perms = *aa_lookup_perms(rules->policy, state); 623 594 if (AA_MAY_UMOUNT & ~perms.allow) 624 595 error = -EACCES; 625 596 626 597 audit: 627 - return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL, 598 + return audit_mount(subj_cred, profile, OP_UMOUNT, name, NULL, NULL, 599 + NULL, 0, NULL, 628 600 AA_MAY_UMOUNT, &perms, info, error); 629 601 } 630 602 631 - int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags) 603 + int aa_umount(const struct cred *subj_cred, struct aa_label *label, 604 + struct vfsmount *mnt, int flags) 632 605 { 633 606 struct aa_profile *profile; 634 607 char *buffer = NULL; ··· 645 614 return -ENOMEM; 646 615 647 616 error = fn_for_each_confined(label, profile, 648 - profile_umount(profile, &path, buffer)); 617 + profile_umount(subj_cred, profile, &path, buffer)); 649 618 aa_put_buffer(buffer); 650 619 651 620 return error; ··· 655 624 * 656 625 * Returns: label for transition or ERR_PTR. Does not return NULL 657 626 */ 658 - static struct aa_label *build_pivotroot(struct aa_profile *profile, 627 + static struct aa_label *build_pivotroot(const struct cred *subj_cred, 628 + struct aa_profile *profile, 659 629 const struct path *new_path, 660 630 char *new_buffer, 661 631 const struct path *old_path, ··· 690 658 goto audit; 691 659 692 660 error = -EACCES; 693 - state = aa_dfa_match(rules->policy.dfa, 694 - rules->policy.start[AA_CLASS_MOUNT], 661 + state = aa_dfa_match(rules->policy->dfa, 662 + rules->policy->start[AA_CLASS_MOUNT], 695 663 new_name); 696 - state = aa_dfa_null_transition(rules->policy.dfa, state); 697 - state = aa_dfa_match(rules->policy.dfa, state, old_name); 698 - perms = *aa_lookup_perms(&rules->policy, state); 664 + state = aa_dfa_null_transition(rules->policy->dfa, state); 665 + state = aa_dfa_match(rules->policy->dfa, state, old_name); 666 + perms = *aa_lookup_perms(rules->policy, state); 699 667 700 668 if (AA_MAY_PIVOTROOT & perms.allow) 701 669 error = 0; 702 670 703 671 audit: 704 - error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name, 672 + error = audit_mount(subj_cred, profile, OP_PIVOTROOT, new_name, 673 + old_name, 705 674 NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT, 706 675 &perms, info, error); 707 676 if (error) ··· 711 678 return aa_get_newest_label(&profile->label); 712 679 } 713 680 714 - int aa_pivotroot(struct aa_label *label, const struct path *old_path, 681 + int aa_pivotroot(const struct cred *subj_cred, struct aa_label *label, 682 + const struct path *old_path, 715 683 const struct path *new_path) 716 684 { 717 685 struct aa_profile *profile; ··· 730 696 if (!old_buffer || !new_buffer) 731 697 goto out; 732 698 target = fn_label_build(label, profile, GFP_KERNEL, 733 - build_pivotroot(profile, new_path, new_buffer, 699 + build_pivotroot(subj_cred, profile, new_path, 700 + new_buffer, 734 701 old_path, old_buffer)); 735 702 if (!target) { 736 703 info = "label build failed"; ··· 757 722 fail: 758 723 /* TODO: add back in auditing of new_name and old_name */ 759 724 error = fn_for_each(label, profile, 760 - audit_mount(profile, OP_PIVOTROOT, NULL /*new_name */, 725 + audit_mount(subj_cred, profile, OP_PIVOTROOT, 726 + NULL /*new_name */, 761 727 NULL /* old_name */, 762 728 NULL, NULL, 763 729 0, NULL, AA_MAY_PIVOTROOT, &nullperms, info,
+35 -30
security/apparmor/net.c
··· 71 71 void audit_net_cb(struct audit_buffer *ab, void *va) 72 72 { 73 73 struct common_audit_data *sa = va; 74 + struct apparmor_audit_data *ad = aad(sa); 74 75 75 76 if (address_family_names[sa->u.net->family]) 76 77 audit_log_format(ab, " family=\"%s\"", ··· 79 78 else 80 79 audit_log_format(ab, " family=\"unknown(%d)\"", 81 80 sa->u.net->family); 82 - if (sock_type_names[aad(sa)->net.type]) 81 + if (sock_type_names[ad->net.type]) 83 82 audit_log_format(ab, " sock_type=\"%s\"", 84 - sock_type_names[aad(sa)->net.type]); 83 + sock_type_names[ad->net.type]); 85 84 else 86 85 audit_log_format(ab, " sock_type=\"unknown(%d)\"", 87 - aad(sa)->net.type); 88 - audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol); 86 + ad->net.type); 87 + audit_log_format(ab, " protocol=%d", ad->net.protocol); 89 88 90 - if (aad(sa)->request & NET_PERMS_MASK) { 89 + if (ad->request & NET_PERMS_MASK) { 91 90 audit_log_format(ab, " requested_mask="); 92 - aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0, 91 + aa_audit_perm_mask(ab, ad->request, NULL, 0, 93 92 net_mask_names, NET_PERMS_MASK); 94 93 95 - if (aad(sa)->denied & NET_PERMS_MASK) { 94 + if (ad->denied & NET_PERMS_MASK) { 96 95 audit_log_format(ab, " denied_mask="); 97 - aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0, 96 + aa_audit_perm_mask(ab, ad->denied, NULL, 0, 98 97 net_mask_names, NET_PERMS_MASK); 99 98 } 100 99 } 101 - if (aad(sa)->peer) { 100 + if (ad->peer) { 102 101 audit_log_format(ab, " peer="); 103 - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 102 + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, 104 103 FLAGS_NONE, GFP_ATOMIC); 105 104 } 106 105 } 107 106 108 107 /* Generic af perm */ 109 - int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, 110 - u32 request, u16 family, int type) 108 + int aa_profile_af_perm(struct aa_profile *profile, 109 + struct apparmor_audit_data *ad, u32 request, u16 family, 110 + int type) 111 111 { 112 112 struct aa_ruleset *rules = list_first_entry(&profile->rules, 113 113 typeof(*rules), list); ··· 127 125 128 126 buffer[0] = cpu_to_be16(family); 129 127 buffer[1] = cpu_to_be16((u16) type); 130 - state = aa_dfa_match_len(rules->policy.dfa, state, (char *) &buffer, 128 + state = aa_dfa_match_len(rules->policy->dfa, state, (char *) &buffer, 131 129 4); 132 - perms = *aa_lookup_perms(&rules->policy, state); 130 + perms = *aa_lookup_perms(rules->policy, state); 133 131 aa_apply_modes_to_perms(profile, &perms); 134 132 135 - return aa_check_perms(profile, &perms, request, sa, audit_net_cb); 133 + return aa_check_perms(profile, &perms, request, ad, audit_net_cb); 136 134 } 137 135 138 - int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, 139 - int type, int protocol) 136 + int aa_af_perm(const struct cred *subj_cred, struct aa_label *label, 137 + const char *op, u32 request, u16 family, int type, int protocol) 140 138 { 141 139 struct aa_profile *profile; 142 - DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol); 140 + DEFINE_AUDIT_NET(ad, op, NULL, family, type, protocol); 143 141 144 142 return fn_for_each_confined(label, profile, 145 - aa_profile_af_perm(profile, &sa, request, family, 143 + aa_profile_af_perm(profile, &ad, request, family, 146 144 type)); 147 145 } 148 146 149 - static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request, 147 + static int aa_label_sk_perm(const struct cred *subj_cred, 148 + struct aa_label *label, 149 + const char *op, u32 request, 150 150 struct sock *sk) 151 151 { 152 152 struct aa_sk_ctx *ctx = SK_CTX(sk); ··· 159 155 160 156 if (ctx->label != kernel_t && !unconfined(label)) { 161 157 struct aa_profile *profile; 162 - DEFINE_AUDIT_SK(sa, op, sk); 158 + DEFINE_AUDIT_SK(ad, op, sk); 163 159 160 + ad.subj_cred = subj_cred; 164 161 error = fn_for_each_confined(label, profile, 165 - aa_profile_af_sk_perm(profile, &sa, request, sk)); 162 + aa_profile_af_sk_perm(profile, &ad, request, sk)); 166 163 } 167 164 168 165 return error; ··· 179 174 180 175 /* TODO: switch to begin_current_label ???? */ 181 176 label = begin_current_label_crit_section(); 182 - error = aa_label_sk_perm(label, op, request, sk); 177 + error = aa_label_sk_perm(current_cred(), label, op, request, sk); 183 178 end_current_label_crit_section(label); 184 179 185 180 return error; 186 181 } 187 182 188 183 189 - int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, 190 - struct socket *sock) 184 + int aa_sock_file_perm(const struct cred *subj_cred, struct aa_label *label, 185 + const char *op, u32 request, struct socket *sock) 191 186 { 192 187 AA_BUG(!label); 193 188 AA_BUG(!sock); 194 189 AA_BUG(!sock->sk); 195 190 196 - return aa_label_sk_perm(label, op, request, sock->sk); 191 + return aa_label_sk_perm(subj_cred, label, op, request, sock->sk); 197 192 } 198 193 199 194 #ifdef CONFIG_NETWORK_SECMARK ··· 219 214 } 220 215 221 216 static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid, 222 - struct common_audit_data *sa) 217 + struct apparmor_audit_data *ad) 223 218 { 224 219 int i, ret; 225 220 struct aa_perms perms = { }; ··· 250 245 251 246 aa_apply_modes_to_perms(profile, &perms); 252 247 253 - return aa_check_perms(profile, &perms, request, sa, audit_net_cb); 248 + return aa_check_perms(profile, &perms, request, ad, audit_net_cb); 254 249 } 255 250 256 251 int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, 257 252 u32 secid, const struct sock *sk) 258 253 { 259 254 struct aa_profile *profile; 260 - DEFINE_AUDIT_SK(sa, op, sk); 255 + DEFINE_AUDIT_SK(ad, op, sk); 261 256 262 257 return fn_for_each_confined(label, profile, 263 258 aa_secmark_perm(profile, request, secid, 264 - &sa)); 259 + &ad)); 265 260 } 266 261 #endif
+84 -49
security/apparmor/policy.c
··· 88 88 #include "include/resource.h" 89 89 90 90 int unprivileged_userns_apparmor_policy = 1; 91 + int aa_unprivileged_unconfined_restricted; 91 92 92 93 const char *const aa_profile_mode_names[] = { 93 94 "enforce", ··· 97 96 "unconfined", 98 97 "user", 99 98 }; 99 + 100 + 101 + static void aa_free_pdb(struct aa_policydb *policy) 102 + { 103 + if (policy) { 104 + aa_put_dfa(policy->dfa); 105 + if (policy->perms) 106 + kvfree(policy->perms); 107 + aa_free_str_table(&policy->trans); 108 + } 109 + } 110 + 111 + /** 112 + * aa_pdb_free_kref - free aa_policydb by kref (called by aa_put_pdb) 113 + * @kref: kref callback for freeing of a dfa (NOT NULL) 114 + */ 115 + void aa_pdb_free_kref(struct kref *kref) 116 + { 117 + struct aa_policydb *pdb = container_of(kref, struct aa_policydb, count); 118 + 119 + aa_free_pdb(pdb); 120 + } 121 + 122 + 123 + struct aa_policydb *aa_alloc_pdb(gfp_t gfp) 124 + { 125 + struct aa_policydb *pdb = kzalloc(sizeof(struct aa_policydb), gfp); 126 + 127 + if (!pdb) 128 + return NULL; 129 + 130 + kref_init(&pdb->count); 131 + 132 + return pdb; 133 + } 100 134 101 135 102 136 /** ··· 236 200 for (i = 0; i < attach->xattr_count; i++) 237 201 kfree_sensitive(attach->xattrs[i]); 238 202 kfree_sensitive(attach->xattrs); 239 - aa_destroy_policydb(&attach->xmatch); 203 + aa_put_pdb(attach->xmatch); 240 204 } 241 205 242 206 static void free_ruleset(struct aa_ruleset *rules) 243 207 { 244 208 int i; 245 209 246 - aa_destroy_policydb(&rules->file); 247 - aa_destroy_policydb(&rules->policy); 210 + aa_put_pdb(rules->file); 211 + aa_put_pdb(rules->policy); 248 212 aa_free_cap_rules(&rules->caps); 249 213 aa_free_rlimit_rules(&rules->rlimits); 250 214 ··· 291 255 292 256 aa_put_ns(profile->ns); 293 257 kfree_sensitive(profile->rename); 258 + kfree_sensitive(profile->disconnected); 294 259 295 260 free_attachment(&profile->attach); 296 261 ··· 322 285 /** 323 286 * aa_alloc_profile - allocate, initialize and return a new profile 324 287 * @hname: name of the profile (NOT NULL) 288 + * @proxy: proxy to use OR null if to allocate a new one 325 289 * @gfp: allocation type 326 290 * 327 291 * Returns: refcount profile or NULL on failure ··· 626 588 /* TODO: ideally we should inherit abi from parent */ 627 589 profile->label.flags |= FLAG_NULL; 628 590 rules = list_first_entry(&profile->rules, typeof(*rules), list); 629 - rules->file.dfa = aa_get_dfa(nulldfa); 630 - rules->file.perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL); 631 - if (!rules->file.perms) 632 - goto fail; 633 - rules->file.size = 2; 634 - rules->policy.dfa = aa_get_dfa(nulldfa); 635 - rules->policy.perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL); 636 - if (!rules->policy.perms) 637 - goto fail; 638 - rules->policy.size = 2; 591 + rules->file = aa_get_pdb(nullpdb); 592 + rules->policy = aa_get_pdb(nullpdb); 639 593 640 594 if (parent) { 641 595 profile->path_flags = parent->path_flags; ··· 638 608 } 639 609 640 610 return profile; 641 - 642 - fail: 643 - aa_free_profile(profile); 644 - 645 - return NULL; 646 611 } 647 612 648 613 /** ··· 746 721 static void audit_cb(struct audit_buffer *ab, void *va) 747 722 { 748 723 struct common_audit_data *sa = va; 724 + struct apparmor_audit_data *ad = aad(sa); 749 725 750 - if (aad(sa)->iface.ns) { 726 + if (ad->iface.ns) { 751 727 audit_log_format(ab, " ns="); 752 - audit_log_untrustedstring(ab, aad(sa)->iface.ns); 728 + audit_log_untrustedstring(ab, ad->iface.ns); 753 729 } 754 730 } 755 731 756 732 /** 757 733 * audit_policy - Do auditing of policy changes 758 - * @label: label to check if it can manage policy 734 + * @subj_label: label to check if it can manage policy 759 735 * @op: policy operation being performed 760 736 * @ns_name: name of namespace being manipulated 761 737 * @name: name of profile being manipulated (NOT NULL) ··· 765 739 * 766 740 * Returns: the error to be returned after audit is done 767 741 */ 768 - static int audit_policy(struct aa_label *label, const char *op, 742 + static int audit_policy(struct aa_label *subj_label, const char *op, 769 743 const char *ns_name, const char *name, 770 744 const char *info, int error) 771 745 { 772 - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, op); 746 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, op); 773 747 774 - aad(&sa)->iface.ns = ns_name; 775 - aad(&sa)->name = name; 776 - aad(&sa)->info = info; 777 - aad(&sa)->error = error; 778 - aad(&sa)->label = label; 748 + ad.iface.ns = ns_name; 749 + ad.name = name; 750 + ad.info = info; 751 + ad.error = error; 752 + ad.subj_label = subj_label; 779 753 780 - aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, audit_cb); 754 + aa_audit_msg(AUDIT_APPARMOR_STATUS, &ad, audit_cb); 781 755 782 756 return error; 783 757 } ··· 785 759 /* don't call out to other LSMs in the stack for apparmor policy admin 786 760 * permissions 787 761 */ 788 - static int policy_ns_capable(struct aa_label *label, 762 + static int policy_ns_capable(const struct cred *subj_cred, 763 + struct aa_label *label, 789 764 struct user_namespace *userns, int cap) 790 765 { 791 766 int err; 792 767 793 768 /* check for MAC_ADMIN cap in cred */ 794 - err = cap_capable(current_cred(), userns, cap, CAP_OPT_NONE); 769 + err = cap_capable(subj_cred, userns, cap, CAP_OPT_NONE); 795 770 if (!err) 796 - err = aa_capable(label, cap, CAP_OPT_NONE); 771 + err = aa_capable(subj_cred, label, cap, CAP_OPT_NONE); 797 772 798 773 return err; 799 774 } 800 775 801 776 /** 802 777 * aa_policy_view_capable - check if viewing policy in at @ns is allowed 803 - * label: label that is trying to view policy in ns 804 - * ns: namespace being viewed by @label (may be NULL if @label's ns) 778 + * @subj_cred: cred of subject 779 + * @label: label that is trying to view policy in ns 780 + * @ns: namespace being viewed by @label (may be NULL if @label's ns) 781 + * 805 782 * Returns: true if viewing policy is allowed 806 783 * 807 784 * If @ns is NULL then the namespace being viewed is assumed to be the 808 785 * tasks current namespace. 809 786 */ 810 - bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns) 787 + bool aa_policy_view_capable(const struct cred *subj_cred, 788 + struct aa_label *label, struct aa_ns *ns) 811 789 { 812 - struct user_namespace *user_ns = current_user_ns(); 790 + struct user_namespace *user_ns = subj_cred->user_ns; 813 791 struct aa_ns *view_ns = labels_view(label); 814 792 bool root_in_user_ns = uid_eq(current_euid(), make_kuid(user_ns, 0)) || 815 793 in_egroup_p(make_kgid(user_ns, 0)); ··· 830 800 return response; 831 801 } 832 802 833 - bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns) 803 + bool aa_policy_admin_capable(const struct cred *subj_cred, 804 + struct aa_label *label, struct aa_ns *ns) 834 805 { 835 - struct user_namespace *user_ns = current_user_ns(); 836 - bool capable = policy_ns_capable(label, user_ns, CAP_MAC_ADMIN) == 0; 806 + struct user_namespace *user_ns = subj_cred->user_ns; 807 + bool capable = policy_ns_capable(subj_cred, label, user_ns, 808 + CAP_MAC_ADMIN) == 0; 837 809 838 810 AA_DEBUG("cap_mac_admin? %d\n", capable); 839 811 AA_DEBUG("policy locked? %d\n", aa_g_lock_policy); 840 812 841 - return aa_policy_view_capable(label, ns) && capable && 813 + return aa_policy_view_capable(subj_cred, label, ns) && capable && 842 814 !aa_g_lock_policy; 843 815 } 844 816 ··· 850 818 bool res; 851 819 852 820 label = __begin_current_label_crit_section(); 853 - res = aa_policy_view_capable(label, ns); 821 + res = aa_policy_view_capable(current_cred(), label, ns); 854 822 __end_current_label_crit_section(label); 855 823 856 824 return res; ··· 862 830 bool res; 863 831 864 832 label = __begin_current_label_crit_section(); 865 - res = aa_policy_admin_capable(label, ns); 833 + res = aa_policy_admin_capable(current_cred(), label, ns); 866 834 __end_current_label_crit_section(label); 867 835 868 836 return res; ··· 870 838 871 839 /** 872 840 * aa_may_manage_policy - can the current task manage policy 841 + * @subj_cred: subjects cred 873 842 * @label: label to check if it can manage policy 843 + * @ns: namespace being managed by @label (may be NULL if @label's ns) 874 844 * @mask: contains the policy manipulation operation being done 875 845 * 876 846 * Returns: 0 if the task is allowed to manipulate policy else error 877 847 */ 878 - int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask) 848 + int aa_may_manage_policy(const struct cred *subj_cred, struct aa_label *label, 849 + struct aa_ns *ns, u32 mask) 879 850 { 880 851 const char *op; 881 852 ··· 894 859 return audit_policy(label, op, NULL, NULL, "policy_locked", 895 860 -EACCES); 896 861 897 - if (!aa_policy_admin_capable(label, ns)) 862 + if (!aa_policy_admin_capable(subj_cred, label, ns)) 898 863 return audit_policy(label, op, NULL, NULL, "not policy admin", 899 864 -EACCES); 900 865 ··· 985 950 986 951 /** 987 952 * __lookup_replace - lookup replacement information for a profile 988 - * @ns - namespace the lookup occurs in 989 - * @hname - name of profile to lookup 990 - * @noreplace - true if not replacing an existing profile 991 - * @p - Returns: profile to be replaced 992 - * @info - Returns: info string on why lookup failed 953 + * @ns: namespace the lookup occurs in 954 + * @hname: name of profile to lookup 955 + * @noreplace: true if not replacing an existing profile 956 + * @p: Returns - profile to be replaced 957 + * @info: Returns - info string on why lookup failed 993 958 * 994 959 * Returns: profile to replace (no ref) on success else ptr error 995 960 */
+1
security/apparmor/policy_compat.c
··· 143 143 * compute_fperms - convert dfa compressed perms to internal perms and store 144 144 * them so they can be retrieved later. 145 145 * @dfa: a dfa using fperms to remap to internal permissions 146 + * @size: Returns the permission table size 146 147 * 147 148 * Returns: remapped perm table 148 149 */
-37
security/apparmor/policy_ns.c
··· 160 160 } 161 161 162 162 /** 163 - * aa_findn_ns - look up a profile namespace on the namespace list 164 - * @root: namespace to search in (NOT NULL) 165 - * @name: name of namespace to find (NOT NULL) 166 - * @n: length of @name 167 - * 168 - * Returns: a refcounted namespace on the list, or NULL if no namespace 169 - * called @name exists. 170 - * 171 - * refcount released by caller 172 - */ 173 - struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n) 174 - { 175 - struct aa_ns *ns = NULL; 176 - 177 - rcu_read_lock(); 178 - ns = aa_get_ns(__aa_findn_ns(&root->sub_ns, name, n)); 179 - rcu_read_unlock(); 180 - 181 - return ns; 182 - } 183 - 184 - /** 185 - * aa_find_ns - look up a profile namespace on the namespace list 186 - * @root: namespace to search in (NOT NULL) 187 - * @name: name of namespace to find (NOT NULL) 188 - * 189 - * Returns: a refcounted namespace on the list, or NULL if no namespace 190 - * called @name exists. 191 - * 192 - * refcount released by caller 193 - */ 194 - struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name) 195 - { 196 - return aa_findn_ns(root, name, strlen(name)); 197 - } 198 - 199 - /** 200 163 * __aa_lookupn_ns - lookup the namespace matching @hname 201 164 * @view: namespace to search in (NOT NULL) 202 165 * @hname: hierarchical ns name (NOT NULL)
+74 -78
security/apparmor/policy_unpack.c
··· 34 34 static void audit_cb(struct audit_buffer *ab, void *va) 35 35 { 36 36 struct common_audit_data *sa = va; 37 + struct apparmor_audit_data *ad = aad(sa); 37 38 38 - if (aad(sa)->iface.ns) { 39 + if (ad->iface.ns) { 39 40 audit_log_format(ab, " ns="); 40 - audit_log_untrustedstring(ab, aad(sa)->iface.ns); 41 + audit_log_untrustedstring(ab, ad->iface.ns); 41 42 } 42 - if (aad(sa)->name) { 43 + if (ad->name) { 43 44 audit_log_format(ab, " name="); 44 - audit_log_untrustedstring(ab, aad(sa)->name); 45 + audit_log_untrustedstring(ab, ad->name); 45 46 } 46 - if (aad(sa)->iface.pos) 47 - audit_log_format(ab, " offset=%ld", aad(sa)->iface.pos); 47 + if (ad->iface.pos) 48 + audit_log_format(ab, " offset=%ld", ad->iface.pos); 48 49 } 49 50 50 51 /** ··· 64 63 int error) 65 64 { 66 65 struct aa_profile *profile = labels_profile(aa_current_raw_label()); 67 - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); 66 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); 68 67 if (e) 69 - aad(&sa)->iface.pos = e->pos - e->start; 70 - aad(&sa)->iface.ns = ns_name; 68 + ad.iface.pos = e->pos - e->start; 69 + ad.iface.ns = ns_name; 71 70 if (new) 72 - aad(&sa)->name = new->base.hname; 71 + ad.name = new->base.hname; 73 72 else 74 - aad(&sa)->name = name; 75 - aad(&sa)->info = info; 76 - aad(&sa)->error = error; 73 + ad.name = name; 74 + ad.info = info; 75 + ad.error = error; 77 76 78 - return aa_audit(AUDIT_APPARMOR_STATUS, profile, &sa, audit_cb); 77 + return aa_audit(AUDIT_APPARMOR_STATUS, profile, &ad, audit_cb); 79 78 } 80 79 81 80 void __aa_loaddata_update(struct aa_loaddata *data, long revision) ··· 706 705 return -EPROTO; 707 706 } 708 707 709 - static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, 708 + static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy, 710 709 bool required_dfa, bool required_trans, 711 710 const char **info) 712 711 { 712 + struct aa_policydb *pdb; 713 713 void *pos = e->pos; 714 714 int i, flags, error = -EPROTO; 715 715 ssize_t size; 716 716 717 - size = unpack_perms_table(e, &policy->perms); 717 + pdb = aa_alloc_pdb(GFP_KERNEL); 718 + if (!pdb) 719 + return -ENOMEM; 720 + 721 + size = unpack_perms_table(e, &pdb->perms); 718 722 if (size < 0) { 719 723 error = size; 720 - policy->perms = NULL; 724 + pdb->perms = NULL; 721 725 *info = "failed to unpack - perms"; 722 726 goto fail; 723 727 } 724 - policy->size = size; 728 + pdb->size = size; 725 729 726 - if (policy->perms) { 730 + if (pdb->perms) { 727 731 /* perms table present accept is index */ 728 732 flags = TO_ACCEPT1_FLAG(YYTD_DATA32); 729 733 } else { ··· 737 731 TO_ACCEPT2_FLAG(YYTD_DATA32); 738 732 } 739 733 740 - policy->dfa = unpack_dfa(e, flags); 741 - if (IS_ERR(policy->dfa)) { 742 - error = PTR_ERR(policy->dfa); 743 - policy->dfa = NULL; 734 + pdb->dfa = unpack_dfa(e, flags); 735 + if (IS_ERR(pdb->dfa)) { 736 + error = PTR_ERR(pdb->dfa); 737 + pdb->dfa = NULL; 744 738 *info = "failed to unpack - dfa"; 745 739 goto fail; 746 - } else if (!policy->dfa) { 740 + } else if (!pdb->dfa) { 747 741 if (required_dfa) { 748 742 *info = "missing required dfa"; 749 743 goto fail; ··· 757 751 * sadly start was given different names for file and policydb 758 752 * but since it is optional we can try both 759 753 */ 760 - if (!aa_unpack_u32(e, &policy->start[0], "start")) 754 + if (!aa_unpack_u32(e, &pdb->start[0], "start")) 761 755 /* default start state */ 762 - policy->start[0] = DFA_START; 763 - if (!aa_unpack_u32(e, &policy->start[AA_CLASS_FILE], "dfa_start")) { 756 + pdb->start[0] = DFA_START; 757 + if (!aa_unpack_u32(e, &pdb->start[AA_CLASS_FILE], "dfa_start")) { 764 758 /* default start state for xmatch and file dfa */ 765 - policy->start[AA_CLASS_FILE] = DFA_START; 759 + pdb->start[AA_CLASS_FILE] = DFA_START; 766 760 } /* setup class index */ 767 761 for (i = AA_CLASS_FILE + 1; i <= AA_CLASS_LAST; i++) { 768 - policy->start[i] = aa_dfa_next(policy->dfa, policy->start[0], 762 + pdb->start[i] = aa_dfa_next(pdb->dfa, pdb->start[0], 769 763 i); 770 764 } 771 - if (!unpack_trans_table(e, &policy->trans) && required_trans) { 765 + if (!unpack_trans_table(e, &pdb->trans) && required_trans) { 772 766 *info = "failed to unpack profile transition table"; 773 767 goto fail; 774 768 } ··· 776 770 /* TODO: move compat mapping here, requires dfa merging first */ 777 771 /* TODO: move verify here, it has to be done after compat mappings */ 778 772 out: 773 + *policy = pdb; 779 774 return 0; 780 775 781 776 fail: 777 + aa_put_pdb(pdb); 782 778 e->pos = pos; 783 779 return error; 784 780 } ··· 815 807 const char *info = "failed to unpack profile"; 816 808 size_t ns_len; 817 809 struct rhashtable_params params = { 0 }; 818 - char *key = NULL; 810 + char *key = NULL, *disconnected = NULL; 819 811 struct aa_data *data; 820 812 int error = -EPROTO; 821 813 kernel_cap_t tmpcap; ··· 864 856 } 865 857 866 858 /* neither xmatch_len not xmatch_perms are optional if xmatch is set */ 867 - if (profile->attach.xmatch.dfa) { 859 + if (profile->attach.xmatch->dfa) { 868 860 if (!aa_unpack_u32(e, &tmp, NULL)) { 869 861 info = "missing xmatch len"; 870 862 goto fail; 871 863 } 872 864 profile->attach.xmatch_len = tmp; 873 - profile->attach.xmatch.start[AA_CLASS_XMATCH] = DFA_START; 874 - if (!profile->attach.xmatch.perms) { 875 - error = aa_compat_map_xmatch(&profile->attach.xmatch); 865 + profile->attach.xmatch->start[AA_CLASS_XMATCH] = DFA_START; 866 + if (!profile->attach.xmatch->perms) { 867 + error = aa_compat_map_xmatch(profile->attach.xmatch); 876 868 if (error) { 877 869 info = "failed to convert xmatch permission table"; 878 870 goto fail; ··· 881 873 } 882 874 883 875 /* disconnected attachment string is optional */ 884 - (void) aa_unpack_str(e, &profile->disconnected, "disconnected"); 876 + (void) aa_unpack_strdup(e, &disconnected, "disconnected"); 877 + profile->disconnected = disconnected; 885 878 886 879 /* per profile debug flags (complain, audit) */ 887 880 if (!aa_unpack_nameX(e, AA_STRUCT, "flags")) { ··· 989 980 if (error) 990 981 goto fail; 991 982 /* Fixup: drop when we get rid of start array */ 992 - if (aa_dfa_next(rules->policy.dfa, rules->policy.start[0], 983 + if (aa_dfa_next(rules->policy->dfa, rules->policy->start[0], 993 984 AA_CLASS_FILE)) 994 - rules->policy.start[AA_CLASS_FILE] = 995 - aa_dfa_next(rules->policy.dfa, 996 - rules->policy.start[0], 985 + rules->policy->start[AA_CLASS_FILE] = 986 + aa_dfa_next(rules->policy->dfa, 987 + rules->policy->start[0], 997 988 AA_CLASS_FILE); 998 989 if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) 999 990 goto fail; 1000 - if (!rules->policy.perms) { 1001 - error = aa_compat_map_policy(&rules->policy, 991 + if (!rules->policy->perms) { 992 + error = aa_compat_map_policy(rules->policy, 1002 993 e->version); 1003 994 if (error) { 1004 995 info = "failed to remap policydb permission table"; ··· 1006 997 } 1007 998 } 1008 999 } else { 1009 - rules->policy.dfa = aa_get_dfa(nulldfa); 1010 - rules->policy.perms = kcalloc(2, sizeof(struct aa_perms), 1011 - GFP_KERNEL); 1012 - if (!rules->policy.perms) 1013 - goto fail; 1014 - rules->policy.size = 2; 1000 + rules->policy = aa_get_pdb(nullpdb); 1015 1001 } 1016 1002 /* get file rules */ 1017 1003 error = unpack_pdb(e, &rules->file, false, true, &info); 1018 1004 if (error) { 1019 1005 goto fail; 1020 - } else if (rules->file.dfa) { 1021 - if (!rules->file.perms) { 1022 - error = aa_compat_map_file(&rules->file); 1006 + } else if (rules->file->dfa) { 1007 + if (!rules->file->perms) { 1008 + error = aa_compat_map_file(rules->file); 1023 1009 if (error) { 1024 1010 info = "failed to remap file permission table"; 1025 1011 goto fail; 1026 1012 } 1027 1013 } 1028 - } else if (rules->policy.dfa && 1029 - rules->policy.start[AA_CLASS_FILE]) { 1030 - rules->file.dfa = aa_get_dfa(rules->policy.dfa); 1031 - rules->file.start[AA_CLASS_FILE] = rules->policy.start[AA_CLASS_FILE]; 1032 - rules->file.perms = kcalloc(rules->policy.size, 1033 - sizeof(struct aa_perms), 1034 - GFP_KERNEL); 1035 - if (!rules->file.perms) 1036 - goto fail; 1037 - memcpy(rules->file.perms, rules->policy.perms, 1038 - rules->policy.size * sizeof(struct aa_perms)); 1039 - rules->file.size = rules->policy.size; 1014 + } else if (rules->policy->dfa && 1015 + rules->policy->start[AA_CLASS_FILE]) { 1016 + rules->file = aa_get_pdb(rules->policy); 1040 1017 } else { 1041 - rules->file.dfa = aa_get_dfa(nulldfa); 1042 - rules->file.perms = kcalloc(2, sizeof(struct aa_perms), 1043 - GFP_KERNEL); 1044 - if (!rules->file.perms) 1045 - goto fail; 1046 - rules->file.size = 2; 1018 + rules->file = aa_get_pdb(nullpdb); 1047 1019 } 1048 1020 error = -EPROTO; 1049 1021 if (aa_unpack_nameX(e, AA_STRUCT, "data")) { ··· 1160 1170 /** 1161 1171 * verify_dfa_accept_index - verify accept indexes are in range of perms table 1162 1172 * @dfa: the dfa to check accept indexes are in range 1163 - * table_size: the permission table size the indexes should be within 1173 + * @table_size: the permission table size the indexes should be within 1164 1174 */ 1165 1175 static bool verify_dfa_accept_index(struct aa_dfa *dfa, int table_size) 1166 1176 { ··· 1231 1241 if (!rules) 1232 1242 return 0; 1233 1243 1234 - if ((rules->file.dfa && !verify_dfa_accept_index(rules->file.dfa, 1235 - rules->file.size)) || 1236 - (rules->policy.dfa && 1237 - !verify_dfa_accept_index(rules->policy.dfa, rules->policy.size))) { 1244 + if (rules->file->dfa && !verify_dfa_accept_index(rules->file->dfa, 1245 + rules->file->size)) { 1238 1246 audit_iface(profile, NULL, NULL, 1239 - "Unpack: Invalid named transition", NULL, -EPROTO); 1247 + "Unpack: file Invalid named transition", NULL, 1248 + -EPROTO); 1249 + return -EPROTO; 1250 + } 1251 + if (rules->policy->dfa && 1252 + !verify_dfa_accept_index(rules->policy->dfa, rules->policy->size)) { 1253 + audit_iface(profile, NULL, NULL, 1254 + "Unpack: policy Invalid named transition", NULL, 1255 + -EPROTO); 1240 1256 return -EPROTO; 1241 1257 } 1242 1258 1243 - if (!verify_perms(&rules->file)) { 1259 + if (!verify_perms(rules->file)) { 1244 1260 audit_iface(profile, NULL, NULL, 1245 1261 "Unpack: Invalid perm index", NULL, -EPROTO); 1246 1262 return -EPROTO; 1247 1263 } 1248 - if (!verify_perms(&rules->policy)) { 1264 + if (!verify_perms(rules->policy)) { 1249 1265 audit_iface(profile, NULL, NULL, 1250 1266 "Unpack: Invalid perm index", NULL, -EPROTO); 1251 1267 return -EPROTO; 1252 1268 } 1253 - if (!verify_perms(&profile->attach.xmatch)) { 1269 + if (!verify_perms(profile->attach.xmatch)) { 1254 1270 audit_iface(profile, NULL, NULL, 1255 1271 "Unpack: Invalid perm index", NULL, -EPROTO); 1256 1272 return -EPROTO;
+31 -23
security/apparmor/resource.c
··· 30 30 static void audit_cb(struct audit_buffer *ab, void *va) 31 31 { 32 32 struct common_audit_data *sa = va; 33 + struct apparmor_audit_data *ad = aad(sa); 33 34 34 35 audit_log_format(ab, " rlimit=%s value=%lu", 35 - rlim_names[aad(sa)->rlim.rlim], aad(sa)->rlim.max); 36 - if (aad(sa)->peer) { 36 + rlim_names[ad->rlim.rlim], ad->rlim.max); 37 + if (ad->peer) { 37 38 audit_log_format(ab, " peer="); 38 - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 39 + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, 39 40 FLAGS_NONE, GFP_ATOMIC); 40 41 } 41 42 } 42 43 43 44 /** 44 45 * audit_resource - audit setting resource limit 46 + * @subj_cred: cred setting the resource 45 47 * @profile: profile being enforced (NOT NULL) 46 48 * @resource: rlimit being auditing 47 49 * @value: value being set ··· 51 49 * @info: info being auditing 52 50 * @error: error value 53 51 * 54 - * Returns: 0 or sa->error else other error code on failure 52 + * Returns: 0 or ad->error else other error code on failure 55 53 */ 56 - static int audit_resource(struct aa_profile *profile, unsigned int resource, 54 + static int audit_resource(const struct cred *subj_cred, 55 + struct aa_profile *profile, unsigned int resource, 57 56 unsigned long value, struct aa_label *peer, 58 57 const char *info, int error) 59 58 { 60 - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_RLIMITS, 59 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_RLIMITS, 61 60 OP_SETRLIMIT); 62 61 63 - aad(&sa)->rlim.rlim = resource; 64 - aad(&sa)->rlim.max = value; 65 - aad(&sa)->peer = peer; 66 - aad(&sa)->info = info; 67 - aad(&sa)->error = error; 62 + ad.subj_cred = subj_cred; 63 + ad.rlim.rlim = resource; 64 + ad.rlim.max = value; 65 + ad.peer = peer; 66 + ad.info = info; 67 + ad.error = error; 68 68 69 - return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa, audit_cb); 69 + return aa_audit(AUDIT_APPARMOR_AUTO, profile, &ad, audit_cb); 70 70 } 71 71 72 72 /** ··· 85 81 return rlim_map[resource]; 86 82 } 87 83 88 - static int profile_setrlimit(struct aa_profile *profile, unsigned int resource, 84 + static int profile_setrlimit(const struct cred *subj_cred, 85 + struct aa_profile *profile, unsigned int resource, 89 86 struct rlimit *new_rlim) 90 87 { 91 88 struct aa_ruleset *rules = list_first_entry(&profile->rules, ··· 96 91 if (rules->rlimits.mask & (1 << resource) && new_rlim->rlim_max > 97 92 rules->rlimits.limits[resource].rlim_max) 98 93 e = -EACCES; 99 - return audit_resource(profile, resource, new_rlim->rlim_max, NULL, NULL, 100 - e); 94 + return audit_resource(subj_cred, profile, resource, new_rlim->rlim_max, 95 + NULL, NULL, e); 101 96 } 102 97 103 98 /** 104 99 * aa_task_setrlimit - test permission to set an rlimit 105 - * @label - label confining the task (NOT NULL) 106 - * @task - task the resource is being set on 107 - * @resource - the resource being set 108 - * @new_rlim - the new resource limit (NOT NULL) 100 + * @subj_cred: cred setting the limit 101 + * @label: label confining the task (NOT NULL) 102 + * @task: task the resource is being set on 103 + * @resource: the resource being set 104 + * @new_rlim: the new resource limit (NOT NULL) 109 105 * 110 106 * Control raising the processes hard limit. 111 107 * 112 108 * Returns: 0 or error code if setting resource failed 113 109 */ 114 - int aa_task_setrlimit(struct aa_label *label, struct task_struct *task, 110 + int aa_task_setrlimit(const struct cred *subj_cred, struct aa_label *label, 111 + struct task_struct *task, 115 112 unsigned int resource, struct rlimit *new_rlim) 116 113 { 117 114 struct aa_profile *profile; ··· 132 125 */ 133 126 134 127 if (label != peer && 135 - aa_capable(label, CAP_SYS_RESOURCE, CAP_OPT_NOAUDIT) != 0) 128 + aa_capable(subj_cred, label, CAP_SYS_RESOURCE, CAP_OPT_NOAUDIT) != 0) 136 129 error = fn_for_each(label, profile, 137 - audit_resource(profile, resource, 130 + audit_resource(subj_cred, profile, resource, 138 131 new_rlim->rlim_max, peer, 139 132 "cap_sys_resource", -EACCES)); 140 133 else 141 134 error = fn_for_each_confined(label, profile, 142 - profile_setrlimit(profile, resource, new_rlim)); 135 + profile_setrlimit(subj_cred, profile, resource, 136 + new_rlim)); 143 137 aa_put_label(peer); 144 138 145 139 return error;
+75 -29
security/apparmor/task.c
··· 93 93 * aa_set_current_onexec - set the tasks change_profile to happen onexec 94 94 * @label: system label to set at exec (MAYBE NULL to clear value) 95 95 * @stack: whether stacking should be done 96 - * Returns: 0 or error on failure 97 96 */ 98 - int aa_set_current_onexec(struct aa_label *label, bool stack) 97 + void aa_set_current_onexec(struct aa_label *label, bool stack) 99 98 { 100 99 struct aa_task_ctx *ctx = task_ctx(current); 101 100 ··· 102 103 aa_put_label(ctx->onexec); 103 104 ctx->onexec = label; 104 105 ctx->token = stack; 105 - 106 - return 0; 107 106 } 108 107 109 108 /** ··· 205 208 static void audit_ptrace_cb(struct audit_buffer *ab, void *va) 206 209 { 207 210 struct common_audit_data *sa = va; 211 + struct apparmor_audit_data *ad = aad(sa); 208 212 209 - if (aad(sa)->request & AA_PTRACE_PERM_MASK) { 213 + if (ad->request & AA_PTRACE_PERM_MASK) { 210 214 audit_log_format(ab, " requested_mask=\"%s\"", 211 - audit_ptrace_mask(aad(sa)->request)); 215 + audit_ptrace_mask(ad->request)); 212 216 213 - if (aad(sa)->denied & AA_PTRACE_PERM_MASK) { 217 + if (ad->denied & AA_PTRACE_PERM_MASK) { 214 218 audit_log_format(ab, " denied_mask=\"%s\"", 215 - audit_ptrace_mask(aad(sa)->denied)); 219 + audit_ptrace_mask(ad->denied)); 216 220 } 217 221 } 218 222 audit_log_format(ab, " peer="); 219 - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 223 + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, 220 224 FLAGS_NONE, GFP_ATOMIC); 221 225 } 222 226 223 227 /* assumes check for RULE_MEDIATES is already done */ 224 228 /* TODO: conditionals */ 225 - static int profile_ptrace_perm(struct aa_profile *profile, 226 - struct aa_label *peer, u32 request, 227 - struct common_audit_data *sa) 229 + static int profile_ptrace_perm(const struct cred *cred, 230 + struct aa_profile *profile, 231 + struct aa_label *peer, u32 request, 232 + struct apparmor_audit_data *ad) 228 233 { 229 234 struct aa_ruleset *rules = list_first_entry(&profile->rules, 230 235 typeof(*rules), list); 231 236 struct aa_perms perms = { }; 232 237 233 - aad(sa)->peer = peer; 238 + ad->subj_cred = cred; 239 + ad->peer = peer; 234 240 aa_profile_match_label(profile, rules, peer, AA_CLASS_PTRACE, request, 235 241 &perms); 236 242 aa_apply_modes_to_perms(profile, &perms); 237 - return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); 243 + return aa_check_perms(profile, &perms, request, ad, audit_ptrace_cb); 238 244 } 239 245 240 - static int profile_tracee_perm(struct aa_profile *tracee, 246 + static int profile_tracee_perm(const struct cred *cred, 247 + struct aa_profile *tracee, 241 248 struct aa_label *tracer, u32 request, 242 - struct common_audit_data *sa) 249 + struct apparmor_audit_data *ad) 243 250 { 244 251 if (profile_unconfined(tracee) || unconfined(tracer) || 245 252 !ANY_RULE_MEDIATES(&tracee->rules, AA_CLASS_PTRACE)) 246 253 return 0; 247 254 248 - return profile_ptrace_perm(tracee, tracer, request, sa); 255 + return profile_ptrace_perm(cred, tracee, tracer, request, ad); 249 256 } 250 257 251 - static int profile_tracer_perm(struct aa_profile *tracer, 258 + static int profile_tracer_perm(const struct cred *cred, 259 + struct aa_profile *tracer, 252 260 struct aa_label *tracee, u32 request, 253 - struct common_audit_data *sa) 261 + struct apparmor_audit_data *ad) 254 262 { 255 263 if (profile_unconfined(tracer)) 256 264 return 0; 257 265 258 266 if (ANY_RULE_MEDIATES(&tracer->rules, AA_CLASS_PTRACE)) 259 - return profile_ptrace_perm(tracer, tracee, request, sa); 267 + return profile_ptrace_perm(cred, tracer, tracee, request, ad); 260 268 261 269 /* profile uses the old style capability check for ptrace */ 262 270 if (&tracer->label == tracee) 263 271 return 0; 264 272 265 - aad(sa)->label = &tracer->label; 266 - aad(sa)->peer = tracee; 267 - aad(sa)->request = 0; 268 - aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, 269 - CAP_OPT_NONE); 273 + ad->subj_label = &tracer->label; 274 + ad->peer = tracee; 275 + ad->request = 0; 276 + ad->error = aa_capable(cred, &tracer->label, CAP_SYS_PTRACE, 277 + CAP_OPT_NONE); 270 278 271 - return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb); 279 + return aa_audit(AUDIT_APPARMOR_AUTO, tracer, ad, audit_ptrace_cb); 272 280 } 273 281 274 282 /** ··· 284 282 * 285 283 * Returns: %0 else error code if permission denied or error 286 284 */ 287 - int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, 285 + int aa_may_ptrace(const struct cred *tracer_cred, struct aa_label *tracer, 286 + const struct cred *tracee_cred, struct aa_label *tracee, 288 287 u32 request) 289 288 { 290 289 struct aa_profile *profile; ··· 293 290 DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_PTRACE, OP_PTRACE); 294 291 295 292 return xcheck_labels(tracer, tracee, profile, 296 - profile_tracer_perm(profile, tracee, request, &sa), 297 - profile_tracee_perm(profile, tracer, xrequest, &sa)); 293 + profile_tracer_perm(tracer_cred, profile, tracee, 294 + request, &sa), 295 + profile_tracee_perm(tracee_cred, profile, tracer, 296 + xrequest, &sa)); 297 + } 298 + 299 + /* call back to audit ptrace fields */ 300 + static void audit_ns_cb(struct audit_buffer *ab, void *va) 301 + { 302 + struct apparmor_audit_data *ad = aad_of_va(va); 303 + 304 + if (ad->request & AA_USERNS_CREATE) 305 + audit_log_format(ab, " requested=\"userns_create\""); 306 + 307 + if (ad->denied & AA_USERNS_CREATE) 308 + audit_log_format(ab, " denied=\"userns_create\""); 309 + } 310 + 311 + int aa_profile_ns_perm(struct aa_profile *profile, 312 + struct apparmor_audit_data *ad, 313 + u32 request) 314 + { 315 + struct aa_perms perms = { }; 316 + int error = 0; 317 + 318 + ad->subj_label = &profile->label; 319 + ad->request = request; 320 + 321 + if (!profile_unconfined(profile)) { 322 + struct aa_ruleset *rules = list_first_entry(&profile->rules, 323 + typeof(*rules), 324 + list); 325 + aa_state_t state; 326 + 327 + state = RULE_MEDIATES(rules, ad->class); 328 + if (!state) 329 + /* TODO: add flag to complain about unmediated */ 330 + return 0; 331 + perms = *aa_lookup_perms(rules->policy, state); 332 + aa_apply_modes_to_perms(profile, &perms); 333 + error = aa_check_perms(profile, &perms, request, ad, 334 + audit_ns_cb); 335 + } 336 + 337 + return error; 298 338 }