CVE-2025-21865 in Linuxinfo

Summary

by MITRE • 03/12/2025

In the Linux kernel, the following vulnerability has been resolved:

gtp: Suppress list corruption splat in gtp_net_exit_batch_rtnl().

Brad Spengler reported the list_del() corruption splat in gtp_net_exit_batch_rtnl(). [0]

Commit eb28fd76c0a0 ("gtp: Destroy device along with udp socket's netns dismantle.") added the for_each_netdev() loop in gtp_net_exit_batch_rtnl() to destroy devices in each netns as done in geneve and ip tunnels.

However, this could trigger ->dellink() twice for the same device during ->exit_batch_rtnl().

Say we have two netns A & B and gtp device B that resides in netns B but whose UDP socket is in netns A.

1. cleanup_net() processes netns A and then B.

2. gtp_net_exit_batch_rtnl() finds the device B while iterating netns A's gn->gtp_dev_list and calls ->dellink().

[ device B is not yet unlinked from netns B
as unregister_netdevice_many() has not been called. ]

3. gtp_net_exit_batch_rtnl() finds the device B while iterating netns B's for_each_netdev() and calls ->dellink().

gtp_dellink() cleans up the device's hash table, unlinks the dev from gn->gtp_dev_list, and calls unregister_netdevice_queue().

Basically, calling gtp_dellink() multiple times is fine unless CONFIG_DEBUG_LIST is enabled.

Let's remove for_each_netdev() in gtp_net_exit_batch_rtnl() and delegate the destruction to default_device_exit_batch() as done in bareudp.

