Recently, we spoke about the difficulty of kernel programming; programmers must display absolute accuracy, as a single error or unchecked value could compromise a machine’s stability.
Because of this, kernel programmers rely on the documentation for the network stack they are attempting to implement, along with details of their target platform. If they do not read these details properly, critical issues can arise.
In this blog, Rootshell’s Head of Research and Development, Dr Neil Kettle, demonstrates one of the most curious examples of this: Apple’s almost-devastating software bug.
Apple’s vulnerability was the bug that never was; ‘never was’ because a developer bug in the code prevented the affected code from ever being executed, or even compiled, into the kernel. The vulnerability, if it were ever reachable, was a remote stack buffer overflow in the Apple Mac OS-X (as it was then) kernel. The network stack affected was Apple’s very own AppleTalk.
The affected code is given in below; the overflow is in the ‘GNIReply’ stack buffer.
The issue is due to the construction of the response to the getnetinfo request, which requests a list of zones known to the remote host from the remote system.
The vulnerability relies on the ability to fill the remote hosts zone table with entries remotely. To do this, we utilise spoofed zip replies. Since the AppleTalk stack has no means to identify zip replies to their corresponding request, all replies are parsed by hosts on the network, and the contents cached into the zone table.
The code to parse the zip replies is prefaced with the following:
So, why is this issue not a vulnerability? The code on line #1492 is the underlying reason. The cause of the problem is that ‘network_count’ will always have the value zero, if the underlying machine is little-endian; in other words, if the Mac is utilising an Intel CPU.
The following slide illustrates the value of the ‘network_count’ variable through the code on line #1482 as it occurs on a PowerPC (Apple Mac G3/4/5) machine:
The following is the same but, on the Intel x86 architecture:
On Intel (LE), the compiler constant folds ‘network_count’, as it can never be greater than zero, and thus compiles out the entire loop. We can never poison the zones list, and therefore never trigger the overflow.
In other words, Apple fixed a remote kernel bug by moving its hardware from PowerPC to Intel.
The bug could have been devastating for Apple, hurting anyone with a PowerPC on any network that any Mac was on, provided it was listening on the AppleTalk stack. It’s the first time we’ve ever seen a software bug fixed in hardware.
The original bug was presented at CanSec 2009. The AppleTalk stack was discontinued by Apple and thus removed from the Mac OS-X kernel shortly after the 2009 presentation. It serves as an important reminder to kernel developers to always try to match the protocol specification and read documentation in full to prevent potentially critical issues from occurring.