diff options
author | dfr <dfr@FreeBSD.org> | 1997-05-09 13:18:42 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 1997-05-09 13:18:42 +0000 |
commit | ab4272e09ecd5d3838b564026ac4cbdb411fec35 (patch) | |
tree | fe82f1c42b7455f1d4701351ca1a2b8a529ac19c /sys/nfs | |
parent | 5a3da545f6ed278467b68b3b902c0fa8fcd113a1 (diff) | |
download | FreeBSD-src-ab4272e09ecd5d3838b564026ac4cbdb411fec35.zip FreeBSD-src-ab4272e09ecd5d3838b564026ac4cbdb411fec35.tar.gz |
Prevent a mapped root which appears on the server as e.g. nobody from
accessing files which it shouldn't be able to. This required a better
approximation of VOP_ACCESS for NFSv2 (NFSv3 already has an ACCESS rpc
which is a better solution) and adding a call to VOP_ACCESS from VOP_LOOKUP.
PR: kern/876, kern/2635
Submitted by: David Malone <dwmalone@maths.tcd.ie> (for kern/2635)
Diffstat (limited to 'sys/nfs')
-rw-r--r-- | sys/nfs/nfs_vnops.c | 50 |
1 files changed, 47 insertions, 3 deletions
diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c index 72a7a04..a498820 100644 --- a/sys/nfs/nfs_vnops.c +++ b/sys/nfs/nfs_vnops.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95 - * $Id: nfs_vnops.c,v 1.46 1997/04/04 17:49:33 dfr Exp $ + * $Id: nfs_vnops.c,v 1.47 1997/05/04 09:17:36 phk Exp $ */ @@ -410,8 +410,49 @@ nfs_access(ap) } 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); + } } /* @@ -834,6 +875,9 @@ nfs_lookup(ap) struct vattr vattr; int vpid; + if (error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p)) + return (error); + newvp = *vpp; vpid = newvp->v_id; /* |