From owner-freebsd-security Wed Oct 22 23:38:59 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id XAA03083 for security-outgoing; Wed, 22 Oct 1997 23:38:59 -0700 (PDT) (envelope-from owner-freebsd-security) Received: from joshua.enteract.com (joshua.enteract.com [207.229.129.5]) by hub.freebsd.org (8.8.7/8.8.7) with SMTP id XAA03078 for ; Wed, 22 Oct 1997 23:38:47 -0700 (PDT) (envelope-from tqbf@joshua.enteract.com) From: tqbf@joshua.enteract.com Received: (qmail 19964 invoked by uid 1004); 23 Oct 1997 06:36:36 -0000 Date: 23 Oct 1997 06:36:36 -0000 Message-ID: <19971023063636.19963.qmail@joshua.enteract.com> To: dima@best.net, freebsd-security@freebsd.org Subject: Re: BoS: Possible SERIOUS bug in open()? (fwd) In-Reply-To: <199710230500.WAA11569@burka.rdy.com> Reply-To: tqbf@enteract.com Sender: owner-freebsd-security@freebsd.org X-Loop: FreeBSD.org Precedence: bulk In muc.lists.freebsd.security, you wrote: > fd = open("/dev/rsd0a", -1, 0); Yep. This definitely works on {Free,Net,Open}BSD. This is a variant of a bug Theo de Raadt found in SunOS back in the 1980s. The basic issue is that the code that guards access to the device-specific open() routine checks explicitly for FREAD, FWRITE, and O_TRUNC, and passes the call through if none of these are set. Theo's bug involved using "3" for the open() flag. The problem here is that before calls to open() are even passed to the vnode open() routine (after the vnode is looked up by the generic vfs_syscalls open() syscall handler), the flags field is incremented by one: vfs_syscalls.c:open() ... flags = FFLAGS(uap->flags); ... where FFLAGS() is: ./sys/fcntl.h:#define FFLAGS(oflags) ((oflags) + 1) As you can see, passing a "-1" to open() will result in "flags" becoming "0" - open() ordinarily never passes "0" to the vnode code, since "0" becomes "1" after being converted to fflags format. A fun game you can play with practically no programming ability is to exploit the fact that some devices will initialize themselves immediately upon being opened - particularly amusing is the SCSI tape driver, sys/scsi/st.c, which will rewind itself when opened. Simply run the previously posted example code on /dev/rst0 and destroy tonight's backup. If you want to hack this fixed in FreeBSD, you can apply the enclosed diff to your kernel; this is a total hack, and someone else will provide a "correct" fix soon enough. Incidentally, this is yet another piece of evidence supporting the presence of another systemic secure-coding problem - sanity checking integer arguments and guarding against overflow. This is far from the only place that I've seen problems with unexpected interactions owing to surprise negative arguments. Anyone want to take a guess as to what strncpy() does when it gets a negative "count" argument? Think that can't happen? Think pointer arithmetic. -- ----------------------------------------------------------------------------- Thomas H. Ptacek Secure Networks, Inc. ----------------------------------------------------------------------------- "mmm... sacrilicious..." --- vfs_syscalls.c-orig Thu Oct 23 01:21:58 1997 +++ vfs_syscalls.c Thu Oct 23 01:21:19 1997 @@ -690,6 +690,9 @@ return (error); fp = nfp; flags = FFLAGS(uap->flags); + if(!flags) + flags++; + cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); p->p_dupfd = -indx - 1; /* XXX check for fdopen */