In the Linux kernel, the following vulnerability has been resolved:
uprobe: avoid out-of-bounds memory access of fetching args
Uprobe needs to fetch args into a percpu buffer, and then copy to ring buffer to avoid non-atomic context problem.
Sometimes user-space strings, arrays can be very large, but the size of percpu buffer is only page size. And storetraceargs() won't check whether these data exceeds a single page or not, caused out-of-bounds memory access.
It could be reproduced by following steps: 1. build kernel with CONFIG_KASAN enabled 2. save follow program as test.c
\#include <stdio.h>
\#include <stdlib.h>
\#include <string.h>
// If string length large than MAX_STRING_SIZE, the fetch_store_strlen()
// will return 0, cause __get_data_size() return shorter size, and
// store_trace_args() will not trigger out-of-bounds access.
// So make string length less than 4096.
\#define STRLEN 4093
void generate_string(char *str, int n)
{
int i;
for (i = 0; i < n; ++i)
{
char c = i % 26 + 'a';
str[i] = c;
}
str[n-1] = '\0';
}
void print_string(char *str)
{
printf("%s\n", str);
}
int main()
{
char tmp[STRLEN];
generate_string(tmp, STRLEN);
print_string(tmp);
return 0;
}
3. compile program
gcc -o test test.c
get the offset of print_string()
objdump -t test | grep -w print_string
0000000000401199 g F .text 000000000000001b print_string
configure uprobe with offset 0x1199
off=0x1199
cd /sys/kernel/debug/tracing/
echo "p /root/test:${off} arg1=+0(%di):ustring arg2=\$comm arg3=+0(%di):ustring"
> uprobe_events
echo 1 > events/uprobes/enable
echo 1 > tracing_on
test
, and kasan will report error.BUG: KASAN: use-after-free in strncpyfromuser+0x1d6/0x1f0 Write of size 8 at addr ffff88812311c004 by task test/499CPU: 0 UID: 0 PID: 499 Comm: test Not tainted 6.12.0-rc3+ #18 Hardware name: Red Hat KVM, BIOS 1.16.0-4.al8 04/01/2014 Call Trace: <TASK> dumpstacklvl+0x55/0x70 printaddressdescription.constprop.0+0x27/0x310 kasanreport+0x10f/0x120 ? strncpyfromuser+0x1d6/0x1f0 strncpyfromuser+0x1d6/0x1f0 ? rmqueue.constprop.0+0x70d/0x2ad0 processfetchinsn+0xb26/0x1470 ? pfxprocessfetchinsn+0x10/0x10 ? rawspinlock+0x85/0xe0 ? _pfxrawspinlock+0x10/0x10 ? pteoffsetmap+0x1f/0x2d0 ? unwindnextframe+0xc5f/0x1f80 ? archstackwalk+0x68/0xf0 ? isbpftextaddress+0x23/0x30 ? kerneltextaddress.part.0+0xbb/0xd0 ? _kerneltextaddress+0x66/0xb0 ? unwindgetreturnaddress+0x5e/0xa0 ? _pfxstacktraceconsumeentry+0x10/0x10 ? archstackwalk+0xa2/0xf0 ? rawspinlockirqsave+0x8b/0xf0 ? _pfxrawspinlockirqsave+0x10/0x10 ? depotallocstack+0x4c/0x1f0 ? rawspinunlockirqrestore+0xe/0x30 ? stackdepotsaveflags+0x35d/0x4f0 ? kasansavestack+0x34/0x50 ? kasansavestack+0x24/0x50 ? mutexlock+0x91/0xe0 ? _pfxmutexlock+0x10/0x10 prepareuprobebuffer.part.0+0x2cd/0x500 uprobedispatcher+0x2c3/0x6a0 ? _pfxuprobedispatcher+0x10/0x10 ? _kasanslaballoc+0x4d/0x90 handlerchain+0xdd/0x3e0 handleswbp+0x26e/0x3d0 ? _pfxhandleswbp+0x10/0x10 ? uprobepresstepnotifier+0x151/0x1b0 irqentryexittousermode+0xe2/0x1b0 asmexcint3+0x39/0x40 RIP: 0033:0x401199 Code: 01 c2 0f b6 45 fb 88 02 83 45 fc 01 8b 45 fc 3b 45 e4 7c b7 8b 45 e4 48 98 48 8d 50 ff 48 8b 45 e8 48 01 d0 ce RSP: 002b:00007ffdf00576a8 EFLAGS: 00000206 RAX: 00007ffdf00576b0 RBX: 0000000000000000 RCX: 0000000000000ff2 RDX: 0000000000000ffc RSI: 0000000000000ffd RDI: 00007ffdf00576b0 RBP: 00007ffdf00586b0 R08: 00007feb2f9c0d20 R09: 00007feb2f9c0d20 R10: 0000000000000001 R11: 0000000000000202 R12: 0000000000401040 R13: 00007ffdf0058780 R14: 0000000000000000 R15: 0000000000000000 </TASK>
This commit enforces the buffer's maxlen less than a page-size to avoid storetraceargs() out-of-memory access.
[ { "signature_type": "Function", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@537ad4a431f6dddbf15d40d19f24bb9ee12b55cb", "signature_version": "v1", "target": { "function": "__uprobe_trace_func", "file": "kernel/trace/trace_uprobe.c" }, "digest": { "function_hash": "27302323144367855271033363563375145789", "length": 769.0 }, "id": "CVE-2024-50067-0116249b" }, { "signature_type": "Line", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@537ad4a431f6dddbf15d40d19f24bb9ee12b55cb", "signature_version": "v1", "target": { "file": "kernel/trace/trace_uprobe.c" }, "digest": { "threshold": 0.9, "line_hashes": [ "92111086946447022634393152575276438994", "74383563922761751523850004868591208180", "224979849509588407617076433106983621703", "219607946923543716843843315411661021582", "76849864170651057749405794620238366031", "4360441700087789089619839391582184690", "310880648556049005015979021636985330772", "86473756322200325370578996454381465118", "295057230181597726708757657823462156831", "225773687411582221200009645635901411428", "195384002515595507062049224485000767136", "295691636132663805820677546360265904073" ] }, "id": "CVE-2024-50067-01d82d7a" }, { "signature_type": "Function", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@537ad4a431f6dddbf15d40d19f24bb9ee12b55cb", "signature_version": "v1", "target": { "function": "prepare_uprobe_buffer", "file": "kernel/trace/trace_uprobe.c" }, "digest": { "function_hash": "189724494263727528948143549144441385665", "length": 392.0 }, "id": "CVE-2024-50067-079e8a92" }, { "signature_type": "Line", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@373b9338c9722a368925d83bc622c596896b328e", "signature_version": "v1", "target": { "file": "kernel/trace/trace_uprobe.c" }, "digest": { "threshold": 0.9, "line_hashes": [ "92111086946447022634393152575276438994", "74383563922761751523850004868591208180", "224979849509588407617076433106983621703", "219607946923543716843843315411661021582", "76849864170651057749405794620238366031", "4360441700087789089619839391582184690", "310880648556049005015979021636985330772", "86473756322200325370578996454381465118", "295057230181597726708757657823462156831", "225773687411582221200009645635901411428", "195384002515595507062049224485000767136", "295691636132663805820677546360265904073" ] }, "id": "CVE-2024-50067-0da107f6" }, { "signature_type": "Function", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@0dc3ad9ad2188da7f090b3dbe4d2fcd9ae8ae64f", "signature_version": "v1", "target": { "function": "prepare_uprobe_buffer", "file": "kernel/trace/trace_uprobe.c" }, "digest": { "function_hash": "330020652946098944528964300653603481672", "length": 312.0 }, "id": "CVE-2024-50067-40286203" }, { "signature_type": "Line", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@0dc3ad9ad2188da7f090b3dbe4d2fcd9ae8ae64f", "signature_version": "v1", "target": { "file": "kernel/trace/trace_uprobe.c" }, "digest": { "threshold": 0.9, "line_hashes": [ "92111086946447022634393152575276438994", "74383563922761751523850004868591208180", "224979849509588407617076433106983621703", "219607946923543716843843315411661021582", "305243177611035178269110676192179338957", "58921715925234112491211832380941014456", "214645549357418078969239788164047941782", "86473756322200325370578996454381465118", "295057230181597726708757657823462156831", "225773687411582221200009645635901411428", "195384002515595507062049224485000767136", "295691636132663805820677546360265904073" ] }, "id": "CVE-2024-50067-5efc19ba" }, { "signature_type": "Function", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@373b9338c9722a368925d83bc622c596896b328e", "signature_version": "v1", "target": { "function": "prepare_uprobe_buffer", "file": "kernel/trace/trace_uprobe.c" }, "digest": { "function_hash": "189724494263727528948143549144441385665", "length": 392.0 }, "id": "CVE-2024-50067-725b6f07" }, { "signature_type": "Function", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@373b9338c9722a368925d83bc622c596896b328e", "signature_version": "v1", "target": { "function": "__uprobe_trace_func", "file": "kernel/trace/trace_uprobe.c" }, "digest": { "function_hash": "27302323144367855271033363563375145789", "length": 769.0 }, "id": "CVE-2024-50067-762fc9a8" }, { "signature_type": "Line", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@9e5f93788c9dd4309e75a56860a1ac44a8e117b9", "signature_version": "v1", "target": { "file": "kernel/trace/trace_uprobe.c" }, "digest": { "threshold": 0.9, "line_hashes": [ "92111086946447022634393152575276438994", "74383563922761751523850004868591208180", "224979849509588407617076433106983621703", "219607946923543716843843315411661021582", "76849864170651057749405794620238366031", "4360441700087789089619839391582184690", "310880648556049005015979021636985330772", "86473756322200325370578996454381465118", "295057230181597726708757657823462156831", "225773687411582221200009645635901411428", "195384002515595507062049224485000767136", "295691636132663805820677546360265904073" ] }, "id": "CVE-2024-50067-992e8e4d" }, { "signature_type": "Function", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@9e5f93788c9dd4309e75a56860a1ac44a8e117b9", "signature_version": "v1", "target": { "function": "prepare_uprobe_buffer", "file": "kernel/trace/trace_uprobe.c" }, "digest": { "function_hash": "189724494263727528948143549144441385665", "length": 392.0 }, "id": "CVE-2024-50067-a3ce653f" }, { "signature_type": "Function", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@9e5f93788c9dd4309e75a56860a1ac44a8e117b9", "signature_version": "v1", "target": { "function": "__uprobe_trace_func", "file": "kernel/trace/trace_uprobe.c" }, "digest": { "function_hash": "27302323144367855271033363563375145789", "length": 769.0 }, "id": "CVE-2024-50067-d13ea9a0" }, { "signature_type": "Function", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@0dc3ad9ad2188da7f090b3dbe4d2fcd9ae8ae64f", "signature_version": "v1", "target": { "function": "__uprobe_trace_func", "file": "kernel/trace/trace_uprobe.c" }, "digest": { "function_hash": "27302323144367855271033363563375145789", "length": 769.0 }, "id": "CVE-2024-50067-d7610c86" } ]