From owner-FreeBSD-tech-jp@jp.freebsd.org  Fri Dec 26 21:34:02 1997
Received: by jaz.jp.freebsd.org (8.8.8+3.0Wbeta7/8.7.3) id VAA11159
	Fri, 26 Dec 1997 21:34:02 +0900 (JST)
Received: by jaz.jp.freebsd.org (8.8.8+3.0Wbeta7/8.7.3) with ESMTP id VAA11154
	for <FreeBSD-tech-jp@jp.freebsd.org>; Fri, 26 Dec 1997 21:34:00 +0900 (JST)
Received: from lavender.sanpei.org (u1204.seaple.icc.ne.jp [203.140.41.204])
	by titanium.yy.cs.keio.ac.jp (8.8.8+3.0Wbeta7/3.6W) with ESMTP id VAA07295
	for <FreeBSD-tech-jp@jp.freebsd.org>; Fri, 26 Dec 1997 21:33:59 +0900 (JST)
Received: (from sanpei@localhost)
	by lavender.sanpei.org (8.8.5/3.6Wbeta4) id VAA03526;
	Fri, 26 Dec 1997 21:33:57 +0900 (JST)
Message-Id: <199712261233.VAA03526@lavender.sanpei.org>
To: FreeBSD-tech-jp@jp.freebsd.org
In-Reply-To: Your message of "Fri, 12 Dec 1997 02:48:49 +0900"
References: <19971212024849H.simokawa@sat.t.u-tokyo.ac.jp>
X-Mailer: Mew version 1.70 on Emacs 19.28.1 / Mule 2.3
Mime-Version: 1.0
Content-Type: Multipart/Mixed;
	boundary="--Next_Part(Fri_Dec_26_21:33:47_1997)--"
Content-Transfer-Encoding: 7bit
Date: Fri, 26 Dec 1997 21:33:54 +0900
From: MIHIRA "Sanpei" Yoshiro <sanpei@yy.cs.keio.ac.jp>
Reply-To: FreeBSD-tech-jp@jp.freebsd.org
Precedence: bulk
X-Distribute: distribute [version 2.1 (Alpha) patchlevel=24]
X-Sequence: FreeBSD-tech-jp 1040
Subject: [FreeBSD-tech-jp 1040] Re: NFSv3 server readonly file permissionproblem
Errors-To: owner-FreeBSD-tech-jp@jp.freebsd.org
Sender: owner-FreeBSD-tech-jp@jp.freebsd.org

----Next_Part(Fri_Dec_26_21:33:47_1997)--
Content-Type: Text/Plain; charset=iso-2022-jp
Content-Transfer-Encoding: 7bit

  NFSv3 server $B$G(B readonly file $B$K$b=q9~$G$-$F$7$^$&LdBj$G$9$,(B. $B$_$J$5(B
$B$s$N>pJs$G$I$&$K$+2r7h$G$-(B, $B@h$[$IK\2H$KJs9p$7$F$*$-$^$7$?(B.

  $B7k6I(B NetBSD/OpenBSD $B$G$O2r7h$7$F$$$k$h$&$J$N$G(B, NetBSD $B$N(B 
source-changes $B$d(B OpenBSD $B$N(B CVS repository $B$r;2>H$7$FKvHx$N(B patch 
$B$r$D$/$j$^$7$?(B.

  BSD/OS $B$G$b2r7h$7$F$$$k$H$NOC$G$9$,(B, BSD/OS 3.1 $B$r$*;}$A$N?M$I$&$G(B
$B$7$g$&$+(B? BSD/OS 3.0 $B$G$O$^$@LdBj$,$"$j$^$7$?(B.

sanpei
CVS $B$C$FJXMx$G$9$h$M(B :-)

----Next_Part(Fri_Dec_26_21:33:47_1997)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

for FreeBSD-current
--- sys/nfs/nfs_serv.c.orig	Wed Dec 17 18:11:16 1997
+++ sys/nfs/nfs_serv.c	Mon Dec 22 19:53:28 1997
@@ -101,7 +101,7 @@
 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 *));
 
@@ -146,7 +146,7 @@
 	}
 	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 |
@@ -154,14 +154,14 @@
 	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);
@@ -329,7 +329,7 @@
 			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);
@@ -632,8 +632,8 @@
 	}
 	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)
@@ -848,7 +848,7 @@
 	}
 	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);
@@ -1125,7 +1125,7 @@
 		    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)
@@ -1523,7 +1523,7 @@
 		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;
@@ -2579,7 +2579,7 @@
 			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));
@@ -2832,7 +2832,7 @@
 		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);
@@ -3412,18 +3412,20 @@
  * 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.
  */
 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;
@@ -3449,10 +3451,14 @@
 	}
 	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 */
 

----------
for FreeBSD-stable
--- sys/nfs/nfs_serv.c.orig	Tue Dec 16 18:04:11 1997
+++ sys/nfs/nfs_serv.c	Mon Dec 22 19:54:13 1997
@@ -103,7 +103,7 @@
 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 @@
 	}
 	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 @@
 	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 @@
 			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 @@
 	}
 	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 @@
 	}
 	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 @@
 		    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 @@
 		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 @@
 			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 @@
 		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,20 @@
  * 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.
  */
 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 +3431,14 @@
 	}
 	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 */
 

----Next_Part(Fri_Dec_26_21:33:47_1997)----
