Competing in Pwn2Own 2021 Austin: Icarus at the Zenith
Two integer overflows discovered in the NetUSB.ko kernel module for doing USB over IP. Both were in the SoftwareBus_dispatchNormalEPMsgOut
function, which seems to be a dispatch routine of sorts for user-received data.
Bug 1 - mallocPageBuf() call int overflow
The first int overflow was in a call to mallocPageBuf()
for storing user-data. It would take a user-controllable length and add 9 to it (possibly for alignment). There was no checks on the length to ensure it wouldn’t overflow and wrap. mallocPageBuf()
used the buddy page allocator and not kmalloc caches, so it was a bit tricky to exploit. They attempted a strategy detailed by Andrey Konovalov to try to get the kmalloc-1024 cache to grab an adjacent page to their overflow page, but didn’t manage to make it work.
Bug 2 - kmalloc() call int overflow
The second overflow was in the handler code for opcode 0x50. Basically the same issue as the first one, when calling kmalloc()
they would take a received size and add 17 to it. This allowed them to overflow into the kmalloc-128 cache. With some tinkering, they discovered if they waited between the allocation and overflow, they would end up corrupting an “interesting structure” which contained a wait_queue_head_t
object (with a head.next
pointer). They didn’t really investigate what creates this object, but it seems to be somewhat consistent. From there, they were able to craft a fake wait_queue_entry
with a function pointer that lead to code execution.
Reliability was unfortunately a bit of an issue here, and combined with the fact an update shipped for TP-Link before pwn2own occurred, they weren’t able to reproduce it for pwn2own.