lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CANn89i+3_50FX1RWutvipTMROD3FnK-nBeG4L+br86W85fzRdQ@mail.gmail.com>
Date: Wed, 3 Dec 2025 00:05:55 -0800
From: Eric Dumazet <edumazet@...gle.com>
To: Minseong Kim <ii4gsp@...il.com>
Cc: security@...nel.org, davem@...emloft.net, kuba@...nel.org, 
	pabeni@...hat.com, horms@...nel.org, netdev@...r.kernel.org
Subject: Re: [SECURITY] Use-After-Free in /proc/net/atm/mpc QoS list
 (qos_head) due to missing locking

On Tue, Dec 2, 2025 at 11:37 PM Minseong Kim <ii4gsp@...il.com> wrote:
>
> Hello Linux kernel security team and ATM/Networking maintainers,
>

Hello Minseong

Please do not involve security@...nel.org on something you make public.
There is nothing left for us to do, as security officers.
Please read https://www.kernel.org/doc/Documentation/process/security-bugs.rst
for details.

As for the bugs, do you already have fixes for them ?

If so, please send formal patches to netdev@ mailing list.

Thank you.

> I would like to report a reproducible use-after-free issue in the ATM MPOA
> procfs interface.
>
> Subsystem / Files:
>   - net/atm/mpoa_proc.c  (procfs interface that exposes /proc/net/atm/mpc)
>   - net/atm/mpc.c        (qos_head list and QoS management logic)
>
> Vulnerable functions / paths:
>   - Read side:  mpc_show() -> atm_mpoa_disp_qos()
>   - Write side: proc_mpc_write() -> parse_qos() -> atm_mpoa_delete_qos()
>
> Issue summary:
>   atm_mpoa_disp_qos() walks the global QoS list (qos_head) without any
>   locking or refcounting. Concurrently, proc_mpc_write() can delete QoS
>   entries via atm_mpoa_delete_qos(), which unlinks and kfree()s entries
>   immediately. This creates a race where the show path continues to read a
>   freed QoS entry, leading to UAF.
>
>   The code already acknowledges this risk:
>     /* this is buggered - we need locking for qos_head */
>
> Race window / execution flow:
>   Reader (procfs):
>     proc_reg_read -> seq_read_iter -> mpc_show
>       -> atm_mpoa_disp_qos() walks qos_head without lock
>
>   Writer (procfs):
>     proc_reg_write -> proc_mpc_write -> parse_qos("del ...")
>       -> atm_mpoa_delete_qos() deletes entry and kfree()s it immediately
>
>   If deletion happens while atm_mpoa_disp_qos() is printing the same entry,
>   mpc_show continues accessing freed memory => UAF.
>
> Affected versions / prerequisites:
>   - Confirmed on Linux 6.17.8 with CONFIG_ATM + CONFIG_ATM_MPOA enabled.
>   - Requires MPOA being active and QoS entries to exist (qos_head non-NULL).
>   - The qos_head locking model appears unchanged for a long time, so older
>     kernels with MPOA enabled are likely affected as well.
>
> Reproduction:
>   Reproduced reliably with KASAN using a PoC that:
>     (1) continuously reads /proc/net/atm/mpc (triggering atm_mpoa_disp_qos),
>     (2) concurrently adds/deletes QoS entries via proc writes to induce churn.
>   PoC and full logs are available upon request.
>
> KASAN evidence:
> ==================================================================
> [ 15.911538] BUG: KASAN: slab-use-after-free in atm_mpoa_disp_qos+0x202/0x380
> [ 15.911988] Read of size 8 at addr ffff888007517380 by task mpoa_uaf_poc/89
> [ 15.912123]
> [ 15.912717] CPU: 0 UID: 0 PID: 89 Comm: mpoa_uaf_poc Not tainted
> 6.17.8 #1 PREEMPT(voluntary)
> [ 15.912950] Hardware name: QEMU Ubuntu 25.04 PC (i440FX + PIIX,
> 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
> [ 15.913110] Call Trace:
> [ 15.913167] <TASK>
> [ 15.913247] dump_stack_lvl+0x4e/0x70
> [ 15.913343] ? atm_mpoa_disp_qos+0x202/0x380
> [ 15.913364] print_report+0x174/0x4f6
> [ 15.913386] ? __pfx__raw_spin_lock_irqsave+0x10/0x10
> [ 15.913412] ? atm_mpoa_disp_qos+0x202/0x380
> [ 15.913430] kasan_report+0xce/0x100
> [ 15.913453] ? atm_mpoa_disp_qos+0x202/0x380
> [ 15.913475] atm_mpoa_disp_qos+0x202/0x380
> [ 15.913496] mpc_show+0x575/0x700
> [ 15.913515] ? kasan_save_track+0x14/0x30
> [ 15.913532] ? __pfx_mpc_show+0x10/0x10
> [ 15.913550] ? __pfx_mutex_lock+0x10/0x10
> [ 15.913565] ? seq_read_iter+0x697/0x1110
> [ 15.913584] seq_read_iter+0x2bc/0x1110
> [ 15.913607] seq_read+0x267/0x3d0
> [ 15.913623] ? __pfx_seq_read+0x10/0x10
> [ 15.913650] proc_reg_read+0x1ab/0x270
> [ 15.913669] vfs_read+0x175/0xa10
> [ 15.913687] ? do_sys_openat2+0x103/0x170
> [ 15.913701] ? kmem_cache_free+0xc4/0x360
> [ 15.913718] ? getname_flags.part.0+0xf3/0x470
> [ 15.913734] ? __pfx_vfs_read+0x10/0x10
> [ 15.913751] ? mutex_lock+0x81/0xe0
> [ 15.913766] ? __pfx_mutex_lock+0x10/0x10
> [ 15.913782] ? __rseq_handle_notify_resume+0x4c4/0xac0
> [ 15.913802] ? fdget_pos+0x24d/0x4b0
> [ 15.913829] ksys_read+0xf7/0x1c0
> [ 15.913850] ? __pfx_ksys_read+0x10/0x10
> [ 15.913877] do_syscall_64+0xa4/0x290
> [ 15.913917] entry_SYSCALL_64_after_hwframe+0x77/0x7f
> [ 15.913981] RIP: 0033:0x45c982
> [ 15.914171] Code: 08 0f 85 71 ea ff ff 49 89 fb 48 89 f0 48 89 d7 48
> 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08
> 0f 05 <c3> 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 55 48 89
> e5
> [ 15.914239] RSP: 002b:00007f4b2b2cb0d8 EFLAGS: 00000246 ORIG_RAX:
> 0000000000000000
> [ 15.914315] RAX: ffffffffffffffda RBX: 00007f4b2b2cc6c0 RCX: 000000000045c982
> [ 15.914352] RDX: 0000000000000fff RSI: 00007f4b2b2cb220 RDI: 0000000000000014
> [ 15.914382] RBP: 00007f4b2b2cb100 R08: 0000000000000000 R09: 0000000000000000
> [ 15.914413] R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000000a
> [ 15.914445] R13: ffffffffffffffd0 R14: 0000000000000000 R15: 00007ffd386450c0
> [ 15.914483] </TASK>
> [ 15.914533]
> [ 15.916812] Allocated by task 78:
> [ 15.916975] kasan_save_stack+0x30/0x50
> [ 15.917047] kasan_save_track+0x14/0x30
> [ 15.917105] __kasan_kmalloc+0x8f/0xa0
> [ 15.917162] atm_mpoa_add_qos+0x1bb/0x3c0
> [ 15.917220] parse_qos.cold+0x73/0x7d
> [ 15.917276] proc_mpc_write+0xf4/0x150
> [ 15.917331] proc_reg_write+0x1ab/0x270
> [ 15.917379] vfs_write+0x1ce/0xd30
> [ 15.917431] ksys_write+0xf7/0x1c0
> [ 15.917476] do_syscall_64+0xa4/0x290
> [ 15.917523] entry_SYSCALL_64_after_hwframe+0x77/0x7f
> [ 15.917586]
> [ 15.917628] Freed by task 78:
> [ 15.917665] kasan_save_stack+0x30/0x50
> [ 15.917714] kasan_save_track+0x14/0x30
> [ 15.917762] kasan_save_free_info+0x3b/0x70
> [ 15.917811] __kasan_slab_free+0x3e/0x50
> [ 15.918058] kfree+0x121/0x340
> [ 15.918135] atm_mpoa_delete_qos+0xad/0xd0
> [ 15.918196] parse_qos+0x1e5/0x1f0
> [ 15.918339] proc_mpc_write+0xf4/0x150
> [ 15.918438] proc_reg_write+0x1ab/0x270
> [ 15.918494] vfs_write+0x1ce/0xd30
> [ 15.918538] ksys_write+0xf7/0x1c0
> [ 15.918589] do_syscall_64+0xa4/0x290
> [ 15.918634] entry_SYSCALL_64_after_hwframe+0x77/0x7f
> [ 15.918694]
> [ 15.918751] The buggy address belongs to the object at ffff888007517380
> [ 15.918751] which belongs to the cache kmalloc-96 of size 96
> [ 15.918911] The buggy address is located 0 bytes inside of
> [ 15.918911] freed 96-byte region [ffff888007517380, ffff8880075173e0)
> [ 15.919027]
> [ 15.919101] The buggy address belongs to the physical page:
> [ 15.919416] page: refcount:0 mapcount:0 mapping:0000000000000000
> index:0xffff888007517300 pfn:0x7517
> [ 15.919679] anon flags: 0x100000000000000(node=0|zone=1)
> [ 15.920064] page_type: f5(slab)
> [ 15.920361] raw: 0100000000000000 ffff888006c41280 0000000000000000
> dead000000000001
> [ 15.920460] raw: ffff888007517300 0000000080200007 00000000f5000000
> 0000000000000000
> [ 15.920577] page dumped because: kasan: bad access detected
> [ 15.920634]
> [ 15.920663] Memory state around the buggy address:
> [ 15.920860] ffff888007517280: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
> [ 15.920944] ffff888007517300: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
> [ 15.921017] >ffff888007517380: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
> [ 15.921088] ^
> [ 15.921163] ffff888007517400: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
> [ 15.921222] ffff888007517480: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
> [ 15.921313] ==================================================================
>
> Note on reproduction setup:
>   For easier reproduction in a VM without full MPOA/ATM traffic, I applied a
>   local debug-only seeding change in net/atm/mpc.c to create one test
> mpoa_client
>   and a few cache/QoS entries at init time. This seeding patch does NOT change
>   locking or list logic; it only creates the runtime state required to hit the
>   existing race. The underlying UAF is present in upstream code and can be
>   triggered on unmodified kernels whenever MPOA is active and qos entries exist.
>   I can provide the seeding patch separately if helpful.
>
> Impact:
>   - UAF read in procfs show path; can lead to kernel crash (DoS) and
>     potentially info leak.
>   - In my current PoC, concurrent procfs writes were used (root/CAP_NET_ADMIN);
>     I have not confirmed a fully unprivileged trigger path yet.
>
> Proposed fix direction:
>   The minimal fix is to introduce proper synchronization for qos_head:
>     (A) add a dedicated lock to protect qos_head traversal in
> atm_mpoa_disp_qos()
>         (read-side) and add/delete paths (write-side), or
>     (B) convert qos_head/QoS entries to an RCU-protected list and free via
>         kfree_rcu().
>
>   I am happy to prepare and submit a patch if you prefer; please advise which
>   approach fits best for this legacy ATM code.
>
> If this is considered a security issue, I would appreciate guidance on
> CVE assignment.
>
> Thank you,
> Minseong Kim
> ii4gsp@...il.com

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