From owner-freebsd-current Mon Mar 18 16:53:36 2002 Delivered-To: freebsd-current@freebsd.org Received: from elvis.mu.org (elvis.mu.org [192.203.228.196]) by hub.freebsd.org (Postfix) with ESMTP id 5233E37B400; Mon, 18 Mar 2002 16:53:26 -0800 (PST) Received: by elvis.mu.org (Postfix, from userid 1192) id BB448AE25C; Mon, 18 Mar 2002 16:53:25 -0800 (PST) Date: Mon, 18 Mar 2002 16:53:25 -0800 From: Alfred Perlstein To: Dag-Erling Smorgrav Cc: Kris Kennaway , current@freebsd.org, fs@freebsd.org Subject: Re: panic: bwrite: buffer is not busy??? Message-ID: <20020319005325.GA455@elvis.mu.org> References: <20020318061739.GB894@elvis.mu.org> <20020318071623.GD894@elvis.mu.org> <20020318010245.A48956@xor.obsecurity.org> <20020318143204.GA688@elvis.mu.org> <20020318223631.GA23014@elvis.mu.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.3.27i Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG * Dag-Erling Smorgrav [020318 15:03] wrote: > Alfred Perlstein writes: > > * Dag-Erling Smorgrav [020318 08:23] wrote: > > > Alfred Perlstein writes: > > > > I think you're right, I'm pretty sure the fix is basically moving > > > > the p->p_fd = NULL to after the closef will fix things [...] > > > There will still be a race... > > Are you sure? :) > > Almost, though I think the window will be much smaller than it is now. > The only way I see of avoiding it alltogether is to protect p->p_fd > and its mutex with allproc_lock (IOW, destroy the table as the last > thing you do before zombifying the process) Actually... if checkdirs wins the race for proc lock it will do its magic and fdfree will wait while it does that. if fdfree wins, then checkdirs will see a NULL p_fd pointer. > > Btw, is there a way to easily reproduce this bug? > > No, it's a race condition, which makes it hard to trigger on purpose. > > The problem with your patch is that *every* place in the kernel that > calls FILEDESC_LOCK needs to first acquire the proc lock and check if > p->p_fd is NULL. No, only when a sideways access occurs, like in checkdirs(). I think this ought to fix it. Index: kern/vfs_syscalls.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.231 diff -u -r1.231 vfs_syscalls.c --- kern/vfs_syscalls.c 12 Mar 2002 04:00:10 -0000 1.231 +++ kern/vfs_syscalls.c 18 Mar 2002 23:18:34 -0000 @@ -446,29 +446,34 @@ { struct filedesc *fdp; struct proc *p; + int nrele; if (olddp->v_usecount == 1) return; sx_slock(&allproc_lock); LIST_FOREACH(p, &allproc, p_list) { + PROC_LOCK(p); fdp = p->p_fd; - if (fdp == NULL) + if (fdp == NULL) { + PROC_UNLOCK(p); continue; + } + nrele = 0; FILEDESC_LOCK(fdp); if (fdp->fd_cdir == olddp) { VREF(newdp); fdp->fd_cdir = newdp; - FILEDESC_UNLOCK(fdp); - vrele(olddp); - FILEDESC_LOCK(fdp); + nrele++; } if (fdp->fd_rdir == olddp) { VREF(newdp); fdp->fd_rdir = newdp; - FILEDESC_UNLOCK(fdp); + nrele++; + } + FILEDESC_UNLOCK(fdp); + PROC_UNLOCK(p); + while (nrele--) vrele(olddp); - } else - FILEDESC_UNLOCK(fdp); } sx_sunlock(&allproc_lock); if (rootvnode == olddp) { Index: kern/kern_descrip.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_descrip.c,v retrieving revision 1.128 diff -u -r1.128 kern_descrip.c --- kern/kern_descrip.c 15 Mar 2002 08:03:46 -0000 1.128 +++ kern/kern_descrip.c 18 Mar 2002 19:04:24 -0000 @@ -1321,10 +1321,11 @@ fdfree(td) struct thread *td; { - register struct filedesc *fdp = td->td_proc->p_fd; + register struct filedesc *fdp; struct file **fpp; register int i; + fdp = td->td_proc->p_fd; /* Certain daemons might not have file descriptors. */ if (fdp == NULL) return; @@ -1344,6 +1345,11 @@ if (*fpp) (void) closef(*fpp, td); } + + PROC_LOCK(td->td_proc); + td->td_proc->p_fd = NULL; + PROC_UNLOCK(td->td_proc); + if (fdp->fd_nfiles > NDFILE) FREE(fdp->fd_ofiles, M_FILEDESC); if (fdp->fd_cdir) To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message