From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f194.google.com (mail-pl1-f194.google.com [209.85.214.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F1C3E3AE19B for ; Fri, 15 May 2026 05:01:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.194 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778821297; cv=none; b=ko5vLIqTwtR11BFzhALVslc5vOOXuuCep0DiNSutjiVCoF0/sm5dsowrid5ItetRf1L97aaWqOt/kB1UxbTImNHr195bHPLdMtRrvLduenirnxlN377YvVKqN4YLfv4cwLUlG20G7bpVJxRzPui4HyknNWaMIto60N0fQF5u0Qk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778821297; c=relaxed/simple; bh=JNY1W3dItPtvZ7Cceml3Tw2uFnJbYV/RyiE34VbFyM4=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=qDtMOb7LJXvm46DwcQdh2ZQ9ksBuXfnK/vP5dVVktUIy5EwhU5jdobFpHgpVpgNoElrFswKEhhw6Lp0Ir0pWaCgATV9ISbAItYWMY1kw3WjlUGCodKjmOwM6iXLj1I8TEmEFYNbxA3hsvW6/UU70UjPa/CCbs74/3odDMbisEJo= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=m1CsIjdD; arc=none smtp.client-ip=209.85.214.194 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="m1CsIjdD" Received: by mail-pl1-f194.google.com with SMTP id d9443c01a7336-2b9fcf7c91bso87420435ad.0 for ; Thu, 14 May 2026 22:01:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778821295; x=1779426095; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=gqboflgAQ/qafTTrlWTn23PBzb00+Q5WROmi07sXKXI=; b=m1CsIjdDWxH1lwqhAEbsBMX/hX6Vo3eFnFTfM37VWsRJ3xmYf16WOkCAxzD0JiEQT9 YBbUWP/a20IZJuz+2j/t3E+U+EZ+VgTi7yGsalEcUYc3xtj/T/5XtTxjqxrYruK8ytPu xiqDxEMlFMsRIV+DBynHx5AEchGsbzFxE4SdHITfZyCNbsUT+m2DvxTqA7JloNcyzH65 upsb15B8nXEyF6nQ4G96uYg31B/t2WSqz+f9TxJcekCr38eVdjVC0+3DCc1TFP86JP4b NZrXAQ+rjrNJMvr7QlWCecNDZExhn12enXpBq05WbFZfiKLall6T5PX4IcLpB5/kKPa/ HJgg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778821295; x=1779426095; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=gqboflgAQ/qafTTrlWTn23PBzb00+Q5WROmi07sXKXI=; b=a5Q3MMzF7LLAPCvYnVdNdjlXFj+aWvHYR2caPVlao6YRL08njTtuVMIimngirLszO0 u3piJOC0vFaJ/fbpoDEEk67zcTEWz3EvYZRrKZNyQKim5EGoevGHbfz1qlE1Jd1hAMaF u+JqdPiurRBj27S3yODziJ7lq3ovwfUlANYXFxqYg3S+JaJiaLIq5ThC70SDBh9ULUWm arRazzvGspPJ49zghzc03q4Uyud6W/i2n9CWfyvWvwT1nuVdZoOA4oGE32rUe4Zy1p/y dPkvFCsDrHun17eFSaGss1lHUAxwuZsFrSHdC9SeYQ0PguRqG1Xv2mPjNwyRLGyXkiuF w3pQ== X-Forwarded-Encrypted: i=1; AFNElJ8FsigSmTwowWoE4j+Lc9QVXQM/fI1F6xw6YvMlcGXetU2tu6UlrIVOTVXxamTwji2+eQ8k1OKAcTBa6jU=@vger.kernel.org X-Gm-Message-State: AOJu0YyYACMgV+ZOzxwOaKn06r6xovFFf7DdsY4cHYX++aa/0ZhCgqIV 6q1dCVQxASavnzw6fpCzjGyWGopFN4hEHbsKyOjKTkf7rtnqvGD2Wdpc X-Gm-Gg: Acq92OGPk44vrQ0X+NIrznXMLBg+NEZ0tDULAae5icA7vhZ41i2uoNWmM7OHJMYH4sx ntx0/3n6Z6T3CMdsm8g2tcCAiXjIl+Qi80KuXuwtjC2bRr/inw6pdippYysm4KH/zJO37hp2+yy mdEtYYqsFZU9uWsNrkt+GFPcXdwyB3nHAUMzc+d7r2BCMtbrEkV8toNb9peVtVHE7jKXr77t/31 roiUgzpssdgLiKTGIUaWwmXzNGPRH0M2dagN9GkM/M9pwhmZCgejuaLiHGbY3yPbmCwA368YRZq moGvDTEriswaGoL2pz83v6JmyiTauD7RxeQ0TBeztXL0PRBfoWC3Cz5bkGmsEJaK73mTLqAx0pZ ooNVV+IbdvoH5ySbwd6+BeggngSBS6sB7nrCxLSbk4PmSVjPz0KWX7fMJBLenymkXPryIEiLEfp a3OTcn+ssUJBycFl5jG7aHKEGOPhOVhTdkyfVVIfKCkg== X-Received: by 2002:a17:902:b181:b0:2bc:6784:5260 with SMTP id d9443c01a7336-2bd7e966018mr20182025ad.37.1778821294496; Thu, 14 May 2026 22:01:34 -0700 (PDT) Received: from localhost ([111.228.63.84]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2bd5bd5ef1bsm55532965ad.4.2026.05.14.22.01.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 May 2026 22:01:34 -0700 (PDT) From: Zhang Cen To: John Johansen , Paul Moore , James Morris , "Serge E. Hallyn" Cc: apparmor@lists.ubuntu.com, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, zerocling0077@gmail.com, 2045gemini@gmail.com, Zhang Cen Subject: [PATCH] apparmor: hold peer path references in aa_unix_file_perm() Date: Fri, 15 May 2026 13:01:16 +0800 Message-Id: <20260515050116.95754-1-rollkingzzc@gmail.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit aa_unix_file_perm() keeps the connected peer alive with sock_hold(peer_sk), but it then carries unix_sk(peer_sk)->path outside the peer socket state lock without taking a path reference. That copied peer_path can race with unix_release_sock(), which clears u->path under unix_state_lock(peer_sk) and drops the socket-owned path reference with path_put() before the final sock_put(peer_sk). Take peer_sk's unix_state_lock() long enough to snapshot peer_path, cache whether the peer is filesystem-bound, and path_get() a non-NULL path before dropping the lock. Drop that path reference after the last AppArmor peer path check. This restores the ownership invariant for peer_path without changing AF_UNIX shutdown semantics once the peer path has already been cleared. The buggy scenario involves two paths, with each column showing the order within that path: aa_unix_file_perm() [borrower]: unix_release_sock() [peer close]: 1. unix_state_lock(sock->sk) 1. unix_state_lock(peer_sk) 2. peer_sk = unix_peer(sock->sk) 2. Save path = u->path 3. sock_hold(peer_sk) 3. Clear u->path.dentry/mnt 4. unix_state_unlock(sock->sk) 4. unix_state_unlock(peer_sk) 5. peer_path = unix_sk(peer_sk)->path 5. path_put(&path) 6. unix_fs_perm(&peer_path) 6. sock_put(peer_sk) KASAN reported a slab-use-after-free in unix_fs_perm() at security/apparmor/af_unix.c:46, with the free side in unix_release_sock() -> path_put() at net/unix/af_unix.c:730. Signed-off-by: Zhang Cen --- security/apparmor/af_unix.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/security/apparmor/af_unix.c b/security/apparmor/af_unix.c index fdb4a9f21..7a1562f6f 100644 --- a/security/apparmor/af_unix.c +++ b/security/apparmor/af_unix.c @@ -716,7 +716,8 @@ int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label, struct sock *peer_sk = NULL; u32 sk_req = request & ~NET_PEER_MASK; struct path path; - bool is_sk_fs; + struct path peer_path = {}; + bool is_sk_fs, is_peer_fs = false; int error = 0; AA_BUG(!label); @@ -724,9 +725,8 @@ int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label, AA_BUG(!sock->sk); AA_BUG(sock->sk->sk_family != PF_UNIX); - /* investigate only using lock via unix_peer_get() - * addr only needs the memory barrier, but need to investigate - * path + /* addr only needs the memory barrier; hold a peer path reference + * under peer_sk's state lock after sock_hold(peer_sk) */ unix_state_lock(sock->sk); peer_sk = unix_peer(sock->sk); @@ -749,14 +749,18 @@ int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label, goto out; peer_addr = aa_sunaddr(unix_sk(peer_sk), &peer_addrlen); - - struct path peer_path; - - peer_path = unix_sk(peer_sk)->path; - if (!is_sk_fs && is_unix_fs(peer_sk)) { + if (!is_sk_fs) { + unix_state_lock(peer_sk); + is_peer_fs = is_unix_fs(peer_sk); + peer_path = unix_sk(peer_sk)->path; + if (peer_path.dentry) + path_get(&peer_path); + unix_state_unlock(peer_sk); + } + if (!is_sk_fs && is_peer_fs) { last_error(error, unix_fs_perm(op, request, subj_cred, label, - is_unix_fs(peer_sk) ? &peer_path : NULL)); + &peer_path)); } else if (!is_sk_fs) { struct aa_label *plabel; struct aa_sk_ctx *pctx = aa_sock(peer_sk); @@ -772,12 +776,12 @@ int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label, MAY_READ | MAY_WRITE, sock->sk, is_sk_fs ? &path : NULL, peer_addr, peer_addrlen, - is_unix_fs(peer_sk) ? + is_peer_fs ? &peer_path : NULL, plabel), unix_peer_perm(file->f_cred, plabel, op, MAY_READ | MAY_WRITE, peer_sk, - is_unix_fs(peer_sk) ? + is_peer_fs ? &peer_path : NULL, addr, addrlen, is_sk_fs ? &path : NULL, @@ -785,6 +789,8 @@ int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label, if (!error && !__aa_subj_label_is_cached(plabel, label)) update_peer_ctx(peer_sk, pctx, label); } + if (peer_path.dentry) + path_put(&peer_path); sock_put(peer_sk); out: @@ -796,4 +802,3 @@ int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label, return error; } - -- 2.43.0