From a973eeb2c176e00dba8a7ec7bbb2a844ffd832b7 Mon Sep 17 00:00:00 2001 From: Doug Rabson <dfr@FreeBSD.org> Date: Fri, 9 May 1997 13:18:42 +0000 Subject: [PATCH] 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) --- sys/nfs/nfs_vnops.c | 50 ++++++++++++++++++++++++++++++++++++--- sys/nfsclient/nfs_vnops.c | 50 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 94 insertions(+), 6 deletions(-) diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c index 72a7a04287b7..a49882017079 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; /* diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c index 72a7a04287b7..a49882017079 100644 --- a/sys/nfsclient/nfs_vnops.c +++ b/sys/nfsclient/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; /*