Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 May 1997 14:14:49 +0100 (BST)
From:      Doug Rabson <dfr@nlsystems.com>
To:        dwmalone@maths.tcd.ie, simonm@solander.dcs.gla.ac.uk
Cc:        current@freebsd.org
Subject:   Fix for NFS bogusly accessing cached data
Message-ID:  <Pine.BSF.3.95q.970506140830.331K-100000@herring.nlsystems.com>

next in thread | raw e-mail | index | archive | help
Could someone review these fixes for kern/876 and kern/2635.  Since NFSv2
does not have an ACCESS rpc, I have to attempt an uncached read of the
file to approximate a VREAD access check.  This should cope with the
mapped root->nobody case in NFSv2.  NFSv3 already fixed kern/876 since it
has a working ACCESS rpc.

The only part of this which worries me is that for directories I have to
read the first NFS_DIRBLKSIZ bytes of the directory (a limitation of
nfs_readdirrpc).  Since this is only done for root and only for v2, I
think the overhead is ok.

Index: nfs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/nfs/nfs_vnops.c,v
retrieving revision 1.47
diff -u -r1.47 nfs_vnops.c
--- nfs_vnops.c	1997/05/04 09:17:36	1.47
+++ nfs_vnops.c	1997/05/06 13:06:35
@@ -410,8 +410,49 @@
 		}
 		nfsm_reqdone;
 		return (error);
-	} else
-		return (nfsspec_access(ap));
+	} else {
+		if (error = nfsspec_access(ap))
+			return (error);
+
+		/*
+		 * Attempt to prevent a mapped root from accessing a file
+		 * which it shouldn't.  We try to read a byte from the file
+		 * if the user is root and the file is not zero length.
+		 * After calling nfsspec_access, we should have the correct
+		 * file size cached.
+		 */
+		if (ap->a_cred->cr_uid == 0 && (ap->a_mode & VREAD)
+		    && VTONFS(vp)->n_size > 0) {
+			struct iovec aiov;
+			struct uio auio;
+			char buf[1];
+
+			aiov.iov_base = buf;
+			aiov.iov_len = 1;
+			auio.uio_iov = &aiov;
+			auio.uio_iovcnt = 1;
+			auio.uio_offset = 0;
+			auio.uio_resid = 1;
+			auio.uio_segflg = UIO_SYSSPACE;
+			auio.uio_rw = UIO_READ;
+			auio.uio_procp = ap->a_p;
+
+			if (vp->v_type == VREG)
+				error = nfs_readrpc(vp, &auio, ap->a_cred);
+			else if (vp->v_type == VDIR) {
+				char* buf;
+				buf = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK);
+				aiov.iov_base = buf;
+				aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ;
+				error = nfs_readdirrpc(vp, &auio, ap->a_cred);
+				free(buf, M_TEMP);
+			} else if (vp->v_type = VLNK)
+				error = nfs_readlinkrpc(vp, &auio, ap->a_cred);
+			else
+				error = EACCES;
+		}
+		return (error);
+	}
 }
 
 /*
@@ -833,6 +874,9 @@
 	if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) {
 		struct vattr vattr;
 		int vpid;
+
+		if (error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p))
+			return (error);
 
 		newvp = *vpp;
 		vpid = newvp->v_id;


--
Doug Rabson				Mail:  dfr@nlsystems.com
Nonlinear Systems Ltd.			Phone: +44 181 951 1891




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.95q.970506140830.331K-100000>