io_uring: __io_uaddr_map() handles multi-page region dangerously

We discussed this vulnerability during Episode 236 on 15 January 2024

The vulnerability in the __io_uaddr_map() function of the Linux kernel involves the incorrect handling of multi-page regions imported from userspace. This function is intended to map a physically contiguous region of memory from userspace into the kernel’s linear mapping area. While this is fairly deep into some of the kernel’s memory management the fundamental issue I think can be understood more generically.

  1. Incorrect Verification of Constrains. The intend is that only contiguous memory will be imported using this function. To enforce this is checks the pointer for the first and last memory pages to be imported to ensure they are equal. Assuming that if they are equal all the pages in the middle will be also, but this is a constraint easily violated by user-land memory.
  2. Misunderstand how compound pages are represented by the kernel. Without going too deep into the specifics here, there is a misunderstanding of what the expected/good case looks like for importing multiple contiguous pages. It expects as described in the first point that if it is contiguous then the page pointer will be the same (its expecting that the page will be one of the “super-pages” containing multiple pages, but in reality its returning normal pages, and each page gets its own pointer. Meaning it will reject actual cases of contiguous memory.

While these problems are specific to the kernel I think you can apply this to other targets just as a reminder to actually check your assumptions. Its very easy to read code and see the developer did in-fact write a check for something, but that doesn’t mean the check is actually correct.

The result of this is that in the io_uring code when working wiht this imported pages, because it expects it is contiguous memory it will access it by the address of the first page plus an offset that will go into the next pages. Allowing writes into adjacent, non-related memory even if the pages themselves are marked as read-only.