-/* $OpenBSD: nfs_serv.c,v 1.7 1996/11/08 23:20:14 niklas Exp $ */
+/* $OpenBSD: nfs_serv.c,v 1.8 1996/12/14 15:36:50 deraadt Exp $ */
/* $NetBSD: nfs_serv.c,v 1.25 1996/03/02 15:55:52 jtk Exp $ */
/*
}
nfsmode = fxdr_unsigned(u_int32_t, *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 |
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, &va, cred, procp);
vput(vp);
error = EISDIR;
goto out;
} else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
- procp)) != 0)
+ procp, 0)) != 0)
goto out;
}
error = VOP_SETATTR(vp, &va, cred, procp);
}
if (!error) {
nqsrv_getl(vp, ND_READ);
- if ((error = nfsrv_access(vp, VREAD, cred, rdonly, procp)) != 0)
- error = nfsrv_access(vp, VEXEC, cred, rdonly, procp);
+ if ((error = nfsrv_access(vp, VREAD, cred, rdonly, procp, 1)) != 0)
+ error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 1);
}
getret = VOP_GETATTR(vp, &va, cred, procp);
if (!error)
}
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);
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)
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (va.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 = va.va_size;
#endif
}
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));
#endif
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);
* 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.
*/
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;
if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp))
return (ETXTBSY);
}
- error = VOP_GETATTR(vp, &vattr, cred, p);
- if (error)
- return (error);
- if ((error = VOP_ACCESS(vp, flags, cred, p)) != 0 &&
- 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 == EPERM || error == EACCES) &&
+ cred->cr_uid == vattr.va_uid)
+ error = 0;
+ return error;
}