In early 2021, a significant security issue was found and fixed in the Linux kernel’s SCTP (Stream Control Transmission Protocol) subsystem. This vulnerability, now referenced as CVE-2021-46929, involved a use-after-free bug that could lead to kernel panics or possibly privilege escalation attacks. Let's break down what happened, how it was discovered, how it was fixed, and how you could exploit or protect against this bug.

What is SCTP and Where’s the Problem?

SCTP is a transport-layer protocol (like TCP/UDP) used for message-oriented communication in applications such as telephony over IP networks.

The heart of the problem was in how SCTP handled the freeing of its endpoint structures (ep). Here’s a simple explanation:

The kernel code was freeing endpoint memory *immediately* after it was no longer needed.

- But, elsewhere in the code (like during diagnostic dumps or traversals), another part of the kernel might still be using a pointer to the now-freed structure.
- If this happens, it’s called a use-after-free bug, which is dangerous: using a pointer to freed memory can crash the system, leak sensitive data, or—worst of all—be exploited for code execution.

How Was It Detected?

This bug was caught thanks to KASAN (Kernel Address SANitizer), a tool that catches illegal memory use. A sample detected crash looked like this:

BUG: KASAN: use-after-free in __lock_acquire+x36d9/x4c20
Call Trace:
  ...
  sctp_sock_dump+x122/xb20 net/sctp/diag.c:324
  sctp_for_each_transport+x2b5/x370 net/sctp/socket.c:5091
  ...

In simple terms, after a structure (sk, a socket pointer) was freed, its memory was still being accessed during a diagnostic operation. This happened because of a tricky sequence where an SCTP association was "peeled off" to a new socket, and the old one was freed—but another thread still tried to lock and access it.

Vulnerability Details and Exploit Possibilities

Let’s explain how an attacker *could* exploit this in an environment where unprivileged users can interact with SCTP sockets:

1. Create an SCTP association and manipulate it so that the kernel "peels off" the association (moves it from one socket to another).
2. Trigger concurrent diagnostic operations (via netlink, with tools like ss or custom netlink requests) to force the kernel to traverse or dump transporter states at the same time.
3. Race the kernel so that the diagnostic traversal grabs the freed pointer just after the original one is released.
4. If attackers are lucky (or skillful with timing), they could get use-after-free memory corruption—which, with further exploitation techniques, could lead to code execution in kernel space.

*Note: As of the patch date, there is no known public exploit, but the primitive is powerful.*

The Patch: Delayed Free with call_rcu()

The key fix was to not free the endpoint right away. Instead, the kernel now uses call_rcu(), which schedules the memory to be freed only *after* all other kernel code that might be using it is done. This solves the problem.

Before the Patch

(Freeing endpoint immediately)

// Potentially unsafe!
kfree(ep);

After the Patch

(Delaying free with RCU, so it's only freed after it's safe)

// Safely free endpoint after all readers are done
call_rcu(&ep->rcu, sctp_endpoint_destroy_rcu);

...

static void sctp_endpoint_destroy_rcu(struct rcu_head *head) {
    struct sctp_endpoint *ep = container_of(head, struct sctp_endpoint, rcu);
    // Now it's safe to actually free
    kfree(ep);
}

Additionally, the code now checks the endpoint’s validity before accessing it, and skips it if it might have disappeared.

The original patch and discussion:

- Linux mainline kernel commit
- Red Hat security details for CVE-2021-46929

Linux kernel SCTP subsystem source:

- net/sctp/diag.c

What is RCU?

- RCU: Read-Copy-Update for Linux kernel developers

Protecting Yourself

- Update your kernel: Make sure you are running a kernel version with this patch applied (5.12+ or with backport).
- Limit unprivileged SCTP access: Untrusted users should not be able to open raw SCTP sockets unless necessary.
- Keep system tools up-to-date: Tools like ss, netstat, or custom SCTP tools should be run only by trusted users.

Conclusion

The CVE-2021-46929 bug in Linux’s SCTP handling is an excellent example of how tricky memory management and concurrency in kernel space can trigger critical vulnerabilities. The move to use call_rcu() for delayed memory freeing highlights how kernel developers prevent use-after-free bugs in multi-threaded contexts. If you run any production systems with SCTP enabled, patch now!

If you want to learn more, dive into links above or check out the Linux Kernel Mailing List.

Timeline

Published on: 02/27/2024 10:15:07 UTC
Last modified on: 04/10/2024 17:05:51 UTC