CVE-2023-52435 - Linux Kernel skb_segment() Vulnerability Explained With Exploit Example
On some Linux kernel versions, there existed a dangerous vulnerability in the network packet segmentation function, skb_segment(). Identified as CVE-2023-52435, this bug allowed a crafted network packet to trigger a _kernel panic_ or even gain _privileged access_. The root of the problem? An unchecked multiplication, which could overwrite an internal maximum and lead to memory corruption.
This post breaks down how the bug works, how it could be exploited, and how it was fixed, in simple language for sysadmins and security enthusiasts.
Technical Summary
- Affected Function: skb_segment() in net/core/skbuff.c
Kernel Version: Found in Linux 6.7.-rc4, may affect other versions
- Root Cause: No check when computing the new MSS (Maximum Segment Size). Specifically, mss = mss * partial_segs; can overflow to an invalid value, mistakenly matching a reserved value named GSO_BY_FRAGS.
- Crash Trigger: A network packet with carefully chosen settings can cause this overflow, resulting in a _General Protection Fault_ in the kernel.
Here’s a simplified code snippet where the vulnerability happened
// net/core/skbuff.c:~line 4551
mss = mss * partial_segs; // mss can be too high!
if (unlikely(mss >= GSO_BY_FRAGS))
return ERR_PTR(-EINVAL); // This guard was missing!
GSO_BY_FRAGS is a reserved value. If mss reaches it, the segmentation logic misbehaves, leading to memory corruption or kernel crashes.
Reference: The kernel patch discussion
How To Trigger The Crash
Google’s syzkaller fuzzer found this bug with a minimal network program. You can crash the kernel by sending a specially constructed UDP packet with settings that trigger the dangerous calculation.
Here’s a classic simplified “exploit” in C pseudocode
int s = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
char buf[4096];
// Fill buf with crafted packet (fields need careful setting)
struct sockaddr_ll sa = { ... }; // point to loopback, fill appropriately
sendto(s, buf, sizeof(buf), , (struct sockaddr *)&sa, sizeof(sa));
// This will cause skb_segment() to process the bad values and potentially crash the kernel!
You need to set the segment sizes and numbers so that mss * partial_segs == GSO_BY_FRAGS (commonly, 65535, details below).
This is exactly what syzkaller did. See the syzkaller crash report.
Kernel log excerpt
general protection fault, probably for non-canonical address xdffffc000000000e: 000 [#1] PREEMPT SMP KASAN
...
RIP: 001:skb_segment+x181d/x3f30 net/core/skbuff.c:4551
When this bug is triggered
- Kernel Panic: The kernel tries to access memory it shouldn’t, causing an immediate crash (DoS).
- Potential Privilege Escalation: Given the right conditions and more advanced exploitation, memory corruption could lead to running arbitrary code as root.
Triggerable Remotely: Attackers could potentially send malicious packets over the network.
- Unprivileged Users: If the attacker has the ability to make raw packet sockets (needs CAP_NET_RAW, but this is sometimes available on containers or misconfigured systems), they may cause local kernel panic.
Eric Dumazet submitted a small but crucial fix, basically adding a check
// net/core/skbuff.c, recent kernel, fixed version:
if (mss >= GSO_BY_FRAGS)
return ERR_PTR(-EINVAL); // Don't allow invalid MSS!
Commit Reference:
- net: prevent mss overflow in skb_segment() — Patch email
- Linux kernel mainline commit
Are You Vulnerable?
- If you run Linux kernel 6.7-rc4 or nearby versions _and_ allow users CAP_NET_RAW, you might be at risk.
Upgrade to a fixed kernel version.
- Pull in the kernel patches.
Exploit Details
Here’s what a minimal userland exploit _outline_ might look like, based on fuzzer output (do not use maliciously!):
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <netinet/if_ether.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main() {
int s = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
char buf[4096] = {}; // You need to craft the right packet here (not trivial)
struct sockaddr_ll sa = {};
sa.sll_family = AF_PACKET;
sa.sll_protocol = htons(ETH_P_IP);
sa.sll_ifindex = /* interface index, e.g., loopback */;
// You must fill buf and sa with correct crafted parameters.
// The goal: cause GSO to produce mss * partial_segs == 65535 (GSO_BY_FRAGS)
sendto(s, buf, sizeof(buf), , (struct sockaddr *)&sa, sizeof(sa));
close(s);
return ;
}
The exploit is _non-trivial_—you need to understand the kernel’s GSO (Generic Segmentation Offload) layout, which tools like syzkaller automate.
More Reading
- Bug tracker: syzkaller report
- Kernel patch & Discussion
- Linux commit fixing CVE-2023-52435
Summary
CVE-2023-52435 was a critical Linux kernel bug allowing attackers to crash the host via crafted packets, thanks to an unchecked math operation in skb_segment(). The bug is now fixed in the latest kernels, and everyone is urged to update as soon as possible.
If you run multi-user systems, clouds, or exposed Linux devices, patch immediately or at least restrict unprivileged raw socket access.
Timeline
Published on: 02/20/2024 20:15:08 UTC
Last modified on: 03/15/2024 14:06:17 UTC