Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 May 2019 02:58:33 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r347044 - in stable/12/sys/fs: nfs nfsserver
Message-ID:  <201905030258.x432wXJc001318@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Fri May  3 02:58:33 2019
New Revision: 347044
URL: https://svnweb.freebsd.org/changeset/base/347044

Log:
  MFC: r346424
  Add support for the ModeSetMasked attribute to the NFSv4.1 server.
  
  I do not know of an extant NFSv4.1 client that currently does a Setattr
  operation for the ModeSetMasked, but it has been discussed on the linux-nfs
  mailing list.
  This patch adds support for doing a Setattr of ModeSetMasked, so that it
  will work for any future NFSv4.1 client that chooses to do so.
  Tested via a hacked FreeBSD NFSv4.1 client.

Modified:
  stable/12/sys/fs/nfs/nfsproto.h
  stable/12/sys/fs/nfsserver/nfs_nfsdport.c
  stable/12/sys/fs/nfsserver/nfs_nfsdserv.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/fs/nfs/nfsproto.h
==============================================================================
--- stable/12/sys/fs/nfs/nfsproto.h	Fri May  3 02:55:54 2019	(r347043)
+++ stable/12/sys/fs/nfs/nfsproto.h	Fri May  3 02:58:33 2019	(r347044)
@@ -1090,7 +1090,7 @@ struct nfsv3_sattr {
  */
 #define	NFSATTRBIT_SUPPSETONLY1	 (NFSATTRBM_TIMEACCESSSET |		\
 				 NFSATTRBM_TIMEMODIFYSET)
-#define	NFSATTRBIT_SUPPSETONLY2	0
+#define	NFSATTRBIT_SUPPSETONLY2	(NFSATTRBM_MODESETMASKED)
 
 /*
  * NFSATTRBIT_SETABLE - SETABLE0 - bits 0<->31
@@ -1106,7 +1106,8 @@ struct nfsv3_sattr {
  	NFSATTRBM_OWNERGROUP |						\
  	NFSATTRBM_TIMEACCESSSET |					\
  	NFSATTRBM_TIMEMODIFYSET)
-#define	NFSATTRBIT_SETABLE2		0
+#define	NFSATTRBIT_SETABLE2						\
+	(NFSATTRBM_MODESETMASKED)
 
 /*
  * NFSATTRBIT_NFSV41 - Attributes only supported by NFSv4.1.

Modified: stable/12/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- stable/12/sys/fs/nfsserver/nfs_nfsdport.c	Fri May  3 02:55:54 2019	(r347043)
+++ stable/12/sys/fs/nfsserver/nfs_nfsdport.c	Fri May  3 02:58:33 2019	(r347044)
@@ -2696,10 +2696,12 @@ nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, str
 	int attrsum = 0;
 	int i, j;
 	int error, attrsize, bitpos, aclsize, aceerr, retnotsup = 0;
-	int toclient = 0;
+	int moderet, toclient = 0;
 	u_char *cp, namestr[NFSV4_SMALLSTR + 1];
 	uid_t uid;
 	gid_t gid;
+	u_short mode, mask;		/* Same type as va_mode. */
+	struct vattr va;
 
 	error = nfsrv_getattrbits(nd, attrbitp, NULL, &retnotsup);
 	if (error)
@@ -2717,6 +2719,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, str
 	} else {
 		bitpos = 0;
 	}
+	moderet = 0;
 	for (; bitpos < NFSATTRBIT_MAX; bitpos++) {
 	    if (attrsum > attrsize) {
 		error = NFSERR_BADXDR;
@@ -2766,6 +2769,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, str
 			attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(i));
 			break;
 		case NFSATTRBIT_MODE:
+			moderet = NFSERR_INVAL;	/* Can't do MODESETMASKED. */
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 			nvap->na_mode = nfstov_mode(*tl);
 			attrsum += NFSX_UNSIGNED;
@@ -2868,6 +2872,32 @@ nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, str
 			    if (!toclient)
 				nvap->na_vaflags |= VA_UTIMES_NULL;
 			}
+			break;
+		case NFSATTRBIT_MODESETMASKED:
+			NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
+			mode = fxdr_unsigned(u_short, *tl++);
+			mask = fxdr_unsigned(u_short, *tl);
+			/*
+			 * vp == NULL implies an Open/Create operation.
+			 * This attribute can only be used for Setattr and
+			 * only for NFSv4.1 or higher.
+			 * If moderet != 0, a mode attribute has also been
+			 * specified and this attribute cannot be done in the
+			 * same Setattr operation.
+			 */
+			if ((nd->nd_flag & ND_NFSV41) == 0)
+				nd->nd_repstat = NFSERR_ATTRNOTSUPP;
+			else if ((mode & ~07777) != 0 || (mask & ~07777) != 0 ||
+			    vp == NULL)
+				nd->nd_repstat = NFSERR_INVAL;
+			else if (moderet == 0)
+				moderet = VOP_GETATTR(vp, &va, nd->nd_cred);
+			if (moderet == 0)
+				nvap->na_mode = (mode & mask) |
+				    (va.va_mode & ~mask);
+			else
+				nd->nd_repstat = moderet;
+			attrsum += 2 * NFSX_UNSIGNED;
 			break;
 		default:
 			nd->nd_repstat = NFSERR_ATTRNOTSUPP;

Modified: stable/12/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- stable/12/sys/fs/nfsserver/nfs_nfsdserv.c	Fri May  3 02:55:54 2019	(r347043)
+++ stable/12/sys/fs/nfsserver/nfs_nfsdserv.c	Fri May  3 02:58:33 2019	(r347044)
@@ -461,13 +461,18 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int
 		}
 	    }
 	    if (!nd->nd_repstat &&
-		NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE)) {
+		(NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE) ||
+		 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODESETMASKED))) {
 		NFSVNO_ATTRINIT(&nva2);
 		NFSVNO_SETATTRVAL(&nva2, mode, nva.na_mode);
 		nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
 		    exp);
-		if (!nd->nd_repstat)
-		    NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODE);
+		if (!nd->nd_repstat) {
+		    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE))
+			NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODE);
+		    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODESETMASKED))
+			NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODESETMASKED);
+		}
 	    }
 
 #ifdef NFS4_ACL_EXTATTR_NAME



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