153: Big int trouble
This week on BSDNow, we have a variety of news to discuss, covering quite the spectrum of BSD. (Including a new DragonFly release!).
This episode was brought to you by
/>

Headlines
- “The NCC Group report describes the bugs, but not the history of the code.”
- “Several of them, as reported by NCC, involved similar integer truncation issues. Actually, they involved very similar modern 64 bit code meeting classic 32 bit code”
- “The thrsleep system call is a part of the kernel code that supports threads. As the name implies, it gives userland a measure of control over scheduling and lets a thread sleep until something happens. As such, it takes a timeout in the form of a timespec. The kernel, however, internally implements time keeping using ticks (there are HZ, 100, ticks per second). The tsleep function (t is for timed) takes an int number of ticks and performs basic validation by checking that it’s not negative. A negative timeout would indicate that the caller has miscalculated. The kernel panics so you can fix the bug, instead of stalling forever.”
- “The trouble therefore is when userland is allowed to specify a timeout that could be negative. The existing code made an attempt to handle various tricks by converting the timespec to a ticks value stored as a 64 bit long long which was checked against INT_MAX before passing to sleep. Any value over INT_MAX would be truncated, so we can’t allow that. Instead, we saturate the value to INT_MAX. Unfortunately, this check didn’t account for the possibility that the tick conversion from the timespec could also overflow and result in a negative value.”
- Then there is the description of the kqueue flaw:
- “Every kqueue keeps a list of all the attached events it’s watching for. A simple array is used to store file events, indexed by fd.”
- “This array is scaled to accommodate the largest fd that needs to be stored. This would obviously cause trouble, consuming too much memory, if the identifier were not validated first. Which is exactly what kqueue tries to do. The fd_getfile function checks that the identifier is a file that the process has open. One wrinkle. fd_getfile takes an int argument but ident is a uintptr_t, possibly 64 bits. An ident of 232 + 2 will look like a valid file descriptor, but then cause the array to be resized to gargantuan proportions.”
- “Again, the fix is pretty simple. We must check that the ident is bounded by INT_MAX before calling fd_getfile. This bug likely would have been exploitable beyond a panic, but the array allocation was changed to use mallocarray instead of multiplying arguments by hand, thus preventing another overflow.”
- Then there is a description of the anonymous mmap flaw, and the “secret magic” __MAP_NOFAULT flag
***