[0]:
list_del corruption, ffff8880aaa62c00->next (autoslab_size_M_dev_P_net_core_dev_11127_8_1328_8_S_4096_A_64_n_139+0xc00/0x1000 [slab object]) is LIST_POISON1 (ffffffffffffff02) (prev is 0xffffffffffffff04)
kernel BUG at lib/list_debug.c:58! Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN
CPU: 1 UID: 0 PID: 1804 Comm: kworker/u8:7 Tainted: G T 6.12.13-grsec-full-20250211091339 #1 Tainted: [T]=RANDSTRUCT
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 Workqueue: netns cleanup_net RIP: 0010:[] __list_del_entry_valid_or_report+0x141/0x200 lib/list_debug.c:58
Code: c2 76 91 31 c0 e8 9f b1 f7 fc 0f 0b 4d 89 f0 48 c7 c1 02 ff ff ff 48 89 ea 48 89 ee 48 c7 c7 e0 c2 76 91 31 c0 e8 7f b1 f7 fc 0b 4d 89 e8 48 c7 c1 04 ff ff ff 48 89 ea 48 89 ee 48 c7 c7 60 RSP: 0018:fffffe8040b4fbd0 EFLAGS: 00010283 RAX: 00000000000000cc RBX: dffffc0000000000 RCX: ffffffff818c4054 RDX: ffffffff84947381 RSI: ffffffff818d1512 RDI: 0000000000000000 RBP: ffff8880aaa62c00 R08: 0000000000000001 R09: fffffbd008169f32 R10: fffffe8040b4f997 R11: 0000000000000001 R12: a1988d84f24943e4 R13: ffffffffffffff02 R14: ffffffffffffff04 R15: ffff8880aaa62c08 RBX: kasan shadow of 0x0 RCX: __wake_up_klogd.part.0+0x74/0xe0 kernel/printk/printk.c:4554 RDX: __list_del_entry_valid_or_report+0x141/0x200 lib/list_debug.c:58 RSI: vprintk+0x72/0x100 kernel/printk/printk_safe.c:71 RBP: autoslab_size_M_dev_P_net_core_dev_11127_8_1328_8_S_4096_A_64_n_139+0xc00/0x1000 [slab object]
RSP: process kstack fffffe8040b4fbd0+0x7bd0/0x8000 [kworker/u8:7+netns 1804 ]
R09: kasan shadow of process kstack fffffe8040b4f990+0x7990/0x8000 [kworker/u8:7+netns 1804 ]
R10: process kstack fffffe8040b4f997+0x7997/0x8000 [kworker/u8:7+netns 1804 ]
R15: autoslab_size_M_dev_P_net_core_dev_11127_8_1328_8_S_4096_A_64_n_139+0xc08/0x1000 [slab object]
FS: 0000000000000000(0000) GS:ffff888116000000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000748f5372c000 CR3: 0000000015408000 CR4: 00000000003406f0 shadow CR4: 00000000003406f0 Stack: 0000000000000000 ffffffff8a0c35e7 ffffffff8a0c3603 ffff8880aaa62c00 ffff8880aaa62c00 0000000000000004 ffff88811145311c 0000000000000005 0000000000000001 ffff8880aaa62000 fffffe8040b4fd40 ffffffff8a0c360d Call Trace: [] __list_del_entry_valid include/linux/list.h:131 [inline] fffffe8040b4fc28
[] __list_del_entry include/linux/list.h:248 [inline] fffffe8040b4fc28
[] list_del include/linux/list.h:262 [inl
---truncated---

Once again VulDB remains the best source for vulnerability data.

Analysis

by VulDB Data Team • 12/14/2025

The vulnerability CVE-2025-21865 resides within the Linux kernel's GTP (GPRS Tunneling Protocol) implementation, specifically in the `gtp_net_exit_batch_rtnl()` function. This flaw manifests as a list corruption splat, triggered when the function attempts to delete the same network device multiple times during the cleanup of network namespaces. The issue was introduced by commit eb28fd76c0a0, which added a `for_each_netdev()` loop to destroy GTP devices within each network namespace during the `exit_batch_rtnl()` process. This modification was intended to align GTP behavior with that of Geneve and IP tunnels, but it inadvertently caused a double deletion scenario when network devices span across different namespaces.

Brad Spengler identified the root cause of this issue, which lies in the interaction between network namespace cleanup and device destruction. When the kernel processes network namespace cleanup, it iterates through each namespace and calls `gtp_net_exit_batch_rtnl()`. In certain configurations, particularly when a GTP device resides in one namespace while its underlying UDP socket is in another, the function ends up calling `->dellink()` on the same device more than once. The first call removes the device from the global list and initiates its unregistration, but the second call, triggered by the `for_each_netdev()` loop iterating over a different namespace, attempts to operate on an already partially or fully unregistered device. This leads to corruption of the linked list structure, especially when `CONFIG_DEBUG_LIST` is enabled, resulting in a kernel panic and invalid opcode error.

The technical implications of this vulnerability are severe, particularly in environments where network namespaces are heavily utilized and GTP devices are configured across multiple namespaces. The kernel crash occurs due to a corrupted linked list entry, with the error message indicating that `list_del` has encountered an invalid list state. The stack trace reveals that the error originates in `lib/list_debug.c`, specifically in the `__list_del_entry_valid_or_report` function, which is part of the kernel's debugging infrastructure designed to detect list corruption. This behavior is consistent with CWE-1174, which addresses improper handling of list structures in kernel code. The vulnerability can be exploited in scenarios where an attacker has control over network namespace creation and GTP device configuration, potentially leading to denial of service or system instability.

Mitigation of this vulnerability requires modifying the `gtp_net_exit_batch_rtnl()` function to avoid the double deletion scenario. The recommended fix involves removing the `for_each_netdev()` loop from the function and delegating device destruction to the standard `default_device_exit_batch()` function, as is done in similar implementations like BareUDP. This approach ensures that each device is properly handled only once during namespace cleanup, eliminating the possibility of list corruption. The fix aligns with ATT&CK technique T1499.004, which involves maintaining persistence through kernel-level modifications, by ensuring that kernel subsystems properly handle resource cleanup without introducing corruption. Organizations should update their kernel versions to include the patch that resolves this issue, as it directly impacts the stability and reliability of systems using GTP networking capabilities.

Responsible

Linux

Reservation

12/29/2024

Disclosure

03/12/2025

Moderation

accepted

CPE

ready

EPSS

0.00012

KEV

no

Activities

very low

Sources

Do you know our Splunk app?

Download it now for free!