[BUG] apparmor: AA_BUG aa_policy_destroy on aa_alloc_profile error path

Farhad Alemi farhad.alemi at berkeley.edu
Fri May 29 03:32:10 UTC 2026


Hello John and the AppArmor team,

I am reporting an AppArmor AA_BUG WARN in aa_policy_destroy() found
by syzkaller as part of research at the SEFCOM Lab at ASU.

Summary:
A write(2) to /proc/<pid>/attr/<lsm>/current that drives the
aa_change_hat() -> aa_new_learning_profile() -> aa_alloc_null() ->
aa_alloc_profile() chain takes the error-rollback path at
security/apparmor/policy.c:409 (aa_alloc_profile()'s `fail:` label
calling aa_free_profile(profile)). aa_free_profile() then calls
aa_policy_destroy(&profile->base) at security/apparmor/policy.c:327,
which trips its first AA_BUG at security/apparmor/lib.c:509:

  void aa_policy_destroy(struct aa_policy *policy)
  {
          AA_BUG(on_list_rcu(&policy->profiles));   <-- :509
          AA_BUG(on_list_rcu(&policy->list));
          ...
  }

  /* security/apparmor/include/policy.h:60 */
  #define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2)

The WARN reproduces the macro's condition verbatim (the kernel prints
the full stringified expression including the LIST_POISON2 numeric
0x122 + 0xdead000000000000UL); see crash-report.txt for the full
header.

Observed on:
- Linux v7.1-rc3-200-g70eda68668d1-dirty (the only local dirty file
  is drivers/tty/serial/serial_core.c, a console guard our fuzzing
  harness uses, unrelated to security/apparmor/), x86_64, QEMU Q35
- AA_BUG asserts enabled + panic_on_warn (the crash tail prints
  "Kernel panic - not syncing: kernel: panic_on_warn set")
- Source inspection of linus/master at commit e8c2f9fdadee
  (v7.1-rc4-754-ge8c2f9fdadee) shows the buggy structure is
  unchanged: security/apparmor/lib.c:509 still does
  AA_BUG(on_list_rcu(&policy->profiles)); aa_alloc_profile()'s fail
  path at security/apparmor/policy.c:409 still calls
  aa_free_profile(profile); aa_free_profile() at policy.c:327 still
  calls aa_policy_destroy(&profile->base). As no reproducer is available
  for this seed, I have not re-triggered the crash against e8c2f9fdadee.

