From nobody  Tue Nov 25 08:37:35 1997
Received: (from nobody@localhost)
          by hub.freebsd.org (8.8.7/8.8.7) id IAA24971;
          Tue, 25 Nov 1997 08:37:35 -0800 (PST)
          (envelope-from nobody)
Message-Id: <199711251637.IAA24971@hub.freebsd.org>
Date: Tue, 25 Nov 1997 08:37:35 -0800 (PST)
From: Joel.Faedi@esial.u-nancy.fr
To: freebsd-gnats-submit@freebsd.org
Subject: mode of file and access  on NFS mounted partitions
X-Send-Pr-Version: www-1.0

>Number:         5148
>Category:       bin
>Synopsis:       mode of file and access  on NFS mounted partitions [PATCH]
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    peter
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Nov 25 08:40:00 PST 1997
>Closed-Date:    Fri Mar 19 05:31:40 PST 1999
>Last-Modified:  Fri Mar 19 05:32:56 PST 1999
>Originator:     Joel Faedi
>Release:        2.2.5 - 3.0-971123-SNAP
>Organization:
ESIAL - Nancy (France)
>Environment:
>Description:
Owner mode is nver tested on NFS mounted file system from FreeBSD
server.An exemple will explain problem:

1) on an UFS partition:
   --------------------
> touch foo
> chmod 0000 foo
> ls -al foo
----------  1 faedi  admin  21 Nov 25 11:31 foo
> more foo 
foo: Permission denied
> echo Hello >> foo
foo: Permission denied.
>

2) on the same partition NFS mounted (on another machine):
   -------------------------------------------------------
> ls -al foo
----------  1 faedi  admin  21 Nov 25 11:31 foo
> more foo
Should never be seen
> echo Hello >> foo
> more foo
Should never be seen
Hello
>


>How-To-Repeat:
See example in full description.
>Fix:
Fix the function "nfsrv_access" in the file /usr/src/sys/nfs/nfs_serv.c.

(near line 3430)

	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 (0);

>Release-Note:
>Audit-Trail:

From: MIHIRA "Sanpei" Yoshiro <sanpei@yy.cs.keio.ac.jp>
To: freebsd-gnats-submit@freebsd.org, Joel.Faedi@esial.u-nancy.fr
Cc:  Subject: Re: bin/5148: mode of file and access  on NFS mounted partitions
Date: Thu, 11 Dec 1997 17:23:30 +0900

 Hi.
 
   I also send-pr-ed[1] this problem. 
 
   I checked NetBSD system, it is still solved. And I checked NetBSD
 source-changes mailing list, I got below message[2].
 
 ----------From NetBSD source-changes Mailing list----
 Date: 22 Feb 1997 03:00:03 -0000
 Message-ID: <19970222030003.14225.qmail@mail.NetBSD.ORG>
 From: source@NetBSD.ORG
 To: source-changes@NetBSD.ORG
 Subject: NetBSD master CVS tree commits
 Sender: source-changes-owner@NetBSD.ORG
 Precedence: list
 
 ((omitted))
 
 fvdl
 Fri Feb 21 18:56:02 PST 1997
 Update of /a/cvsroot/src/sys/nfs
 In directory netbsd1:/var/slash-tmp/cvs-serv13955
 
 Modified Files:
 	nfs_serv.c 
 Log Message:
 Fixes from BSDI (thanks go to Keith Bostic). Original RCS message:
 
 date: 1996/11/20 20:02:54;  author: pjd;  state: Exp;  lines: +7 -4
 In nfsrv_access(), if VOP_ACCESS() returns an error and the
 error == EPERM or its not the owner doing the access, return the error.
 ----------From NetBSD source-changes Mailing list----
 
   I think this problem is from NET/2 or Lite2(?). BSD/OS and NetBSD
 was already fixed....
 
   I will review NetBSD nfs_serv.c code, but I don't have enough time
 to create patch.
 
 [1] bin/4805 NFSv3 server readonly file permission problem
 http://www.freebsd.org/cgi/query-pr.cgi?pr=4805
 
 [2] NetBSD source-changes mailing list
 ftp://ftp.iij.ad.jp/pub/NetBSD/mailing-lists/source-changes/source-changes.0317
 
 ---
 Yoshiro MIHIRA
 sanpei@jp.freebsd.org
 sanpei@yy.cs.keio.ac.jp

From: MIHIRA "Sanpei" Yoshiro <sanpei@yy.cs.keio.ac.jp>
To: freebsd-gnats-submit@freebsd.org, Joel.Faedi@esial.u-nancy.fr,
        dfr@freebsd.org
Cc:  Subject: Re: bin/5148: mode of file and access  on NFS mounted partitions
Date: Fri, 26 Dec 1997 21:10:12 +0900

   I reviewd related sources on NetBSD/OpenBSD.  In OpenBSD CVS[1],
 sys/nfs/nfs_serv.c rev.1.8 and rev.1.9. and nfs_serv.c in
 NetBSD-current[2], is for this problem.
 
   I made patch for FreeBSD-current, FreeBSD-stable source from these
 changes in Net/OpenBSD.
 
   By the way, nfs_serv.c is different between NetBSD and OpenBSD.
 NetBSD check only NACCES, but OpenBSD check NACCES and EPERM.  I
 think VOP_ACCESS function is only returned
 EACCESS(sys/ufs/ufs/ufs_vnops.c:ufs_access function.) In my patch, I
 only check NACCESS.
 
   I hope to merge these.
 
 Thank you.
 ---
 Yoshiro MIHIRA
 Dr. Candidate, Yamamoto Lab.
 Department of Computer Science
 Keio University. Yokohama, Japan
 
 [1] OpenBSD CVS repository
 http://www.openbsd.org/cgi-bin/cvsweb/src/sys/nfs/nfs_serv.c
 
 [2] NetBSD source tree
 ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/sys/nfs
 
 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 */
  
Responsible-Changed-From-To: freebsd-bugs->peter 
Responsible-Changed-By: peter 
Responsible-Changed-When: Sat Apr 25 22:46:06 PDT 1998 
Responsible-Changed-Why:  
I'll take this one.. 

From: MIHIRA Sanpei Yoshiro <sanpei@sanpei.org>
To: freebsd-gnats-submit@freebsd.org, sanpei@yy.cs.keio.ac.jp,
        Joel.Faedi@esial.u-nancy.fr
Cc:  Subject: Re: bin/5148: mode of file and access  on NFS mounted partitions [PATCH]
Date: Mon, 04 Jan 1999 00:20:17 +0900

 Hi.
 
 This problem already fixed below commit.  Please close this PR.
 
 http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/nfs/nfs_serv.c
 >1.61 Wed May 20 9:05:48 1998 UTC by peter 
 >
 >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>
 
 Thank you
 MIHIRA Yoshiro
State-Changed-From-To: open->closed 
State-Changed-By: sheldonh 
State-Changed-When: Fri Mar 19 05:31:40 PST 1999 
State-Changed-Why:  
Fixed in src/sys/nfs/nfs_serv.c rev >1.61 . 
>Unformatted:
