From 383d6d14c140a4be1197182b80e258d63f5abad5 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Thu, 23 Aug 2012 17:00:49 -0700 Subject: [PATCH] linprocfs - Fix process exit / procfs vnode access race & stepping races * Taken from procfs, fix exit / vnode access races * Fix stepping races. --- sys/emulation/linux/i386/linprocfs/linprocfs.h | 2 ++ .../linux/i386/linprocfs/linprocfs_subr.c | 2 +- .../linux/i386/linprocfs/linprocfs_vnops.c | 17 +++++++++++++---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/sys/emulation/linux/i386/linprocfs/linprocfs.h b/sys/emulation/linux/i386/linprocfs/linprocfs.h index aba5d72412..33d3aaae6e 100644 --- a/sys/emulation/linux/i386/linprocfs/linprocfs.h +++ b/sys/emulation/linux/i386/linprocfs/linprocfs.h @@ -167,6 +167,8 @@ int linprocfs_validfile (struct proc *); #define PROCFS_LOCKED 0x01 #define PROCFS_WANT 0x02 +#define PFS_DEAD 0x80000000 /* or'd with pid */ + int linprocfs_root (struct mount *, struct vnode **); int linprocfs_rw (struct vop_read_args *); #endif /* _KERNEL */ diff --git a/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c b/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c index d2db8e3148..6ad4d68140 100644 --- a/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c +++ b/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c @@ -456,7 +456,7 @@ restart: if (pfs->pfs_pid == pid) { vp = PFSTOV(pfs); vx_get(vp); - vgone_vxlocked(vp); + pfs->pfs_pid |= PFS_DEAD; vx_put(vp); goto restart; } diff --git a/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c b/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c index cc41daaa6b..ff2d48c27a 100644 --- a/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c +++ b/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c @@ -244,8 +244,10 @@ linprocfs_close(struct vop_close_args *ap) if ((ap->a_vp->v_opencount < 2) && (p = linprocfs_pfind(pfs->pfs_pid)) && !(p->p_pfsflags & PF_LINGER)) { + spin_lock(&p->p_spin); p->p_stops = 0; p->p_step = 0; + spin_unlock(&p->p_spin); wakeup(&p->p_stype); } if (p) @@ -302,22 +304,27 @@ linprocfs_ioctl(struct vop_ioctl_args *ap) *(unsigned int*)ap->a_data = (unsigned int)procp->p_pfsflags; case PIOCSTATUS: psp = (struct procfs_status *)ap->a_data; - psp->state = (procp->p_step == 0); psp->flags = procp->p_pfsflags; psp->events = procp->p_stops; + spin_lock(&procp->p_spin); if (procp->p_step) { + psp->state = 0; psp->why = procp->p_stype; psp->val = procp->p_xstat; + spin_unlock(&procp->p_spin); } else { - psp->why = psp->val = 0; /* Not defined values */ + psp->state = 1; + spin_unlock(&procp->p_spin); + psp->why = 0; /* Not defined values */ + psp->val = 0; /* Not defined values */ } break; case PIOCWAIT: psp = (struct procfs_status *)ap->a_data; spin_lock(&procp->p_spin); if (procp->p_step == 0) { - spin_unlock(&procp->p_spin); tsleep_interlock(&procp->p_stype, PCATCH); + spin_unlock(&procp->p_spin); if (procp->p_stops == 0) { error = EINVAL; goto done; @@ -404,8 +411,10 @@ linprocfs_bmap(struct vop_bmap_args *ap) static int linprocfs_inactive(struct vop_inactive_args *ap) { - /*struct vnode *vp = ap->a_vp;*/ + struct pfsnode *pfs = VTOPFS(ap->a_vp); + if (pfs->pfs_pid & PFS_DEAD) + vrecycle(ap->a_vp); return (0); } -- 2.41.0