The linux beep utility is a small utility command to literally send a tone to the user’s speaker. A subtle error in the utility gives arise to a local privilege escalation that was recently reported as CVE-2018-0492. It’s important to note that security vulnerabilities can exist even in small pieces of code (249 LOC in this case) and remain undetected for a long time. In this case, the vulnerability is a privilege escalation which is made possible when the beep utility is configured to run as setuid root.
The Anatomy of the Beep Vulnerability
The beep command is a straightforward utility, it parses some command line arguments and sends a command to the system function, ioctl(), to send a tone to the speaker. A signal handler is used to detect an interruption by the user and it’s within this signal handler a data race condition exists which allows for potential privilege escalation. It’s described in detail here but in summary, the race condition allows for an attacker to specify an arbitrary file during execution to which the beep will write. That file could be a symbolic link to any file, including sensitive system files. There is a proof of concept exploit here.What does CodeSonar Find?
The use of signal handlers in code needs to be thought through carefully. Programmers should understand that the handler code can be called at any time, including during the middle of another C statement. Thus the main program and the signal handler are similar to two separate concurrent threads of execution with arbitrary context switches from the main thread to the handler. Consequently, the program may have data races even if it is a single-threaded program. A data race is present when the “threads” access a shared variable where one of the accesses is a write, and there is no mechanism such as a lock or other form of synchronization on those accesses.
In the beep example, there is a data race on the shared variable
console_device. Let’s look at the output from CodeSonar when analyzing the beep source code:
CodeSonar has detected the data race in beep.c and indicates the start of thread 1 which is the main program thread. The second thread entry point is the signal handler code:
The data race is indicated in two places, in the signal handler as above and in the main program where the conflicting access to
console_device is detected.
CodeSonar was able to detect the main culprit in this vulnerability, as the data race on console_device. Despite being a small, seemingly innocuous utility, therein lies a fairly subtle flaw that can lead to a serious exploit. The good news is that advanced static analysis tools like GrammaTech CodeSonar are able to detect these issues early so they don’t make it into production and wide distribution.