kernel/linprocfs: Fix accessing files in /proc (such as /proc/meminfo).
authorSascha Wildner <saw@online.de>
Tue, 21 Aug 2012 18:57:19 +0000 (20:57 +0200)
committerSascha Wildner <saw@online.de>
Tue, 21 Aug 2012 20:46:26 +0000 (22:46 +0200)
It is the same fix that was applied to procfs with 198c0ff2.

sys/emulation/linux/i386/linprocfs/linprocfs.h
sys/emulation/linux/i386/linprocfs/linprocfs_subr.c
sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c

index 488c5c2..aba5d72 100644 (file)
@@ -136,6 +136,7 @@ int linprocfs_freevp (struct vnode *);
 int linprocfs_allocvp (struct mount *, struct vnode **, long, pfstype);
 int linprocfs_sstep (struct proc *);
 void linprocfs_fix_sstep (struct proc *);
+struct proc *linprocfs_pfind(pid_t pfs_pid);
 #if 0
 int linprocfs_read_regs (struct proc *, struct reg *);
 int linprocfs_write_regs (struct proc *, struct reg *);
index 8dc4f8f..d2db8e3 100644 (file)
@@ -251,6 +251,26 @@ linprocfs_freevp(struct vnode *vp)
        return (0);
 }
 
+/*
+ * Try to find the calling pid. Note that pfind()
+ * now references the proc structure to be returned
+ * and needs to be released later with PRELE().
+ */
+struct proc *
+linprocfs_pfind(pid_t pfs_pid)
+{
+       struct proc *p = NULL;
+
+       if (pfs_pid == 0) {
+               p = &proc0;
+               PHOLD(p);
+       } else {
+               p = pfind(pfs_pid);
+       }
+
+       return p;
+}
+
 int
 linprocfs_rw(struct vop_read_args *ap)
 {
@@ -266,12 +286,14 @@ linprocfs_rw(struct vop_read_args *ap)
        curp = td->td_proc;
        KKASSERT(curp);
 
-       p = pfind(pfs->pfs_pid);
-       if (p == NULL)
-               return (EINVAL);
+       p = linprocfs_pfind(pfs->pfs_pid);
+       if (p == NULL) {
+               rtval = EINVAL;
+               goto out;
+       }
        if (p->p_pid == 1 && securelevel > 0 && uio->uio_rw == UIO_WRITE) {
-               PRELE(p);
-               return (EACCES);
+               rtval = EACCES;
+               goto out;
        }
        lp = FIRST_LWP_IN_PROC(p);
        LWPHOLD(lp);
@@ -340,12 +362,14 @@ linprocfs_rw(struct vop_read_args *ap)
                break;
        }
        LWPRELE(lp);
-       PRELE(p);
 
        lwkt_gettoken(&pfs_token);
        pfs->pfs_lockowner = NULL;
        wakeup(&pfs->pfs_lockowner);
        lwkt_reltoken(&pfs_token);
+out:
+       if (p)
+               PRELE(p);
 
        return rtval;
 }
index 65c0c1d..18bbd76 100644 (file)
@@ -176,7 +176,7 @@ linprocfs_open(struct vop_open_args *ap)
        struct pfsnode *pfs = VTOPFS(ap->a_vp);
        struct proc *p2;
 
-       p2 = PFIND(pfs->pfs_pid);
+       p2 = linprocfs_pfind(pfs->pfs_pid);
        if (p2 == NULL)
                return (ENOENT);
        if (pfs->pfs_pid && !PRISON_CHECK(ap->a_cred, p2->p_ucred))
@@ -230,7 +230,7 @@ linprocfs_close(struct vop_close_args *ap)
                 */
                p = NULL;
                if ((ap->a_vp->v_opencount < 2)
-                   && (p = pfind(pfs->pfs_pid))
+                   && (p = linprocfs_pfind(pfs->pfs_pid))
                    && !(p->p_pfsflags & PF_LINGER)) {
                        p->p_stops = 0;
                        p->p_step = 0;
@@ -259,7 +259,7 @@ linprocfs_ioctl(struct vop_ioctl_args *ap)
        struct procfs_status *psp;
        unsigned char flags;
 
-       procp = pfind(pfs->pfs_pid);
+       procp = linprocfs_pfind(pfs->pfs_pid);
        if (procp == NULL) {
                return ENOTTY;
        }
@@ -464,7 +464,7 @@ linprocfs_getattr(struct vop_getattr_args *ap)
                break;
 
        default:
-               procp = PFIND(pfs->pfs_pid);
+               procp = linprocfs_pfind(pfs->pfs_pid);
                if (procp == NULL || procp->p_ucred == NULL)
                        return (ENOENT);
        }
@@ -843,7 +843,7 @@ linprocfs_lookup(struct vop_old_lookup_args *ap)
                if (pid == NO_PID)
                        break;
 
-               p = PFIND(pid);
+               p = linprocfs_pfind(pid);
                if (p == NULL)
                        break;
 
@@ -863,7 +863,7 @@ linprocfs_lookup(struct vop_old_lookup_args *ap)
                        goto out;
                }
 
-               p = PFIND(pfs->pfs_pid);
+               p = linprocfs_pfind(pfs->pfs_pid);
                if (p == NULL)
                        break;
 
@@ -990,7 +990,7 @@ linprocfs_readdir_proc(struct vop_readdir_args *ap)
        struct uio *uio = ap->a_uio;
 
        pfs = VTOPFS(ap->a_vp);
-       p = PFIND(pfs->pfs_pid);
+       p = linprocfs_pfind(pfs->pfs_pid);
        if (p == NULL)
                return(0);
        if (!PRISON_CHECK(ap->a_cred, p->p_ucred))
@@ -1516,7 +1516,7 @@ linprocfs_readlink(struct vop_readlink_args *ap)
         * from under us...
         */
        case Pexe:
-               procp = PFIND(pfs->pfs_pid);
+               procp = linprocfs_pfind(pfs->pfs_pid);
                if (procp == NULL || procp->p_ucred == NULL) {
                        kprintf("linprocfs_readlink: pid %d disappeared\n",
                            pfs->pfs_pid);
@@ -1531,7 +1531,7 @@ linprocfs_readlink(struct vop_readlink_args *ap)
                kfree(freepath, M_TEMP);
                return (error);
        case Pcwd:
-               procp = PFIND(pfs->pfs_pid);
+               procp = linprocfs_pfind(pfs->pfs_pid);
                if (procp == NULL || procp->p_ucred == NULL) {
                        kprintf("linprocfs_readlink: pid %d disappeared\n",
                            pfs->pfs_pid);
@@ -1546,7 +1546,7 @@ linprocfs_readlink(struct vop_readlink_args *ap)
                kfree(freepath, M_TEMP);
                return (error);
        case Pprocroot:
-               procp = PFIND(pfs->pfs_pid);
+               procp = linprocfs_pfind(pfs->pfs_pid);
                if (procp == NULL || procp->p_ucred == NULL) {
                        kprintf("linprocfs_readlink: pid %d disappeared\n",
                            pfs->pfs_pid);
@@ -1562,7 +1562,7 @@ linprocfs_readlink(struct vop_readlink_args *ap)
                kfree(freepath, M_TEMP);
                return (error);
        case Pfd:
-               procp = PFIND(pfs->pfs_pid);
+               procp = linprocfs_pfind(pfs->pfs_pid);
                if (procp == NULL || procp->p_ucred == NULL) {
                        kprintf("linprocfs_readlink: pid %d disappeared\n",
                            pfs->pfs_pid);