From: Matthew Dillon Date: Thu, 23 Aug 2012 23:49:08 +0000 (-0700) Subject: linprocfs - Fix missing PRELE()s. X-Git-Tag: v3.2.0~277 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/db6bd503b8e22352c7086aa0c3f0cb1628a05ea6?ds=sidebyside linprocfs - Fix missing PRELE()s. * The DFly pfind() API changed a while ago and now PHOLD()s the process, add missing PRELE()s to linprocfs that were missed during that change-over. Reported-by: marino, alexh --- diff --git a/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c b/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c index 7ea306168a..cc41daaa6b 100644 --- a/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c +++ b/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c @@ -176,31 +176,42 @@ linprocfs_open(struct vop_open_args *ap) { struct pfsnode *pfs = VTOPFS(ap->a_vp); struct proc *p2; + int error; p2 = linprocfs_pfind(pfs->pfs_pid); - if (p2 == NULL) - return (ENOENT); - if (pfs->pfs_pid && !PRISON_CHECK(ap->a_cred, p2->p_ucred)) - return (ENOENT); - - 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); - - if (p_trespass(ap->a_cred, p2->p_ucred)) - return (EPERM); - - if (ap->a_mode & FWRITE) - pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL); - - break; - default: - break; + if (p2 == NULL) { + error = ENOENT; + } else if (pfs->pfs_pid && !PRISON_CHECK(ap->a_cred, p2->p_ucred)) { + error = ENOENT; + } else { + error = 0; + + 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))) { + error = EBUSY; + break; + } + + if (p_trespass(ap->a_cred, p2->p_ucred)) { + error = EPERM; + break; + } + if (ap->a_mode & FWRITE) + pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL); + break; + default: + break; + } } - - return (vop_stdopen(ap)); + if (error == 0) + error = vop_stdopen(ap); + if (p2) + PRELE(p2); + return error; } /* @@ -261,9 +272,8 @@ linprocfs_ioctl(struct vop_ioctl_args *ap) unsigned char flags; procp = linprocfs_pfind(pfs->pfs_pid); - if (procp == NULL) { + if (procp == NULL) return ENOTTY; - } if (p_trespass(ap->a_cred, procp->p_ucred)) { error = EPERM; @@ -466,8 +476,10 @@ linprocfs_getattr(struct vop_getattr_args *ap) default: procp = linprocfs_pfind(pfs->pfs_pid); - if (procp == NULL || procp->p_ucred == NULL) - return (ENOENT); + if (procp == NULL || procp->p_ucred == NULL) { + error = ENOENT; + goto done; + } } error = 0; @@ -635,7 +647,9 @@ linprocfs_getattr(struct vop_getattr_args *ap) default: panic("linprocfs_getattr"); } - +done: + if (procp) + PRELE(procp); return (error); } @@ -734,6 +748,7 @@ linprocfs_lookup(struct vop_old_lookup_args *ap) int error; *vpp = NULL; + p = NULL; if (cnp->cn_nameiop == NAMEI_DELETE || cnp->cn_nameiop == NAMEI_RENAME || @@ -904,6 +919,8 @@ linprocfs_lookup(struct vop_old_lookup_args *ap) * so if dvp != *vpp and CNP_LOCKPARENT is not set, unlock dvp. */ out: + if (p) + PRELE(p); if (error == 0) { if (*vpp != dvp && (cnp->cn_flags & CNP_LOCKPARENT) == 0) { cnp->cn_flags |= CNP_PDIRUNLOCK; @@ -994,8 +1011,10 @@ linprocfs_readdir_proc(struct vop_readdir_args *ap) p = linprocfs_pfind(pfs->pfs_pid); if (p == NULL) return(0); - if (!PRISON_CHECK(ap->a_cred, p->p_ucred)) + if (!PRISON_CHECK(ap->a_cred, p->p_ucred)) { + PRELE(p); return(0); + } error = 0; i = uio->uio_offset; @@ -1013,6 +1032,7 @@ linprocfs_readdir_proc(struct vop_readdir_args *ap) } uio->uio_offset = i; + PRELE(p); return(error); } @@ -1504,6 +1524,9 @@ linprocfs_readlink(struct vop_readlink_args *ap) char *fullpath, *freepath; int error, len; + error = 0; + procp = NULL; + switch (pfs->pfs_type) { case Pself: if (pfs->pfs_fileno != PROCFS_FILENO(0, Pself)) @@ -1511,7 +1534,8 @@ linprocfs_readlink(struct vop_readlink_args *ap) len = ksnprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid); - return (uiomove(buf, len, ap->a_uio)); + error = uiomove(buf, len, ap->a_uio); + break; /* * There _should_ be no way for an entire process to disappear * from under us... @@ -1521,67 +1545,84 @@ linprocfs_readlink(struct vop_readlink_args *ap) if (procp == NULL || procp->p_ucred == NULL) { kprintf("linprocfs_readlink: pid %d disappeared\n", pfs->pfs_pid); - return (uiomove("unknown", sizeof("unknown") - 1, - ap->a_uio)); + error = uiomove("unknown", sizeof("unknown") - 1, + ap->a_uio); + break; } error = cache_fullpath(procp, &procp->p_textnch, &fullpath, &freepath, 0); - if (error != 0) - return (uiomove("unknown", sizeof("unknown") - 1, - ap->a_uio)); + if (error != 0) { + error = uiomove("unknown", sizeof("unknown") - 1, + ap->a_uio); + break; + } error = uiomove(fullpath, strlen(fullpath), ap->a_uio); kfree(freepath, M_TEMP); - return (error); + break; case Pcwd: procp = linprocfs_pfind(pfs->pfs_pid); if (procp == NULL || procp->p_ucred == NULL) { kprintf("linprocfs_readlink: pid %d disappeared\n", - pfs->pfs_pid); - return (uiomove("unknown", sizeof("unknown") - 1, - ap->a_uio)); + pfs->pfs_pid); + error = uiomove("unknown", sizeof("unknown") - 1, + ap->a_uio); + break; + } + error = cache_fullpath(procp, &procp->p_fd->fd_ncdir, + &fullpath, &freepath, 0); + if (error != 0) { + error = uiomove("unknown", sizeof("unknown") - 1, + ap->a_uio); + break; } - error = cache_fullpath(procp, &procp->p_fd->fd_ncdir, &fullpath, &freepath, 0); - if (error != 0) - return (uiomove("unknown", sizeof("unknown") - 1, - ap->a_uio)); error = uiomove(fullpath, strlen(fullpath), ap->a_uio); kfree(freepath, M_TEMP); - return (error); + break; case Pprocroot: procp = linprocfs_pfind(pfs->pfs_pid); if (procp == NULL || procp->p_ucred == NULL) { kprintf("linprocfs_readlink: pid %d disappeared\n", pfs->pfs_pid); - return (uiomove("unknown", sizeof("unknown") - 1, - ap->a_uio)); + error = uiomove("unknown", sizeof("unknown") - 1, + ap->a_uio); + break; } nchp = jailed(procp->p_ucred) ? &procp->p_fd->fd_njdir : &procp->p_fd->fd_nrdir; error = cache_fullpath(procp, nchp, &fullpath, &freepath, 0); - if (error != 0) - return (uiomove("unknown", sizeof("unknown") - 1, - ap->a_uio)); + if (error != 0) { + error = uiomove("unknown", sizeof("unknown") - 1, + ap->a_uio); + break; + } error = uiomove(fullpath, strlen(fullpath), ap->a_uio); kfree(freepath, M_TEMP); - return (error); + break; case Pfd: procp = linprocfs_pfind(pfs->pfs_pid); if (procp == NULL || procp->p_ucred == NULL) { kprintf("linprocfs_readlink: pid %d disappeared\n", pfs->pfs_pid); - return (uiomove("unknown", sizeof("unknown") - 1, - ap->a_uio)); + error = uiomove("unknown", sizeof("unknown") - 1, + ap->a_uio); + break; } if (procp == curproc) { - return (uiomove("/dev/fd", sizeof("/dev/fd") - 1, - ap->a_uio)); + error = uiomove("/dev/fd", sizeof("/dev/fd") - 1, + ap->a_uio); + break; } else { - return (uiomove("unknown", sizeof("unknown") - 1, - ap->a_uio)); + error = uiomove("unknown", sizeof("unknown") - 1, + ap->a_uio); + break; } /* notreached */ break; default: - return (EINVAL); + error = EINVAL; + break; } + if (procp) + PRELE(procp); + return error; } /*