[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Locally exploitable races in OpenBSD VFS (fwd)



The relevant people have probably seen it, but is there a fix?

: -----Original Message-----
: From: Alexander Viro [mailto:viro@math.psu.edu]
: Sent: Saturday, June 02, 2001 7:00 PM
: To: BUGTRAQ@SECURITYFOCUS.COM
: Subject: Locally exploitable races in OpenBSD VFS
: 
: 
: [my apologies if it ends up submitted twice]
: Let's start with the trivial: good old aliasing bugs.
: 
: Example 1:
: dup2() vs. close(). Relevant file: kern/kern_descrip.c
: 
: sys_dup2(p, v, retval)
:         struct proc *p;
:         void *v;
:         register_t *retval;
: {
: [snip]
:         if ((u_int)old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL ||
:             (u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
:             (u_int)new >= maxfiles)
:                 return (EBADF);
: OK, we've checked (among other things) that old is indeed opened.
: [snip]
:         if (new >= fdp->fd_nfiles) {
: We either expand a descriptor table
: [snip]
:         } else {
: Or reuse existing descriptor, closing file if it's opened.
:                 (void) fdrelease(p, new);
: Which is the blocking operation, BTW.
:         }
:         return (finishdup(fdp, old, new, retval));
: }
: [snip]
: finishdup(fdp, old, new, retval)
:         register struct filedesc *fdp;
:         register int old, new;
:         register_t *retval;
: {
:         register struct file *fp;
: 
:         fp = fdp->fd_ofiles[old];
: Got the struct sile of the file we are trying to dup...
:         if (fp->f_count == LONG_MAX-2)
: ... and dereference it. We had checked that it's non-NULL, right?
: 
: Wrong. Another thread might be sharing our descriptor table (man rfork).
: IOW, fdp points to shared data structure. So we had done the equivalent of
: 
: 	if (global_var) {
: 		blocking_call();
: 		if (global_var->f_count)
: 			...
: 	}
: 
: Sloppy? Yes, and way beyond that. We have a nice shiny race between
: dup2(0,1); and close(0). And it's a wide one. Turning that into
: full-blown exploit is left as an exercise for readers.
: 
: Example 2:
: pipe() vs. close() (kern/sys_pipe.c)
: 
: sys_opipe(p, v, retval)
: [snip]
:         error = falloc(p, &rf, &fd);
:         if (error)
:                 goto free2;
: [snip]
:         retval[0] = fd;
: 
:         error = falloc(p, &wf, &fd);
:         if (error)
:                 goto free3;
: [snip]
:         return (0);
: free3:
:         ffree(rf);
:         fdremove(fdp, retval[0]);
: free2:
: [snip]
: 
: 	Think what happens if the second allocation fails.  It is a
: blocking call. During that time another thread had a nice possibility
: to call close(retval[0]); since that value is very easy to predict -
: it's the first available file descriptor. close() would
: 	* remove pointer from fdp[retval[0]]
: 	* call ffree() on it.
: Now, we come back and do _another_ ffree() on the poor beast. Welcome to
: kernel panic...
: 
: 	Code is equivalent to
: 
: 	global_var = p = alloc_foo();
: 	blocking_call();
: 	release_foo(p);
: 	global_var = NULL;
: 
: It's not just sloppy. It's obviously broken - obviously for anyone with
: half of clue.
: 
: I can easily provide more examples of the same crap and so can anyone
: who would bother to RTFS the descriptor handling in kern/*. Apparently
: that had never happened during the last 5 years or so.
: 
: I'm not talking about the bugs that would require anything nontrivial to
: find and understand. Just follow the yello^Wpiles of sloppy C and nearly
: every one will turn out to be exploitable. And no, it's not limited to
: descriptor handling - same goes for sys_pipe.c, etc.
: 
: Theo had been informed about that crap. Couple of weeks ago. Finding and
: fixing these bugs is a simple matter of grep. So far it hadn't been done.
: I've proposed to help with that, but apparently it got no interest. <shrug> 
: Very well, there are other piles of garbage in need of fixing and seeing
: crappy code in obscure Linux drivers is less disturbing than that in core
: kernel.
: 
: Frankly. my respect to Theo went way down. This code had never been read
: through, let alone audited. And that's the core kernel. Moreover, the
: same bugs had been fixed in FreeBSD half a year ago. In other words, just
: keeping an eye on other *BSD trees would be enough to catch them. Same
: for lurking on freebsd-hackers. Same for watching the Linux tree, where
: an audit of relevant areas had been done nearly two years ago. Done and
: discussed on linux-kernel. Sad...
: 
: #include <stdrants/people_dont_bother_to_RTFS.h>
: 
: -- 
: "You're one of those condescending Unix computer users!"
: "Here's a nickel, kid.  Get yourself a better computer" - Dilbert.
: