Re: [Labeled-nfs] [RFC v3] Security Label Support for NFSv4

Previous thread: [PATCH] x86: enable CPUID on Cyrix cpus with CPUID disabled by Krzysztof Helt on Monday, September 29, 2008 - 10:24 am. (3 messages)

Next thread: [PATCH 00/31] cpumask: Provide new cpumask API by Mike Travis on Monday, September 29, 2008 - 11:02 am. (1 message)
From: David P. Quigley
Date: Monday, September 29, 2008 - 10:06 am

I sent this patchset out just before LPC so I think it might have been
overlooked by some people. I am resending the patchset with some corrections
based on comments by Casey and Steve in hopes that it gets more attention this
time.

It has been six months since the last time we submitted a patch set to the
mailing list for review. In this time we have fixed almost all of the issues
that people have had with the last patch set and have added a new feature to
allow for process labels to be transported with the RPC request. Below I
review each of the issues raised with the last patch set and what was done to
fix them. I also list the features present in this patch set and known issues.

When reviewing the code please be critical of it. We have reached the point
where we think we have the proper set of initial features implemented so we
would like to address all of the major and minor concerns with the code so it
can be cleaned up and submitted for inclusion. If you want a tree with the
patches already applied we have posted a public git tree that is ready for
cloning and use. This tree can be found at http://git.selinuxproject.org/git
and can be cloned with the command below. You can also find information on how
to setup a labeled nfs mount at http://www.selinuxproject.org/page/Labeled_NFS
however the putclientlabel mount option specified in the setup document is no
longer supported.

git-clone git://git.selinuxproject.org/~dpquigl/lnfs.git

Features:

* Client
	* Obtains labels from server for NFS files while still allowing for
	SELinux context mounts to override untrusted labeled servers.
	* Allows setting labels on files over NFS via xattr interface.
	* New security flavor (auth_seclabel) to transport process label to
	  server. This is a derivative of auth_unix so it does not support
	  kerberos which has its own issues that need to be dealt with.
* Server
	* Exports labels to clients. As of the moment there is no ability to
	restrict this based on label components such ...
From: David P. Quigley
Date: Monday, September 29, 2008 - 10:06 am

This factors out the part of the vfs_setxattr function that performs the
setting of the xattr and its notification. This is needed so the SELinux
implementation of inode_setsecctx can handle the setting of it's xattr while
maintaining the proper separation of layers.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/xattr.c            |   55 +++++++++++++++++++++++++++++++++++++-----------
 include/linux/xattr.h |    1 +
 2 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/fs/xattr.c b/fs/xattr.c
index 468377e..2f93006 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -66,22 +66,28 @@ xattr_permission(struct inode *inode, const char *name, int mask)
 	return inode_permission(inode, mask);
 }
 
-int
-vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
-		size_t size, int flags)
+/**
+ *  __vfs_setxattr_noperm - perform setxattr operation without performing
+ *  permission checks.
+ *
+ *  @dentry - object to perform setxattr on
+ *  @name - xattr name to set
+ *  @value - value to set @name to
+ *  @size - size of @value
+ *  @flags - flags to pass into filesystem operations
+ *
+ *  returns the result of the internal setxattr or setsecurity operations.
+ *
+ *  This function requires the caller to lock the inode's i_mutex before it
+ *  is executed. It also assumes that the caller will make the appropriate
+ *  permission checks.
+ */
+int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags)
 {
 	struct inode *inode = dentry->d_inode;
-	int error;
-
-	error = xattr_permission(inode, name, MAY_WRITE);
-	if (error)
-		return error;
+	int error = -EOPNOTSUPP;
 
-	mutex_lock(&inode->i_mutex);
-	error = security_inode_setxattr(dentry, name, value, size, flags);
-	if (error)
-		goto out;
-	error = -EOPNOTSUPP;
 	if (inode->i_op->setxattr) {
 		error = inode->i_op->setxattr(dentry, name, value, size, ...
From: Serge E. Hallyn
Date: Tuesday, September 30, 2008 - 12:51 pm

This part surely looks reasonable.

--

From: David P. Quigley
Date: Monday, September 29, 2008 - 10:06 am

This patch adds two entries into the fs/KConfig file. The first entry
NFS_V4_SECURITY_LABEL enables security label support for the NFSv4 client while
the second entry NFSD_V4_SECURITY_LABEL enables security labeling support on
the server side.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/Kconfig |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index abccb5d..47ffb42 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1633,6 +1633,7 @@ config NFS_V4
 
 	  If unsure, say N.
 
+
 config ROOT_NFS
 	bool "Root file system on NFS"
 	depends on NFS_FS=y && IP_PNP
@@ -1644,6 +1645,15 @@ config ROOT_NFS
 
 	  Most people say N here.
 
+config NFS_V4_SECURITY_LABEL
+	bool "Provide Security Label support for NFSv4 client"
+	depends on NFS_V4 && SECURITY
+	help
+	  Say Y here if you want label attribute support for NFS version 4.
+
+
+	  If unsure, say N.
+
 config NFSD
 	tristate "NFS server support"
 	depends on INET
@@ -1725,6 +1735,13 @@ config NFSD_V4
 
 	  If unsure, say N.
 
+config NFSD_V4_SECURITY_LABEL
+	bool "Provide Security Label support for NFSv4 server"
+	depends on NFSD_V4 && SECURITY
+	help
+	  If you would like to include support for label file attributes
+	  over NFSv4, say Y here.
+
 config LOCKD
 	tristate
 
-- 
1.5.5.1

--

From: Serge E. Hallyn
Date: Tuesday, September 30, 2008 - 1:40 pm

A little more here :)

"Say Y here if you want security label attribute support for NFS version
4.  Security labels allow security modules like SELinux and Smack to
label files to facilitate enforcement of their policies.

If you do not wish to enforce SELinux or Smack policies on NFSv4 files,
say N."

Or something...  the idea being to make it clear to anyone configuring
--

From: David P. Quigley
Date: Monday, September 29, 2008 - 10:06 am

There currently doesn't exist a labeling type that is adequate for use with
labeled NFS. Since NFS doesn't really support xattrs we can't use the use xattr
labeling behavior. For this we developed a new labeling type. The native
labeling type is used solely by NFS to ensure NFS inodes are labeled at runtime
by the NFS code instead of relying on the SELinux security server on the client
end.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 security/selinux/hooks.c            |   74 +++++++++++++++++++++++++++-------
 security/selinux/include/security.h |    4 ++
 security/selinux/ss/policydb.c      |    5 ++-
 3 files changed, 66 insertions(+), 17 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 248fa5c..78e79d3 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -88,7 +88,7 @@
 #define XATTR_SELINUX_SUFFIX "selinux"
 #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
 
-#define NUM_SEL_MNT_OPTS 4
+#define NUM_SEL_MNT_OPTS 5
 
 extern unsigned int policydb_loaded_version;
 extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
@@ -300,13 +300,14 @@ extern int ss_initialized;
 
 /* The file system's label must be initialized prior to use. */
 
-static char *labeling_behaviors[6] = {
+static char *labeling_behaviors[7] = {
 	"uses xattr",
 	"uses transition SIDs",
 	"uses task SIDs",
 	"uses genfs_contexts",
 	"not configured for labeling",
 	"uses mountpoint labeling",
+	"uses native labels",
 };
 
 static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
@@ -322,6 +323,7 @@ enum {
 	Opt_fscontext = 2,
 	Opt_defcontext = 3,
 	Opt_rootcontext = 4,
+	Opt_native_labels = 5,
 };
 
 static match_table_t tokens = {
@@ -329,6 +331,7 @@ static match_table_t tokens = {
 	{Opt_fscontext, FSCONTEXT_STR "%s"},
 	{Opt_defcontext, DEFCONTEXT_STR "%s"},
 	{Opt_rootcontext, ...
From: David P. Quigley
Date: Monday, September 29, 2008 - 10:06 am

In order to mimic the way that NFSv4 ACLs are implemented we have created a
structure to be used to pass label data up and down the call chain. This patch
adds the new structure and new members to the required NFSv4 call structures.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 include/linux/nfs4.h      |    6 ++++++
 include/linux/nfs_xdr.h   |    3 +++
 include/linux/nfsd/xdr4.h |    3 +++
 3 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 144eacf..dd99b27 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -112,6 +112,12 @@ struct nfs4_acl {
 	struct nfs4_ace	aces[0];
 };
 
+struct nfs4_label {
+	void		*label;
+	u32		len;
+};
+
+
 typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
 typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
 
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 0d77568..c4fa2df 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -135,6 +135,7 @@ struct nfs_openargs {
 	const struct nfs_server *server;	 /* Needed for ID mapping */
 	const u32 *		bitmask;
 	__u32			claim;
+	const struct nfs4_label *label;
 };
 
 struct nfs_openres {
@@ -353,6 +354,7 @@ struct nfs_setattrargs {
 	struct iattr *                  iap;
 	const struct nfs_server *	server; /* Needed for name mapping */
 	const u32 *			bitmask;
+	const struct nfs4_label *	label;
 };
 
 struct nfs_setaclargs {
@@ -577,6 +579,7 @@ struct nfs4_create_arg {
 	const struct iattr *		attrs;
 	const struct nfs_fh *		dir_fh;
 	const u32 *			bitmask;
+	const struct nfs4_label *	label;
 };
 
 struct nfs4_create_res {
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 27bd3e3..a0f3d79 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -94,6 +94,7 @@ struct nfsd4_create {
 	struct iattr	cr_iattr;           /* request */
 ...
From: David P. Quigley
Date: Monday, September 29, 2008 - 10:06 am

This patch adds a new RPC flavor that allows the NFSv4 client to pass the
process label of the calling process on the client to the server to make an
access control decision. This is accomplished by taking the credential from the
wire and replacing the acting credential on the server for the NFSD process
with that new context.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/nfs/nfs4proc.c               |    6 +-
 fs/nfsd/auth.c                  |   21 +++
 include/linux/sunrpc/auth.h     |    4 +
 include/linux/sunrpc/msg_prot.h |    1 +
 include/linux/sunrpc/svcauth.h  |    4 +
 net/sunrpc/Makefile             |    1 +
 net/sunrpc/auth.c               |   16 ++
 net/sunrpc/auth_seclabel.c      |  291 +++++++++++++++++++++++++++++++++++++++
 net/sunrpc/svc.c                |    1 +
 net/sunrpc/svcauth.c            |    6 +
 net/sunrpc/svcauth_unix.c       |   97 +++++++++++++-
 security/security.c             |    2 +
 security/selinux/hooks.c        |    2 +-
 13 files changed, 446 insertions(+), 6 deletions(-)
 create mode 100644 net/sunrpc/auth_seclabel.c

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index c4a4271..92522cc 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1410,6 +1410,9 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 	struct nfs4_state *state;
 	struct dentry *res;
 
+	cred = rpc_lookup_cred();
+	if (IS_ERR(cred))
+		return (struct dentry *)cred;
 	if (nd->flags & LOOKUP_CREATE) {
 		attr.ia_mode = nd->intent.open.create_mode;
 		attr.ia_valid = ATTR_MODE;
@@ -1420,9 +1423,6 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 		BUG_ON(nd->intent.open.flags & O_CREAT);
 	}
 
-	cred = rpc_lookup_cred();
-	if (IS_ERR(cred))
-		return (struct dentry *)cred;
 	parent = dentry->d_parent;
 	/* Protect against concurrent sillydeletes */
 	nfs_block_sillyrename(parent);
diff --git ...

On Mon, Sep 29, 2008 at 01:06:23PM -0400, David P. Quigley wrote:

checkpatch picked up on a suspect code indent for this hunk.  It is
unhappy about the second if expecting it to be indented.  By the looks
of this I am suspecting a miss-merge of the change in this function and
the second if should have been removed.  To my reading it actually still
does the right thing but ...

-apw
--


This does appear to be a miss-merge.
--

From: David P. Quigley
Date: Monday, September 29, 2008 - 10:06 am

This patch adds two new text options to to the NFS mount options to specify
security labeling. It also sends certain LSM related mount options into the
module for handling.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/nfs/super.c             |    9 +++++++++
 include/linux/nfs4_mount.h |    6 +++++-
 security/selinux/hooks.c   |    2 +-
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 9abcd2b..256ce27 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -75,6 +75,7 @@ enum {
 	Opt_acl, Opt_noacl,
 	Opt_rdirplus, Opt_nordirplus,
 	Opt_sharecache, Opt_nosharecache,
+	Opt_security_label, Opt_nosecurity_label,
 
 	/* Mount options that take integer arguments */
 	Opt_port,
@@ -128,6 +129,8 @@ static match_table_t nfs_mount_option_tokens = {
 	{ Opt_nordirplus, "nordirplus" },
 	{ Opt_sharecache, "sharecache" },
 	{ Opt_nosharecache, "nosharecache" },
+	{ Opt_security_label, "security_label" },
+	{ Opt_nosecurity_label, "nosecurity_label" },
 
 	{ Opt_port, "port=%u" },
 	{ Opt_rsize, "rsize=%u" },
@@ -1033,6 +1036,12 @@ static int nfs_parse_mount_options(char *raw,
 		case Opt_nosharecache:
 			mnt->flags |= NFS_MOUNT_UNSHARED;
 			break;
+		case Opt_nosecurity_label:
+			mnt->flags &= ~NFS4_MOUNT_SECURITY_LABEL;
+			break;
+		case Opt_security_label:
+			mnt->flags |= NFS4_MOUNT_SECURITY_LABEL;
+			break;
 
 		/*
 		 * options that take numeric values
diff --git a/include/linux/nfs4_mount.h b/include/linux/nfs4_mount.h
index a0dcf66..e65067b 100644
--- a/include/linux/nfs4_mount.h
+++ b/include/linux/nfs4_mount.h
@@ -17,6 +17,7 @@
  * but here they are anyway.
  */
 #define NFS4_MOUNT_VERSION	1
+#define NFS4_MAX_CONTEXT_LEN	4096
 
 struct nfs_string {
 	unsigned int len;
@@ -53,6 +54,8 @@ struct nfs4_mount_data {
 	/* Pseudo-flavours to use for authentication. See RFC2623 */
 	int auth_flavourlen;			/* 1 */
 	int __user ...
From: David P. Quigley
Date: Monday, September 29, 2008 - 10:06 am

The existing NFSv4 xattr handlers do not accept xattr calls to the security
namespace. This patch extends these handlers to accept xattrs from the security
namespace in addition to the default NFSv4 ACL namespace.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/nfs/nfs4proc.c   |   52 ++++++++++++++++++++++++++++++++++++++++----------
 security/security.c |    1 +
 2 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 622bf71..845e1da 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3934,10 +3934,17 @@ int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
 {
 	struct inode *inode = dentry->d_inode;
 
-	if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
-		return -EOPNOTSUPP;
-
-	return nfs4_proc_set_acl(inode, buf, buflen);
+	if (strcmp(key, XATTR_NAME_NFSV4_ACL) == 0) {
+		if (!S_ISREG(inode->i_mode) &&
+		   (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
+			return -EPERM;
+		return nfs4_proc_set_acl(inode, buf, buflen);
+	}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (security_ismaclabel(key))
+		return nfs4_set_security_label(dentry, buf, buflen);
+#endif
+	return -EOPNOTSUPP;
 }
 
 /* The getxattr man page suggests returning -ENODATA for unknown attributes,
@@ -3949,22 +3956,45 @@ ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf,
 {
 	struct inode *inode = dentry->d_inode;
 
-	if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
-		return -EOPNOTSUPP;
+	if (strcmp(key, XATTR_NAME_NFSV4_ACL) == 0)
+		return nfs4_proc_get_acl(inode, buf, buflen);
 
-	return nfs4_proc_get_acl(inode, buf, buflen);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (security_ismaclabel(key))
+		return nfs4_get_security_label(inode, buf, buflen);
+#endif
+	return -EOPNOTSUPP;
 }
 
 ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
 {
-	size_t len = strlen(XATTR_NAME_NFSV4_ACL) + ...
From: James Morris
Date: Monday, October 13, 2008 - 4:31 pm

This is a problem, as discussed last year:

http://linux-nfs.org/pipermail/labeled-nfs/2007-November/000110.html

We can't require the use of a new auth flavor which is incompatible with 
auth_gss.


- James
-- 
James Morris
<jmorris@namei.org>
--

From: Matthew N. Dodd
Date: Monday, October 13, 2008 - 7:15 pm

auth_seclabel demonstrates the flavor independent changes required for 
any RPC layer process label transport.  A GSS solution is currently 
under discussion.
--

From: Trond Myklebust
Date: Tuesday, October 14, 2008 - 6:20 am

Right, but I'm not particularly interested in merging "demonstration"
code that might end up requiring permanent support. I'd very much like
to see all of this get further through the IETF process before we talk
about merging into mainline.

Cheers
  Trond

--

From: David P. Quigley
Date: Tuesday, October 14, 2008 - 7:28 am

Hello,
    Nico seems to have come up with a reasonable solution for this
problem we just need to sit down and draw up a document for it.
Apparently he already created a mechanism in rpcsec_gss for allowing you
to bind the rpc session to more than just the normal credentials. Once
we finalize this and get it into a draft we will work on implementing it
in the rpcsec_gss auth flavor.

Dave

--

Previous thread: [PATCH] x86: enable CPUID on Cyrix cpus with CPUID disabled by Krzysztof Helt on Monday, September 29, 2008 - 10:24 am. (3 messages)

Next thread: [PATCH 00/31] cpumask: Provide new cpumask API by Mike Travis on Monday, September 29, 2008 - 11:02 am. (1 message)