update_sk_ctx will, under certain circumstances, replace a socket's ctx->peer_lastupdate, but it does not put the refcount on that value after doing the update. Properly put the old value to avoid refcount leaks.
Signed-off-by: Ryan Lee <[email protected]> --- security/apparmor/af_unix.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/security/apparmor/af_unix.c b/security/apparmor/af_unix.c index 2730f4ad08d3..f17dc208e776 100644 --- a/security/apparmor/af_unix.c +++ b/security/apparmor/af_unix.c @@ -649,7 +649,7 @@ int aa_unix_peer_perm(const struct cred *subj_cred, static bool update_sk_ctx(struct sock *sk, struct aa_label *label, struct aa_label *plabel) { - struct aa_label *l, *old; + struct aa_label *l, *old, *old_plastupdate; struct aa_sk_ctx *ctx = aa_sock(sk); bool update_sk; bool plabel_used = false; @@ -674,7 +674,9 @@ static bool update_sk_ctx(struct sock *sk, struct aa_label *label, } else aa_put_label(l); } - if (plabel && rcu_access_pointer(ctx->peer_lastupdate) != plabel) { + old_plastupdate = rcu_dereference_protected(ctx->peer_lastupdate, + lockdep_is_held(&unix_sk(sk)->lock)); + if (plabel && old_plastupdate != plabel) { old = rcu_dereference_protected(ctx->peer, lockdep_is_held(&unix_sk(sk)->lock)); if (old == plabel) { @@ -686,6 +688,9 @@ static bool update_sk_ctx(struct sock *sk, struct aa_label *label, aa_put_label(old); plabel_used = true; } /* else race or a subset - don't update */ + + if (plabel_used) + aa_put_label(old_plastupdate); } spin_unlock(&unix_sk(sk)->lock); return plabel_used; -- 2.43.0
