linux/security/apparmor/include
Ruslan Valiyev b17f0c59cc apparmor: fix use-after-free in rawdata dedup loop
[ Upstream commit 6f060496d0 ]

aa_replace_profiles() walks ns->rawdata_list to dedup the incoming
policy blob against entries already attached to existing profiles.
Per the kernel-doc on struct aa_loaddata, list membership does not
hold a reference: profiles hold pcount, and when the last pcount
drops, do_ploaddata_rmfs() is queued on a workqueue that takes
ns->lock and removes the entry. Between dropping the last pcount
and the workqueue running, an entry remains on the list with
pcount == 0.

aa_get_profile_loaddata() is an unconditional kref_get() on
pcount, so when the dedup loop hits such an entry, refcount
hardening reports

  refcount_t: addition on 0; use-after-free.

inside aa_replace_profiles(), and the poisoned counter then
trips "saturated" and "underflow" warnings on the subsequent
uses of the same loaddata.

Before commit a0b7091c4d ("apparmor: fix race on rawdata
dereference") the dedup path used a get_unless_zero-style helper
on a single counter, so the existing "if (tmp)" guard was
meaningful. The split-refcount refactor introduced
aa_get_profile_loaddata(), which has plain kref_get() semantics,
and the guard quietly became a no-op.

Introduce aa_get_profile_loaddata_not0(), matching the existing
_not0 convention used by aa_get_profile_not0(), and use it for
the rawdata_list dedup lookup so dying entries are skipped.

Reproduced on x86_64 with v7.1-rc5 in QEMU+KVM running Ubuntu
24.04 + stress-ng 0.17.06:

  stress-ng --apparmor 1 --klog-check --timeout 60s

Without this patch the three refcount_t warnings fire within a
few seconds. With it the same 60 s run is clean. Coverage is a
smoke-test only; a longer soak with CONFIG_KASAN, CONFIG_KCSAN
and CONFIG_PROVE_LOCKING would be welcome from anyone with the
cycles.

Fixes: a0b7091c4d ("apparmor: fix race on rawdata dereference")
Reported-by: Colin Ian King <colin.i.king@gmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221513
Cc: stable@vger.kernel.org
Signed-off-by: Ruslan Valiyev <linuxoid@gmail.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
History 2026-07-24 15:51:16 +02:00
..
apparmor.h + Features 2019-12-03 12:51:35 -08:00
apparmorfs.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 441 2019-06-05 17:37:17 +02:00
audit.h ima: Avoid blocking in RCU read-side critical section 2024-07-18 13:07:34 +02:00
capability.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 441 2019-06-05 17:37:17 +02:00
cred.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 441 2019-06-05 17:37:17 +02:00
crypto.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 441 2019-06-05 17:37:17 +02:00
domain.h exec: Factor security_bprm_creds_for_exec out of security_bprm_set_creds 2020-05-20 14:45:31 -05:00
file.h mm, treewide: rename kzfree() to kfree_sensitive() 2020-08-07 11:33:22 -07:00
ipc.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 441 2019-06-05 17:37:17 +02:00
label.h apparmor: fix race between freeing data and fs accessing it 2026-04-18 10:33:36 +02:00
lib.h apparmor: fix race between freeing data and fs accessing it 2026-04-18 10:33:36 +02:00
match.h apparmor: fix differential encoding verification 2026-04-18 10:33:36 +02:00
mount.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 441 2019-06-05 17:37:17 +02:00
net.h security: add const qualifier to struct sock in various places 2020-12-03 12:56:03 -08:00
path.h + Features 2019-12-03 12:51:35 -08:00
perms.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 441 2019-06-05 17:37:17 +02:00
policy.h apparmor: fix race between freeing data and fs accessing it 2026-04-18 10:33:36 +02:00
policy_ns.h apparmor: fix: limit the number of levels of policy namespaces 2026-04-18 10:33:36 +02:00
policy_unpack.h apparmor: fix use-after-free in rawdata dedup loop 2026-07-24 15:51:16 +02:00
procattr.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 441 2019-06-05 17:37:17 +02:00
resource.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 441 2019-06-05 17:37:17 +02:00
secid.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 441 2019-06-05 17:37:17 +02:00
sig_names.h apparmor: audit unknown signal numbers 2018-02-09 11:30:01 -08:00
task.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 441 2019-06-05 17:37:17 +02:00