Expected behavior:
Either aa_alloc_profile()'s rollback path must guarantee
profile->base.profiles is empty (or list_del'd so prev == LIST_POISON2)
before calling aa_free_profile(), or aa_policy_destroy()'s AA_BUG
should be softened to a WARN_ON-and-drain so it does not panic on an
alloc-rollback path. The maintainers are best placed to choose which
side of the contract owns this.

Reproducer:
A standalone .syz or C reproducer was not produced for this seed;
the crash fired during automated /proc/<pid>/attr/* fuzzing. The
console report is attached as crash-report.txt.

Novelty check:
I searched the syzbot dashboard's upstream open, fixed, stable, and
invalid (per-subsystem apparmor) namespaces; the Android dashboard;
the marc.info linux-security-module archive; and the complete
apparmor at lists.ubuntu.com list archive (2010 through 2026, full
message bodies), for "aa_policy_destroy", "on_list_rcu(&policy->
profiles)", "aa_alloc_profile" + "WARNING", and "AA_BUG" +
"policy->profiles". I did not find a prior report of this crash. The
three apparmor-titled entries in the syzbot invalid namespace are in
different functions (apparmor_sk_free_security UAF, aa_label_sk_perm
UAF, apparmor_file_open data-race). The only aa_policy_destroy
mentions on the AppArmor list are a 2022 "Fix memleak in alloc_ns()"
patch (a different aa_policy_destroy(&ns->base) call site), and there
is no occurrence of on_list_rcu(&policy->profiles) anywhere in the
list history.

I appreciate your time and consideration, and I'm grateful for your
work on this subsystem. I'd be glad to test any candidate patches.

Regards,
-------------- next part --------------
 </TASK>
------------[ cut here ]------------
AppArmor WARN aa_policy_destroy: (((!list_empty(&policy->profiles) && (&policy->profiles)->prev != ((void *) 0x122 + (0xdead000000000000UL))))): 
WARNING: security/apparmor/lib.c:509 at aa_policy_destroy+0x169/0x1c0 security/apparmor/lib.c:509, CPU#0: syz.3.739/13898
Modules linked in:
CPU: 0 UID: 0 PID: 13898 Comm: syz.3.739 Not tainted 7.1.0-rc3-00200-g70eda68668d1-dirty #1 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:aa_policy_destroy+0x170/0x1c0 security/apparmor/lib.c:509
Code: 85 ed 7e 4d e8 c1 9a dc fd 5b 41 5c 41 5e 41 5f 5d c3 cc cc cc cc cc e8 ae 9a dc fd 48 8d 3d 87 1c 0b 05 48 c7 c6 b8 a7 82 87 <67> 48 0f b9 3a e9 04 ff ff ff e8 91 9a dc fd 48 8d 3d 7a 1c 0b 05
RSP: 0018:ffffc9000141f500 EFLAGS: 00010293
RAX: ffffffff83a572b2 RBX: ffff88811907a400 RCX: ffff88812f778000
RDX: 0000000000000000 RSI: ffffffff8782a7b8 RDI: ffffffff88b08f40
RBP: 0000000000000cc0 R08: 0000000000000cc0 R09: 00000000ffffffff
R10: dffffc0000000000 R11: fffffbfff100a27f R12: dead000000000122
R13: ffff88811907a400 R14: ffff88811907a428 R15: dffffc0000000000
FS:  00007f51fd2d76c0(0000) GS:ffff8882ab6b6000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f51fe8cfe10 CR3: 000000011b6ea000 CR4: 0000000000750ef0
PKRU: 80000000
Call Trace:
 <TASK>
 aa_free_profile+0xa2/0x9f0 security/apparmor/policy.c:327
 aa_alloc_profile+0x1f1/0x3f0 security/apparmor/policy.c:409
 aa_alloc_null+0x2d/0x530 security/apparmor/policy.c:690
 aa_new_learning_profile+0x226/0x4e0 security/apparmor/policy.c:767
 build_change_hat+0x292/0x400 security/apparmor/domain.c:1079
 change_hat security/apparmor/domain.c:1193 [inline]
 aa_change_hat+0x1177/0x2fb0 security/apparmor/domain.c:1269
 aa_setprocattr_changehat+0x4a6/0x5b0 security/apparmor/procattr.c:138
 do_setattr+0x548/0x6a0
 proc_pid_attr_write+0x5d1/0x630 fs/proc/base.c:2844
 vfs_write+0x29f/0xb90 fs/read_write.c:686
 ksys_write+0x155/0x270 fs/read_write.c:740
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x15f/0x560 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f51fe88778d
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f51fd2d7018 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007f51feb15fa0 RCX: 00007f51fe88778d
RDX: 0000000000000022 RSI: 00002000000000c0 RDI: 0000000000000003
RBP: 00007f51fd2d7080 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
R13: 00007f51feb16038 R14: 00007f51feb15fa0 R15: 00007ffc4916b870
 </TASK>
----------------
Code disassembly (best guess):
   0:	85 ed                	test   %ebp,%ebp
   2:	7e 4d                	jle    0x51
   4:	e8 c1 9a dc fd       	call   0xfddc9aca
   9:	5b                   	pop    %rbx
   a:	41 5c                	pop    %r12
   c:	41 5e                	pop    %r14
   e:	41 5f                	pop    %r15
  10:	5d                   	pop    %rbp
  11:	c3                   	ret
  12:	cc                   	int3
  13:	cc                   	int3
  14:	cc                   	int3
  15:	cc                   	int3
  16:	cc                   	int3
  17:	e8 ae 9a dc fd       	call   0xfddc9aca
  1c:	48 8d 3d 87 1c 0b 05 	lea    0x50b1c87(%rip),%rdi        # 0x50b1caa
  23:	48 c7 c6 b8 a7 82 87 	mov    $0xffffffff8782a7b8,%rsi
* 2a:	67 48 0f b9 3a       	ud1    (%edx),%rdi <-- trapping instruction
  2f:	e9 04 ff ff ff       	jmp    0xffffff38
  34:	e8 91 9a dc fd       	call   0xfddc9aca
  39:	48 8d 3d 7a 1c 0b 05 	lea    0x50b1c7a(%rip),%rdi        # 0x50b1cba

<<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>>

Modules linked in:
CPU: 0 UID: 0 PID: 13898 Comm: syz.3.739 Not tainted 7.1.0-rc3-00200-g70eda68668d1-dirty #1 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:aa_policy_destroy+0x170/0x1c0
Code: 85 ed 7e 4d e8 c1 9a dc fd 5b 41 5c 41 5e 41 5f 5d c3 cc cc cc cc cc e8 ae 9a dc fd 48 8d 3d 87 1c 0b 05 48 c7 c6 b8 a7 82 87 <67> 48 0f b9 3a e9 04 ff ff ff e8 91 9a dc fd 48 8d 3d 7a 1c 0b 05
RSP: 0018:ffffc9000141f500 EFLAGS: 00010293
RAX: ffffffff83a572b2 RBX: ffff88811907a400 RCX: ffff88812f778000
RDX: 0000000000000000 RSI: ffffffff8782a7b8 RDI: ffffffff88b08f40
RBP: 0000000000000cc0 R08: 0000000000000cc0 R09: 00000000ffffffff
R10: dffffc0000000000 R11: fffffbfff100a27f R12: dead000000000122
R13: ffff88811907a400 R14: ffff88811907a428 R15: dffffc0000000000
FS:  00007f51fd2d76c0(0000) GS:ffff8882ab6b6000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f51fe8cfe10 CR3: 000000011b6ea000 CR4: 0000000000750ef0
PKRU: 80000000
Call Trace:
 <TASK>
 aa_free_profile+0xa2/0x9f0
 aa_alloc_profile+0x1f1/0x3f0
 aa_alloc_null+0x2d/0x530
 aa_new_learning_profile+0x226/0x4e0
 build_change_hat+0x292/0x400
 aa_change_hat+0x1177/0x2fb0
 aa_setprocattr_changehat+0x4a6/0x5b0
 do_setattr+0x548/0x6a0
 proc_pid_attr_write+0x5d1/0x630
 vfs_write+0x29f/0xb90
 ksys_write+0x155/0x270
 do_syscall_64+0x15f/0x560
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f51fe88778d
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f51fd2d7018 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007f51feb15fa0 RCX: 00007f51fe88778d
RDX: 0000000000000022 RSI: 00002000000000c0 RDI: 0000000000000003
RBP: 00007f51fd2d7080 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
R13: 00007f51feb16038 R14: 00007f51feb15fa0 R15: 00007ffc4916b870
 </TASK>
Kernel panic - not syncing: kernel: panic_on_warn set ...
CPU: 0 UID: 0 PID: 13898 Comm: syz.3.739 Not tainted 7.1.0-rc3-00200-g70eda68668d1-dirty #1 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
Call Trace:
 <TASK>
 vpanic+0x571/0xa60
 panic+0xca/0xd0
 __warn+0x31a/0x4d0
 __report_bug+0x29a/0x540
 report_bug_entry+0x19a/0x290
 handle_bug+0xce/0x200
 exc_invalid_op+0x1a/0x50
 asm_exc_invalid_op+0x1a/0x20
RIP: 0010:aa_policy_destroy+0x170/0x1c0
Code: 85 ed 7e 4d e8 c1 9a dc fd 5b 41 5c 41 5e 41 5f 5d c3 cc cc cc cc cc e8 ae 9a dc fd 48 8d 3d 87 1c 0b 05 48 c7 c6 b8 a7 82 87 <67> 48 0f b9 3a e9 04 ff ff ff e8 91 9a dc fd 48 8d 3d 7a 1c 0b 05
RSP: 0018:ffffc9000141f500 EFLAGS: 00010293
RAX: ffffffff83a572b2 RBX: ffff88811907a400 RCX: ffff88812f778000
RDX: 0000000000000000 RSI: ffffffff8782a7b8 RDI: ffffffff88b08f40
RBP: 0000000000000cc0 R08: 0000000000000cc0 R09: 00000000ffffffff
R10: dffffc0000000000 R11: fffffbfff100a27f R12: dead000000000122
R13: ffff88811907a400 R14: ffff88811907a428 R15: dffffc0000000000
 aa_free_profile+0xa2/0x9f0
 aa_alloc_profile+0x1f1/0x3f0
 aa_alloc_null+0x2d/0x530
 aa_new_learning_profile+0x226/0x4e0
 build_change_hat+0x292/0x400
 aa_change_hat+0x1177/0x2fb0
 aa_setprocattr_changehat+0x4a6/0x5b0
 do_setattr+0x548/0x6a0
 proc_pid_attr_write+0x5d1/0x630
 vfs_write+0x29f/0xb90
 ksys_write+0x155/0x270
 do_syscall_64+0x15f/0x560
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f51fe88778d
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f51fd2d7018 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007f51feb15fa0 RCX: 00007f51fe88778d
RDX: 0000000000000022 RSI: 00002000000000c0 RDI: 0000000000000003
RBP: 00007f51fd2d7080 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
R13: 00007f51feb16038 R14: 00007f51feb15fa0 R15: 00007ffc4916b870
 </TASK>
Kernel Offset: disabled
Rebooting in 86400 seconds..

<<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>>



More information about the Linux-security-module-archive mailing list