This Old Vulnerability: rfork

Thomas Ptacek | May 17th, 2006 | Filed Under: This Old Vulnerability

It’s a dark and stormy night. Theo relaxes contentedly in the basement. Idly polishes a cherished stack of Sun IPX’s. Pauses now and again to berate his developers on ICB.

He has reason to be smug. His team has just finished an audit of the OpenBSD userland code, establishing for a glorious ten days a factual basis for OpenBSD’s security boasts and a role for Theo as a lanky, cave-dwelling Sun King of open source security. In some cases, his auditors didn’t even use ‘grep’ to find their stack overflows, meticulously scanning loops by hand to root out vulnerabilities. Such is OpenBSD’s greatness during this eternally memorable age.

Devil’s work. Idle hands. Theo picks up a project. OpenBSD doesn’t have kernel threads. Theo doesn’t like threads. Plan9 has an alternative: true lightweight processes. You fork them like normal processes, but they can share memory and file descriptors. You create them with the rfork system call.

Time passes. A year almost to the day. Champion competitive cup-stacker Danny Dulai (credo: “People with 1 tongue have no idea what they are missing”) is poking around at OpenBSD. “Isn’t this a security problem, Theo? Theo? Wake up, Theo. Here, have some free SCSI cards.” Free hardware… Theo rouses from a malarial stupor.

Panic. Commotion. An advisory. It is a problem: rfork conflicts with the Unix security model. It gives parent processes control over SUID child processes. A user runs “passwd”, which assumes superuser creds to edit the password database. But passwd is working with the user’s descriptor table, not its own, and as it opens sensitive files, it’s handing them directly to the user. The kernel checks access at open(), not on “read()” or “write()”.

The patch is easy (don’t honor SUID when exec is called on a process that shares a descriptor table). So easy that Linux had it from the start. A strange anomaly. The Sun King has introduced a vulnerability into OpenBSD. It will never happen again. Rfork goes on to be such an important part of the BSD API that calamity ensues when the most popular BSD fails to officially include it.

Years later, FreeBSD manages to snatch defeat from the jaws of not working with Theo. Georgi Guninski, of the one legitimate qmail finding, notices that FreeBSD has added functionality to rfork; with RFSIGSHARE, FreeBSD rfork also shares signal handlers with the child process. User aims SIGINT handler into the environment. Populates the environment with shellcode. Runs “passwd”, RFSIGSHARE. Delivers SIGINT. “passwd”, running as root, with the inherited poisoned SIGINT handler, diverts control to the user’s code. Somewhere in the celestial clouds, an angel chokes, clutches its throat, breathes its last, and expires.

2 Comments so far

  • Jason Haley

    May 18th, 2006 4:14 pm

    Interesting Finds: May 18, 2006 PM edition

  • Dr. Strangelove

    May 19th, 2006 10:43 am

    Superfluous comment about how much Nirva rules.

  • Leave a reply