procfs_allocvp():

* do not set *vpp unless successful, otherwise we'd trigger
    DIAGNOSTIC panic in lookup(9) on error return
  * on error, make sure to free malloc'ed memory and ungetnewvnode() the
    previously acquired vnode

this fixes panic on 'tail -f <file> &; ls -l /proc/$!/fd' reported by
Andrew Brown

fix reviewed by Christos Zoulas
This commit is contained in:
jdolecek 2003-02-03 22:27:42 +00:00
parent a25898cf6e
commit b1fc5ffac3
1 changed files with 15 additions and 6 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs_subr.c,v 1.43 2003/01/18 09:18:06 thorpej Exp $ */ /* $NetBSD: procfs_subr.c,v 1.44 2003/02/03 22:27:42 jdolecek Exp $ */
/* /*
* Copyright (c) 1994 Christopher G. Demetriou. All rights reserved. * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved.
@ -41,7 +41,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.43 2003/01/18 09:18:06 thorpej Exp $"); __KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.44 2003/02/03 22:27:42 jdolecek Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -112,12 +112,11 @@ procfs_allocvp(mp, vpp, pid, pfs_type, fd)
return (0); return (0);
} while (lockmgr(&pfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0)); } while (lockmgr(&pfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0));
if ((error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp)) != 0) { if ((error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, &vp)) != 0) {
*vpp = NULL; *vpp = NULL;
lockmgr(&pfs_hashlock, LK_RELEASE, NULL); lockmgr(&pfs_hashlock, LK_RELEASE, NULL);
return (error); return (error);
} }
vp = *vpp;
MALLOC(pfs, void *, sizeof(struct pfsnode), M_TEMP, M_WAITOK); MALLOC(pfs, void *, sizeof(struct pfsnode), M_TEMP, M_WAITOK);
vp->v_data = pfs; vp->v_data = pfs;
@ -151,8 +150,11 @@ procfs_allocvp(mp, vpp, pid, pfs_type, fd)
} else { /* /proc/N/fd/M = [ps-]rw------- */ } else { /* /proc/N/fd/M = [ps-]rw------- */
struct file *fp; struct file *fp;
struct vnode *vxp; struct vnode *vxp;
/* XXX can procfs_getfp() ever fail here? */
if ((error = procfs_getfp(pfs, &fp)) != 0) if ((error = procfs_getfp(pfs, &fp)) != 0)
return error; goto bad;
pfs->pfs_mode = S_IRUSR|S_IWUSR; pfs->pfs_mode = S_IRUSR|S_IWUSR;
switch (fp->f_type) { switch (fp->f_type) {
case DTYPE_VNODE: case DTYPE_VNODE:
@ -167,7 +169,8 @@ procfs_allocvp(mp, vpp, pid, pfs_type, fd)
break; break;
case DTYPE_KQUEUE: case DTYPE_KQUEUE:
case DTYPE_MISC: case DTYPE_MISC:
return EOPNOTSUPP; error = EOPNOTSUPP;
goto bad;
default: default:
panic("unknown file type %d\n", fp->f_type); panic("unknown file type %d\n", fp->f_type);
} }
@ -213,6 +216,12 @@ procfs_allocvp(mp, vpp, pid, pfs_type, fd)
uvm_vnp_setsize(vp, 0); uvm_vnp_setsize(vp, 0);
lockmgr(&pfs_hashlock, LK_RELEASE, NULL); lockmgr(&pfs_hashlock, LK_RELEASE, NULL);
*vpp = vp;
return (0);
bad:
FREE(pfs, M_TEMP);
ungetnewvnode(vp);
return (error); return (error);
} }