summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>1998-05-20 11:36:37 +0000
committerPeter Wemm <peter@FreeBSD.org>1998-05-20 11:36:37 +0000
commita6d2b31c56a0381a146d16e1d2b688d277c33bf3 (patch)
tree7ba12d2f310da9120a1e01c5646582e26c914b3c
parente819e61bd43013c03a0a64f21850c8ae96b84012 (diff)
Notes
-rw-r--r--sys/nfs/nfs_serv.c53
1 files changed, 31 insertions, 22 deletions
diff --git a/sys/nfs/nfs_serv.c b/sys/nfs/nfs_serv.c
index 54690b19d289..b0079e673004 100644
--- a/sys/nfs/nfs_serv.c
+++ b/sys/nfs/nfs_serv.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_serv.c 8.3 (Berkeley) 1/12/94
- * $Id: nfs_serv.c,v 1.34.2.2 1997/06/16 11:24:27 bde Exp $
+ * $Id: nfs_serv.c,v 1.34.2.3 1998/03/01 22:33:27 steve Exp $
*/
/*
@@ -103,7 +103,7 @@ int nfs_async;
SYSCTL_INT(_vfs_nfs, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0, "");
static int nfsrv_access __P((struct vnode *,int,struct ucred *,int,
- struct proc *));
+ struct proc *, int));
static void nfsrvw_coalesce __P((struct nfsrv_descript *,
struct nfsrv_descript *));
@@ -148,7 +148,7 @@ nfsrv3_access(nfsd, slp, procp, mrq)
}
nfsmode = fxdr_unsigned(u_long, *tl);
if ((nfsmode & NFSV3ACCESS_READ) &&
- nfsrv_access(vp, VREAD, cred, rdonly, procp))
+ nfsrv_access(vp, VREAD, cred, rdonly, procp, 0))
nfsmode &= ~NFSV3ACCESS_READ;
if (vp->v_type == VDIR)
testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
@@ -156,14 +156,14 @@ nfsrv3_access(nfsd, slp, procp, mrq)
else
testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
if ((nfsmode & testmode) &&
- nfsrv_access(vp, VWRITE, cred, rdonly, procp))
+ nfsrv_access(vp, VWRITE, cred, rdonly, procp, 0))
nfsmode &= ~testmode;
if (vp->v_type == VDIR)
testmode = NFSV3ACCESS_LOOKUP;
else
testmode = NFSV3ACCESS_EXECUTE;
if ((nfsmode & testmode) &&
- nfsrv_access(vp, VEXEC, cred, rdonly, procp))
+ nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0))
nfsmode &= ~testmode;
getret = VOP_GETATTR(vp, vap, cred, procp);
vput(vp);
@@ -331,7 +331,7 @@ nfsrv_setattr(nfsd, slp, procp, mrq)
error = EISDIR;
goto out;
} else if (error = nfsrv_access(vp, VWRITE, cred, rdonly,
- procp))
+ procp, 0))
goto out;
}
error = VOP_SETATTR(vp, vap, cred, procp);
@@ -588,8 +588,8 @@ nfsrv_read(nfsd, slp, procp, mrq)
}
if (!error) {
nqsrv_getl(vp, ND_READ);
- if (error = nfsrv_access(vp, VREAD, cred, rdonly, procp))
- error = nfsrv_access(vp, VEXEC, cred, rdonly, procp);
+ if (error = nfsrv_access(vp, VREAD, cred, rdonly, procp, 1))
+ error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 1);
}
getret = VOP_GETATTR(vp, vap, cred, procp);
if (!error)
@@ -804,7 +804,7 @@ nfsrv_write(nfsd, slp, procp, mrq)
}
if (!error) {
nqsrv_getl(vp, ND_WRITE);
- error = nfsrv_access(vp, VWRITE, cred, rdonly, procp);
+ error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
}
if (error) {
vput(vp);
@@ -1078,7 +1078,7 @@ loop1:
vp = NULL;
if (!error) {
nqsrv_getl(vp, ND_WRITE);
- error = nfsrv_access(vp, VWRITE, cred, rdonly, procp);
+ error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
}
if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
@@ -1476,7 +1476,7 @@ nfsrv_create(nfsd, slp, procp, mrq)
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (vap->va_size != -1) {
error = nfsrv_access(vp, VWRITE, cred,
- (nd.ni_cnd.cn_flags & RDONLY), procp);
+ (nd.ni_cnd.cn_flags & RDONLY), procp, 0);
if (!error) {
nqsrv_getl(vp, ND_WRITE);
tempsize = vap->va_size;
@@ -2533,7 +2533,7 @@ nfsrv_readdir(nfsd, slp, procp, mrq)
error = NFSERR_BAD_COOKIE;
}
if (!error)
- error = nfsrv_access(vp, VEXEC, cred, rdonly, procp);
+ error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
if (error) {
vput(vp);
nfsm_reply(NFSX_POSTOPATTR(v3));
@@ -2799,7 +2799,7 @@ nfsrv_readdirplus(nfsd, slp, procp, mrq)
error = NFSERR_BAD_COOKIE;
if (!error) {
nqsrv_getl(vp, ND_READ);
- error = nfsrv_access(vp, VEXEC, cred, rdonly, procp);
+ error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
}
if (error) {
vput(vp);
@@ -3392,18 +3392,23 @@ nfsrv_noop(nfsd, slp, procp, mrq)
* refer to files already opened by a Unix client. You cannot just use
* vn_writechk() and VOP_ACCESS() for two reasons.
* 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
- * 2 - The owner is to be given access irrespective of mode bits so that
- * processes that chmod after opening a file don't break. I don't like
- * this because it opens a security hole, but since the nfs server opens
- * a security hole the size of a barn door anyhow, what the heck.
+ * 2 - The owner is to be given access irrespective of mode bits for some
+ * operations, so that processes that chmod after opening a file don't
+ * break. I don't like this because it opens a security hole, but since
+ * the nfs server opens a security hole the size of a barn door anyhow,
+ * what the heck.
+ *
+ * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
+ * will return EPERM instead of EACCESS. EPERM is always an error.
*/
static int
-nfsrv_access(vp, flags, cred, rdonly, p)
+nfsrv_access(vp, flags, cred, rdonly, p, override)
register struct vnode *vp;
int flags;
register struct ucred *cred;
int rdonly;
struct proc *p;
+ int override;
{
struct vattr vattr;
int error;
@@ -3429,10 +3434,14 @@ nfsrv_access(vp, flags, cred, rdonly, p)
}
if (error = VOP_GETATTR(vp, &vattr, cred, p))
return (error);
- if ((error = VOP_ACCESS(vp, flags, cred, p)) &&
- cred->cr_uid != vattr.va_uid)
- return (error);
- return (0);
+ error = VOP_ACCESS(vp, flags, cred, p);
+ /*
+ * Allow certain operations for the owner (reads and writes
+ * on files that are already open).
+ */
+ if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
+ error = 0;
+ return error;
}
#endif /* NFS_NOSERVER */