X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/1b2c87ca31619b40819b35bc5430c95daea509a2..4643740aa6f3eac7d3dfab05967ec55b5d8ba984:/sys/vfs/procfs/procfs_vnops.c diff --git a/sys/vfs/procfs/procfs_vnops.c b/sys/vfs/procfs/procfs_vnops.c index 581f489031..0613945c0b 100644 --- a/sys/vfs/procfs/procfs_vnops.c +++ b/sys/vfs/procfs/procfs_vnops.c @@ -37,7 +37,6 @@ * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95 * * $FreeBSD: src/sys/miscfs/procfs/procfs_vnops.c,v 1.76.2.7 2002/01/22 17:22:59 nectar Exp $ - * $DragonFly: src/sys/vfs/procfs/procfs_vnops.c,v 1.46 2007/11/20 21:03:50 dillon Exp $ */ /* @@ -150,7 +149,7 @@ static struct proc_target { { DT_LNK, N("file"), Pfile, NULL }, #undef N }; -static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]); +static const int nproc_targets = NELEM(proc_targets); static pid_t atopid (const char *, u_int); @@ -173,26 +172,35 @@ procfs_open(struct vop_open_args *ap) { struct pfsnode *pfs = VTOPFS(ap->a_vp); struct proc *p1, *p2; + int error; - p2 = PFIND(pfs->pfs_pid); + p2 = pfs_pfind(pfs->pfs_pid); if (p2 == NULL) return (ENOENT); - if (pfs->pfs_pid && !PRISON_CHECK(ap->a_cred, p2->p_ucred)) - return (ENOENT); + if (pfs->pfs_pid && !PRISON_CHECK(ap->a_cred, p2->p_ucred)) { + error = ENOENT; + goto done; + } switch (pfs->pfs_type) { case Pmem: if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) || - ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) - return (EBUSY); + ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) { + error = EBUSY; + goto done; + } p1 = curproc; KKASSERT(p1); /* Can't trace a process that's currently exec'ing. */ - if ((p2->p_flag & P_INEXEC) != 0) - return EAGAIN; - if (!CHECKIO(p1, p2) || p_trespass(ap->a_cred, p2->p_ucred)) - return (EPERM); + if ((p2->p_flags & P_INEXEC) != 0) { + error = EAGAIN; + goto done; + } + if (!CHECKIO(p1, p2) || p_trespass(ap->a_cred, p2->p_ucred)) { + error = EPERM; + goto done; + } if (ap->a_mode & FWRITE) pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL); @@ -202,8 +210,10 @@ procfs_open(struct vop_open_args *ap) default: break; } - - return (vop_stdopen(ap)); + error = vop_stdopen(ap); +done: + PRELE(p2); + return error; } /* @@ -236,15 +246,18 @@ procfs_close(struct vop_close_args *ap) * told to stop on an event, but then the requesting process * has gone away or forgotten about it. */ + p = NULL; if ((ap->a_vp->v_opencount < 2) && (p = pfind(pfs->pfs_pid)) && !(p->p_pfsflags & PF_LINGER)) { - spin_lock_wr(&p->p_spin); + spin_lock(&p->p_spin); p->p_stops = 0; p->p_step = 0; - spin_unlock_wr(&p->p_spin); + spin_unlock(&p->p_spin); wakeup(&p->p_step); } + if (p) + PRELE(p); break; default: break; @@ -272,14 +285,20 @@ procfs_ioctl(struct vop_ioctl_args *ap) if (procp == NULL) return ENOTTY; p = curproc; - if (p == NULL) - return EINVAL; + if (p == NULL) { + error = EINVAL; + goto done; + } /* Can't trace a process that's currently exec'ing. */ - if ((procp->p_flag & P_INEXEC) != 0) - return EAGAIN; - if (!CHECKIO(p, procp) || p_trespass(ap->a_cred, procp->p_ucred)) - return EPERM; + if ((procp->p_flags & P_INEXEC) != 0) { + error = EAGAIN; + goto done; + } + if (!CHECKIO(p, procp) || p_trespass(ap->a_cred, procp->p_ucred)) { + error = EPERM; + goto done; + } switch (ap->a_command) { case PIOCBIS: @@ -296,7 +315,7 @@ procfs_ioctl(struct vop_ioctl_args *ap) #define NFLAGS (PF_ISUGID) flags = (unsigned char)*(unsigned int*)ap->a_data; if (flags & NFLAGS && (error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0))) - return error; + goto done; procp->p_pfsflags = flags; break; case PIOCGFL: @@ -310,15 +329,15 @@ procfs_ioctl(struct vop_ioctl_args *ap) psp = (struct procfs_status *)ap->a_data; psp->flags = procp->p_pfsflags; psp->events = procp->p_stops; - spin_lock_wr(&procp->p_spin); + spin_lock(&procp->p_spin); if (procp->p_step) { psp->state = 0; psp->why = procp->p_stype; psp->val = procp->p_xstat; - spin_unlock_wr(&procp->p_spin); + spin_unlock(&procp->p_spin); } else { psp->state = 1; - spin_unlock_wr(&procp->p_spin); + spin_unlock(&procp->p_spin); psp->why = 0; /* Not defined values */ psp->val = 0; /* Not defined values */ } @@ -329,16 +348,16 @@ procfs_ioctl(struct vop_ioctl_args *ap) * the MP lock. */ psp = (struct procfs_status *)ap->a_data; - spin_lock_wr(&procp->p_spin); + spin_lock(&procp->p_spin); while (procp->p_step == 0) { tsleep_interlock(&procp->p_stype, PCATCH); - spin_unlock_wr(&procp->p_spin); + spin_unlock(&procp->p_spin); error = tsleep(&procp->p_stype, PCATCH | PINTERLOCKED, "piocwait", 0); if (error) - return error; - spin_lock_wr(&procp->p_spin); + goto done; + spin_lock(&procp->p_spin); } - spin_unlock_wr(&procp->p_spin); + spin_unlock(&procp->p_spin); psp->state = 1; /* It stopped */ psp->flags = procp->p_pfsflags; psp->events = procp->p_stops; @@ -351,19 +370,27 @@ procfs_ioctl(struct vop_ioctl_args *ap) * the MP lock. However, the caller is presumably interlocked * by having waited. */ - if (procp->p_step == 0) - return EINVAL; /* Can only start a stopped process */ + if (procp->p_step == 0) { + error = EINVAL; /* Can only start a stopped process */ + goto done; + } if ((signo = *(int*)ap->a_data) != 0) { - if (signo >= NSIG || signo <= 0) - return EINVAL; + if (signo >= NSIG || signo <= 0) { + error = EINVAL; + goto done; + } ksignal(procp, signo); } procp->p_step = 0; wakeup(&procp->p_step); break; default: - return (ENOTTY); + error = ENOTTY; + goto done; } + error = 0; +done: + PRELE(procp); return 0; } @@ -482,13 +509,15 @@ procfs_getattr(struct vop_getattr_args *ap) switch (pfs->pfs_type) { case Proot: case Pcurproc: - procp = 0; + procp = NULL; break; default: - procp = PFIND(pfs->pfs_pid); - if (procp == NULL || procp->p_ucred == NULL) - return (ENOENT); + procp = pfs_pfind(pfs->pfs_pid); + if (procp == NULL || procp->p_ucred == NULL) { + error = ENOENT; + goto done; + } } error = 0; @@ -527,7 +556,7 @@ procfs_getattr(struct vop_getattr_args *ap) case Pfpregs: case Pdbregs: case Pmem: - if (procp->p_flag & P_SUGID) + if (procp->p_flags & P_SUGID) vap->va_mode &= ~((VREAD|VWRITE)| ((VREAD|VWRITE)>>3)| ((VREAD|VWRITE)>>6)); @@ -597,7 +626,7 @@ procfs_getattr(struct vop_getattr_args *ap) * change the owner to root - otherwise 'ps' and friends * will break even though they are setgid kmem. *SIGH* */ - if (procp->p_flag & P_SUGID) + if (procp->p_flags & P_SUGID) vap->va_uid = 0; else vap->va_uid = procp->p_ucred->cr_uid; @@ -628,7 +657,9 @@ procfs_getattr(struct vop_getattr_args *ap) default: panic("procfs_getattr"); } - +done: + if (procp) + PRELE(procp); return (error); } @@ -700,6 +731,7 @@ procfs_lookup(struct vop_old_lookup_args *ap) if (cnp->cn_nameiop == NAMEI_DELETE || cnp->cn_nameiop == NAMEI_RENAME) return (EROFS); + p = NULL; error = 0; if (cnp->cn_namelen == 1 && *pname == '.') { *vpp = dvp; @@ -722,7 +754,7 @@ procfs_lookup(struct vop_old_lookup_args *ap) if (pid == NO_PID) break; - p = PFIND(pid); + p = pfs_pfind(pid); if (p == NULL) break; @@ -742,7 +774,7 @@ procfs_lookup(struct vop_old_lookup_args *ap) goto out; } - p = PFIND(pfs->pfs_pid); + p = pfs_pfind(pfs->pfs_pid); if (p == NULL) break; /* XXX lwp */ @@ -788,6 +820,8 @@ out: vn_unlock(dvp); } } + if (p) + PRELE(p); return (error); } @@ -858,18 +892,22 @@ procfs_readdir_proc(struct vop_readdir_args *ap) struct uio *uio = ap->a_uio; pfs = VTOPFS(ap->a_vp); - p = PFIND(pfs->pfs_pid); + p = pfs_pfind(pfs->pfs_pid); if (p == NULL) return(0); - if (!PRISON_CHECK(ap->a_cred, p->p_ucred)) - return(0); - /* XXX lwp */ + if (!PRISON_CHECK(ap->a_cred, p->p_ucred)) { + error = 0; + goto done; + } + /* XXX lwp, not MPSAFE */ lp = FIRST_LWP_IN_PROC(p); error = 0; i = (int)uio->uio_offset; - if (i < 0) - return (EINVAL); + if (i < 0) { + error = EINVAL; + goto done; + } for (pt = &proc_targets[i]; !error && uio->uio_resid > 0 && i < nproc_targets; pt++, i++) { @@ -884,8 +922,10 @@ procfs_readdir_proc(struct vop_readdir_args *ap) } uio->uio_offset = (off_t)i; - - return(0); + error = 0; +done: + PRELE(p); + return error; } struct procfs_readdir_root_info { @@ -1033,19 +1073,26 @@ procfs_readlink(struct vop_readlink_args *ap) * from under us... */ case Pfile: - procp = PFIND(pfs->pfs_pid); + procp = pfs_pfind(pfs->pfs_pid); if (procp == NULL || procp->p_ucred == NULL) { kprintf("procfs_readlink: pid %d disappeared\n", pfs->pfs_pid); + if (procp) + PRELE(procp); return (uiomove("unknown", sizeof("unknown") - 1, ap->a_uio)); } error = cache_fullpath(procp, &procp->p_textnch, &fullpath, &freepath, 0); - if (error != 0) + if (error != 0) { + if (procp) + PRELE(procp); return (uiomove("unknown", sizeof("unknown") - 1, ap->a_uio)); + } error = uiomove(fullpath, strlen(fullpath), ap->a_uio); kfree(freepath, M_TEMP); + if (procp) + PRELE(procp); return (error); default: return (EINVAL);