Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 2 Mar 2020 00:19:32 +0000
From:      Rick Macklem <rmacklem@uoguelph.ca>
To:        Luoqi Chen <luoqi.chen@gmail.com>, Martin Simmons <martin@lispworks.com>
Cc:        freebsd-fs <freebsd-fs@freebsd.org>
Subject:   Re: Linux could write to read only files on FreeBSD NFS server
Message-ID:  <YTBPR01MB337401285CAA695E1D7AA5BADDE70@YTBPR01MB3374.CANPRD01.PROD.OUTLOOK.COM>
In-Reply-To: <CAHJqQjt4M_j5=85wcb2hcMC7nepV0ktAtOxbinvj%2BVv2cFWG5g@mail.gmail.com>
References:  <CAHJqQjuEVpL4xV1dAf6scFqFfMNm1gY3jOaO64ZQJTCQi_qzcQ@mail.gmail.com> <707243CD-C67E-4DAD-AC5A-68EC11CFFDFD@lysator.liu.se> <6EC06026-DA28-4CAC-8D56-5C7856D4625E@lysator.liu.se> <YTBPR01MB3374713F573B548791A22F98DDEB0@YTBPR01MB3374.CANPRD01.PROD.OUTLOOK.COM> <CAHJqQjsP-w9LAS4AV64Pu9Jmv0kVFodKdT_jLUcyop3sNVh_EA@mail.gmail.com> <202002281113.01SBDlsl017697@higson.cam.lispworks.com>, <CAHJqQjt4M_j5=85wcb2hcMC7nepV0ktAtOxbinvj%2BVv2cFWG5g@mail.gmail.com>

index | next in thread | previous in thread | raw e-mail

[-- Attachment #1 --]
Luoqi Chen wrote:
>On Fri, Feb 28, 2020 at 3:13 AM Martin Simmons ><martin@lispworks.com<mailto:martin@lispworks.com>> wrote:
>>>>>> On Thu, 27 Feb 2020 14:58:55 -0800, Luoqi Chen said:
>>
>> One more piece of information that might help: this behavior started
>> somewhere between centos 5 and 6, kernel 2.6.18 and 2.6.32, i.e., the same
>> script would fail on 2.6.18. Timing wise I believe it coincided with the
>> introduction of nfsv4.
>
>Have you tried mounting it with nfsv3 recently?  I can't repeat it with that
>version (I don't run nfsv4 at all).
>
>Looks like I'm getting senile... The script works correctly with nfsv3 mounts. This is
>a nfsv4 specific problem.
Ok, I've re-read the Open section of the NFSv4 RFCs. They all have similar wording.
I can see how it can be interpreted multiple ways. Here's the RFC 5661 snippet:

   Based on the share_access value (OPEN4_SHARE_ACCESS_READ,
   OPEN4_SHARE_ACCESS_WRITE, or OPEN4_SHARE_ACCESS_BOTH), the client
   should check that the requester has the proper access rights to
   perform the specified operation.  This would generally be the results
   of applying the ACL access rules to the file for the current
   requester.  However, just as with the ACCESS operation, the client
   should not attempt to second-guess the server's decisions, as access
   rights may change and may be subject to server administrative
   controls outside the ACL framework.  If the requester's READ or WRITE
   operation is not authorized (depending on the share_access value),
   the server MUST return NFS4ERR_ACCESS.

Now, I had interpreted the last sentence meaning "apply the same check
as Read/Write does". Since the owner of the file is always allowed to Read/Write
(as explained in a previous post), that is what the FreeBSD NFSv4 server does.
However, I can see that it could be interpreted as "return NFS4ERR_ACCESS if
the file modes/ACL would result in an EACCES error".
--> As such, although it could result in an inconsistency between NFSv3 and
       NFSv4, I could see the Linux client depending on that instead of using
       the replied information for the Access operation to decide if a POSIX
       Open should be allowed.

Anyhow, I've attached a trivial patch that changes the NFSv4 Open semantics
to conform to what the mode/ACL indicates.
I am not sure that this patch should be applicable to head, but if it makes the
Linux client happy, I can see it being optionally enabled via a sysctl.

Please let me know if you can test the patch and determine if the Linux NFSv4
mount works with the patched FreeBSD server.

rick

[-- Attachment #2 --]
--- fs/nfsserver/nfs_nfsdserv.c.ownerover	2020-03-01 07:20:18.576052000 -0800
+++ fs/nfsserver/nfs_nfsdserv.c	2020-03-01 07:51:00.162266000 -0800
@@ -2784,7 +2784,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int is
 	u_int32_t *tl;
 	int i, retext;
 	struct nfsstate *stp = NULL;
-	int error = 0, create, claim, exclusive_flag = 0;
+	int error = 0, create, claim, exclusive_flag = 0, override;
 	u_int32_t rflags = NFSV4OPEN_LOCKTYPEPOSIX, acemask;
 	int how = NFSCREATE_UNCHECKED;
 	int32_t cverf[2], tverf[2] = { 0, 0 };
@@ -3088,15 +3088,16 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int is
 		 */
 		nd->nd_repstat = (vp->v_type == VDIR) ? NFSERR_ISDIR : NFSERR_SYMLINK;
 	}
+	override = NFSACCCHK_NOOVERRIDE;
 	if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_WRITEACCESS))
 	    nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred,
-	        exp, p, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL);
+	        exp, p, override, NFSACCCHK_VPISLOCKED, NULL);
 	if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_READACCESS)) {
 	    nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred,
-	        exp, p, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL);
+	        exp, p, override, NFSACCCHK_VPISLOCKED, NULL);
 	    if (nd->nd_repstat)
 		nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
-		    nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
+		    nd->nd_cred, exp, p, override,
 		    NFSACCCHK_VPISLOCKED, NULL);
 	}
 
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?YTBPR01MB337401285CAA695E1D7AA5BADDE70>