diff options
author | peter <peter@FreeBSD.org> | 1998-05-20 09:05:48 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1998-05-20 09:05:48 +0000 |
commit | ef0bb328547d6b6927ca95d893f6318c71aa1b9f (patch) | |
tree | fcbcbae9d3b6c0434a2662d79353b4bc59567425 /sys/nfsserver | |
parent | 8da2aa7242a16cd01ce73206cc04fc2e9e907eba (diff) | |
download | FreeBSD-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/nfsserver')
-rw-r--r-- | sys/nfsserver/nfs_serv.c | 53 |
1 files changed, 31 insertions, 22 deletions
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c index b938de1..bfae28d 100644 --- a/sys/nfsserver/nfs_serv.c +++ b/sys/nfsserver/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 */ |