Skip to contentSkip to conversation

nfsd: fix supported attributes for acl & labels

PATCH New J. Bruce Fields 2 participants 4 messages Jan 12, 2017

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/3 nfsd: fix supported attributes for acl & labels

From: "J. Bruce Fields" <[email protected]>

Oops--in 916d2d844afd I moved some constants into an array for convenience, but here I'm accidentally writing to that array.

The effect is that if you ever encounter a filesystem lacking support for ACLs or security labels, then all queries of supported attributes will report that attribute as unsupported from then on.

Fixes 916d2d844afd "nfsd: clean up supported attribute handling"
---
 fs/nfsd/nfs4xdr.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
fs/nfsd/nfs4xdr.c +3 -1
index 64c262aef633..048b06861f94 100644
@@ -2439,7 +2439,9 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
 	p++;                /* to be backfilled later */
 
 	if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
-		u32 *supp = nfsd_suppattrs[minorversion];
+		u32 supp[3];
+
+		memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
 
 		if (!IS_POSIXACL(dentry->d_inode))
 			supp[0] &= ~FATTR4_WORD0_ACL;
Signature · 1 line
2.9.3
#1 lore raw

PATCH 2/3 nfsd: constify nfsd_suppatttrs

From: "J. Bruce Fields" <[email protected]>

To keep me from making that mistake again.

---
 fs/nfsd/nfs4xdr.c | 2 +-
 fs/nfsd/nfsd.h    | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)
fs/nfsd/nfs4xdr.c +1 -1
index 048b06861f94..7a63d442042c 100644
@@ -58,7 +58,7 @@
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
 
-u32 nfsd_suppattrs[3][3] = {
+const u32 nfsd_suppattrs[3][3] = {
 	{NFSD4_SUPPORTED_ATTRS_WORD0,
 	 NFSD4_SUPPORTED_ATTRS_WORD1,
 	 NFSD4_SUPPORTED_ATTRS_WORD2},
fs/nfsd/nfsd.h +3 -3
index d74c8c44dc35..d96606801d47 100644
@@ -362,16 +362,16 @@ void		nfsd_lockd_shutdown(void);
 	FATTR4_WORD2_MODE_UMASK | \
 	NFSD4_2_SECURITY_ATTRS)
 
-extern u32 nfsd_suppattrs[3][3];
+extern const u32 nfsd_suppattrs[3][3];
 
-static inline bool bmval_is_subset(u32 *bm1, u32 *bm2)
+static inline bool bmval_is_subset(const u32 *bm1, const u32 *bm2)
 {
 	return !((bm1[0] & ~bm2[0]) ||
 	         (bm1[1] & ~bm2[1]) ||
 		 (bm1[2] & ~bm2[2]));
 }
 
-static inline bool nfsd_attrs_supported(u32 minorversion, u32 *bmval)
+static inline bool nfsd_attrs_supported(u32 minorversion, const u32 *bmval)
 {
 	return bmval_is_subset(bmval, nfsd_suppattrs[minorversion]);
 }
Signature · 1 line
2.9.3
#2 lore raw

PATCH 3/3 nfsd: opt in to labeled nfs per export

In reply to J. Bruce Fields

From: "J. Bruce Fields" <[email protected]>

Currently turning on NFSv4.2 results in 4.2 clients suddenly seeing the individual file labels as they're set on the server. This is not what they've previously seen, and not appropriate in may cases. (In particular, if clients have heterogenous security policies then one client's labels may not even make sense to another.) Labeled NFS should be opted in only in those cases when the administrator knows it makes sense.

It's helpful to be able to turn 4.2 on by default, and otherwise the protocol upgrade seems free of regressions. So, default labeled NFS to off and provide an export flag to reenable it.

Users wanting labeled NFS support on an export will henceforth need to:

- make sure 4.2 support is enabled on client and server (as before), and
- upgrade the server nfs-utils to a version supporting the new "security_label" export flag.
- set that "security_label" flag on the export.

This is commit may be seen as a regression to anyone currently depending on security labels. We believe those cases are currently rare.

---
 fs/nfsd/export.c                 | 1 +
 fs/nfsd/nfs4proc.c               | 4 ++++
 fs/nfsd/nfs4xdr.c                | 5 ++++-
 include/uapi/linux/nfsd/export.h | 5 +++--
 4 files changed, 12 insertions(+), 3 deletions(-)
fs/nfsd/export.c +1 -0
index 43e109cc0ccc..e71f11b1a180 100644
@@ -1102,6 +1102,7 @@ static struct flags {
 	{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
 	{ NFSEXP_V4ROOT, {"v4root", ""}},
 	{ NFSEXP_PNFS, {"pnfs", ""}},
+	{ NFSEXP_SECURITY_LABEL, {"security_label", ""}},
 	{ 0, {"", ""}}
 };
 
fs/nfsd/nfs4proc.c +4 -0
index 74a6e573e061..6f0b89d1c09b 100644
@@ -95,11 +95,15 @@ check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		   u32 *bmval, u32 *writable)
 {
 	struct dentry *dentry = cstate->current_fh.fh_dentry;
+	struct svc_export *exp = cstate->current_fh.fh_export;
 
 	if (!nfsd_attrs_supported(cstate->minorversion, bmval))
 		return nfserr_attrnotsupp;
 	if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry)))
 		return nfserr_attrnotsupp;
