From 8921482286116af193980f04f2f2755775a410a5 Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Sun, 25 Jun 2023 09:13:44 +0800 Subject: apparmor: Fix kernel-doc warnings in apparmor/lib.c Fix kernel-doc warnings: security/apparmor/lib.c:33: warning: Excess function parameter 'str' description in 'aa_free_str_table' security/apparmor/lib.c:33: warning: Function parameter or member 't' not described in 'aa_free_str_table' security/apparmor/lib.c:94: warning: Function parameter or member 'n' not described in 'skipn_spaces' security/apparmor/lib.c:390: warning: Excess function parameter 'deny' description in 'aa_check_perms' Signed-off-by: Gaosheng Cui Signed-off-by: John Johansen --- security/apparmor/lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'security/apparmor/lib.c') diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index a630c951bb3b..8e1073477c09 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c @@ -27,7 +27,7 @@ struct aa_perms allperms = { .allow = ALL_PERMS_MASK, /** * aa_free_str_table - free entries str table - * @str: the string table to free (MAYBE NULL) + * @t: the string table to free (MAYBE NULL) */ void aa_free_str_table(struct aa_str_table *t) { @@ -85,6 +85,7 @@ char *aa_split_fqname(char *fqname, char **ns_name) /** * skipn_spaces - Removes leading whitespace from @str. * @str: The string to be stripped. + * @n: length of str to parse, will stop at \0 if encountered before n * * Returns a pointer to the first non-whitespace character in @str. * if all whitespace will return NULL @@ -371,7 +372,6 @@ int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, * @profile: profile being checked * @perms: perms computed for the request * @request: requested perms - * @deny: Returns: explicit deny set * @sa: initialized audit structure (MAY BE NULL if not auditing) * @cb: callback fn for type specific fields (MAY BE NULL) * -- cgit From bd7bd201ca46c211c3ab251ca9854787d1331a2f Mon Sep 17 00:00:00 2001 From: John Johansen Date: Wed, 14 Sep 2022 00:20:12 -0700 Subject: apparmor: combine common_audit_data and apparmor_audit_data Everywhere where common_audit_data is used apparmor audit_data is also used. We can simplify the code and drop the use of the aad macro everywhere by combining the two structures. Reviewed-by: Georgia Garcia Signed-off-by: John Johansen --- security/apparmor/audit.c | 70 +++++++++++++++++++-------------------- security/apparmor/capability.c | 24 +++++++------- security/apparmor/file.c | 68 ++++++++++++++++++------------------- security/apparmor/include/audit.h | 34 ++++++++++--------- security/apparmor/include/net.h | 13 ++++---- security/apparmor/include/perms.h | 4 +-- security/apparmor/ipc.c | 39 +++++++++++----------- security/apparmor/lib.c | 47 +++++++++++++------------- security/apparmor/lsm.c | 12 +++---- security/apparmor/mount.c | 41 ++++++++++++----------- security/apparmor/net.c | 44 ++++++++++++------------ security/apparmor/policy.c | 19 ++++++----- security/apparmor/policy_unpack.c | 29 ++++++++-------- security/apparmor/resource.c | 23 +++++++------ security/apparmor/task.c | 35 ++++++++++---------- 15 files changed, 257 insertions(+), 245 deletions(-) (limited to 'security/apparmor/lib.c') diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index a3db0f8bd4f8..06ad6a8fcce1 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c @@ -85,37 +85,36 @@ static const char *const aa_class_names[] = { /** * audit_pre() - core AppArmor function. * @ab: audit buffer to fill (NOT NULL) - * @ca: audit structure containing data to audit (NOT NULL) + * @va: audit structure containing data to audit (NOT NULL) * - * Record common AppArmor audit data from @sa + * Record common AppArmor audit data from @va */ -static void audit_pre(struct audit_buffer *ab, void *ca) +static void audit_pre(struct audit_buffer *ab, void *va) { - struct common_audit_data *sa = ca; + struct apparmor_audit_data *ad = aad_of_va(va); if (aa_g_audit_header) { audit_log_format(ab, "apparmor=\"%s\"", - aa_audit_type[aad(sa)->type]); + aa_audit_type[ad->type]); } - if (aad(sa)->op) { - audit_log_format(ab, " operation=\"%s\"", aad(sa)->op); - } + if (ad->op) + audit_log_format(ab, " operation=\"%s\"", ad->op); - if (aad(sa)->class) + if (ad->class) audit_log_format(ab, " class=\"%s\"", - aad(sa)->class <= AA_CLASS_LAST ? - aa_class_names[aad(sa)->class] : + ad->class <= AA_CLASS_LAST ? + aa_class_names[ad->class] : "unknown"); - if (aad(sa)->info) { - audit_log_format(ab, " info=\"%s\"", aad(sa)->info); - if (aad(sa)->error) - audit_log_format(ab, " error=%d", aad(sa)->error); + if (ad->info) { + audit_log_format(ab, " info=\"%s\"", ad->info); + if (ad->error) + audit_log_format(ab, " error=%d", ad->error); } - if (aad(sa)->label) { - struct aa_label *label = aad(sa)->label; + if (ad->label) { + struct aa_label *label = ad->label; if (label_isprofile(label)) { struct aa_profile *profile = labels_profile(label); @@ -134,43 +133,44 @@ static void audit_pre(struct audit_buffer *ab, void *ca) } } - if (aad(sa)->name) { + if (ad->name) { audit_log_format(ab, " name="); - audit_log_untrustedstring(ab, aad(sa)->name); + audit_log_untrustedstring(ab, ad->name); } } /** * aa_audit_msg - Log a message to the audit subsystem * @type: audit type for the message - * @sa: audit event structure (NOT NULL) + * @ad: audit event structure (NOT NULL) * @cb: optional callback fn for type specific fields (MAYBE NULL) */ -void aa_audit_msg(int type, struct common_audit_data *sa, +void aa_audit_msg(int type, struct apparmor_audit_data *ad, void (*cb) (struct audit_buffer *, void *)) { - aad(sa)->type = type; - common_lsm_audit(sa, audit_pre, cb); + ad->type = type; + common_lsm_audit(&ad->common, audit_pre, cb); } /** * aa_audit - Log a profile based audit event to the audit subsystem * @type: audit type for the message * @profile: profile to check against (NOT NULL) - * @sa: audit event (NOT NULL) + * @ad: audit event (NOT NULL) * @cb: optional callback fn for type specific fields (MAYBE NULL) * * Handle default message switching based off of audit mode flags * * Returns: error on failure */ -int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa, +int aa_audit(int type, struct aa_profile *profile, + struct apparmor_audit_data *ad, void (*cb) (struct audit_buffer *, void *)) { AA_BUG(!profile); if (type == AUDIT_APPARMOR_AUTO) { - if (likely(!aad(sa)->error)) { + if (likely(!ad->error)) { if (AUDIT_MODE(profile) != AUDIT_ALL) return 0; type = AUDIT_APPARMOR_AUDIT; @@ -182,24 +182,24 @@ int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa, if (AUDIT_MODE(profile) == AUDIT_QUIET || (type == AUDIT_APPARMOR_DENIED && AUDIT_MODE(profile) == AUDIT_QUIET_DENIED)) - return aad(sa)->error; + return ad->error; if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) type = AUDIT_APPARMOR_KILL; - aad(sa)->label = &profile->label; + ad->label = &profile->label; - aa_audit_msg(type, sa, cb); + aa_audit_msg(type, ad, cb); - if (aad(sa)->type == AUDIT_APPARMOR_KILL) + if (ad->type == AUDIT_APPARMOR_KILL) (void)send_sig_info(SIGKILL, NULL, - sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ? - sa->u.tsk : current); + ad->common.type == LSM_AUDIT_DATA_TASK && + ad->common.u.tsk ? ad->common.u.tsk : current); - if (aad(sa)->type == AUDIT_APPARMOR_ALLOWED) - return complain_error(aad(sa)->error); + if (ad->type == AUDIT_APPARMOR_ALLOWED) + return complain_error(ad->error); - return aad(sa)->error; + return ad->error; } struct aa_audit_rule { diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c index 8ebf0fcb796c..35979a832994 100644 --- a/security/apparmor/capability.c +++ b/security/apparmor/capability.c @@ -51,7 +51,7 @@ static void audit_cb(struct audit_buffer *ab, void *va) /** * audit_caps - audit a capability - * @sa: audit data + * @as: audit data * @profile: profile being tested for confinement (NOT NULL) * @cap: capability tested * @error: error code returned by test @@ -59,9 +59,9 @@ static void audit_cb(struct audit_buffer *ab, void *va) * Do auditing of capability and handle, audit/complain/kill modes switching * and duplicate message elimination. * - * Returns: 0 or sa->error on success, error code on failure + * Returns: 0 or ad->error on success, error code on failure */ -static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, +static int audit_caps(struct apparmor_audit_data *ad, struct aa_profile *profile, int cap, int error) { struct aa_ruleset *rules = list_first_entry(&profile->rules, @@ -69,7 +69,7 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, struct audit_cache *ent; int type = AUDIT_APPARMOR_AUTO; - aad(sa)->error = error; + ad->error = error; if (likely(!error)) { /* test if auditing is being forced */ @@ -101,7 +101,7 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, } put_cpu_var(audit_cache); - return aa_audit(type, profile, sa, audit_cb); + return aa_audit(type, profile, ad, audit_cb); } /** @@ -109,12 +109,12 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, * @profile: profile being enforced (NOT NULL, NOT unconfined) * @cap: capability to test if allowed * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated - * @sa: audit data (MAY BE NULL indicating no auditing) + * @ad: audit data (MAY BE NULL indicating no auditing) * * Returns: 0 if allowed else -EPERM */ static int profile_capable(struct aa_profile *profile, int cap, - unsigned int opts, struct common_audit_data *sa) + unsigned int opts, struct apparmor_audit_data *ad) { struct aa_ruleset *rules = list_first_entry(&profile->rules, typeof(*rules), list); @@ -132,10 +132,10 @@ static int profile_capable(struct aa_profile *profile, int cap, /* audit the cap request in complain mode but note that it * should be optional. */ - aad(sa)->info = "optional: no audit"; + ad->info = "optional: no audit"; } - return audit_caps(sa, profile, cap, error); + return audit_caps(ad, profile, cap, error); } /** @@ -152,11 +152,11 @@ int aa_capable(struct aa_label *label, int cap, unsigned int opts) { struct aa_profile *profile; int error = 0; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, AA_CLASS_CAP, OP_CAPABLE); + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_CAP, AA_CLASS_CAP, OP_CAPABLE); - sa.u.cap = cap; + ad.common.u.cap = cap; error = fn_for_each_confined(label, profile, - profile_capable(profile, cap, opts, &sa)); + profile_capable(profile, cap, opts, &ad)); return error; } diff --git a/security/apparmor/file.c b/security/apparmor/file.c index c0fc5e77e889..01ff612c060e 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c @@ -44,33 +44,34 @@ static u32 map_mask_to_chr_mask(u32 mask) static void file_audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); kuid_t fsuid = current_fsuid(); char str[10]; - if (aad(sa)->request & AA_AUDIT_FILE_MASK) { + if (ad->request & AA_AUDIT_FILE_MASK) { aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs, - map_mask_to_chr_mask(aad(sa)->request)); + map_mask_to_chr_mask(ad->request)); audit_log_format(ab, " requested_mask=\"%s\"", str); } - if (aad(sa)->denied & AA_AUDIT_FILE_MASK) { + if (ad->denied & AA_AUDIT_FILE_MASK) { aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs, - map_mask_to_chr_mask(aad(sa)->denied)); + map_mask_to_chr_mask(ad->denied)); audit_log_format(ab, " denied_mask=\"%s\"", str); } - if (aad(sa)->request & AA_AUDIT_FILE_MASK) { + if (ad->request & AA_AUDIT_FILE_MASK) { audit_log_format(ab, " fsuid=%d", from_kuid(&init_user_ns, fsuid)); audit_log_format(ab, " ouid=%d", - from_kuid(&init_user_ns, aad(sa)->fs.ouid)); + from_kuid(&init_user_ns, ad->fs.ouid)); } - if (aad(sa)->peer) { + if (ad->peer) { audit_log_format(ab, " target="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + aa_label_xaudit(ab, labels_ns(ad->label), ad->peer, FLAG_VIEW_SUBNS, GFP_KERNEL); - } else if (aad(sa)->fs.target) { + } else if (ad->fs.target) { audit_log_format(ab, " target="); - audit_log_untrustedstring(ab, aad(sa)->fs.target); + audit_log_untrustedstring(ab, ad->fs.target); } } @@ -95,50 +96,49 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, kuid_t ouid, const char *info, int error) { int type = AUDIT_APPARMOR_AUTO; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, AA_CLASS_FILE, op); - - sa.u.tsk = NULL; - aad(&sa)->request = request; - aad(&sa)->name = name; - aad(&sa)->fs.target = target; - aad(&sa)->peer = tlabel; - aad(&sa)->fs.ouid = ouid; - aad(&sa)->info = info; - aad(&sa)->error = error; - sa.u.tsk = NULL; - - if (likely(!aad(&sa)->error)) { + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_TASK, AA_CLASS_FILE, op); + + ad.request = request; + ad.name = name; + ad.fs.target = target; + ad.peer = tlabel; + ad.fs.ouid = ouid; + ad.info = info; + ad.error = error; + ad.common.u.tsk = NULL; + + if (likely(!ad.error)) { u32 mask = perms->audit; if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL)) mask = 0xffff; /* mask off perms that are not being force audited */ - aad(&sa)->request &= mask; + ad.request &= mask; - if (likely(!aad(&sa)->request)) + if (likely(!ad.request)) return 0; type = AUDIT_APPARMOR_AUDIT; } else { /* only report permissions that were denied */ - aad(&sa)->request = aad(&sa)->request & ~perms->allow; - AA_BUG(!aad(&sa)->request); + ad.request = ad.request & ~perms->allow; + AA_BUG(!ad.request); - if (aad(&sa)->request & perms->kill) + if (ad.request & perms->kill) type = AUDIT_APPARMOR_KILL; /* quiet known rejects, assumes quiet and kill do not overlap */ - if ((aad(&sa)->request & perms->quiet) && + if ((ad.request & perms->quiet) && AUDIT_MODE(profile) != AUDIT_NOQUIET && AUDIT_MODE(profile) != AUDIT_ALL) - aad(&sa)->request &= ~perms->quiet; + ad.request &= ~perms->quiet; - if (!aad(&sa)->request) - return aad(&sa)->error; + if (!ad.request) + return ad.error; } - aad(&sa)->denied = aad(&sa)->request & ~perms->allow; - return aa_audit(type, profile, &sa, file_audit_cb); + ad.denied = ad.request & ~perms->allow; + return aa_audit(type, profile, &ad, file_audit_cb); } static int path_name(const char *op, struct aa_label *label, diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h index c328f07f11cd..85931ec94e91 100644 --- a/security/apparmor/include/audit.h +++ b/security/apparmor/include/audit.h @@ -152,33 +152,35 @@ struct apparmor_audit_data { unsigned long flags; } mnt; }; + + struct common_audit_data common; }; /* macros for dealing with apparmor_audit_data structure */ -#define aad(SA) ((SA)->apparmor_audit_data) +#define aad(SA) (container_of(SA, struct apparmor_audit_data, common)) +#define aad_of_va(VA) aad((struct common_audit_data *)(VA)) + #define DEFINE_AUDIT_DATA(NAME, T, C, X) \ /* TODO: cleanup audit init so we don't need _aad = {0,} */ \ - struct apparmor_audit_data NAME ## _aad = { \ + struct apparmor_audit_data NAME = { \ .class = (C), \ .op = (X), \ - }; \ - struct common_audit_data NAME = \ - { \ - .type = (T), \ - .u.tsk = NULL, \ - }; \ - NAME.apparmor_audit_data = &(NAME ## _aad) - -void aa_audit_msg(int type, struct common_audit_data *sa, + .common.type = (T), \ + .common.u.tsk = NULL, \ + .common.apparmor_audit_data = &NAME, \ + }; + +void aa_audit_msg(int type, struct apparmor_audit_data *ad, void (*cb) (struct audit_buffer *, void *)); -int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa, +int aa_audit(int type, struct aa_profile *profile, + struct apparmor_audit_data *ad, void (*cb) (struct audit_buffer *, void *)); -#define aa_audit_error(ERROR, SA, CB) \ +#define aa_audit_error(ERROR, AD, CB) \ ({ \ - aad((SA))->error = (ERROR); \ - aa_audit_msg(AUDIT_APPARMOR_ERROR, (SA), (CB)); \ - aad((SA))->error; \ + (AD)->error = (ERROR); \ + aa_audit_msg(AUDIT_APPARMOR_ERROR, (AD), (CB)); \ + (AD)->error; \ }) diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h index e29f011be3d7..e0068a3a4efd 100644 --- a/security/apparmor/include/net.h +++ b/security/apparmor/include/net.h @@ -65,9 +65,9 @@ static inline struct aa_sk_ctx *aa_sock(const struct sock *sk) LSM_AUDIT_DATA_NONE, \ AA_CLASS_NET, \ OP); \ - NAME.u.net = &(NAME ## _net); \ - aad(&NAME)->net.type = (T); \ - aad(&NAME)->net.protocol = (P) + NAME.common.u.net = &(NAME ## _net); \ + NAME.net.type = (T); \ + NAME.net.protocol = (P) #define DEFINE_AUDIT_SK(NAME, OP, SK) \ DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \ @@ -94,16 +94,17 @@ struct aa_secmark { extern struct aa_sfs_entry aa_sfs_entry_network[]; void audit_net_cb(struct audit_buffer *ab, void *va); -int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, +int aa_profile_af_perm(struct aa_profile *profile, + struct apparmor_audit_data *ad, u32 request, u16 family, int type); int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, int type, int protocol); static inline int aa_profile_af_sk_perm(struct aa_profile *profile, - struct common_audit_data *sa, + struct apparmor_audit_data *ad, u32 request, struct sock *sk) { - return aa_profile_af_perm(profile, sa, request, sk->sk_family, + return aa_profile_af_perm(profile, ad, request, sk->sk_family, sk->sk_type); } int aa_sk_perm(const char *op, u32 request, struct sock *sk); diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h index 797a7a00644d..83534df8939f 100644 --- a/security/apparmor/include/perms.h +++ b/security/apparmor/include/perms.h @@ -212,8 +212,8 @@ void aa_profile_match_label(struct aa_profile *profile, int type, u32 request, struct aa_perms *perms); int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, u32 request, int type, u32 *deny, - struct common_audit_data *sa); + struct apparmor_audit_data *ad); int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, - u32 request, struct common_audit_data *sa, + u32 request, struct apparmor_audit_data *ad, void (*cb)(struct audit_buffer *, void *)); #endif /* __AA_PERM_H */ diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index 5acde746775f..f198b8d620a4 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c @@ -52,31 +52,32 @@ static const char *audit_signal_mask(u32 mask) static void audit_signal_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); - if (aad(sa)->request & AA_SIGNAL_PERM_MASK) { + if (ad->request & AA_SIGNAL_PERM_MASK) { audit_log_format(ab, " requested_mask=\"%s\"", - audit_signal_mask(aad(sa)->request)); - if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) { + audit_signal_mask(ad->request)); + if (ad->denied & AA_SIGNAL_PERM_MASK) { audit_log_format(ab, " denied_mask=\"%s\"", - audit_signal_mask(aad(sa)->denied)); + audit_signal_mask(ad->denied)); } } - if (aad(sa)->signal == SIGUNKNOWN) + if (ad->signal == SIGUNKNOWN) audit_log_format(ab, "signal=unknown(%d)", - aad(sa)->unmappedsig); - else if (aad(sa)->signal < MAXMAPPED_SIGNAME) - audit_log_format(ab, " signal=%s", sig_names[aad(sa)->signal]); + ad->unmappedsig); + else if (ad->signal < MAXMAPPED_SIGNAME) + audit_log_format(ab, " signal=%s", sig_names[ad->signal]); else audit_log_format(ab, " signal=rtmin+%d", - aad(sa)->signal - SIGRT_BASE); + ad->signal - SIGRT_BASE); audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + aa_label_xaudit(ab, labels_ns(ad->label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } static int profile_signal_perm(struct aa_profile *profile, struct aa_label *peer, u32 request, - struct common_audit_data *sa) + struct apparmor_audit_data *ad) { struct aa_ruleset *rules = list_first_entry(&profile->rules, typeof(*rules), list); @@ -87,24 +88,24 @@ static int profile_signal_perm(struct aa_profile *profile, !ANY_RULE_MEDIATES(&profile->rules, AA_CLASS_SIGNAL)) return 0; - aad(sa)->peer = peer; + ad->peer = peer; /* TODO: secondary cache check */ state = aa_dfa_next(rules->policy.dfa, rules->policy.start[AA_CLASS_SIGNAL], - aad(sa)->signal); + ad->signal); aa_label_match(profile, rules, peer, state, false, request, &perms); aa_apply_modes_to_perms(profile, &perms); - return aa_check_perms(profile, &perms, request, sa, audit_signal_cb); + return aa_check_perms(profile, &perms, request, ad, audit_signal_cb); } int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig) { struct aa_profile *profile; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_SIGNAL, OP_SIGNAL); + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_SIGNAL, OP_SIGNAL); - aad(&sa)->signal = map_signal_num(sig); - aad(&sa)->unmappedsig = sig; + ad.signal = map_signal_num(sig); + ad.unmappedsig = sig; return xcheck_labels(sender, target, profile, - profile_signal_perm(profile, target, MAY_WRITE, &sa), - profile_signal_perm(profile, sender, MAY_READ, &sa)); + profile_signal_perm(profile, target, MAY_WRITE, &ad), + profile_signal_perm(profile, sender, MAY_READ, &ad)); } diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index 8e1073477c09..d6b2750fd72e 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c @@ -144,10 +144,10 @@ const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name, void aa_info_message(const char *str) { if (audit_enabled) { - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); - aad(&sa)->info = str; - aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); + ad.info = str; + aa_audit_msg(AUDIT_APPARMOR_STATUS, &ad, NULL); } printk(KERN_INFO "AppArmor: %s\n", str); } @@ -282,21 +282,22 @@ void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, static void aa_audit_perms_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); - if (aad(sa)->request) { + if (ad->request) { audit_log_format(ab, " requested_mask="); - aa_audit_perm_mask(ab, aad(sa)->request, aa_file_perm_chrs, + aa_audit_perm_mask(ab, ad->request, aa_file_perm_chrs, PERMS_CHRS_MASK, aa_file_perm_names, PERMS_NAMES_MASK); } - if (aad(sa)->denied) { + if (ad->denied) { audit_log_format(ab, "denied_mask="); - aa_audit_perm_mask(ab, aad(sa)->denied, aa_file_perm_chrs, + aa_audit_perm_mask(ab, ad->denied, aa_file_perm_chrs, PERMS_CHRS_MASK, aa_file_perm_names, PERMS_NAMES_MASK); } audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + aa_label_xaudit(ab, labels_ns(ad->label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } @@ -350,21 +351,21 @@ void aa_profile_match_label(struct aa_profile *profile, /* currently unused */ int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, u32 request, int type, u32 *deny, - struct common_audit_data *sa) + struct apparmor_audit_data *ad) { struct aa_ruleset *rules = list_first_entry(&profile->rules, typeof(*rules), list); struct aa_perms perms; - aad(sa)->label = &profile->label; - aad(sa)->peer = &target->label; - aad(sa)->request = request; + ad->label = &profile->label; + ad->peer = &target->label; + ad->request = request; aa_profile_match_label(profile, rules, &target->label, type, request, &perms); aa_apply_modes_to_perms(profile, &perms); *deny |= request & perms.deny; - return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb); + return aa_check_perms(profile, &perms, request, ad, aa_audit_perms_cb); } /** @@ -372,7 +373,7 @@ int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, * @profile: profile being checked * @perms: perms computed for the request * @request: requested perms - * @sa: initialized audit structure (MAY BE NULL if not auditing) + * @ad: initialized audit structure (MAY BE NULL if not auditing) * @cb: callback fn for type specific fields (MAY BE NULL) * * Returns: 0 if permission else error code @@ -385,7 +386,7 @@ int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, * with a positive value. */ int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, - u32 request, struct common_audit_data *sa, + u32 request, struct apparmor_audit_data *ad, void (*cb)(struct audit_buffer *, void *)) { int type, error; @@ -394,7 +395,7 @@ int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, if (likely(!denied)) { /* mask off perms that are not being force audited */ request &= perms->audit; - if (!request || !sa) + if (!request || !ad) return 0; type = AUDIT_APPARMOR_AUDIT; @@ -413,16 +414,16 @@ int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, error = -ENOENT; denied &= ~perms->quiet; - if (!sa || !denied) + if (!ad || !denied) return error; } - if (sa) { - aad(sa)->label = &profile->label; - aad(sa)->request = request; - aad(sa)->denied = denied; - aad(sa)->error = error; - aa_audit_msg(type, sa, cb); + if (ad) { + ad->label = &profile->label; + ad->request = request; + ad->denied = denied; + ad->error = error; + aa_audit_msg(type, ad, cb); } if (type == AUDIT_APPARMOR_ALLOWED) diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 63c6f21fb5ea..a8c8b179a16c 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -662,7 +662,7 @@ static int apparmor_setprocattr(const char *name, void *value, char *command, *largs = NULL, *args = value; size_t arg_size; int error; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, OP_SETPROCATTR); if (size == 0) @@ -722,11 +722,11 @@ out: return error; fail: - aad(&sa)->label = begin_current_label_crit_section(); - aad(&sa)->info = name; - aad(&sa)->error = error = -EINVAL; - aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL); - end_current_label_crit_section(aad(&sa)->label); + ad.label = begin_current_label_crit_section(); + ad.info = name; + ad.error = error = -EINVAL; + aa_audit_msg(AUDIT_APPARMOR_DENIED, &ad, NULL); + end_current_label_crit_section(ad.label); goto out; } diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c index cdfa430ae216..3830bceff9c8 100644 --- a/security/apparmor/mount.c +++ b/security/apparmor/mount.c @@ -86,27 +86,28 @@ static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags) static void audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); - if (aad(sa)->mnt.type) { + if (ad->mnt.type) { audit_log_format(ab, " fstype="); - audit_log_untrustedstring(ab, aad(sa)->mnt.type); + audit_log_untrustedstring(ab, ad->mnt.type); } - if (aad(sa)->mnt.src_name) { + if (ad->mnt.src_name) { audit_log_format(ab, " srcname="); - audit_log_untrustedstring(ab, aad(sa)->mnt.src_name); + audit_log_untrustedstring(ab, ad->mnt.src_name); } - if (aad(sa)->mnt.trans) { + if (ad->mnt.trans) { audit_log_format(ab, " trans="); - audit_log_untrustedstring(ab, aad(sa)->mnt.trans); + audit_log_untrustedstring(ab, ad->mnt.trans); } - if (aad(sa)->mnt.flags) { + if (ad->mnt.flags) { audit_log_format(ab, " flags=\""); - audit_mnt_flags(ab, aad(sa)->mnt.flags); + audit_mnt_flags(ab, ad->mnt.flags); audit_log_format(ab, "\""); } - if (aad(sa)->mnt.data) { + if (ad->mnt.data) { audit_log_format(ab, " options="); - audit_log_untrustedstring(ab, aad(sa)->mnt.data); + audit_log_untrustedstring(ab, ad->mnt.data); } } @@ -134,7 +135,7 @@ static int audit_mount(struct aa_profile *profile, const char *op, struct aa_perms *perms, const char *info, int error) { int audit_type = AUDIT_APPARMOR_AUTO; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_MOUNT, op); + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_MOUNT, op); if (likely(!error)) { u32 mask = perms->audit; @@ -165,17 +166,17 @@ static int audit_mount(struct aa_profile *profile, const char *op, return error; } - aad(&sa)->name = name; - aad(&sa)->mnt.src_name = src_name; - aad(&sa)->mnt.type = type; - aad(&sa)->mnt.trans = trans; - aad(&sa)->mnt.flags = flags; + ad.name = name; + ad.mnt.src_name = src_name; + ad.mnt.type = type; + ad.mnt.trans = trans; + ad.mnt.flags = flags; if (data && (perms->audit & AA_AUDIT_DATA)) - aad(&sa)->mnt.data = data; - aad(&sa)->info = info; - aad(&sa)->error = error; + ad.mnt.data = data; + ad.info = info; + ad.error = error; - return aa_audit(audit_type, profile, &sa, audit_cb); + return aa_audit(audit_type, profile, &ad, audit_cb); } /** diff --git a/security/apparmor/net.c b/security/apparmor/net.c index 788be1609a86..0c7304cd479c 100644 --- a/security/apparmor/net.c +++ b/security/apparmor/net.c @@ -71,6 +71,7 @@ static const char * const net_mask_names[] = { void audit_net_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); if (address_family_names[sa->u.net->family]) audit_log_format(ab, " family=\"%s\"", @@ -78,35 +79,36 @@ void audit_net_cb(struct audit_buffer *ab, void *va) else audit_log_format(ab, " family=\"unknown(%d)\"", sa->u.net->family); - if (sock_type_names[aad(sa)->net.type]) + if (sock_type_names[ad->net.type]) audit_log_format(ab, " sock_type=\"%s\"", - sock_type_names[aad(sa)->net.type]); + sock_type_names[ad->net.type]); else audit_log_format(ab, " sock_type=\"unknown(%d)\"", - aad(sa)->net.type); - audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol); + ad->net.type); + audit_log_format(ab, " protocol=%d", ad->net.protocol); - if (aad(sa)->request & NET_PERMS_MASK) { + if (ad->request & NET_PERMS_MASK) { audit_log_format(ab, " requested_mask="); - aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0, + aa_audit_perm_mask(ab, ad->request, NULL, 0, net_mask_names, NET_PERMS_MASK); - if (aad(sa)->denied & NET_PERMS_MASK) { + if (ad->denied & NET_PERMS_MASK) { audit_log_format(ab, " denied_mask="); - aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0, + aa_audit_perm_mask(ab, ad->denied, NULL, 0, net_mask_names, NET_PERMS_MASK); } } - if (aad(sa)->peer) { + if (ad->peer) { audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + aa_label_xaudit(ab, labels_ns(ad->label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } } /* Generic af perm */ -int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, - u32 request, u16 family, int type) +int aa_profile_af_perm(struct aa_profile *profile, + struct apparmor_audit_data *ad, u32 request, u16 family, + int type) { struct aa_ruleset *rules = list_first_entry(&profile->rules, typeof(*rules), list); @@ -130,17 +132,17 @@ int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, perms = *aa_lookup_perms(&rules->policy, state); aa_apply_modes_to_perms(profile, &perms); - return aa_check_perms(profile, &perms, request, sa, audit_net_cb); + return aa_check_perms(profile, &perms, request, ad, audit_net_cb); } int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, int type, int protocol) { struct aa_profile *profile; - DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol); + DEFINE_AUDIT_NET(ad, op, NULL, family, type, protocol); return fn_for_each_confined(label, profile, - aa_profile_af_perm(profile, &sa, request, family, + aa_profile_af_perm(profile, &ad, request, family, type)); } @@ -155,10 +157,10 @@ static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request, if (ctx->label != kernel_t && !unconfined(label)) { struct aa_profile *profile; - DEFINE_AUDIT_SK(sa, op, sk); + DEFINE_AUDIT_SK(ad, op, sk); error = fn_for_each_confined(label, profile, - aa_profile_af_sk_perm(profile, &sa, request, sk)); + aa_profile_af_sk_perm(profile, &ad, request, sk)); } return error; @@ -214,7 +216,7 @@ static int apparmor_secmark_init(struct aa_secmark *secmark) } static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid, - struct common_audit_data *sa) + struct apparmor_audit_data *ad) { int i, ret; struct aa_perms perms = { }; @@ -245,17 +247,17 @@ static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid, aa_apply_modes_to_perms(profile, &perms); - return aa_check_perms(profile, &perms, request, sa, audit_net_cb); + return aa_check_perms(profile, &perms, request, ad, audit_net_cb); } int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, u32 secid, const struct sock *sk) { struct aa_profile *profile; - DEFINE_AUDIT_SK(sa, op, sk); + DEFINE_AUDIT_SK(ad, op, sk); return fn_for_each_confined(label, profile, aa_secmark_perm(profile, request, secid, - &sa)); + &ad)); } #endif diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index d7525f228c43..4e26c97f1396 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -723,10 +723,11 @@ static int replacement_allowed(struct aa_profile *profile, int noreplace, static void audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); - if (aad(sa)->iface.ns) { + if (ad->iface.ns) { audit_log_format(ab, " ns="); - audit_log_untrustedstring(ab, aad(sa)->iface.ns); + audit_log_untrustedstring(ab, ad->iface.ns); } } @@ -745,15 +746,15 @@ static int audit_policy(struct aa_label *label, const char *op, const char *ns_name, const char *name, const char *info, int error) { - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, op); + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, op); - aad(&sa)->iface.ns = ns_name; - aad(&sa)->name = name; - aad(&sa)->info = info; - aad(&sa)->error = error; - aad(&sa)->label = label; + ad.iface.ns = ns_name; + ad.name = name; + ad.info = info; + ad.error = error; + ad.label = label; - aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, audit_cb); + aa_audit_msg(AUDIT_APPARMOR_STATUS, &ad, audit_cb); return error; } diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 8b2ad42c80ba..cb8b5c497812 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -34,17 +34,18 @@ static void audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); - if (aad(sa)->iface.ns) { + if (ad->iface.ns) { audit_log_format(ab, " ns="); - audit_log_untrustedstring(ab, aad(sa)->iface.ns); + audit_log_untrustedstring(ab, ad->iface.ns); } - if (aad(sa)->name) { + if (ad->name) { audit_log_format(ab, " name="); - audit_log_untrustedstring(ab, aad(sa)->name); + audit_log_untrustedstring(ab, ad->name); } - if (aad(sa)->iface.pos) - audit_log_format(ab, " offset=%ld", aad(sa)->iface.pos); + if (ad->iface.pos) + audit_log_format(ab, " offset=%ld", ad->iface.pos); } /** @@ -63,18 +64,18 @@ static int audit_iface(struct aa_profile *new, const char *ns_name, int error) { struct aa_profile *profile = labels_profile(aa_current_raw_label()); - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); if (e) - aad(&sa)->iface.pos = e->pos - e->start; - aad(&sa)->iface.ns = ns_name; + ad.iface.pos = e->pos - e->start; + ad.iface.ns = ns_name; if (new) - aad(&sa)->name = new->base.hname; + ad.name = new->base.hname; else - aad(&sa)->name = name; - aad(&sa)->info = info; - aad(&sa)->error = error; + ad.name = name; + ad.info = info; + ad.error = error; - return aa_audit(AUDIT_APPARMOR_STATUS, profile, &sa, audit_cb); + return aa_audit(AUDIT_APPARMOR_STATUS, profile, &ad, audit_cb); } void __aa_loaddata_update(struct aa_loaddata *data, long revision) diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c index 2bebc5d9e741..b6b5e1bfe9a2 100644 --- a/security/apparmor/resource.c +++ b/security/apparmor/resource.c @@ -30,12 +30,13 @@ struct aa_sfs_entry aa_sfs_entry_rlimit[] = { static void audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); audit_log_format(ab, " rlimit=%s value=%lu", - rlim_names[aad(sa)->rlim.rlim], aad(sa)->rlim.max); - if (aad(sa)->peer) { + rlim_names[ad->rlim.rlim], ad->rlim.max); + if (ad->peer) { audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + aa_label_xaudit(ab, labels_ns(ad->label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } } @@ -49,22 +50,22 @@ static void audit_cb(struct audit_buffer *ab, void *va) * @info: info being auditing * @error: error value * - * Returns: 0 or sa->error else other error code on failure + * Returns: 0 or ad->error else other error code on failure */ static int audit_resource(struct aa_profile *profile, unsigned int resource, unsigned long value, struct aa_label *peer, const char *info, int error) { - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_RLIMITS, + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_RLIMITS, OP_SETRLIMIT); - aad(&sa)->rlim.rlim = resource; - aad(&sa)->rlim.max = value; - aad(&sa)->peer = peer; - aad(&sa)->info = info; - aad(&sa)->error = error; + ad.rlim.rlim = resource; + ad.rlim.max = value; + ad.peer = peer; + ad.info = info; + ad.error = error; - return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa, audit_cb); + return aa_audit(AUDIT_APPARMOR_AUTO, profile, &ad, audit_cb); } /** diff --git a/security/apparmor/task.c b/security/apparmor/task.c index 5671a716fcd2..b2a777ed14d8 100644 --- a/security/apparmor/task.c +++ b/security/apparmor/task.c @@ -205,18 +205,19 @@ static const char *audit_ptrace_mask(u32 mask) static void audit_ptrace_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); - if (aad(sa)->request & AA_PTRACE_PERM_MASK) { + if (ad->request & AA_PTRACE_PERM_MASK) { audit_log_format(ab, " requested_mask=\"%s\"", - audit_ptrace_mask(aad(sa)->request)); + audit_ptrace_mask(ad->request)); - if (aad(sa)->denied & AA_PTRACE_PERM_MASK) { + if (ad->denied & AA_PTRACE_PERM_MASK) { audit_log_format(ab, " denied_mask=\"%s\"", - audit_ptrace_mask(aad(sa)->denied)); + audit_ptrace_mask(ad->denied)); } } audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + aa_label_xaudit(ab, labels_ns(ad->label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } @@ -224,51 +225,51 @@ static void audit_ptrace_cb(struct audit_buffer *ab, void *va) /* TODO: conditionals */ static int profile_ptrace_perm(struct aa_profile *profile, struct aa_label *peer, u32 request, - struct common_audit_data *sa) + struct apparmor_audit_data *ad) { struct aa_ruleset *rules = list_first_entry(&profile->rules, typeof(*rules), list); struct aa_perms perms = { }; - aad(sa)->peer = peer; + ad->peer = peer; aa_profile_match_label(profile, rules, peer, AA_CLASS_PTRACE, request, &perms); aa_apply_modes_to_perms(profile, &perms); - return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); + return aa_check_perms(profile, &perms, request, ad, audit_ptrace_cb); } static int profile_tracee_perm(struct aa_profile *tracee, struct aa_label *tracer, u32 request, - struct common_audit_data *sa) + struct apparmor_audit_data *ad) { if (profile_unconfined(tracee) || unconfined(tracer) || !ANY_RULE_MEDIATES(&tracee->rules, AA_CLASS_PTRACE)) return 0; - return profile_ptrace_perm(tracee, tracer, request, sa); + return profile_ptrace_perm(tracee, tracer, request, ad); } static int profile_tracer_perm(struct aa_profile *tracer, struct aa_label *tracee, u32 request, - struct common_audit_data *sa) + struct apparmor_audit_data *ad) { if (profile_unconfined(tracer)) return 0; if (ANY_RULE_MEDIATES(&tracer->rules, AA_CLASS_PTRACE)) - return profile_ptrace_perm(tracer, tracee, request, sa); + return profile_ptrace_perm(tracer, tracee, request, ad); /* profile uses the old style capability check for ptrace */ if (&tracer->label == tracee) return 0; - aad(sa)->label = &tracer->label; - aad(sa)->peer = tracee; - aad(sa)->request = 0; - aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, + ad->label = &tracer->label; + ad->peer = tracee; + ad->request = 0; + ad->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, CAP_OPT_NONE); - return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb); + return aa_audit(AUDIT_APPARMOR_AUTO, tracer, ad, audit_ptrace_cb); } /** -- cgit From d20f5a1a6e792d22199c9989ec7ab9e95c48d60c Mon Sep 17 00:00:00 2001 From: John Johansen Date: Mon, 19 Sep 2022 00:46:09 -0700 Subject: apparmor: rename audit_data->label to audit_data->subj_label rename audit_data's label field to subj_label to better reflect its use. Also at the same time drop unneeded assignments to ->subj_label as the later call to aa_check_perms will do the assignment if needed. Reviewed-by: Georgia Garcia Signed-off-by: John Johansen --- security/apparmor/audit.c | 6 +++--- security/apparmor/file.c | 2 +- security/apparmor/include/audit.h | 2 +- security/apparmor/ipc.c | 2 +- security/apparmor/lib.c | 5 ++--- security/apparmor/lsm.c | 4 ++-- security/apparmor/net.c | 2 +- security/apparmor/policy.c | 6 +++--- security/apparmor/resource.c | 2 +- security/apparmor/task.c | 4 ++-- 10 files changed, 17 insertions(+), 18 deletions(-) (limited to 'security/apparmor/lib.c') diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index 06ad6a8fcce1..6933cb2f679b 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c @@ -113,8 +113,8 @@ static void audit_pre(struct audit_buffer *ab, void *va) audit_log_format(ab, " error=%d", ad->error); } - if (ad->label) { - struct aa_label *label = ad->label; + if (ad->subj_label) { + struct aa_label *label = ad->subj_label; if (label_isprofile(label)) { struct aa_profile *profile = labels_profile(label); @@ -187,7 +187,7 @@ int aa_audit(int type, struct aa_profile *profile, if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) type = AUDIT_APPARMOR_KILL; - ad->label = &profile->label; + ad->subj_label = &profile->label; aa_audit_msg(type, ad, cb); diff --git a/security/apparmor/file.c b/security/apparmor/file.c index 01ff612c060e..26d45effdbc7 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c @@ -67,7 +67,7 @@ static void file_audit_cb(struct audit_buffer *ab, void *va) if (ad->peer) { audit_log_format(ab, " target="); - aa_label_xaudit(ab, labels_ns(ad->label), ad->peer, + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, FLAG_VIEW_SUBNS, GFP_KERNEL); } else if (ad->fs.target) { audit_log_format(ab, " target="); diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h index 85931ec94e91..096f0a04af87 100644 --- a/security/apparmor/include/audit.h +++ b/security/apparmor/include/audit.h @@ -109,7 +109,7 @@ struct apparmor_audit_data { int type; u16 class; const char *op; - struct aa_label *label; + struct aa_label *subj_label; const char *name; const char *info; u32 request; diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index f198b8d620a4..fd8306399b82 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c @@ -71,7 +71,7 @@ static void audit_signal_cb(struct audit_buffer *ab, void *va) audit_log_format(ab, " signal=rtmin+%d", ad->signal - SIGRT_BASE); audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(ad->label), ad->peer, + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index d6b2750fd72e..c87bccafff44 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c @@ -297,7 +297,7 @@ static void aa_audit_perms_cb(struct audit_buffer *ab, void *va) PERMS_NAMES_MASK); } audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(ad->label), ad->peer, + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } @@ -357,7 +357,6 @@ int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, typeof(*rules), list); struct aa_perms perms; - ad->label = &profile->label; ad->peer = &target->label; ad->request = request; @@ -419,7 +418,7 @@ int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, } if (ad) { - ad->label = &profile->label; + ad->subj_label = &profile->label; ad->request = request; ad->denied = denied; ad->error = error; diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index a8c8b179a16c..3a9a9902d117 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -722,11 +722,11 @@ out: return error; fail: - ad.label = begin_current_label_crit_section(); + ad.subj_label = begin_current_label_crit_section(); ad.info = name; ad.error = error = -EINVAL; aa_audit_msg(AUDIT_APPARMOR_DENIED, &ad, NULL); - end_current_label_crit_section(ad.label); + end_current_label_crit_section(ad.subj_label); goto out; } diff --git a/security/apparmor/net.c b/security/apparmor/net.c index 0c7304cd479c..5e50f80e35db 100644 --- a/security/apparmor/net.c +++ b/security/apparmor/net.c @@ -100,7 +100,7 @@ void audit_net_cb(struct audit_buffer *ab, void *va) } if (ad->peer) { audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(ad->label), ad->peer, + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } } diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 4e26c97f1396..d78970d4a851 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -733,7 +733,7 @@ static void audit_cb(struct audit_buffer *ab, void *va) /** * audit_policy - Do auditing of policy changes - * @label: label to check if it can manage policy + * @subj_label: label to check if it can manage policy * @op: policy operation being performed * @ns_name: name of namespace being manipulated * @name: name of profile being manipulated (NOT NULL) @@ -742,7 +742,7 @@ static void audit_cb(struct audit_buffer *ab, void *va) * * Returns: the error to be returned after audit is done */ -static int audit_policy(struct aa_label *label, const char *op, +static int audit_policy(struct aa_label *subj_label, const char *op, const char *ns_name, const char *name, const char *info, int error) { @@ -752,7 +752,7 @@ static int audit_policy(struct aa_label *label, const char *op, ad.name = name; ad.info = info; ad.error = error; - ad.label = label; + ad.subj_label = subj_label; aa_audit_msg(AUDIT_APPARMOR_STATUS, &ad, audit_cb); diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c index b6b5e1bfe9a2..73ba26c646a5 100644 --- a/security/apparmor/resource.c +++ b/security/apparmor/resource.c @@ -36,7 +36,7 @@ static void audit_cb(struct audit_buffer *ab, void *va) rlim_names[ad->rlim.rlim], ad->rlim.max); if (ad->peer) { audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(ad->label), ad->peer, + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } } diff --git a/security/apparmor/task.c b/security/apparmor/task.c index b2a777ed14d8..552442844ff8 100644 --- a/security/apparmor/task.c +++ b/security/apparmor/task.c @@ -217,7 +217,7 @@ static void audit_ptrace_cb(struct audit_buffer *ab, void *va) } } audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(ad->label), ad->peer, + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } @@ -263,7 +263,7 @@ static int profile_tracer_perm(struct aa_profile *tracer, if (&tracer->label == tracee) return 0; - ad->label = &tracer->label; + ad->subj_label = &tracer->label; ad->peer = tracee; ad->request = 0; ad->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, -- cgit From 98b824ff8984fd523fc264fbb13208098ab09da3 Mon Sep 17 00:00:00 2001 From: John Johansen Date: Fri, 28 Apr 2023 05:32:52 -0700 Subject: apparmor: refcount the pdb With the move to permission tables the dfa is no longer a stand alone entity when used, needing a minimum of a permission table. However it still could be shared among different pdbs each using a different permission table. Instead of duping the permission table when sharing a pdb, add a refcount to the pdb so it can be easily shared. Reviewed-by: Georgia Garcia Signed-off-by: John Johansen --- security/apparmor/apparmorfs.c | 18 +++---- security/apparmor/domain.c | 60 ++++++++++----------- security/apparmor/file.c | 12 ++--- security/apparmor/include/lib.h | 2 + security/apparmor/include/match.h | 6 --- security/apparmor/include/policy.h | 49 ++++++++++++----- security/apparmor/ipc.c | 4 +- security/apparmor/label.c | 18 +++---- security/apparmor/lib.c | 4 +- security/apparmor/lsm.c | 63 ++++++++++++++++++++++ security/apparmor/match.c | 44 --------------- security/apparmor/mount.c | 20 +++---- security/apparmor/net.c | 4 +- security/apparmor/policy.c | 58 +++++++++++++------- security/apparmor/policy_unpack.c | 108 +++++++++++++++++-------------------- 15 files changed, 260 insertions(+), 210 deletions(-) (limited to 'security/apparmor/lib.c') diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index f20d923944e4..0bba46ccdb71 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -619,23 +619,23 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms, if (profile_unconfined(profile)) return; - if (rules->file.dfa && *match_str == AA_CLASS_FILE) { - state = aa_dfa_match_len(rules->file.dfa, - rules->file.start[AA_CLASS_FILE], + if (rules->file->dfa && *match_str == AA_CLASS_FILE) { + state = aa_dfa_match_len(rules->file->dfa, + rules->file->start[AA_CLASS_FILE], match_str + 1, match_len - 1); if (state) { struct path_cond cond = { }; - tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); + tmp = *(aa_lookup_fperms(rules->file, state, &cond)); } - } else if (rules->policy.dfa) { + } else if (rules->policy->dfa) { if (!RULE_MEDIATES(rules, *match_str)) return; /* no change to current perms */ - state = aa_dfa_match_len(rules->policy.dfa, - rules->policy.start[0], + state = aa_dfa_match_len(rules->policy->dfa, + rules->policy->start[0], match_str, match_len); if (state) - tmp = *aa_lookup_perms(&rules->policy, state); + tmp = *aa_lookup_perms(rules->policy, state); } aa_apply_modes_to_perms(profile, &tmp); aa_perms_accum_raw(perms, &tmp); @@ -1096,7 +1096,7 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v) struct aa_profile *profile = labels_profile(label); if (profile->attach.xmatch_str) seq_printf(seq, "%s\n", profile->attach.xmatch_str); - else if (profile->attach.xmatch.dfa) + else if (profile->attach.xmatch->dfa) seq_puts(seq, "\n"); else seq_printf(seq, "%s\n", profile->base.name); diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index d95292a23bcf..87dfa0e40398 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c @@ -77,7 +77,7 @@ out: /**** TODO: dedup to aa_label_match - needs perm and dfa, merging * specifically this is an exact copy of aa_label_match except * aa_compute_perms is replaced with aa_compute_fperms - * and policy.dfa with file.dfa + * and policy->dfa with file->dfa ****/ /* match a profile and its associated ns component if needed * Assumes visibility test has already been done. @@ -93,16 +93,16 @@ static inline aa_state_t match_component(struct aa_profile *profile, const char *ns_name; if (stack) - state = aa_dfa_match(rules->file.dfa, state, "&"); + state = aa_dfa_match(rules->file->dfa, state, "&"); if (profile->ns == tp->ns) - return aa_dfa_match(rules->file.dfa, state, tp->base.hname); + return aa_dfa_match(rules->file->dfa, state, tp->base.hname); /* try matching with namespace name and then profile */ ns_name = aa_ns_name(profile->ns, tp->ns, true); - state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); - state = aa_dfa_match(rules->file.dfa, state, ns_name); - state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); - return aa_dfa_match(rules->file.dfa, state, tp->base.hname); + state = aa_dfa_match_len(rules->file->dfa, state, ":", 1); + state = aa_dfa_match(rules->file->dfa, state, ns_name); + state = aa_dfa_match_len(rules->file->dfa, state, ":", 1); + return aa_dfa_match(rules->file->dfa, state, tp->base.hname); } /** @@ -150,12 +150,12 @@ next: label_for_each_cont(i, label, tp) { if (!aa_ns_visible(profile->ns, tp->ns, subns)) continue; - state = aa_dfa_match(rules->file.dfa, state, "//&"); + state = aa_dfa_match(rules->file->dfa, state, "//&"); state = match_component(profile, tp, false, state); if (!state) goto fail; } - *perms = *(aa_lookup_fperms(&(rules->file), state, &cond)); + *perms = *(aa_lookup_fperms(rules->file, state, &cond)); aa_apply_modes_to_perms(profile, perms); if ((perms->allow & request) != request) return -EACCES; @@ -210,7 +210,7 @@ static int label_components_match(struct aa_profile *profile, return 0; next: - tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); + tmp = *(aa_lookup_fperms(rules->file, state, &cond)); aa_apply_modes_to_perms(profile, &tmp); aa_perms_accum(perms, &tmp); label_for_each_cont(i, label, tp) { @@ -219,7 +219,7 @@ next: state = match_component(profile, tp, stack, start); if (!state) goto fail; - tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); + tmp = *(aa_lookup_fperms(rules->file, state, &cond)); aa_apply_modes_to_perms(profile, &tmp); aa_perms_accum(perms, &tmp); } @@ -317,7 +317,7 @@ static int aa_xattrs_match(const struct linux_binprm *bprm, might_sleep(); /* transition from exec match to xattr set */ - state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); + state = aa_dfa_outofband_transition(attach->xmatch->dfa, state); d = bprm->file->f_path.dentry; for (i = 0; i < attach->xattr_count; i++) { @@ -331,20 +331,20 @@ static int aa_xattrs_match(const struct linux_binprm *bprm, * that not present xattr can be distinguished from a 0 * length value or rule that matches any value */ - state = aa_dfa_null_transition(attach->xmatch.dfa, + state = aa_dfa_null_transition(attach->xmatch->dfa, state); /* Check xattr value */ - state = aa_dfa_match_len(attach->xmatch.dfa, state, + state = aa_dfa_match_len(attach->xmatch->dfa, state, value, size); - index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; - perm = attach->xmatch.perms[index].allow; + index = ACCEPT_TABLE(attach->xmatch->dfa)[state]; + perm = attach->xmatch->perms[index].allow; if (!(perm & MAY_EXEC)) { ret = -EINVAL; goto out; } } /* transition to next element */ - state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); + state = aa_dfa_outofband_transition(attach->xmatch->dfa, state); if (size < 0) { /* * No xattr match, so verify if transition to @@ -413,16 +413,16 @@ restart: * as another profile, signal a conflict and refuse to * match. */ - if (attach->xmatch.dfa) { + if (attach->xmatch->dfa) { unsigned int count; aa_state_t state; u32 index, perm; - state = aa_dfa_leftmatch(attach->xmatch.dfa, - attach->xmatch.start[AA_CLASS_XMATCH], + state = aa_dfa_leftmatch(attach->xmatch->dfa, + attach->xmatch->start[AA_CLASS_XMATCH], name, &count); - index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; - perm = attach->xmatch.perms[index].allow; + index = ACCEPT_TABLE(attach->xmatch->dfa)[state]; + perm = attach->xmatch->perms[index].allow; /* any accepting state means a valid match. */ if (perm & MAY_EXEC) { int ret = 0; @@ -525,7 +525,7 @@ struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, /* TODO: move lookup parsing to unpack time so this is a straight * index into the resultant label */ - for (*name = rules->file.trans.table[index]; !label && *name; + for (*name = rules->file->trans.table[index]; !label && *name; *name = next_name(xtype, *name)) { if (xindex & AA_X_CHILD) { struct aa_profile *new_profile; @@ -579,7 +579,7 @@ static struct aa_label *x_to_label(struct aa_profile *profile, break; case AA_X_TABLE: /* TODO: fix when perm mapping done at unload */ - stack = rules->file.trans.table[xindex & AA_X_INDEX_MASK]; + stack = rules->file->trans.table[xindex & AA_X_INDEX_MASK]; if (*stack != '&') { /* released by caller */ new = x_table_lookup(profile, xindex, lookupname); @@ -638,7 +638,7 @@ static struct aa_label *profile_transition(const struct cred *subj_cred, typeof(*rules), list); struct aa_label *new = NULL; const char *info = NULL, *name = NULL, *target = NULL; - aa_state_t state = rules->file.start[AA_CLASS_FILE]; + aa_state_t state = rules->file->start[AA_CLASS_FILE]; struct aa_perms perms = {}; bool nonewprivs = false; int error = 0; @@ -672,7 +672,7 @@ static struct aa_label *profile_transition(const struct cred *subj_cred, } /* find exec permissions for name */ - state = aa_str_perms(&(rules->file), state, name, cond, &perms); + state = aa_str_perms(rules->file, state, name, cond, &perms); if (perms.allow & MAY_EXEC) { /* exec permission determine how to transition */ new = x_to_label(profile, bprm, name, perms.xindex, &target, @@ -738,7 +738,7 @@ static int profile_onexec(const struct cred *subj_cred, { struct aa_ruleset *rules = list_first_entry(&profile->rules, typeof(*rules), list); - aa_state_t state = rules->file.start[AA_CLASS_FILE]; + aa_state_t state = rules->file->start[AA_CLASS_FILE]; struct aa_perms perms = {}; const char *xname = NULL, *info = "change_profile onexec"; int error = -EACCES; @@ -771,7 +771,7 @@ static int profile_onexec(const struct cred *subj_cred, } /* find exec permissions for name */ - state = aa_str_perms(&(rules->file), state, xname, cond, &perms); + state = aa_str_perms(rules->file, state, xname, cond, &perms); if (!(perms.allow & AA_MAY_ONEXEC)) { info = "no change_onexec valid for executable"; goto audit; @@ -780,7 +780,7 @@ static int profile_onexec(const struct cred *subj_cred, * onexec permission is linked to exec with a standard pairing * exec\0change_profile */ - state = aa_dfa_null_transition(rules->file.dfa, state); + state = aa_dfa_null_transition(rules->file->dfa, state); error = change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC, state, &perms); if (error) { @@ -1300,7 +1300,7 @@ static int change_profile_perms_wrapper(const char *op, const char *name, if (!error) error = change_profile_perms(profile, target, stack, request, - rules->file.start[AA_CLASS_FILE], + rules->file->start[AA_CLASS_FILE], perms); if (error) error = aa_audit_file(subj_cred, profile, perms, op, request, diff --git a/security/apparmor/file.c b/security/apparmor/file.c index 48afcef45694..c03eb7c19f16 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c @@ -236,7 +236,7 @@ static int __aa_path_perm(const char *op, const struct cred *subj_cred, if (profile_unconfined(profile)) return 0; - aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], + aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE], name, cond, perms); if (request & ~perms->allow) e = -EACCES; @@ -353,16 +353,16 @@ static int profile_path_link(const struct cred *subj_cred, error = -EACCES; /* aa_str_perms - handles the case of the dfa being NULL */ - state = aa_str_perms(&(rules->file), - rules->file.start[AA_CLASS_FILE], lname, + state = aa_str_perms(rules->file, + rules->file->start[AA_CLASS_FILE], lname, cond, &lperms); if (!(lperms.allow & AA_MAY_LINK)) goto audit; /* test to see if target can be paired with link */ - state = aa_dfa_null_transition(rules->file.dfa, state); - aa_str_perms(&(rules->file), state, tname, cond, &perms); + state = aa_dfa_null_transition(rules->file->dfa, state); + aa_str_perms(rules->file, state, tname, cond, &perms); /* force audit/quiet masks for link are stored in the second entry * in the link pair. @@ -384,7 +384,7 @@ static int profile_path_link(const struct cred *subj_cred, /* Do link perm subset test requiring allowed permission on link are * a subset of the allowed permissions on target. */ - aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], + aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE], tname, cond, &perms); /* AA_MAY_LINK is not considered in the subset test */ diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h index 73c8a32c6861..d7a894b1031f 100644 --- a/security/apparmor/include/lib.h +++ b/security/apparmor/include/lib.h @@ -16,6 +16,8 @@ #include "match.h" +extern struct aa_dfa *stacksplitdfa; + /* * DEBUG remains global (no per profile flag) since it is mostly used in sysctl * which is not related to profile accesses. diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h index 58fbf67139b9..4bb0405c9190 100644 --- a/security/apparmor/include/match.h +++ b/security/apparmor/include/match.h @@ -102,9 +102,6 @@ struct aa_dfa { struct table_header *tables[YYTD_ID_TSIZE]; }; -extern struct aa_dfa *nulldfa; -extern struct aa_dfa *stacksplitdfa; - #define byte_to_byte(X) (X) #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX) \ @@ -122,9 +119,6 @@ static inline size_t table_size(size_t len, size_t el_size) return ALIGN(sizeof(struct table_header) + len * el_size, 8); } -int aa_setup_dfa_engine(void); -void aa_teardown_dfa_engine(void); - #define aa_state_t unsigned int struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags); diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index 5572447d7c37..e69c91619a7c 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h @@ -74,12 +74,14 @@ enum profile_mode { /* struct aa_policydb - match engine for a policy + * count: refcount for the pdb * dfa: dfa pattern match * perms: table of permissions * strs: table of strings, index by x * start: set of start states for the different classes of data */ struct aa_policydb { + struct kref count; struct aa_dfa *dfa; struct { struct aa_perms *perms; @@ -89,13 +91,36 @@ struct aa_policydb { aa_state_t start[AA_CLASS_LAST + 1]; }; -static inline void aa_destroy_policydb(struct aa_policydb *policy) +extern struct aa_policydb *nullpdb; + +struct aa_policydb *aa_alloc_pdb(gfp_t gfp); +void aa_pdb_free_kref(struct kref *kref); + +/** + * aa_get_pdb - increment refcount on @pdb + * @pdb: policydb (MAYBE NULL) + * + * Returns: pointer to @pdb if @pdb is NULL will return NULL + * Requires: @pdb must be held with valid refcount when called + */ +static inline struct aa_policydb *aa_get_pdb(struct aa_policydb *pdb) { - aa_put_dfa(policy->dfa); - if (policy->perms) - kvfree(policy->perms); - aa_free_str_table(&policy->trans); + if (pdb) + kref_get(&(pdb->count)); + return pdb; +} + +/** + * aa_put_pdb - put a pdb refcount + * @pdb: pdb to put refcount (MAYBE NULL) + * + * Requires: if @pdb != NULL that a valid refcount be held + */ +static inline void aa_put_pdb(struct aa_policydb *pdb) +{ + if (pdb) + kref_put(&pdb->count, aa_pdb_free_kref); } static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy, @@ -139,8 +164,8 @@ struct aa_ruleset { int size; /* TODO: merge policy and file */ - struct aa_policydb policy; - struct aa_policydb file; + struct aa_policydb *policy; + struct aa_policydb *file; struct aa_caps caps; struct aa_rlimit rlimits; @@ -159,7 +184,7 @@ struct aa_ruleset { */ struct aa_attachment { const char *xmatch_str; - struct aa_policydb xmatch; + struct aa_policydb *xmatch; unsigned int xmatch_len; int xattr_count; char **xattrs; @@ -267,10 +292,10 @@ static inline aa_state_t RULE_MEDIATES(struct aa_ruleset *rules, unsigned char class) { if (class <= AA_CLASS_LAST) - return rules->policy.start[class]; + return rules->policy->start[class]; else - return aa_dfa_match_len(rules->policy.dfa, - rules->policy.start[0], &class, 1); + return aa_dfa_match_len(rules->policy->dfa, + rules->policy->start[0], &class, 1); } static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) @@ -280,7 +305,7 @@ static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) if (!state) return DFA_NOMATCH; - return aa_dfa_match_len(rules->policy.dfa, state, (char *) &be_af, 2); + return aa_dfa_match_len(rules->policy->dfa, state, (char *) &be_af, 2); } static inline aa_state_t ANY_RULE_MEDIATES(struct list_head *head, diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index c0d0dbd7b4c4..0cdf4340b02d 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c @@ -92,8 +92,8 @@ static int profile_signal_perm(const struct cred *cred, ad->subj_cred = cred; ad->peer = peer; /* TODO: secondary cache check */ - state = aa_dfa_next(rules->policy.dfa, - rules->policy.start[AA_CLASS_SIGNAL], + state = aa_dfa_next(rules->policy->dfa, + rules->policy->start[AA_CLASS_SIGNAL], ad->signal); aa_label_match(profile, rules, peer, state, false, request, &perms); aa_apply_modes_to_perms(profile, &perms); diff --git a/security/apparmor/label.c b/security/apparmor/label.c index 8a74e89b05f4..c71e4615dd46 100644 --- a/security/apparmor/label.c +++ b/security/apparmor/label.c @@ -1270,14 +1270,14 @@ static inline aa_state_t match_component(struct aa_profile *profile, const char *ns_name; if (profile->ns == tp->ns) - return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); + return aa_dfa_match(rules->policy->dfa, state, tp->base.hname); /* try matching with namespace name and then profile */ ns_name = aa_ns_name(profile->ns, tp->ns, true); - state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1); - state = aa_dfa_match(rules->policy.dfa, state, ns_name); - state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1); - return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); + state = aa_dfa_match_len(rules->policy->dfa, state, ":", 1); + state = aa_dfa_match(rules->policy->dfa, state, ns_name); + state = aa_dfa_match_len(rules->policy->dfa, state, ":", 1); + return aa_dfa_match(rules->policy->dfa, state, tp->base.hname); } /** @@ -1323,12 +1323,12 @@ next: label_for_each_cont(i, label, tp) { if (!aa_ns_visible(profile->ns, tp->ns, subns)) continue; - state = aa_dfa_match(rules->policy.dfa, state, "//&"); + state = aa_dfa_match(rules->policy->dfa, state, "//&"); state = match_component(profile, rules, tp, state); if (!state) goto fail; } - *perms = *aa_lookup_perms(&rules->policy, state); + *perms = *aa_lookup_perms(rules->policy, state); aa_apply_modes_to_perms(profile, perms); if ((perms->allow & request) != request) return -EACCES; @@ -1381,7 +1381,7 @@ static int label_components_match(struct aa_profile *profile, return 0; next: - tmp = *aa_lookup_perms(&rules->policy, state); + tmp = *aa_lookup_perms(rules->policy, state); aa_apply_modes_to_perms(profile, &tmp); aa_perms_accum(perms, &tmp); label_for_each_cont(i, label, tp) { @@ -1390,7 +1390,7 @@ next: state = match_component(profile, rules, tp, start); if (!state) goto fail; - tmp = *aa_lookup_perms(&rules->policy, state); + tmp = *aa_lookup_perms(rules->policy, state); aa_apply_modes_to_perms(profile, &tmp); aa_perms_accum(perms, &tmp); } diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index c87bccafff44..4c198d273f09 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c @@ -341,8 +341,8 @@ void aa_profile_match_label(struct aa_profile *profile, /* TODO: doesn't yet handle extended types */ aa_state_t state; - state = aa_dfa_next(rules->policy.dfa, - rules->policy.start[AA_CLASS_LABEL], + state = aa_dfa_next(rules->policy->dfa, + rules->policy->start[AA_CLASS_LABEL], type); aa_label_match(profile, rules, label, state, false, request, perms); } diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 9e31a932a644..bcfe8b9cb4c1 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1887,6 +1887,69 @@ static int __init apparmor_nf_ip_init(void) __initcall(apparmor_nf_ip_init); #endif +static char nulldfa_src[] = { + #include "nulldfa.in" +}; +struct aa_dfa *nulldfa; + +static char stacksplitdfa_src[] = { + #include "stacksplitdfa.in" +}; +struct aa_dfa *stacksplitdfa; +struct aa_policydb *nullpdb; + +static int __init aa_setup_dfa_engine(void) +{ + int error = -ENOMEM; + + nullpdb = aa_alloc_pdb(GFP_KERNEL); + if (!nullpdb) + return -ENOMEM; + + nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src), + TO_ACCEPT1_FLAG(YYTD_DATA32) | + TO_ACCEPT2_FLAG(YYTD_DATA32)); + if (IS_ERR(nulldfa)) { + error = PTR_ERR(nulldfa); + goto fail; + } + nullpdb->dfa = aa_get_dfa(nulldfa); + nullpdb->perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL); + if (!nullpdb->perms) + goto fail; + nullpdb->size = 2; + + stacksplitdfa = aa_dfa_unpack(stacksplitdfa_src, + sizeof(stacksplitdfa_src), + TO_ACCEPT1_FLAG(YYTD_DATA32) | + TO_ACCEPT2_FLAG(YYTD_DATA32)); + if (IS_ERR(stacksplitdfa)) { + error = PTR_ERR(stacksplitdfa); + goto fail; + } + + return 0; + +fail: + aa_put_pdb(nullpdb); + aa_put_dfa(nulldfa); + nullpdb = NULL; + nulldfa = NULL; + stacksplitdfa = NULL; + + return error; +} + +static void __init aa_teardown_dfa_engine(void) +{ + aa_put_dfa(stacksplitdfa); + aa_put_dfa(nulldfa); + aa_put_pdb(nullpdb); + nullpdb = NULL; + stacksplitdfa = NULL; + nulldfa = NULL; +} + static int __init apparmor_init(void) { int error; diff --git a/security/apparmor/match.c b/security/apparmor/match.c index 7bdcca2aed7d..517d77d3c34c 100644 --- a/security/apparmor/match.c +++ b/security/apparmor/match.c @@ -21,50 +21,6 @@ #define base_idx(X) ((X) & 0xffffff) -static char nulldfa_src[] = { - #include "nulldfa.in" -}; -struct aa_dfa *nulldfa; - -static char stacksplitdfa_src[] = { - #include "stacksplitdfa.in" -}; -struct aa_dfa *stacksplitdfa; - -int __init aa_setup_dfa_engine(void) -{ - int error; - - nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src), - TO_ACCEPT1_FLAG(YYTD_DATA32) | - TO_ACCEPT2_FLAG(YYTD_DATA32)); - if (IS_ERR(nulldfa)) { - error = PTR_ERR(nulldfa); - nulldfa = NULL; - return error; - } - - stacksplitdfa = aa_dfa_unpack(stacksplitdfa_src, - sizeof(stacksplitdfa_src), - TO_ACCEPT1_FLAG(YYTD_DATA32) | - TO_ACCEPT2_FLAG(YYTD_DATA32)); - if (IS_ERR(stacksplitdfa)) { - aa_put_dfa(nulldfa); - nulldfa = NULL; - error = PTR_ERR(stacksplitdfa); - stacksplitdfa = NULL; - return error; - } - - return 0; -} - -void __init aa_teardown_dfa_engine(void) -{ - aa_put_dfa(stacksplitdfa); - aa_put_dfa(nulldfa); -} - /** * unpack_table - unpack a dfa table (one of accept, default, base, next check) * @blob: data to unpack (NOT NULL) diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c index 2bb77aacc49a..3455dd4b1f99 100644 --- a/security/apparmor/mount.c +++ b/security/apparmor/mount.c @@ -332,8 +332,8 @@ static int match_mnt_path_str(const struct cred *subj_cred, } error = -EACCES; - pos = do_match_mnt(&rules->policy, - rules->policy.start[AA_CLASS_MOUNT], + pos = do_match_mnt(rules->policy, + rules->policy->start[AA_CLASS_MOUNT], mntpnt, devname, type, flags, data, binary, &perms); if (pos) { info = mnt_info_table[pos]; @@ -606,10 +606,10 @@ static int profile_umount(const struct cred *subj_cred, if (error) goto audit; - state = aa_dfa_match(rules->policy.dfa, - rules->policy.start[AA_CLASS_MOUNT], + state = aa_dfa_match(rules->policy->dfa, + rules->policy->start[AA_CLASS_MOUNT], name); - perms = *aa_lookup_perms(&rules->policy, state); + perms = *aa_lookup_perms(rules->policy, state); if (AA_MAY_UMOUNT & ~perms.allow) error = -EACCES; @@ -680,12 +680,12 @@ static struct aa_label *build_pivotroot(const struct cred *subj_cred, goto audit; error = -EACCES; - state = aa_dfa_match(rules->policy.dfa, - rules->policy.start[AA_CLASS_MOUNT], + state = aa_dfa_match(rules->policy->dfa, + rules->policy->start[AA_CLASS_MOUNT], new_name); - state = aa_dfa_null_transition(rules->policy.dfa, state); - state = aa_dfa_match(rules->policy.dfa, state, old_name); - perms = *aa_lookup_perms(&rules->policy, state); + state = aa_dfa_null_transition(rules->policy->dfa, state); + state = aa_dfa_match(rules->policy->dfa, state, old_name); + perms = *aa_lookup_perms(rules->policy, state); if (AA_MAY_PIVOTROOT & perms.allow) error = 0; diff --git a/security/apparmor/net.c b/security/apparmor/net.c index 704c171232ab..87e934b2b548 100644 --- a/security/apparmor/net.c +++ b/security/apparmor/net.c @@ -127,9 +127,9 @@ int aa_profile_af_perm(struct aa_profile *profile, buffer[0] = cpu_to_be16(family); buffer[1] = cpu_to_be16((u16) type); - state = aa_dfa_match_len(rules->policy.dfa, state, (char *) &buffer, + state = aa_dfa_match_len(rules->policy->dfa, state, (char *) &buffer, 4); - perms = *aa_lookup_perms(&rules->policy, state); + perms = *aa_lookup_perms(rules->policy, state); aa_apply_modes_to_perms(profile, &perms); return aa_check_perms(profile, &perms, request, ad, audit_net_cb); diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 6f80e1207d24..0b36bd6a6f33 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -98,6 +98,41 @@ const char *const aa_profile_mode_names[] = { }; +static void aa_free_pdb(struct aa_policydb *policy) +{ + if (policy) { + aa_put_dfa(policy->dfa); + if (policy->perms) + kvfree(policy->perms); + aa_free_str_table(&policy->trans); + } +} + +/** + * aa_pdb_free_kref - free aa_policydb by kref (called by aa_put_pdb) + * @kr: kref callback for freeing of a dfa (NOT NULL) + */ +void aa_pdb_free_kref(struct kref *kref) +{ + struct aa_policydb *pdb = container_of(kref, struct aa_policydb, count); + + aa_free_pdb(pdb); +} + + +struct aa_policydb *aa_alloc_pdb(gfp_t gfp) +{ + struct aa_policydb *pdb = kzalloc(sizeof(struct aa_policydb), gfp); + + if (!pdb) + return NULL; + + kref_init(&pdb->count); + + return pdb; +} + + /** * __add_profile - add a profiles to list and label tree * @list: list to add it to (NOT NULL) @@ -200,15 +235,15 @@ static void free_attachment(struct aa_attachment *attach) for (i = 0; i < attach->xattr_count; i++) kfree_sensitive(attach->xattrs[i]); kfree_sensitive(attach->xattrs); - aa_destroy_policydb(&attach->xmatch); + aa_put_pdb(attach->xmatch); } static void free_ruleset(struct aa_ruleset *rules) { int i; - aa_destroy_policydb(&rules->file); - aa_destroy_policydb(&rules->policy); + aa_put_pdb(rules->file); + aa_put_pdb(rules->policy); aa_free_cap_rules(&rules->caps); aa_free_rlimit_rules(&rules->rlimits); @@ -590,16 +625,8 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name, /* TODO: ideally we should inherit abi from parent */ profile->label.flags |= FLAG_NULL; rules = list_first_entry(&profile->rules, typeof(*rules), list); - rules->file.dfa = aa_get_dfa(nulldfa); - rules->file.perms = kcalloc(2, sizeof(struct aa_perms), gfp); - if (!rules->file.perms) - goto fail; - rules->file.size = 2; - rules->policy.dfa = aa_get_dfa(nulldfa); - rules->policy.perms = kcalloc(2, sizeof(struct aa_perms), gfp); - if (!rules->policy.perms) - goto fail; - rules->policy.size = 2; + rules->file = aa_get_pdb(nullpdb); + rules->policy = aa_get_pdb(nullpdb); if (parent) { profile->path_flags = parent->path_flags; @@ -610,11 +637,6 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name, } return profile; - -fail: - aa_free_profile(profile); - - return NULL; } /** diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 1eb98d6994e8..3fad34b68fdc 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -703,24 +703,29 @@ fail_reset: return -EPROTO; } -static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, +static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy, bool required_dfa, bool required_trans, const char **info) { + struct aa_policydb *pdb; void *pos = e->pos; int i, flags, error = -EPROTO; ssize_t size; - size = unpack_perms_table(e, &policy->perms); + pdb = aa_alloc_pdb(GFP_KERNEL); + if (!pdb) + return -ENOMEM; + + size = unpack_perms_table(e, &pdb->perms); if (size < 0) { error = size; - policy->perms = NULL; + pdb->perms = NULL; *info = "failed to unpack - perms"; goto fail; } - policy->size = size; + pdb->size = size; - if (policy->perms) { + if (pdb->perms) { /* perms table present accept is index */ flags = TO_ACCEPT1_FLAG(YYTD_DATA32); } else { @@ -729,13 +734,13 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, TO_ACCEPT2_FLAG(YYTD_DATA32); } - policy->dfa = unpack_dfa(e, flags); - if (IS_ERR(policy->dfa)) { - error = PTR_ERR(policy->dfa); - policy->dfa = NULL; + pdb->dfa = unpack_dfa(e, flags); + if (IS_ERR(pdb->dfa)) { + error = PTR_ERR(pdb->dfa); + pdb->dfa = NULL; *info = "failed to unpack - dfa"; goto fail; - } else if (!policy->dfa) { + } else if (!pdb->dfa) { if (required_dfa) { *info = "missing required dfa"; goto fail; @@ -749,18 +754,18 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, * sadly start was given different names for file and policydb * but since it is optional we can try both */ - if (!aa_unpack_u32(e, &policy->start[0], "start")) + if (!aa_unpack_u32(e, &pdb->start[0], "start")) /* default start state */ - policy->start[0] = DFA_START; - if (!aa_unpack_u32(e, &policy->start[AA_CLASS_FILE], "dfa_start")) { + pdb->start[0] = DFA_START; + if (!aa_unpack_u32(e, &pdb->start[AA_CLASS_FILE], "dfa_start")) { /* default start state for xmatch and file dfa */ - policy->start[AA_CLASS_FILE] = DFA_START; + pdb->start[AA_CLASS_FILE] = DFA_START; } /* setup class index */ for (i = AA_CLASS_FILE + 1; i <= AA_CLASS_LAST; i++) { - policy->start[i] = aa_dfa_next(policy->dfa, policy->start[0], + pdb->start[i] = aa_dfa_next(pdb->dfa, pdb->start[0], i); } - if (!unpack_trans_table(e, &policy->trans) && required_trans) { + if (!unpack_trans_table(e, &pdb->trans) && required_trans) { *info = "failed to unpack profile transition table"; goto fail; } @@ -768,9 +773,11 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, /* TODO: move compat mapping here, requires dfa merging first */ /* TODO: move verify here, it has to be done after compat mappings */ out: + *policy = pdb; return 0; fail: + aa_put_pdb(pdb); e->pos = pos; return error; } @@ -854,15 +861,15 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) } /* neither xmatch_len not xmatch_perms are optional if xmatch is set */ - if (profile->attach.xmatch.dfa) { + if (profile->attach.xmatch->dfa) { if (!aa_unpack_u32(e, &tmp, NULL)) { info = "missing xmatch len"; goto fail; } profile->attach.xmatch_len = tmp; - profile->attach.xmatch.start[AA_CLASS_XMATCH] = DFA_START; - if (!profile->attach.xmatch.perms) { - error = aa_compat_map_xmatch(&profile->attach.xmatch); + profile->attach.xmatch->start[AA_CLASS_XMATCH] = DFA_START; + if (!profile->attach.xmatch->perms) { + error = aa_compat_map_xmatch(profile->attach.xmatch); if (error) { info = "failed to convert xmatch permission table"; goto fail; @@ -979,16 +986,16 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) if (error) goto fail; /* Fixup: drop when we get rid of start array */ - if (aa_dfa_next(rules->policy.dfa, rules->policy.start[0], + if (aa_dfa_next(rules->policy->dfa, rules->policy->start[0], AA_CLASS_FILE)) - rules->policy.start[AA_CLASS_FILE] = - aa_dfa_next(rules->policy.dfa, - rules->policy.start[0], + rules->policy->start[AA_CLASS_FILE] = + aa_dfa_next(rules->policy->dfa, + rules->policy->start[0], AA_CLASS_FILE); if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) goto fail; - if (!rules->policy.perms) { - error = aa_compat_map_policy(&rules->policy, + if (!rules->policy->perms) { + error = aa_compat_map_policy(rules->policy, e->version); if (error) { info = "failed to remap policydb permission table"; @@ -996,44 +1003,25 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) } } } else { - rules->policy.dfa = aa_get_dfa(nulldfa); - rules->policy.perms = kcalloc(2, sizeof(struct aa_perms), - GFP_KERNEL); - if (!rules->policy.perms) - goto fail; - rules->policy.size = 2; + rules->policy = aa_get_pdb(nullpdb); } /* get file rules */ error = unpack_pdb(e, &rules->file, false, true, &info); if (error) { goto fail; - } else if (rules->file.dfa) { - if (!rules->file.perms) { - error = aa_compat_map_file(&rules->file); + } else if (rules->file->dfa) { + if (!rules->file->perms) { + error = aa_compat_map_file(rules->file); if (error) { info = "failed to remap file permission table"; goto fail; } } - } else if (rules->policy.dfa && - rules->policy.start[AA_CLASS_FILE]) { - rules->file.dfa = aa_get_dfa(rules->policy.dfa); - rules->file.start[AA_CLASS_FILE] = rules->policy.start[AA_CLASS_FILE]; - rules->file.perms = kcalloc(rules->policy.size, - sizeof(struct aa_perms), - GFP_KERNEL); - if (!rules->file.perms) - goto fail; - memcpy(rules->file.perms, rules->policy.perms, - rules->policy.size * sizeof(struct aa_perms)); - rules->file.size = rules->policy.size; + } else if (rules->policy->dfa && + rules->policy->start[AA_CLASS_FILE]) { + rules->file = aa_get_pdb(rules->policy); } else { - rules->file.dfa = aa_get_dfa(nulldfa); - rules->file.perms = kcalloc(2, sizeof(struct aa_perms), - GFP_KERNEL); - if (!rules->file.perms) - goto fail; - rules->file.size = 2; + rules->file = aa_get_pdb(nullpdb); } error = -EPROTO; if (aa_unpack_nameX(e, AA_STRUCT, "data")) { @@ -1240,32 +1228,32 @@ static int verify_profile(struct aa_profile *profile) if (!rules) return 0; - if (rules->file.dfa && !verify_dfa_accept_index(rules->file.dfa, - rules->file.size)) { + if (rules->file->dfa && !verify_dfa_accept_index(rules->file->dfa, + rules->file->size)) { audit_iface(profile, NULL, NULL, "Unpack: file Invalid named transition", NULL, -EPROTO); return -EPROTO; } - if (rules->policy.dfa && - !verify_dfa_accept_index(rules->policy.dfa, rules->policy.size)) { + if (rules->policy->dfa && + !verify_dfa_accept_index(rules->policy->dfa, rules->policy->size)) { audit_iface(profile, NULL, NULL, "Unpack: policy Invalid named transition", NULL, -EPROTO); return -EPROTO; } - if (!verify_perms(&rules->file)) { + if (!verify_perms(rules->file)) { audit_iface(profile, NULL, NULL, "Unpack: Invalid perm index", NULL, -EPROTO); return -EPROTO; } - if (!verify_perms(&rules->policy)) { + if (!verify_perms(rules->policy)) { audit_iface(profile, NULL, NULL, "Unpack: Invalid perm index", NULL, -EPROTO); return -EPROTO; } - if (!verify_perms(&profile->attach.xmatch)) { + if (!verify_perms(profile->attach.xmatch)) { audit_iface(profile, NULL, NULL, "Unpack: Invalid perm index", NULL, -EPROTO); return -EPROTO; -- cgit