According to a report, the problem occurs because the 32-bit call emulation layer does not check whether the call is truly in the Syscall table. Ben Hawkes, who discovered the problem, says the vulnerability can be exploited to execute arbitrary code with kernel rights. An exploit (direct download of source code) is already in circulation; in a test conducted by The H’s associates at heise Security on 64-bit Ubuntu 10.04, it opened a shell with root rights.source
and the technical description tells us that it involves a missing register clear operation that was fixed once and then reintroduced.
All well and good, but this bug was patched in 22.214.171.124. They fixed the bug by reloading (and thus zero-extending) the original value of eax from the stack. But… strangely enough, in the LOAD_ARGS32 macro that was responsible for this reloading, I couldn’t actually see a specific reloading of eax anymore:
I showed this to my friend Robert Swiecki who had written an exploit for the original bug in 2007, and he immediately said something along the lines of “well this is interesting”. We pulled up his old exploit from 2007, and with a few minor modifications to the privilege escalation code, we had a root shell. So what happened to the patch for CVE-2007-4573? Unfortunately in early 2008 there was a regression that removed eax reloading from LOAD_ARGS32:
and then we look at the change that caused the problem to re-appear and we see two things.
This unifies and cleans up the syscall tracing code on i386 and x86_64.
Using a single function for entry and exit tracing on 32-bit made the
do_syscall_trace() into some terrible spaghetti. The logic is clear and
simple using separate syscall_trace_enter() and syscall_trace_leave()
functions as on 64-bit.
First, there is no regression testing. Sad. Second working code is changed to “clean it up”.