Competing in Pwn2Own 2021 Austin: Icarus at the Zenith

We discussed this vulnerability during Episode 144 on 10 May 2022

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.