summaryrefslogtreecommitdiffstats
path: root/sys/nfs/nfs_serv.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1998-05-20 09:05:48 +0000
committerpeter <peter@FreeBSD.org>1998-05-20 09:05:48 +0000
commitef0bb328547d6b6927ca95d893f6318c71aa1b9f (patch)
treefcbcbae9d3b6c0434a2662d79353b4bc59567425 /sys/nfs/nfs_serv.c
parent8da2aa7242a16cd01ce73206cc04fc2e9e907eba (diff)
downloadFreeBSD-src-ef0bb328547d6b6927ca95d893f6318c71aa1b9f.zip
FreeBSD-src-ef0bb328547d6b6927ca95d893f6318c71aa1b9f.tar.gz
Only ignore "owner" permissions selectively rather than always. In some
cases we ignore it (eg: read/write) to maintain chmod-after-open semantics but in other cases we do care, eg: creating files, access() etc. Never ignore errors from VOP_ACCESS() on immutable files. This apparently comes from BSDI (from Keith Bostic) via NetBSD. PR: 5148 Submitted by: Yoshiro MIHIRA <sanpei@yy.cs.keio.ac.jp>
Diffstat (limited to 'sys/nfs/nfs_serv.c')
-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 b938de1..bfae28d 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.59 1998/03/30 09:53:56 phk Exp $
+ * $Id: nfs_serv.c,v 1.60 1998/05/07 04:58:51 msmith Exp $
*/
/*
@@ -103,7 +103,7 @@ static 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);
@@ -634,8 +634,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)
@@ -850,7 +850,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);
@@ -1127,7 +1127,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)
@@ -1528,7 +1528,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;
@@ -2590,7 +2590,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));
@@ -2843,7 +2843,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);
@@ -3427,18 +3427,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;
@@ -3464,10 +3469,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 */
OpenPOWER on IntegriCloud