From 2cf002d194977c4ec8848496a9a9804a317099dd Mon Sep 17 00:00:00 2001 From: Mauricio Faria de Oliveira Date: Tue, 2 Jun 2020 18:15:16 -0300 Subject: apparmor: check/put label on apparmor_sk_clone_security() Currently apparmor_sk_clone_security() does not check for existing label/peer in the 'new' struct sock; it just overwrites it, if any (with another reference to the label of the source sock.) static void apparmor_sk_clone_security(const struct sock *sk, struct sock *newsk) { struct aa_sk_ctx *ctx = SK_CTX(sk); struct aa_sk_ctx *new = SK_CTX(newsk); new->label = aa_get_label(ctx->label); new->peer = aa_get_label(ctx->peer); } This might leak label references, which might overflow under load. Thus, check for and put labels, to prevent such errors. Note this is similarly done on: static int apparmor_socket_post_create(struct socket *sock, ...) ... if (sock->sk) { struct aa_sk_ctx *ctx = SK_CTX(sock->sk); aa_put_label(ctx->label); ctx->label = aa_get_label(label); } ... Context: ------- The label reference count leak is observed if apparmor_sock_graft() is called previously: this sets the 'ctx->label' field by getting a reference to the current label (later overwritten, without put.) static void apparmor_sock_graft(struct sock *sk, ...) { struct aa_sk_ctx *ctx = SK_CTX(sk); if (!ctx->label) ctx->label = aa_get_current_label(); } And that is the case on crypto/af_alg.c:af_alg_accept(): int af_alg_accept(struct sock *sk, struct socket *newsock, ...) ... struct sock *sk2; ... sk2 = sk_alloc(...); ... security_sock_graft(sk2, newsock); security_sk_clone(sk, sk2); ... Apparently both calls are done on their own right, especially for other LSMs, being introduced in 2010/2014, before apparmor socket mediation in 2017 (see commits [1,2,3,4]). So, it looks OK there! Let's fix the reference leak in apparmor. Test-case: --------- Exercise that code path enough to overflow label reference count. $ cat aa-refcnt-af_alg.c #include #include #include #include #include int main() { int sockfd; struct sockaddr_alg sa; /* Setup the crypto API socket */ sockfd = socket(AF_ALG, SOCK_SEQPACKET, 0); if (sockfd < 0) { perror("socket"); return 1; } memset(&sa, 0, sizeof(sa)); sa.salg_family = AF_ALG; strcpy((char *) sa.salg_type, "rng"); strcpy((char *) sa.salg_name, "stdrng"); if (bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { perror("bind"); return 1; } /* Accept a "connection" and close it; repeat. */ while (!close(accept(sockfd, NULL, 0))); return 0; } $ gcc -o aa-refcnt-af_alg aa-refcnt-af_alg.c $ ./aa-refcnt-af_alg [ 9928.475953] refcount_t overflow at apparmor_sk_clone_security+0x37/0x70 in aa-refcnt-af_alg[1322], uid/euid: 1000/1000 ... [ 9928.507443] RIP: 0010:apparmor_sk_clone_security+0x37/0x70 ... [ 9928.514286] security_sk_clone+0x33/0x50 [ 9928.514807] af_alg_accept+0x81/0x1c0 [af_alg] [ 9928.516091] alg_accept+0x15/0x20 [af_alg] [ 9928.516682] SYSC_accept4+0xff/0x210 [ 9928.519609] SyS_accept+0x10/0x20 [ 9928.520190] do_syscall_64+0x73/0x130 [ 9928.520808] entry_SYSCALL_64_after_hwframe+0x3d/0xa2 Note that other messages may be seen, not just overflow, depending on the value being incremented by kref_get(); on another run: [ 7273.182666] refcount_t: saturated; leaking memory. ... [ 7273.185789] refcount_t: underflow; use-after-free. Kprobes: ------- Using kprobe events to monitor sk -> sk_security -> label -> count (kref): Original v5.7 (one reference leak every iteration) ... (af_alg_accept+0x0/0x1c0) label=0xffff8a0f36c25eb0 label_refcnt=0x11fd2 ... (af_alg_release_parent+0x0/0xd0) label=0xffff8a0f36c25eb0 label_refcnt=0x11fd4 ... (af_alg_accept+0x0/0x1c0) label=0xffff8a0f36c25eb0 label_refcnt=0x11fd3 ... (af_alg_release_parent+0x0/0xd0) label=0xffff8a0f36c25eb0 label_refcnt=0x11fd5 ... (af_alg_accept+0x0/0x1c0) label=0xffff8a0f36c25eb0 label_refcnt=0x11fd4 ... (af_alg_release_parent+0x0/0xd0) label=0xffff8a0f36c25eb0 label_refcnt=0x11fd6 Patched v5.7 (zero reference leak per iteration) ... (af_alg_accept+0x0/0x1c0) label=0xffff9ff376c25eb0 label_refcnt=0x593 ... (af_alg_release_parent+0x0/0xd0) label=0xffff9ff376c25eb0 label_refcnt=0x594 ... (af_alg_accept+0x0/0x1c0) label=0xffff9ff376c25eb0 label_refcnt=0x593 ... (af_alg_release_parent+0x0/0xd0) label=0xffff9ff376c25eb0 label_refcnt=0x594 ... (af_alg_accept+0x0/0x1c0) label=0xffff9ff376c25eb0 label_refcnt=0x593 ... (af_alg_release_parent+0x0/0xd0) label=0xffff9ff376c25eb0 label_refcnt=0x594 Commits: ------- [1] commit 507cad355fc9 ("crypto: af_alg - Make sure sk_security is initialized on accept()ed sockets") [2] commit 4c63f83c2c2e ("crypto: af_alg - properly label AF_ALG socket") [3] commit 2acce6aa9f65 ("Networking") a.k.a ("crypto: af_alg - Avoid sock_graft call warning) [4] commit 56974a6fcfef ("apparmor: add base infastructure for socket mediation") Reported-by: Brian Moyles Signed-off-by: Mauricio Faria de Oliveira Signed-off-by: John Johansen --- security/apparmor/lsm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index b621ad74f54a..66a8504c8bea 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -804,7 +804,12 @@ static void apparmor_sk_clone_security(const struct sock *sk, struct aa_sk_ctx *ctx = SK_CTX(sk); struct aa_sk_ctx *new = SK_CTX(newsk); + if (new->label) + aa_put_label(new->label); new->label = aa_get_label(ctx->label); + + if (new->peer) + aa_put_label(new->peer); new->peer = aa_get_label(ctx->peer); } -- cgit v1.2.3 From 5268d795d6888b202ad9f2b16a254cd00d0de77b Mon Sep 17 00:00:00 2001 From: John Johansen Date: Fri, 5 Jun 2020 18:12:21 -0700 Subject: apparmor: fix introspection of of task mode for unconfined tasks Fix two issues with introspecting the task mode. 1. If a task is attached to a unconfined profile that is not the ns->unconfined profile then. Mode the mode is always reported as - $ ps -Z LABEL PID TTY TIME CMD unconfined 1287 pts/0 00:00:01 bash test (-) 1892 pts/0 00:00:00 ps instead of the correct value of (unconfined) as shown below $ ps -Z LABEL PID TTY TIME CMD unconfined 2483 pts/0 00:00:01 bash test (unconfined) 3591 pts/0 00:00:00 ps 2. if a task is confined by a stack of profiles that are unconfined the output of label mode is again the incorrect value of (-) like above, instead of (unconfined). This is because the visibile profile count increment is skipped by the special casing of unconfined. Signed-off-by: John Johansen --- security/apparmor/label.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/security/apparmor/label.c b/security/apparmor/label.c index 676eebcbfd68..23f7a193df4f 100644 --- a/security/apparmor/label.c +++ b/security/apparmor/label.c @@ -1558,13 +1558,13 @@ static const char *label_modename(struct aa_ns *ns, struct aa_label *label, label_for_each(i, label, profile) { if (aa_ns_visible(ns, profile->ns, flags & FLAG_VIEW_SUBNS)) { - if (profile->mode == APPARMOR_UNCONFINED) + count++; + if (profile == profile->ns->unconfined) /* special case unconfined so stacks with * unconfined don't report as mixed. ie. * profile_foo//&:ns1:unconfined (mixed) */ continue; - count++; if (mode == -1) mode = profile->mode; else if (mode != profile->mode) -- cgit v1.2.3 From 92de220a7f336367127351da58cff691da5bb17b Mon Sep 17 00:00:00 2001 From: John Johansen Date: Tue, 30 Jun 2020 17:00:11 -0700 Subject: apparmor: update policy capable checks to use a label Previously the policy capable checks assumed they were using the current task. Make them take the task label so the query can be made against an arbitrary task. Signed-off-by: John Johansen --- security/apparmor/apparmorfs.c | 4 ++-- security/apparmor/include/label.h | 1 + security/apparmor/include/policy.h | 6 ++++-- security/apparmor/lsm.c | 22 ++++++++++---------- security/apparmor/policy.c | 41 ++++++++++++++++++++++++++++++-------- 5 files changed, 51 insertions(+), 23 deletions(-) diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index d65324415980..3275e074e5f8 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -1357,7 +1357,7 @@ static int rawdata_open(struct inode *inode, struct file *file) struct aa_loaddata *loaddata; struct rawdata_f_data *private; - if (!policy_view_capable(NULL)) + if (!aa_current_policy_view_capable(NULL)) return -EACCES; loaddata = __aa_get_loaddata(inode->i_private); @@ -2266,7 +2266,7 @@ static const struct seq_operations aa_sfs_profiles_op = { static int profiles_open(struct inode *inode, struct file *file) { - if (!policy_view_capable(NULL)) + if (!aa_current_policy_view_capable(NULL)) return -EACCES; return seq_open(file, &aa_sfs_profiles_op); diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h index 255764ab06e2..f5b5485e20c9 100644 --- a/security/apparmor/include/label.h +++ b/security/apparmor/include/label.h @@ -148,6 +148,7 @@ do { \ #define __label_make_stale(X) ((X)->flags |= FLAG_STALE) #define labels_ns(X) (vec_ns(&((X)->vec[0]), (X)->size)) #define labels_set(X) (&labels_ns(X)->labels) +#define labels_view(X) labels_ns(X) #define labels_profile(X) ((X)->vec[(X)->size - 1]) diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index b5b4b8190e65..cb5ef21991b7 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h @@ -301,9 +301,11 @@ static inline int AUDIT_MODE(struct aa_profile *profile) return profile->audit; } -bool policy_view_capable(struct aa_ns *ns); -bool policy_admin_capable(struct aa_ns *ns); +bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns); +bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns); int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask); +bool aa_current_policy_view_capable(struct aa_ns *ns); +bool aa_current_policy_admin_capable(struct aa_ns *ns); #endif /* __AA_POLICY_H */ diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 66a8504c8bea..64d6020ffd50 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1392,7 +1392,7 @@ static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp { if (!apparmor_enabled) return -EINVAL; - if (apparmor_initialized && !policy_admin_capable(NULL)) + if (apparmor_initialized && !aa_current_policy_admin_capable(NULL)) return -EPERM; return param_set_bool(val, kp); } @@ -1401,7 +1401,7 @@ static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp) { if (!apparmor_enabled) return -EINVAL; - if (apparmor_initialized && !policy_view_capable(NULL)) + if (apparmor_initialized && !aa_current_policy_view_capable(NULL)) return -EPERM; return param_get_bool(buffer, kp); } @@ -1410,7 +1410,7 @@ static int param_set_aabool(const char *val, const struct kernel_param *kp) { if (!apparmor_enabled) return -EINVAL; - if (apparmor_initialized && !policy_admin_capable(NULL)) + if (apparmor_initialized && !aa_current_policy_admin_capable(NULL)) return -EPERM; return param_set_bool(val, kp); } @@ -1419,7 +1419,7 @@ static int param_get_aabool(char *buffer, const struct kernel_param *kp) { if (!apparmor_enabled) return -EINVAL; - if (apparmor_initialized && !policy_view_capable(NULL)) + if (apparmor_initialized && !aa_current_policy_view_capable(NULL)) return -EPERM; return param_get_bool(buffer, kp); } @@ -1445,7 +1445,7 @@ static int param_get_aauint(char *buffer, const struct kernel_param *kp) { if (!apparmor_enabled) return -EINVAL; - if (apparmor_initialized && !policy_view_capable(NULL)) + if (apparmor_initialized && !aa_current_policy_view_capable(NULL)) return -EPERM; return param_get_uint(buffer, kp); } @@ -1516,7 +1516,7 @@ static int param_get_aacompressionlevel(char *buffer, { if (!apparmor_enabled) return -EINVAL; - if (apparmor_initialized && !policy_view_capable(NULL)) + if (apparmor_initialized && !aa_current_policy_view_capable(NULL)) return -EPERM; return param_get_int(buffer, kp); } @@ -1525,7 +1525,7 @@ static int param_get_audit(char *buffer, const struct kernel_param *kp) { if (!apparmor_enabled) return -EINVAL; - if (apparmor_initialized && !policy_view_capable(NULL)) + if (apparmor_initialized && !aa_current_policy_view_capable(NULL)) return -EPERM; return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]); } @@ -1538,7 +1538,7 @@ static int param_set_audit(const char *val, const struct kernel_param *kp) return -EINVAL; if (!val) return -EINVAL; - if (apparmor_initialized && !policy_admin_capable(NULL)) + if (apparmor_initialized && !aa_current_policy_admin_capable(NULL)) return -EPERM; i = match_string(audit_mode_names, AUDIT_MAX_INDEX, val); @@ -1553,7 +1553,7 @@ static int param_get_mode(char *buffer, const struct kernel_param *kp) { if (!apparmor_enabled) return -EINVAL; - if (apparmor_initialized && !policy_view_capable(NULL)) + if (apparmor_initialized && !aa_current_policy_view_capable(NULL)) return -EPERM; return sprintf(buffer, "%s", aa_profile_mode_names[aa_g_profile_mode]); @@ -1567,7 +1567,7 @@ static int param_set_mode(const char *val, const struct kernel_param *kp) return -EINVAL; if (!val) return -EINVAL; - if (apparmor_initialized && !policy_admin_capable(NULL)) + if (apparmor_initialized && !aa_current_policy_admin_capable(NULL)) return -EPERM; i = match_string(aa_profile_mode_names, APPARMOR_MODE_NAMES_MAX_INDEX, @@ -1703,7 +1703,7 @@ static int __init alloc_buffers(void) static int apparmor_dointvec(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { - if (!policy_admin_capable(NULL)) + if (!aa_current_policy_admin_capable(NULL)) return -EPERM; if (!apparmor_enabled) return -EINVAL; diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 269f2f53c0b1..e680121e013e 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -632,17 +632,18 @@ static int audit_policy(struct aa_label *label, const char *op, } /** - * policy_view_capable - check if viewing policy in at @ns is allowed - * ns: namespace being viewed by current task (may be NULL) + * aa_policy_view_capable - check if viewing policy in at @ns is allowed + * label: label that is trying to view policy in ns + * ns: namespace being viewed by @label (may be NULL if @label's ns) * Returns: true if viewing policy is allowed * * If @ns is NULL then the namespace being viewed is assumed to be the * tasks current namespace. */ -bool policy_view_capable(struct aa_ns *ns) +bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns) { struct user_namespace *user_ns = current_user_ns(); - struct aa_ns *view_ns = aa_get_current_ns(); + struct aa_ns *view_ns = labels_view(label); bool root_in_user_ns = uid_eq(current_euid(), make_kuid(user_ns, 0)) || in_egroup_p(make_kgid(user_ns, 0)); bool response = false; @@ -654,12 +655,11 @@ bool policy_view_capable(struct aa_ns *ns) (unprivileged_userns_apparmor_policy != 0 && user_ns->level == view_ns->level))) response = true; - aa_put_ns(view_ns); return response; } -bool policy_admin_capable(struct aa_ns *ns) +bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns) { struct user_namespace *user_ns = current_user_ns(); bool capable = ns_capable(user_ns, CAP_MAC_ADMIN); @@ -667,7 +667,32 @@ bool policy_admin_capable(struct aa_ns *ns) AA_DEBUG("cap_mac_admin? %d\n", capable); AA_DEBUG("policy locked? %d\n", aa_g_lock_policy); - return policy_view_capable(ns) && capable && !aa_g_lock_policy; + return aa_policy_view_capable(label, ns) && capable && + !aa_g_lock_policy; +} + +bool aa_current_policy_view_capable(struct aa_ns *ns) +{ + struct aa_label *label; + bool res; + + label = __begin_current_label_crit_section(); + res = aa_policy_view_capable(label, ns); + __end_current_label_crit_section(label); + + return res; +} + +bool aa_current_policy_admin_capable(struct aa_ns *ns) +{ + struct aa_label *label; + bool res; + + label = __begin_current_label_crit_section(); + res = aa_policy_admin_capable(label, ns); + __end_current_label_crit_section(label); + + return res; } /** @@ -693,7 +718,7 @@ int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask) return audit_policy(label, op, NULL, NULL, "policy_locked", -EACCES); - if (!policy_admin_capable(ns)) + if (!aa_policy_admin_capable(label, ns)) return audit_policy(label, op, NULL, NULL, "not policy admin", -EACCES); -- cgit v1.2.3 From 31ec99e13346c22a7c8ca18e044684a870063cef Mon Sep 17 00:00:00 2001 From: John Johansen Date: Wed, 1 Jul 2020 02:18:18 -0700 Subject: apparmor: switch to apparmor to internal capable check for policy management With LSM stacking calling back into capable to check for MAC_ADMIN for apparmor policy results in asking the other stacked LSMs for MAC_ADMIN resulting in the other LSMs answering based on their policy management. For apparmor policy management we just need to call apparmor's capability fn directly. Signed-off-by: John Johansen --- security/apparmor/policy.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index e680121e013e..9ce93966401a 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -631,6 +631,22 @@ static int audit_policy(struct aa_label *label, const char *op, return error; } +/* don't call out to other LSMs in the stack for apparmor policy admin + * permissions + */ +static int policy_ns_capable(struct aa_label *label, + struct user_namespace *userns, int cap) +{ + int err; + + /* check for MAC_ADMIN cap in cred */ + err = cap_capable(current_cred(), userns, cap, CAP_OPT_NONE); + if (!err) + err = aa_capable(label, cap, CAP_OPT_NONE); + + return err; +} + /** * aa_policy_view_capable - check if viewing policy in at @ns is allowed * label: label that is trying to view policy in ns @@ -662,7 +678,7 @@ bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns) bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns) { struct user_namespace *user_ns = current_user_ns(); - bool capable = ns_capable(user_ns, CAP_MAC_ADMIN); + bool capable = policy_ns_capable(label, user_ns, CAP_MAC_ADMIN); AA_DEBUG("cap_mac_admin? %d\n", capable); AA_DEBUG("policy locked? %d\n", aa_g_lock_policy); -- cgit v1.2.3 From ef70454508c00a415a41156a19cb771a186c55d0 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 25 Jan 2021 11:53:50 -0800 Subject: security: apparmor: file.h: delete duplicated word Delete the doubled word "then" in a comment. Signed-off-by: Randy Dunlap Reviewed-by: Seth Arnold Signed-off-by: John Johansen --- security/apparmor/include/file.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h index aff26fc71407..a7672dacd001 100644 --- a/security/apparmor/include/file.h +++ b/security/apparmor/include/file.h @@ -167,7 +167,7 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, * @perms: permission table indexed by the matched state accept entry of @dfa * @trans: transition table for indexed by named x transitions * - * File permission are determined by matching a path against @dfa and then + * File permission are determined by matching a path against @dfa and * then using the value of the accept entry for the matching state as * an index into @perms. If a named exec transition is required it is * looked up in the transition table. -- cgit v1.2.3 From 4af7c863fc85ad756b7a978fe1096b80a855543c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 7 Aug 2020 09:50:55 -0700 Subject: security: apparmor: delete repeated words in comments Drop repeated words in comments. {a, then, to} Signed-off-by: Randy Dunlap Reviewed-by: Seth Arnold Signed-off-by: John Johansen --- security/apparmor/path.c | 2 +- security/apparmor/policy_unpack.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/security/apparmor/path.c b/security/apparmor/path.c index b02dfdbff7cd..45ec994b558d 100644 --- a/security/apparmor/path.c +++ b/security/apparmor/path.c @@ -83,7 +83,7 @@ static int disconnect(const struct path *path, char *buf, char **name, * * Returns: %0 else error code if path lookup fails * When no error the path name is returned in @name which points to - * to a position in @buf + * a position in @buf */ static int d_namespace_path(const struct path *path, char *buf, char **name, int flags, const char *disconnected) diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index d9ef9a99c26e..12e6677868c3 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -39,7 +39,7 @@ /* * The AppArmor interface treats data as a type byte followed by the - * actual data. The interface has the notion of a a named entry + * actual data. The interface has the notion of a named entry * which has a name (AA_NAME typecode followed by name string) followed by * the entries typecode and data. Named types allow for optional * elements and extensions to be added and tested for without breaking -- cgit v1.2.3 From d108370c644b153382632b3e5511ade575c91c86 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sun, 4 Oct 2020 07:24:22 -0700 Subject: apparmor: fix error check clang static analysis reports this representative problem: label.c:1463:16: warning: Assigned value is garbage or undefined label->hname = name; ^ ~~~~ In aa_update_label_name(), this the problem block of code if (aa_label_acntsxprint(&name, ...) == -1) return res; On failure, aa_label_acntsxprint() has a more complicated return that just -1. So check for a negative return. It was also noted that the aa_label_acntsxprint() main comment refers to a nonexistent parameter, so clean up the comment. Fixes: f1bd904175e8 ("apparmor: add the base fns() for domain labels") Signed-off-by: Tom Rix Reviewed-by: Nick Desaulniers Signed-off-by: John Johansen --- security/apparmor/label.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/security/apparmor/label.c b/security/apparmor/label.c index 23f7a193df4f..f5eb9ac07e9b 100644 --- a/security/apparmor/label.c +++ b/security/apparmor/label.c @@ -1453,7 +1453,7 @@ bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp) if (label->hname || labels_ns(label) != ns) return res; - if (aa_label_acntsxprint(&name, ns, label, FLAGS_NONE, gfp) == -1) + if (aa_label_acntsxprint(&name, ns, label, FLAGS_NONE, gfp) < 0) return res; ls = labels_set(label); @@ -1703,7 +1703,7 @@ int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label, /** * aa_label_acntsxprint - allocate a __counted string buffer and print label - * @strp: buffer to write to. (MAY BE NULL if @size == 0) + * @strp: buffer to write to. * @ns: namespace profile is being viewed from * @label: label to view (NOT NULL) * @flags: flags controlling what label info is printed -- cgit v1.2.3 From dc155617fa5bf5bddbeb99dc781dd011ed23b90f Mon Sep 17 00:00:00 2001 From: John Johansen Date: Sat, 3 Apr 2021 11:07:37 -0700 Subject: apparmor: Fix internal policy capable check for policy management The check was incorrectly treating a returned error as a boolean. Fixes: 31ec99e13346 ("apparmor: switch to apparmor to internal capable check for policy management") Signed-off-by: John Johansen --- security/apparmor/policy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 9ce93966401a..4da4f3df9d4a 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -678,7 +678,7 @@ bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns) bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns) { struct user_namespace *user_ns = current_user_ns(); - bool capable = policy_ns_capable(label, user_ns, CAP_MAC_ADMIN); + bool capable = policy_ns_capable(label, user_ns, CAP_MAC_ADMIN) == 0; AA_DEBUG("cap_mac_admin? %d\n", capable); AA_DEBUG("policy locked? %d\n", aa_g_lock_policy); -- cgit v1.2.3 From c75ea024094e7307219a4f9c706dad5ea461509a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 22 Mar 2021 12:00:08 +0100 Subject: apparmor: avoid -Wempty-body warning Building with 'make W=1' shows a warning for an empty macro: security/apparmor/label.c: In function '__label_update': security/apparmor/label.c:2096:59: error: suggest braces around empty body in an 'else' statement [-Werror=empty-body] 2096 | AA_BUG(labels_ns(label) != labels_ns(new)); Change the macro definition to use no_printk(), which improves format string checking and avoids the warning. Signed-off-by: Arnd Bergmann Signed-off-by: John Johansen --- security/apparmor/include/lib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h index 7d27db740bc2..67fbb81a11f3 100644 --- a/security/apparmor/include/lib.h +++ b/security/apparmor/include/lib.h @@ -36,7 +36,7 @@ #define AA_BUG_FMT(X, fmt, args...) \ WARN((X), "AppArmor WARN %s: (" #X "): " fmt, __func__, ##args) #else -#define AA_BUG_FMT(X, fmt, args...) +#define AA_BUG_FMT(X, fmt, args...) no_printk(fmt, ##args) #endif #define AA_ERROR(fmt, args...) \ -- cgit v1.2.3 From 7e50e9ffdee6fa8b375baddbac85fcb8ffee156a Mon Sep 17 00:00:00 2001 From: Shaokun Zhang Date: Sat, 29 May 2021 16:40:48 +0800 Subject: apparmor: Remove the repeated declaration Function 'aa_labelset_destroy' and 'aa_labelset_init' are declared twice, so remove the repeated declaration and unnecessary blank line. Cc: John Johansen Cc: James Morris Cc: "Serge E. Hallyn" Signed-off-by: Shaokun Zhang Signed-off-by: John Johansen --- security/apparmor/include/label.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h index f5b5485e20c9..7ead1474769e 100644 --- a/security/apparmor/include/label.h +++ b/security/apparmor/include/label.h @@ -77,10 +77,6 @@ struct aa_labelset { #define __labelset_for_each(LS, N) \ for ((N) = rb_first(&(LS)->root); (N); (N) = rb_next(N)) -void aa_labelset_destroy(struct aa_labelset *ls); -void aa_labelset_init(struct aa_labelset *ls); - - enum label_flags { FLAG_HAT = 1, /* profile is a hat */ FLAG_UNCONFINED = 2, /* label unconfined only if all */ -- cgit v1.2.3 From aa4ceed7c3276852031a3e3d6fa767ff1858831f Mon Sep 17 00:00:00 2001 From: ChenXiaoSong Date: Mon, 7 Jun 2021 14:30:22 +0800 Subject: apparmor: fix doc warning Fix gcc W=1 warning: security/apparmor/apparmorfs.c:2125: warning: Function parameter or member 'p' not described in '__next_profile' Signed-off-by: ChenXiaoSong Signed-off-by: John Johansen --- security/apparmor/apparmorfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index 3275e074e5f8..a515d1f6d951 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -2115,7 +2115,7 @@ static struct aa_profile *__first_profile(struct aa_ns *root, /** * __next_profile - step to the next profile in a profile tree - * @profile: current profile in tree (NOT NULL) + * @p: current profile in tree (NOT NULL) * * Perform a depth first traversal on the profile tree in a namespace * -- cgit v1.2.3 From d0d845a790d31adb0c90f1f8364de199b23128c8 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Fri, 30 Jul 2021 01:23:55 -0400 Subject: apparmor: use per file locks for transactional queries As made mention of in commit 1dea3b41e84c5 ("apparmor: speed up transactional queries"), a single lock is currently used to synchronize transactional queries. We can, use the lock allocated for each file by VFS instead. Signed-off-by: Hamza Mahfooz Signed-off-by: John Johansen --- security/apparmor/apparmorfs.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index a515d1f6d951..0920f5188631 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -811,8 +811,6 @@ struct multi_transaction { }; #define MULTI_TRANSACTION_LIMIT (PAGE_SIZE - sizeof(struct multi_transaction)) -/* TODO: replace with per file lock */ -static DEFINE_SPINLOCK(multi_transaction_lock); static void multi_transaction_kref(struct kref *kref) { @@ -846,10 +844,10 @@ static void multi_transaction_set(struct file *file, AA_BUG(n > MULTI_TRANSACTION_LIMIT); new->size = n; - spin_lock(&multi_transaction_lock); + spin_lock(&file->f_lock); old = (struct multi_transaction *) file->private_data; file->private_data = new; - spin_unlock(&multi_transaction_lock); + spin_unlock(&file->f_lock); put_multi_transaction(old); } @@ -878,9 +876,10 @@ static ssize_t multi_transaction_read(struct file *file, char __user *buf, struct multi_transaction *t; ssize_t ret; - spin_lock(&multi_transaction_lock); + spin_lock(&file->f_lock); t = get_multi_transaction(file->private_data); - spin_unlock(&multi_transaction_lock); + spin_unlock(&file->f_lock); + if (!t) return 0; -- cgit v1.2.3 From 4d47fbbe54bf75b72eac3f5a0caa664300937620 Mon Sep 17 00:00:00 2001 From: John Johansen Date: Thu, 2 Sep 2021 23:27:31 -0700 Subject: apparmor: fix zero-length compiler warning in AA_BUG() Uses of AA_BUG() without a message can result in the compiler warning warning: zero-length gnu_printf format string [-Wformat-zero-length] Fix this with a pragma for now. A larger rework of AA_BUG() will follow. Signed-off-by: John Johansen --- security/apparmor/include/lib.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h index 67fbb81a11f3..e2e8df0c6f1c 100644 --- a/security/apparmor/include/lib.h +++ b/security/apparmor/include/lib.h @@ -31,7 +31,12 @@ #define AA_WARN(X) WARN((X), "APPARMOR WARN %s: %s\n", __func__, #X) -#define AA_BUG(X, args...) AA_BUG_FMT((X), "" args) +#define AA_BUG(X, args...) \ + do { \ + _Pragma("GCC diagnostic ignored \"-Wformat-zero-length\""); \ + AA_BUG_FMT((X), "" args); \ + _Pragma("GCC diagnostic warning \"-Wformat-zero-length\""); \ + } while (0) #ifdef CONFIG_SECURITY_APPARMOR_DEBUG_ASSERTS #define AA_BUG_FMT(X, fmt, args...) \ WARN((X), "AppArmor WARN %s: (" #X "): " fmt, __func__, ##args) -- cgit v1.2.3 From f4a2d282cca57607a0d6718fafa1ab2d62703254 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 29 Sep 2021 17:05:26 -0500 Subject: apparmor: Use struct_size() helper in kzalloc() Make use of the struct_size() helper instead of an open-coded version, in order to avoid any potential type mistakes or integer overflows that, in the worse scenario, could lead to heap overflows. Link: https://github.com/KSPP/linux/issues/160 Signed-off-by: Gustavo A. R. Silva Signed-off-by: John Johansen --- security/apparmor/label.c | 3 +-- security/apparmor/policy.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/security/apparmor/label.c b/security/apparmor/label.c index f5eb9ac07e9b..1c89b056337b 100644 --- a/security/apparmor/label.c +++ b/security/apparmor/label.c @@ -424,8 +424,7 @@ struct aa_label *aa_label_alloc(int size, struct aa_proxy *proxy, gfp_t gfp) AA_BUG(size < 1); /* + 1 for null terminator entry on vec */ - new = kzalloc(sizeof(*new) + sizeof(struct aa_profile *) * (size + 1), - gfp); + new = kzalloc(struct_size(new, vec, size + 1), gfp); AA_DEBUG("%s (%p)\n", __func__, new); if (!new) goto fail; diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 4da4f3df9d4a..76cc1949c66f 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -259,8 +259,7 @@ struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy, struct aa_profile *profile; /* freed by free_profile - usually through aa_put_profile */ - profile = kzalloc(sizeof(*profile) + sizeof(struct aa_profile *) * 2, - gfp); + profile = kzalloc(struct_size(profile, label.vec, 2), gfp); if (!profile) return NULL; -- cgit v1.2.3 From 7b7211243afa1058b0f10bae7bd14d562f9767ca Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 11 Oct 2021 16:38:54 +0200 Subject: apparmor: remove unneeded one-line hook wrappers Use the common function directly. Signed-off-by: Florian Westphal Signed-off-by: John Johansen --- security/apparmor/lsm.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 64d6020ffd50..13c2f76bd1f7 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1763,32 +1763,16 @@ static unsigned int apparmor_ip_postroute(void *priv, } -static unsigned int apparmor_ipv4_postroute(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state) -{ - return apparmor_ip_postroute(priv, skb, state); -} - -#if IS_ENABLED(CONFIG_IPV6) -static unsigned int apparmor_ipv6_postroute(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state) -{ - return apparmor_ip_postroute(priv, skb, state); -} -#endif - static const struct nf_hook_ops apparmor_nf_ops[] = { { - .hook = apparmor_ipv4_postroute, + .hook = apparmor_ip_postroute, .pf = NFPROTO_IPV4, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_SELINUX_FIRST, }, #if IS_ENABLED(CONFIG_IPV6) { - .hook = apparmor_ipv6_postroute, + .hook = apparmor_ip_postroute, .pf = NFPROTO_IPV6, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP6_PRI_SELINUX_FIRST, -- cgit v1.2.3 From 582122f1d73af28407234321c94711e09aa3fd04 Mon Sep 17 00:00:00 2001 From: Austin Kim Date: Wed, 3 Nov 2021 09:25:31 +0000 Subject: apparmor: remove duplicated 'Returns:' comments It might look better if duplicated 'Returns:' comment is removed. Signed-off-by: Austin Kim Signed-off-by: John Johansen --- security/apparmor/procattr.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c index c929bf4a3df1..fde332e0ea7d 100644 --- a/security/apparmor/procattr.c +++ b/security/apparmor/procattr.c @@ -21,8 +21,6 @@ * @profile: the profile to print profile info about (NOT NULL) * @string: Returns - string containing the profile info (NOT NULL) * - * Returns: length of @string on success else error on failure - * * Requires: profile != NULL * * Creates a string containing the namespace_name://profile_name for -- cgit v1.2.3