RE: [PATCH net v2] tipc: fix slab-use-after-free Read in tipc_aead_decrypt_done

From: Tung Quang Nguyen

Date: Mon Jun 15 2026 - 02:58:19 EST


>Subject: Re: [PATCH net v2] tipc: fix slab-use-after-free Read in
>tipc_aead_decrypt_done
>
>On Tue, Jun 10, 2026, Tung Quang Nguyen wrote:
>> Can you decode the stack trace (using
>> linux/scripts/decode_stacktrace.sh)
>> for more readable text?
>>
>> Is the issue reproducible on the latest net branch, or just on the old
>> v6.12.92 you mentioned?
>
>Hi Tung,
>
>Thanks for the review. Answers to both questions below.
>
>1) Decoded stack trace
>----------------------
>Decoded with scripts/decode_stacktrace.sh against the vmlinux that produced
>the splat (6.12.92, CONFIG_KASAN_INLINE + CONFIG_TIPC +
>CONFIG_TIPC_CRYPTO).
>The use-after-free read and the allocation/free sites resolve as follows:
>
>BUG: KASAN: slab-use-after-free in tipc_crypto_rcv_complete
>(net/tipc/crypto.c:1917) Read of size 8 at addr ffff888104c8c808 by task
>kworker/3:2/70
>Workqueue: cryptd cryptd_queue_worker
>Call Trace:
> <TASK>
> dump_stack_lvl (lib/dump_stack.c:123)
> print_report (mm/kasan/report.c:378 mm/kasan/report.c:481) kasan_report
>(mm/kasan/report.c:596) tipc_crypto_rcv_complete (net/tipc/crypto.c:1917)
>tipc_aead_decrypt_done (net/tipc/crypto.c:996) cryptd_aead_crypt
>(include/crypto/internal/aead.h:85 crypto/cryptd.c:772) cryptd_queue_worker
>(crypto/cryptd.c:181) process_one_work (kernel/workqueue.c:3264)
>worker_thread (kernel/workqueue.c:3339 kernel/workqueue.c:3426) kthread
>(kernel/kthread.c:389) ret_from_fork (arch/x86/kernel/process.c:152)
>ret_from_fork_asm (arch/x86/entry/entry_64.S:257) </TASK>
>
>Allocated by task 1550:
> kasan_save_stack (mm/kasan/common.c:49) kasan_save_track
>(mm/kasan/common.c:61 mm/kasan/common.c:70) __kasan_kmalloc
>(mm/kasan/common.c:378 mm/kasan/common.c:395) tipc_crypto_start
>(net/tipc/crypto.c:1484) tipc_init_net (net/tipc/core.c:73) ops_init
>(net/core/net_namespace.c:140) setup_net (net/core/net_namespace.c:357)
>copy_net_ns (net/core/net_namespace.c:512) create_new_namespaces
>(kernel/nsproxy.c:110)
>
>(The captured report has the KASAN read trace and the Allocated-by track; the
>free is on the netns teardown path tipc_crypto_stop() <- tipc_exit_net() <-
>cleanup_net(), as described in the changelog.)
>
>So the freed object is the per-netns struct tipc_crypto allocated in
>tipc_crypto_start() at netns creation (crypto.c:1484), and the cryptd worker
>then reads it from the async completion: tipc_aead_decrypt_done()
>(crypto.c:996) -> tipc_crypto_rcv_complete() (crypto.c:1917). Immediately after
>the UAF read the worker also faults dereferencing the stale node pointer in
>tipc_node_put() (net/tipc/node.c:319), confirming the object is gone.
>
>2) Reproducibility on the latest net branch
>--------------------------------------------
>The bug is still present on the latest net tree. I checked out v7.1-rc7 and
>inspected net/tipc/crypto.c first: the encrypt side already carries the
>maybe_get_net() guard from commit e279024617134 ("net/tipc: fix slab-use-
>after-free Read in tipc_aead_encrypt"), but tipc_aead_decrypt() still goes
>straight from tipc_bearer_hold(b) to crypto_aead_decrypt(req) with no
>maybe_get_net(aead->crypto->net) and no matching put_net() -- i.e. the exact
>gap this patch closes. So the decrypt path is unguarded on 7.1-rc7 and the UAF
>is reachable there in the same way.
>
>I also built v7.1-rc7 (HEAD at v7.1-rc7) with KASAN_INLINE + TIPC +
>TIPC_CRYPTO and reproduced the UAF live. The workload is the same as on
>6.12.92: a UDP bearer with a cluster key is flooded with crafted encrypted
>frames from an unknown peer, taking the cluster-key (pick_tx) RX decrypt path,
>while the bearer's netns is repeatedly torn down. Decoded against the rc7
>vmlinux:
>
>BUG: KASAN: slab-use-after-free in tipc_aead_decrypt_done
>(net/tipc/crypto.c:999) Read of size 8 at addr ffff8881056258a8 by task
>kworker/u16:2/51
>CPU: 2 UID: 0 PID: 51 Comm: kworker/u16:2 Not tainted 7.1.0-rc7-00020-... #15
>Workqueue: events_unbound
>Call Trace:
> <TASK>
> dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120) print_report
>(mm/kasan/report.c:378 mm/kasan/report.c:482) kasan_report
>(mm/kasan/report.c:595) tipc_aead_decrypt_done (net/tipc/crypto.c:999)
>process_one_work (kernel/workqueue.c:3314) worker_thread
>(kernel/workqueue.c:3397 kernel/workqueue.c:3478) kthread
>(kernel/kthread.c:436) ret_from_fork (arch/x86/kernel/process.c:158)
>ret_from_fork_asm (arch/x86/entry/entry_64.S:245) </TASK>
>
>Allocated by task 169:
> __kasan_kmalloc (mm/kasan/common.c:398 mm/kasan/common.c:415)
>tipc_crypto_start (net/tipc/crypto.c:1502) tipc_init_net (net/tipc/core.c:72)
>ops_init (net/core/net_namespace.c:137) setup_net
>(net/core/net_namespace.c:446) copy_net_ns
>(net/core/net_namespace.c:579) create_new_namespaces
>(kernel/nsproxy.c:132) unshare_nsproxy_namespaces (kernel/nsproxy.c:234)
>ksys_unshare (kernel/fork.c:3242) __x64_sys_unshare (kernel/fork.c:3316)
> do_syscall_64 (arch/x86/entry/syscall_64.c:63)
>entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
>
>Freed by task 8:
> kfree (mm/slub.c:6566)
> tipc_exit_net (net/tipc/core.c:119)
> ops_undo_list (net/core/net_namespace.c) cleanup_net
>(net/core/net_namespace.c:704) process_one_work
>(kernel/workqueue.c:3314) worker_thread (kernel/workqueue.c) kthread
>(kernel/kthread.c:436)
>
>The freed object is the per-netns struct tipc_crypto allocated in
>tipc_crypto_start() at netns creation (crypto.c:1502 on rc7); the async decrypt
>completion then reads aead->crypto->stats from it (crypto.c:999) after
>cleanup_net() -> tipc_exit_net() -> tipc_crypto_stop() has freed it -- the exact
>read/alloc/free triple this patch closes, now on 7.1-rc7 rather than 6.12.92.
>
>One note on the harness: on x86 the in-tree gcm(aes) the SIMD aead wrapper
>used to register via simd_register_aeads_compat() is, as of the aesni rewrite,
>now registered directly with crypto_register_aeads() and decrypts
>synchronously, so the cryptd async window the original 6.12.92 splat used does
>not arise from the stock aesni path on rc7. To exercise the same async
>completion the changelog describes, I forced tipc_aead_decrypt()'s completion
>onto a workqueue in my test tree; the unguarded aead->crypto dereference in
>tipc_aead_decrypt_done() is what KASAN catches, and that code is byte-for-
>byte the unpatched upstream path. The source state is in any case
>unambiguous: tipc_aead_decrypt() on rc7 still lacks maybe_get_net(aead-
>>crypto->net), so the completion can outlive the free on any config where
>crypto_aead_decrypt() goes async (e.g. cryptd offload).
>
>Reproduced under KASAN on both v6.12.92 and v7.1-rc7; the decrypt path
>lacks the guard on the latest net tree.

Thanks. Please submit v3 with updated changelog (decoded stack trace, remove v6.12.92) because we always prefer latest tree to old one.

>
>Thanks,
>Doruk