+	if ((bmval[2] & FATTR4_WORD2_SECURITY_LABEL) &&
+			!(exp->ex_flags & NFSEXP_SECURITY_LABEL))
+		return nfserr_attrnotsupp;
 	if (writable && !bmval_is_subset(bmval, writable))
 		return nfserr_inval;
 	if (writable && (bmval[2] & FATTR4_WORD2_MODE_UMASK) &&
fs/nfsd/nfs4xdr.c +4 -1
index 7a63d442042c..0d6b257ee1a0 100644
@@ -2416,8 +2416,11 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
 	if ((bmval2 & FATTR4_WORD2_SECURITY_LABEL) ||
 	     bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
-		err = security_inode_getsecctx(d_inode(dentry),
+		if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
+			err = security_inode_getsecctx(d_inode(dentry),
 						&context, &contextlen);
+		else
+			err = -EOPNOTSUPP;
 		contextsupport = (err == 0);
 		if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
 			if (err == -EOPNOTSUPP)
include/uapi/linux/nfsd/export.h +3 -2
index 0df7bd5d2fb1..c3be256107c6 100644
@@ -32,7 +32,8 @@
 #define NFSEXP_ASYNC		0x0010
 #define NFSEXP_GATHERED_WRITES	0x0020
 #define NFSEXP_NOREADDIRPLUS    0x0040
-/* 80 100 currently unused */
+#define NFSEXP_SECURITY_LABEL	0x0080
+/* 0x100 currently unused */
 #define NFSEXP_NOHIDE		0x0200
 #define NFSEXP_NOSUBTREECHECK	0x0400
 #define	NFSEXP_NOAUTHNLM	0x0800		/* Don't authenticate NLM requests - just trust */
@@ -53,7 +54,7 @@
 #define NFSEXP_PNFS		0x20000
 
 /* All flags that we claim to support.  (Note we don't support NOACL.) */
-#define NFSEXP_ALLFLAGS		0x3FE7F
+#define NFSEXP_ALLFLAGS		0x3FEFF
 
 /* The flags that may vary depending on security flavor: */
 #define NFSEXP_SECINFO_FLAGS	(NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
Signature · 1 line
2.9.3
#3 lore raw

PATCH 1/1 exportfs: support "security_label" export option

From: "J. Bruce Fields" <[email protected]>

On recent kernels only exports with NFSEXP_SECURITY_LABEL set will export security labels.

---
 support/include/nfs/export.h | 3 ++-
 support/nfs/exports.c        | 4 ++++
 utils/exportfs/exportfs.c    | 2 ++
 utils/exportfs/exports.man   | 8 ++++++++
 4 files changed, 16 insertions(+), 1 deletion(-)
support/include/nfs/export.h +2 -1
index 1194255899bd..0eca828ee3ad 100644
@@ -18,7 +18,8 @@
 #define NFSEXP_ASYNC		0x0010
 #define NFSEXP_GATHERED_WRITES	0x0020
 #define NFSEXP_NOREADDIRPLUS	0x0040
-/* 80, 100 unused */
+#define NFSEXP_SECURITY_LABEL	0x0080
+/* 0x100 unused */
 #define NFSEXP_NOHIDE		0x0200
 #define NFSEXP_NOSUBTREECHECK	0x0400
 #define NFSEXP_NOAUTHNLM	0x0800
support/nfs/exports.c +4 -0
index d992747c13a1..92bd6e60ddf7 100644
@@ -274,6 +274,8 @@ putexportent(struct exportent *ep)
 		"no_" : "");
 	if (ep->e_flags & NFSEXP_NOREADDIRPLUS)
 		fprintf(fp, "nordirplus,");
+	if (ep->e_flags & NFSEXP_SECURITY_LABEL)
+		fprintf(fp, "security_label,");
 	fprintf(fp, "%spnfs,", (ep->e_flags & NFSEXP_PNFS)? "" : "no_");
 	if (ep->e_flags & NFSEXP_FSID) {
 		fprintf(fp, "fsid=%d,", ep->e_fsid);
@@ -543,6 +545,8 @@ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
 			setflags(NFSEXP_ASYNC, active, ep);
 		else if (!strcmp(opt, "nordirplus"))
 			setflags(NFSEXP_NOREADDIRPLUS, active, ep);
+		else if (!strcmp(opt, "security_label"))
+			setflags(NFSEXP_SECURITY_LABEL, active, ep);
 		else if (!strcmp(opt, "nohide"))
 			setflags(NFSEXP_NOHIDE, active, ep);
 		else if (!strcmp(opt, "hide"))
utils/exportfs/exportfs.c +2 -0
index 15a15835a01f..38039978ef5f 100644
@@ -705,6 +705,8 @@ dump(int verbose, int export_format)
 				c = dumpopt(c, "insecure_locks");
 			if (ep->e_flags & NFSEXP_NOREADDIRPLUS)
 				c = dumpopt(c, "nordirplus");
+			if (ep->e_flags & NFSEXP_SECURITY_LABEL)
+				c = dumpopt(c, "security_label");
 			if (ep->e_flags & NFSEXP_NOACL)
 				c = dumpopt(c, "no_acl");
 			if (ep->e_flags & NFSEXP_PNFS)
utils/exportfs/exports.man +8 -0
index 93092463153b..d8de6bec2583 100644
@@ -417,6 +417,14 @@ devices. The default can be explicitly requested with the
 .I no_pnfs
 option.
 
+.TP
+.IR security_label
+With this option set, clients using NFSv4.2 or higher will be able to
+set and retrieve security labels (such as those used by SELinux).  This
+will only work if all clients use a consistent security policy.  Note
+that early kernels did not support this export option, and instead
+enabled security labels by default.
+
 .SS User ID Mapping
 .PP
 .B nfsd
Signature · 1 line
2.9.3