суббота

[Bug 2173669] [NEW] l2tp: use-after-free (refcount_t: addition on 0) on every L2TP/IPsec VPN connect since 6.8.0-146 - bad backport of CVE-2026-53262 fix in pppol2tp_ioctl()

Public bug reported: ### Summary Starting with linux 6.8.0-146.146 (noble), connecting an L2TP/IPsec VPN (network-manager-l2tp + strongSwan + pppd) triggers a kernel `refcount_t: addition on 0; use-after-free` warning in `l2tp_core` within about one second of the connection coming up, every single time. The slab corruption that follows later takes down unrelated processes (we observed oopses in `kioslave5`, `kscreenlocker_greet` and `rsync` inside `kmalloc`/`kfree`) and ends in a full system freeze. 6.8.0-142.142 is unaffected. 6.8.0-146, 6.8.0-147 and 6.8.0-149 are all affected; 6.8.0-149's "xfrm: add missing rcu_read_lock() ... for xfrm_trans_reinject()" does not fix it. The cause is a reference-counting mismatch introduced by the noble backport of the CVE-2026-53262 fix ("l2tp: pppol2tp: hold reference to session in pppol2tp_ioctl()"). Details and a proposed fix below. ### Environment - Ubuntu 24.04.5 LTS (noble), amd64 - Lenovo ThinkPad (20NECTO1WW), 8 CPUs, 29 GiB RAM, no hardware errors logged (no MCE/EDAC) - Affected kernels: linux-image-6.8.0-146-generic, -147-generic, -149-generic - Unaffected kernel: linux-image-6.8.0-142-generic - VPN stack: network-manager-l2tp 1.20.12-1build2 (uses kl2tpd), strongswan 5.9.13-2ubuntu4.24.04.5, ppp 2.4.9-1+1.1ubuntu4, network-manager 1.46.0-1ubuntu2.8 - VPN type: L2TP over IPsec (IKEv1, ESP in UDP encapsulation) ### Steps to reproduce 1. Boot 6.8.0-146 or later (tested 146, 147, 149). 2. Connect an L2TP/IPsec VPN with network-manager-l2tp. 3. `journalctl -k | grep refcount_t` Expected: no warnings. Actual: within ~1 s of `l2tp_ppp: PPPoL2TP kernel driver, V2.0` being logged, three warnings appear in sequence: ``` refcount_t: addition on 0; use-after-free. (l2tp_tunnel_get_session) refcount_t: underflow; use-after-free. (l2tp_session_dec_refcount / l2tp_session_put in 149) refcount_t: saturated; leaking memory. (l2tp_tunnel_get_session) ``` Reproduces 100% of the time on every connect. Booting 6.8.0-142 with the same VPN and configuration shows no warning. ### Trace (6.8.0-149, first warning; full log attached) ``` refcount_t: addition on 0; use-after-free. WARNING: CPU: 4 PID: 31 at lib/refcount.c:25 refcount_warn_saturate+0x12e/0x150 CPU: 4 PID: 31 Comm: kworker/4:0 Not tainted 6.8.0-149-generic #149-Ubuntu Workqueue: events xfrm_trans_reinject Call Trace: <TASK> l2tp_tunnel_get_session+0xc8/0xd0 [l2tp_core] l2tp_udp_recv_core+0xb1/0x350 [l2tp_core] l2tp_udp_encap_recv+0x2c/0x54 [l2tp_core] udp_queue_rcv_one_skb+0x27b/0x550 udp_queue_rcv_skb+0x4f/0x80 udp_unicast_rcv_skb+0x7a/0xa0 __udp4_lib_rcv+0x627/0x6f0 udp_rcv+0x25/0x40 ip_protocol_deliver_rcu+0xd8/0x210 ip_local_deliver_finish+0x77/0xa0 ip_local_deliver+0x6e/0x120 xfrm4_rcv_encap_finish2+0x3c/0x60 xfrm_trans_reinject+0xf0/0x190 process_one_work+0x184/0x3a0 worker_thread+0x18b/0x330 kthread+0xf2/0x120 ret_from_fork+0x47/0x70 ret_from_fork_asm+0x1b/0x30 </TASK> ``` Later consequences seen on 6.8.0-146 (same machine, 2026-10-05 and 2026-10-06): `BUG: unable to handle page fault` in `kmalloc_trace` (comm kioslave5, then kscreenlocker_greet), `free_large_kmalloc` / `__kmalloc` oops from `cifs_get_fattr` (comm rsync), followed by a hard freeze with the journal cut off. ### Root cause Comparing `net/l2tp/l2tp_ppp.c` between the Ubuntu-6.8.0-142.142 and Ubuntu-6.8.0-146.146 tags (https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/noble), the only change is the backport of l2tp: pppol2tp: hold reference to session in pppol2tp_ioctl() (CVE-2026-53262) The upstream fix targets 6.12+, where `pppol2tp_sock_to_session()` takes a reference on the *session* and callers drop it with `l2tp_session_put()`. In 6.8, `pppol2tp_sock_to_session()` is different: it takes a reference on the *socket* (`sock_hold(sk)`) and takes none on the session: ```c static inline struct l2tp_session *pppol2tp_sock_to_session(struct sock *sk) { ... sock_hold(sk); session = (struct l2tp_session *)(sk->sk_user_data); if (!session) { sock_put(sk); goto out; } ... } ``` Every other caller in 6.8 (`pppol2tp_recvmsg`, `pppol2tp_sendmsg`, `pppol2tp_release`, `pppol2tp_setsockopt`, `pppol2tp_getsockopt`) accordingly releases it with `sock_put(sk)`. The backported `pppol2tp_ioctl()` instead does: ```c session = pppol2tp_sock_to_session(sock->sk); /* sock_hold() only */ ... if (session) l2tp_session_dec_refcount(session); /* drops a session ref it never took */ return err; ``` (In 6.8.0-149 the helper is renamed to `l2tp_session_put()`; the logic is unchanged.) The `-EBADF` path has the same mismatch. Result: every `pppol2tp_ioctl()` call decrements the session refcount by one without a matching increment, and leaks one socket reference. pppd issues ioctls on the pppol2tp socket right after connect (`PPPIOCGL2TPSTATS` etc.), so the session refcount drops to zero while the session is still in the tunnel's session hash. The next incoming L2TP data packet looks it up via `l2tp_tunnel_get_session()`, which uses plain `refcount_inc()`, producing `addition on 0` and a use-after-free. This matches the observed deterministic ~1 s delay (first inbound L2TP packet after the PPP ioctls) and the fact that 142 (no such code) is clean while 146/147/149 (same ioctl logic) all fail. ### Proposed fix In `pppol2tp_ioctl()`, release what was taken: replace both `l2tp_session_dec_refcount(session)` (149: `l2tp_session_put(session)`) calls with `sock_put(sock->sk)`, matching the other callers of `pppol2tp_sock_to_session()` in 6.8. Alternatively, backport the 6.11+ change that makes `pppol2tp_sock_to_session()` take a session reference (and convert all callers), but the one-line `sock_put` change is the minimal correct fix for this branch. The same mismatch should be checked in the other Ubuntu kernels that received this CVE backport on a pre-6.11 `pppol2tp_sock_to_session()` (e.g. 6.8 HWE kernels, jammy 5.15 if applicable). ### Workaround Boot 6.8.0-142 (pinned via GRUB_DEFAULT), or avoid L2TP VPN on affected kernels. (Attachments: full dmesg from 6.8.0-149 after VPN connect, and the 142->146 diff of pppol2tp_ioctl(), will be added after filing.) ** Affects: linux (Ubuntu) Importance: Undecided Status: New ** Tags: noble regression-update ** Attachment added: "dmesg from 6.8.0-149-generic, from l2tp module load (VPN connect) until shutdown; all three refcount_t warnings" https://bugs.launchpad.net/bugs/2173669/+attachment/6016004/+files/dmesg-6.8.0-149-full.txt ** CVE added: https://cve.org/CVERecord?id=CVE-2026-53262 -- You received this bug notification because you are subscribed to linux in Ubuntu. Matching subscriptions: Bgg, Bmail, Nb https://bugs.launchpad.net/bugs/2173669 Title: l2tp: use-after-free (refcount_t: addition on 0) on every L2TP/IPsec VPN connect since 6.8.0-146 - bad backport of CVE-2026-53262 fix in pppol2tp_ioctl() Status in linux package in Ubuntu: New Bug description: ### Summary Starting with linux 6.8.0-146.146 (noble), connecting an L2TP/IPsec VPN (network-manager-l2tp + strongSwan + pppd) triggers a kernel `refcount_t: addition on 0; use-after-free` warning in `l2tp_core` within about one second of the connection coming up, every single time. The slab corruption that follows later takes down unrelated processes (we observed oopses in `kioslave5`, `kscreenlocker_greet` and `rsync` inside `kmalloc`/`kfree`) and ends in a full system freeze. 6.8.0-142.142 is unaffected. 6.8.0-146, 6.8.0-147 and 6.8.0-149 are all affected; 6.8.0-149's "xfrm: add missing rcu_read_lock() ... for xfrm_trans_reinject()" does not fix it. The cause is a reference-counting mismatch introduced by the noble backport of the CVE-2026-53262 fix ("l2tp: pppol2tp: hold reference to session in pppol2tp_ioctl()"). Details and a proposed fix below. ### Environment - Ubuntu 24.04.5 LTS (noble), amd64 - Lenovo ThinkPad (20NECTO1WW), 8 CPUs, 29 GiB RAM, no hardware errors logged (no MCE/EDAC) - Affected kernels: linux-image-6.8.0-146-generic, -147-generic, -149-generic - Unaffected kernel: linux-image-6.8.0-142-generic - VPN stack: network-manager-l2tp 1.20.12-1build2 (uses kl2tpd), strongswan 5.9.13-2ubuntu4.24.04.5, ppp 2.4.9-1+1.1ubuntu4, network-manager 1.46.0-1ubuntu2.8 - VPN type: L2TP over IPsec (IKEv1, ESP in UDP encapsulation) ### Steps to reproduce 1. Boot 6.8.0-146 or later (tested 146, 147, 149). 2. Connect an L2TP/IPsec VPN with network-manager-l2tp. 3. `journalctl -k | grep refcount_t` Expected: no warnings. Actual: within ~1 s of `l2tp_ppp: PPPoL2TP kernel driver, V2.0` being logged, three warnings appear in sequence: ``` refcount_t: addition on 0; use-after-free. (l2tp_tunnel_get_session) refcount_t: underflow; use-after-free. (l2tp_session_dec_refcount / l2tp_session_put in 149) refcount_t: saturated; leaking memory. (l2tp_tunnel_get_session) ``` Reproduces 100% of the time on every connect. Booting 6.8.0-142 with the same VPN and configuration shows no warning. ### Trace (6.8.0-149, first warning; full log attached) ``` refcount_t: addition on 0; use-after-free. WARNING: CPU: 4 PID: 31 at lib/refcount.c:25 refcount_warn_saturate+0x12e/0x150 CPU: 4 PID: 31 Comm: kworker/4:0 Not tainted 6.8.0-149-generic #149-Ubuntu Workqueue: events xfrm_trans_reinject Call Trace: <TASK> l2tp_tunnel_get_session+0xc8/0xd0 [l2tp_core] l2tp_udp_recv_core+0xb1/0x350 [l2tp_core] l2tp_udp_encap_recv+0x2c/0x54 [l2tp_core] udp_queue_rcv_one_skb+0x27b/0x550 udp_queue_rcv_skb+0x4f/0x80 udp_unicast_rcv_skb+0x7a/0xa0 __udp4_lib_rcv+0x627/0x6f0 udp_rcv+0x25/0x40 ip_protocol_deliver_rcu+0xd8/0x210 ip_local_deliver_finish+0x77/0xa0 ip_local_deliver+0x6e/0x120 xfrm4_rcv_encap_finish2+0x3c/0x60 xfrm_trans_reinject+0xf0/0x190 process_one_work+0x184/0x3a0 worker_thread+0x18b/0x330 kthread+0xf2/0x120 ret_from_fork+0x47/0x70 ret_from_fork_asm+0x1b/0x30 </TASK> ``` Later consequences seen on 6.8.0-146 (same machine, 2026-10-05 and 2026-10-06): `BUG: unable to handle page fault` in `kmalloc_trace` (comm kioslave5, then kscreenlocker_greet), `free_large_kmalloc` / `__kmalloc` oops from `cifs_get_fattr` (comm rsync), followed by a hard freeze with the journal cut off. ### Root cause Comparing `net/l2tp/l2tp_ppp.c` between the Ubuntu-6.8.0-142.142 and Ubuntu-6.8.0-146.146 tags (https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/noble), the only change is the backport of l2tp: pppol2tp: hold reference to session in pppol2tp_ioctl() (CVE-2026-53262) The upstream fix targets 6.12+, where `pppol2tp_sock_to_session()` takes a reference on the *session* and callers drop it with `l2tp_session_put()`. In 6.8, `pppol2tp_sock_to_session()` is different: it takes a reference on the *socket* (`sock_hold(sk)`) and takes none on the session: ```c static inline struct l2tp_session *pppol2tp_sock_to_session(struct sock *sk) { ... sock_hold(sk); session = (struct l2tp_session *)(sk->sk_user_data); if (!session) { sock_put(sk); goto out; } ... } ``` Every other caller in 6.8 (`pppol2tp_recvmsg`, `pppol2tp_sendmsg`, `pppol2tp_release`, `pppol2tp_setsockopt`, `pppol2tp_getsockopt`) accordingly releases it with `sock_put(sk)`. The backported `pppol2tp_ioctl()` instead does: ```c session = pppol2tp_sock_to_session(sock->sk); /* sock_hold() only */ ... if (session) l2tp_session_dec_refcount(session); /* drops a session ref it never took */ return err; ``` (In 6.8.0-149 the helper is renamed to `l2tp_session_put()`; the logic is unchanged.) The `-EBADF` path has the same mismatch. Result: every `pppol2tp_ioctl()` call decrements the session refcount by one without a matching increment, and leaks one socket reference. pppd issues ioctls on the pppol2tp socket right after connect (`PPPIOCGL2TPSTATS` etc.), so the session refcount drops to zero while the session is still in the tunnel's session hash. The next incoming L2TP data packet looks it up via `l2tp_tunnel_get_session()`, which uses plain `refcount_inc()`, producing `addition on 0` and a use-after-free. This matches the observed deterministic ~1 s delay (first inbound L2TP packet after the PPP ioctls) and the fact that 142 (no such code) is clean while 146/147/149 (same ioctl logic) all fail. ### Proposed fix In `pppol2tp_ioctl()`, release what was taken: replace both `l2tp_session_dec_refcount(session)` (149: `l2tp_session_put(session)`) calls with `sock_put(sock->sk)`, matching the other callers of `pppol2tp_sock_to_session()` in 6.8. Alternatively, backport the 6.11+ change that makes `pppol2tp_sock_to_session()` take a session reference (and convert all callers), but the one-line `sock_put` change is the minimal correct fix for this branch. The same mismatch should be checked in the other Ubuntu kernels that received this CVE backport on a pre-6.11 `pppol2tp_sock_to_session()` (e.g. 6.8 HWE kernels, jammy 5.15 if applicable). ### Workaround Boot 6.8.0-142 (pinned via GRUB_DEFAULT), or avoid L2TP VPN on affected kernels. (Attachments: full dmesg from 6.8.0-149 after VPN connect, and the 142->146 diff of pppol2tp_ioctl(), will be added after filing.) To manage notifications about this bug go to: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2173669/+subscriptions

Комментариев нет:

Отправить комментарий