All of lore.kernel.org
 help / color / mirror / Atom feed
* Labeled-NFS: Security Label support in NFSv4
@ 2010-07-07 14:31 ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux, linux-nfs

I am reposting this patch set as Bruce suggested since it seems the last time
that I posted it was in the middle of a bake-a-thon. I have already received
comments from Serge and Casey for some of the LSM related patches. I would
greatly appreciate if some of the FS and NFS people could look into the rest of
them.When reviewing the code please be critical of it. 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.


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Labeled-NFS: Security Label support in NFSv4
@ 2010-07-07 14:31 ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux, linux-nfs

I am reposting this patch set as Bruce suggested since it seems the last time
that I posted it was in the middle of a bake-a-thon. I have already received
comments from Serge and Casey for some of the LSM related patches. I would
greatly appreciate if some of the FS and NFS people could look into the rest of
them.When reviewing the code please be critical of it. 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.


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [PATCH 01/10] Security: Add hook to calculate context based on a negative dentry.
  2010-07-07 14:31 ` David P. Quigley
@ 2010-07-07 14:31   ` David P. Quigley
  -1 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

There is a time where we need to calculate a context without the
inode having been created yet. To do this we take the negative dentry and
calculate a context based on the process and the parent directory contexts.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 include/linux/security.h |   22 ++++++++++++++++++++++
 security/capability.c    |    6 ++++++
 security/security.c      |    7 +++++++
 security/selinux/hooks.c |   32 ++++++++++++++++++++++++++++++++
 4 files changed, 67 insertions(+), 0 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 3158dd9..4d01784 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -322,6 +322,14 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	Parse a string of security data filling in the opts structure
  *	@options string containing all mount options known by the LSM
  *	@opts binary data structure usable by the LSM
+ * @dentry_init_security:
+ *	Compute a context for a dentry as the inode is not yet available
+ * 	since NFSv4 has no label backed by an EA anyway.
+ * 	@dentry dentry to use in calculating the context.
+ * 	@mode mode used to determine resource type.
+ * 	@ctx pointer to place the pointer to the resulting context in.
+ * 	@ctxlen point to place the length of the resulting context.
+ *
  *
  * Security hooks for inode operations.
  *
@@ -1501,6 +1509,9 @@ struct security_operations {
 	void (*sb_clone_mnt_opts) (const struct super_block *oldsb,
 				   struct super_block *newsb);
 	int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts);
+	int (*dentry_init_security) (struct dentry *dentry, int mode,
+				     void **ctx, u32 *ctxlen);
+
 
 #ifdef CONFIG_SECURITY_PATH
 	int (*path_unlink) (struct path *dir, struct dentry *dentry);
@@ -1795,6 +1806,8 @@ int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *o
 void security_sb_clone_mnt_opts(const struct super_block *oldsb,
 				struct super_block *newsb);
 int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
+int security_dentry_init_security (struct dentry *dentry, int mode,
+				   void **ctx, u32 *ctxlen);
 
 int security_inode_alloc(struct inode *inode);
 void security_inode_free(struct inode *inode);
@@ -2157,6 +2170,15 @@ static inline int security_inode_alloc(struct inode *inode)
 static inline void security_inode_free(struct inode *inode)
 { }
 
+static inline int security_dentry_init_security (struct dentry *dentry,
+						 int mode,
+						 void **ctx,
+						 u32 *ctxlen)
+{
+	return -EOPNOTSUPP;
+}
+
+
 static inline int security_inode_init_security(struct inode *inode,
 						struct inode *dir,
 						char **name,
diff --git a/security/capability.c b/security/capability.c
index 4875142..9ce1c2f 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -134,6 +134,11 @@ static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
 	return 0;
 }
 
+static int cap_dentry_init_security(struct dentry *dentry, int mode, void **ctx, u32 *ctxlen)
+{
+	return 0;
+}
+
 static int cap_inode_alloc_security(struct inode *inode)
 {
 	return 0;
@@ -952,6 +957,7 @@ void security_fixup_ops(struct security_operations *ops)
 	set_to_cap_if_null(ops, sb_set_mnt_opts);
 	set_to_cap_if_null(ops, sb_clone_mnt_opts);
 	set_to_cap_if_null(ops, sb_parse_opts_str);
+	set_to_cap_if_null(ops, dentry_init_security);
 	set_to_cap_if_null(ops, inode_alloc_security);
 	set_to_cap_if_null(ops, inode_free_security);
 	set_to_cap_if_null(ops, inode_init_security);
diff --git a/security/security.c b/security/security.c
index 687c6fd..c1b6847 100644
--- a/security/security.c
+++ b/security/security.c
@@ -386,6 +386,13 @@ void security_inode_free(struct inode *inode)
 	security_ops->inode_free_security(inode);
 }
 
+int security_dentry_init_security (struct dentry *dentry, int mode,
+				   void **ctx, u32 *ctxlen)
+{
+	return security_ops->dentry_init_security (dentry, mode, ctx, ctxlen);
+}
+EXPORT_SYMBOL(security_dentry_init_security);
+
 int security_inode_init_security(struct inode *inode, struct inode *dir,
 				  char **name, void **value, size_t *len)
 {
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 5feecb4..435c51f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2577,6 +2577,37 @@ static void selinux_inode_free_security(struct inode *inode)
 	inode_free_security(inode);
 }
 
+static int selinux_dentry_init_security(struct dentry *dentry, int mode, void **ctx, u32 *ctxlen)
+{
+	struct cred *cred = current_cred();
+	struct task_security_struct *tsec;
+	struct inode_security_struct *dsec;
+	struct superblock_security_struct *sbsec;
+	struct inode *dir = dentry->d_parent->d_inode;
+	u32 newsid;
+	int rc;
+
+	tsec = cred->security;
+	dsec = dir->i_security;
+	sbsec = dir->i_sb->s_security;
+
+	if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
+		newsid = tsec->create_sid;
+	} else {
+		rc = security_transition_sid(tsec->sid, dsec->sid,
+					     inode_mode_to_security_class(mode),
+					     &newsid);
+		if (rc) {
+			printk(KERN_WARNING "%s:  "
+			       "security_transition_sid failed, rc=%d\n",
+			       __FUNCTION__, -rc);
+			return rc;
+		}
+	}
+
+	return security_sid_to_context(newsid, (char **)ctx, ctxlen);
+}
+
 static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 				       char **name, void **value,
 				       size_t *len)
@@ -5484,6 +5515,7 @@ static struct security_operations selinux_ops = {
 	.sb_clone_mnt_opts =		selinux_sb_clone_mnt_opts,
 	.sb_parse_opts_str = 		selinux_parse_opts_str,
 
+	.dentry_init_security =		selinux_dentry_init_security,
 
 	.inode_alloc_security =		selinux_inode_alloc_security,
 	.inode_free_security =		selinux_inode_free_security,
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 01/10] Security: Add hook to calculate context based on a negative dentry.
@ 2010-07-07 14:31   ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

There is a time where we need to calculate a context without the
inode having been created yet. To do this we take the negative dentry and
calculate a context based on the process and the parent directory contexts.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 include/linux/security.h |   22 ++++++++++++++++++++++
 security/capability.c    |    6 ++++++
 security/security.c      |    7 +++++++
 security/selinux/hooks.c |   32 ++++++++++++++++++++++++++++++++
 4 files changed, 67 insertions(+), 0 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 3158dd9..4d01784 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -322,6 +322,14 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	Parse a string of security data filling in the opts structure
  *	@options string containing all mount options known by the LSM
  *	@opts binary data structure usable by the LSM
+ * @dentry_init_security:
+ *	Compute a context for a dentry as the inode is not yet available
+ * 	since NFSv4 has no label backed by an EA anyway.
+ * 	@dentry dentry to use in calculating the context.
+ * 	@mode mode used to determine resource type.
+ * 	@ctx pointer to place the pointer to the resulting context in.
+ * 	@ctxlen point to place the length of the resulting context.
+ *
  *
  * Security hooks for inode operations.
  *
@@ -1501,6 +1509,9 @@ struct security_operations {
 	void (*sb_clone_mnt_opts) (const struct super_block *oldsb,
 				   struct super_block *newsb);
 	int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts);
+	int (*dentry_init_security) (struct dentry *dentry, int mode,
+				     void **ctx, u32 *ctxlen);
+
 
 #ifdef CONFIG_SECURITY_PATH
 	int (*path_unlink) (struct path *dir, struct dentry *dentry);
@@ -1795,6 +1806,8 @@ int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *o
 void security_sb_clone_mnt_opts(const struct super_block *oldsb,
 				struct super_block *newsb);
 int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
+int security_dentry_init_security (struct dentry *dentry, int mode,
+				   void **ctx, u32 *ctxlen);
 
 int security_inode_alloc(struct inode *inode);
 void security_inode_free(struct inode *inode);
@@ -2157,6 +2170,15 @@ static inline int security_inode_alloc(struct inode *inode)
 static inline void security_inode_free(struct inode *inode)
 { }
 
+static inline int security_dentry_init_security (struct dentry *dentry,
+						 int mode,
+						 void **ctx,
+						 u32 *ctxlen)
+{
+	return -EOPNOTSUPP;
+}
+
+
 static inline int security_inode_init_security(struct inode *inode,
 						struct inode *dir,
 						char **name,
diff --git a/security/capability.c b/security/capability.c
index 4875142..9ce1c2f 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -134,6 +134,11 @@ static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
 	return 0;
 }
 
+static int cap_dentry_init_security(struct dentry *dentry, int mode, void **ctx, u32 *ctxlen)
+{
+	return 0;
+}
+
 static int cap_inode_alloc_security(struct inode *inode)
 {
 	return 0;
@@ -952,6 +957,7 @@ void security_fixup_ops(struct security_operations *ops)
 	set_to_cap_if_null(ops, sb_set_mnt_opts);
 	set_to_cap_if_null(ops, sb_clone_mnt_opts);
 	set_to_cap_if_null(ops, sb_parse_opts_str);
+	set_to_cap_if_null(ops, dentry_init_security);
 	set_to_cap_if_null(ops, inode_alloc_security);
 	set_to_cap_if_null(ops, inode_free_security);
 	set_to_cap_if_null(ops, inode_init_security);
diff --git a/security/security.c b/security/security.c
index 687c6fd..c1b6847 100644
--- a/security/security.c
+++ b/security/security.c
@@ -386,6 +386,13 @@ void security_inode_free(struct inode *inode)
 	security_ops->inode_free_security(inode);
 }
 
+int security_dentry_init_security (struct dentry *dentry, int mode,
+				   void **ctx, u32 *ctxlen)
+{
+	return security_ops->dentry_init_security (dentry, mode, ctx, ctxlen);
+}
+EXPORT_SYMBOL(security_dentry_init_security);
+
 int security_inode_init_security(struct inode *inode, struct inode *dir,
 				  char **name, void **value, size_t *len)
 {
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 5feecb4..435c51f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2577,6 +2577,37 @@ static void selinux_inode_free_security(struct inode *inode)
 	inode_free_security(inode);
 }
 
+static int selinux_dentry_init_security(struct dentry *dentry, int mode, void **ctx, u32 *ctxlen)
+{
+	struct cred *cred = current_cred();
+	struct task_security_struct *tsec;
+	struct inode_security_struct *dsec;
+	struct superblock_security_struct *sbsec;
+	struct inode *dir = dentry->d_parent->d_inode;
+	u32 newsid;
+	int rc;
+
+	tsec = cred->security;
+	dsec = dir->i_security;
+	sbsec = dir->i_sb->s_security;
+
+	if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
+		newsid = tsec->create_sid;
+	} else {
+		rc = security_transition_sid(tsec->sid, dsec->sid,
+					     inode_mode_to_security_class(mode),
+					     &newsid);
+		if (rc) {
+			printk(KERN_WARNING "%s:  "
+			       "security_transition_sid failed, rc=%d\n",
+			       __FUNCTION__, -rc);
+			return rc;
+		}
+	}
+
+	return security_sid_to_context(newsid, (char **)ctx, ctxlen);
+}
+
 static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 				       char **name, void **value,
 				       size_t *len)
@@ -5484,6 +5515,7 @@ static struct security_operations selinux_ops = {
 	.sb_clone_mnt_opts =		selinux_sb_clone_mnt_opts,
 	.sb_parse_opts_str = 		selinux_parse_opts_str,
 
+	.dentry_init_security =		selinux_dentry_init_security,
 
 	.inode_alloc_security =		selinux_inode_alloc_security,
 	.inode_free_security =		selinux_inode_free_security,
-- 
1.6.2.5


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 02/10] Security: Add Hook to test if the particular xattr is part of a MAC model.
  2010-07-07 14:31 ` David P. Quigley
@ 2010-07-07 14:31   ` David P. Quigley
  -1 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

There are areas in the Labeled NFS code where where we need to test if the
attribute being requested exhibits the semantics of a MAC model. This allows us
to make sure that we get the desired semantics from the attribute instead of
something else such as capabilities or a time based LSM.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 include/linux/security.h   |   11 +++++++++++
 security/capability.c      |    6 ++++++
 security/security.c        |    6 ++++++
 security/selinux/hooks.c   |    6 ++++++
 security/smack/smack_lsm.c |   11 +++++++++++
 5 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 4d01784..9597620 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1373,6 +1373,10 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	@pages contains the number of pages.
  *	Return 0 if permission is granted.
  *
+ * @ismaclabel:
+ * 	Check if the extended attribute specified by @name represents a MAC label.
+ * 	@name full extended attribute name to check against LSM as a MAC label.
+ *
  * @secid_to_secctx:
  *	Convert secid to security context.
  *	@secid contains the security ID.
@@ -1664,6 +1668,7 @@ struct security_operations {
 
 	int (*getprocattr) (struct task_struct *p, char *name, char **value);
 	int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size);
+	int (*ismaclabel) (const char * name);
 	int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen);
 	int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid);
 	void (*release_secctx) (char *secdata, u32 seclen);
@@ -1919,6 +1924,7 @@ int security_getprocattr(struct task_struct *p, char *name, char **value);
 int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size);
 int security_netlink_send(struct sock *sk, struct sk_buff *skb);
 int security_netlink_recv(struct sk_buff *skb, int cap);
+int security_ismaclabel(const char *name);
 int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
 int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
 void security_release_secctx(char *secdata, u32 seclen);
@@ -2676,6 +2682,11 @@ static inline int security_netlink_recv(struct sk_buff *skb, int cap)
 	return cap_netlink_recv(skb, cap);
 }
 
+static inline int security_ismaclabel(const char *name)
+{
+	return 0;
+}
+
 static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 {
 	return -EOPNOTSUPP;
diff --git a/security/capability.c b/security/capability.c
index 9ce1c2f..0d8f7e9 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -829,6 +829,11 @@ static int cap_setprocattr(struct task_struct *p, char *name, void *value,
 	return -EINVAL;
 }
 
+static int cap_ismaclabel(const char *name)
+{
+	return 0;
+}
+
 static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 {
 	return -EOPNOTSUPP;
@@ -1064,6 +1069,7 @@ void security_fixup_ops(struct security_operations *ops)
 	set_to_cap_if_null(ops, d_instantiate);
 	set_to_cap_if_null(ops, getprocattr);
 	set_to_cap_if_null(ops, setprocattr);
+	set_to_cap_if_null(ops, ismaclabel);
 	set_to_cap_if_null(ops, secid_to_secctx);
 	set_to_cap_if_null(ops, secctx_to_secid);
 	set_to_cap_if_null(ops, release_secctx);
diff --git a/security/security.c b/security/security.c
index c1b6847..1f0765c 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1013,6 +1013,12 @@ int security_netlink_recv(struct sk_buff *skb, int cap)
 }
 EXPORT_SYMBOL(security_netlink_recv);
 
+int security_ismaclabel(const char *name)
+{
+	return security_ops->ismaclabel(name);
+}
+EXPORT_SYMBOL(security_ismaclabel);
+
 int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 {
 	return security_ops->secid_to_secctx(secid, secdata, seclen);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 435c51f..8239f5c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5372,6 +5372,11 @@ abort_change:
 	return error;
 }
 
+static int selinux_ismaclabel(const char *name)
+{
+	return (strcmp(name,XATTR_NAME_SELINUX) == 0);
+}
+
 static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 {
 	return security_sid_to_context(secid, secdata, seclen);
@@ -5610,6 +5615,7 @@ static struct security_operations selinux_ops = {
 	.getprocattr =			selinux_getprocattr,
 	.setprocattr =			selinux_setprocattr,
 
+	.ismaclabel =			selinux_ismaclabel,
 	.secid_to_secctx =		selinux_secid_to_secctx,
 	.secctx_to_secid =		selinux_secctx_to_secid,
 	.release_secctx =		selinux_release_secctx,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index fdfeaa2..449e223 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3012,6 +3012,16 @@ static void smack_audit_rule_free(void *vrule)
 #endif /* CONFIG_AUDIT */
 
 /**
+ * smack_ismaclabel - check if xattr @name references a smack MAC label
+ * @name: Full xattr name to check.
+ */
+static int smack_ismaclabel(const char *name)
+{
+	return (strcmp(name, XATTR_NAME_SMACK) == 0);
+}
+
+
+/**
  * smack_secid_to_secctx - return the smack label for a secid
  * @secid: incoming integer
  * @secdata: destination
@@ -3199,6 +3209,7 @@ struct security_operations smack_ops = {
 	.audit_rule_free =		smack_audit_rule_free,
 #endif /* CONFIG_AUDIT */
 
+	.ismaclabel =			smack_ismaclabel,
 	.secid_to_secctx = 		smack_secid_to_secctx,
 	.secctx_to_secid = 		smack_secctx_to_secid,
 	.release_secctx = 		smack_release_secctx,
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 02/10] Security: Add Hook to test if the particular xattr is part of a MAC model.
@ 2010-07-07 14:31   ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

There are areas in the Labeled NFS code where where we need to test if the
attribute being requested exhibits the semantics of a MAC model. This allows us
to make sure that we get the desired semantics from the attribute instead of
something else such as capabilities or a time based LSM.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 include/linux/security.h   |   11 +++++++++++
 security/capability.c      |    6 ++++++
 security/security.c        |    6 ++++++
 security/selinux/hooks.c   |    6 ++++++
 security/smack/smack_lsm.c |   11 +++++++++++
 5 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 4d01784..9597620 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1373,6 +1373,10 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	@pages contains the number of pages.
  *	Return 0 if permission is granted.
  *
+ * @ismaclabel:
+ * 	Check if the extended attribute specified by @name represents a MAC label.
+ * 	@name full extended attribute name to check against LSM as a MAC label.
+ *
  * @secid_to_secctx:
  *	Convert secid to security context.
  *	@secid contains the security ID.
@@ -1664,6 +1668,7 @@ struct security_operations {
 
 	int (*getprocattr) (struct task_struct *p, char *name, char **value);
 	int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size);
+	int (*ismaclabel) (const char * name);
 	int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen);
 	int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid);
 	void (*release_secctx) (char *secdata, u32 seclen);
@@ -1919,6 +1924,7 @@ int security_getprocattr(struct task_struct *p, char *name, char **value);
 int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size);
 int security_netlink_send(struct sock *sk, struct sk_buff *skb);
 int security_netlink_recv(struct sk_buff *skb, int cap);
+int security_ismaclabel(const char *name);
 int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
 int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
 void security_release_secctx(char *secdata, u32 seclen);
@@ -2676,6 +2682,11 @@ static inline int security_netlink_recv(struct sk_buff *skb, int cap)
 	return cap_netlink_recv(skb, cap);
 }
 
+static inline int security_ismaclabel(const char *name)
+{
+	return 0;
+}
+
 static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 {
 	return -EOPNOTSUPP;
diff --git a/security/capability.c b/security/capability.c
index 9ce1c2f..0d8f7e9 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -829,6 +829,11 @@ static int cap_setprocattr(struct task_struct *p, char *name, void *value,
 	return -EINVAL;
 }
 
+static int cap_ismaclabel(const char *name)
+{
+	return 0;
+}
+
 static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 {
 	return -EOPNOTSUPP;
@@ -1064,6 +1069,7 @@ void security_fixup_ops(struct security_operations *ops)
 	set_to_cap_if_null(ops, d_instantiate);
 	set_to_cap_if_null(ops, getprocattr);
 	set_to_cap_if_null(ops, setprocattr);
+	set_to_cap_if_null(ops, ismaclabel);
 	set_to_cap_if_null(ops, secid_to_secctx);
 	set_to_cap_if_null(ops, secctx_to_secid);
 	set_to_cap_if_null(ops, release_secctx);
diff --git a/security/security.c b/security/security.c
index c1b6847..1f0765c 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1013,6 +1013,12 @@ int security_netlink_recv(struct sk_buff *skb, int cap)
 }
 EXPORT_SYMBOL(security_netlink_recv);
 
+int security_ismaclabel(const char *name)
+{
+	return security_ops->ismaclabel(name);
+}
+EXPORT_SYMBOL(security_ismaclabel);
+
 int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 {
 	return security_ops->secid_to_secctx(secid, secdata, seclen);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 435c51f..8239f5c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5372,6 +5372,11 @@ abort_change:
 	return error;
 }
 
+static int selinux_ismaclabel(const char *name)
+{
+	return (strcmp(name,XATTR_NAME_SELINUX) == 0);
+}
+
 static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 {
 	return security_sid_to_context(secid, secdata, seclen);
@@ -5610,6 +5615,7 @@ static struct security_operations selinux_ops = {
 	.getprocattr =			selinux_getprocattr,
 	.setprocattr =			selinux_setprocattr,
 
+	.ismaclabel =			selinux_ismaclabel,
 	.secid_to_secctx =		selinux_secid_to_secctx,
 	.secctx_to_secid =		selinux_secctx_to_secid,
 	.release_secctx =		selinux_release_secctx,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index fdfeaa2..449e223 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3012,6 +3012,16 @@ static void smack_audit_rule_free(void *vrule)
 #endif /* CONFIG_AUDIT */
 
 /**
+ * smack_ismaclabel - check if xattr @name references a smack MAC label
+ * @name: Full xattr name to check.
+ */
+static int smack_ismaclabel(const char *name)
+{
+	return (strcmp(name, XATTR_NAME_SMACK) == 0);
+}
+
+
+/**
  * smack_secid_to_secctx - return the smack label for a secid
  * @secid: incoming integer
  * @secdata: destination
@@ -3199,6 +3209,7 @@ struct security_operations smack_ops = {
 	.audit_rule_free =		smack_audit_rule_free,
 #endif /* CONFIG_AUDIT */
 
+	.ismaclabel =			smack_ismaclabel,
 	.secid_to_secctx = 		smack_secid_to_secctx,
 	.secctx_to_secid = 		smack_secctx_to_secid,
 	.release_secctx = 		smack_release_secctx,
-- 
1.6.2.5


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 03/10] LSM: Add flags field to security_sb_set_mnt_opts for in kernel mount data.
  2010-07-07 14:31 ` David P. Quigley
@ 2010-07-07 14:31   ` David P. Quigley
  -1 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley

There is no way to differentiate if a text mount option is passed from user
space or the kernel. A flags field is being added to the
security_sb_set_mnt_opts hook to allow for in kernel security flags to be sent
to the LSM for processing in addition to the text options received from mount.
This patch also updated existing code to fix compilation errors.

Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/nfs/super.c           |    4 ++--
 include/linux/security.h |   11 ++++++++---
 security/capability.c    |    5 ++++-
 security/security.c      |    6 ++++--
 security/selinux/hooks.c |   12 ++++++++++--
 5 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index b4148fc..054bcaa 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2232,7 +2232,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 		goto error_splat_super;
 	}
 
-	error = security_sb_set_mnt_opts(s, &data->lsm_opts);
+	error = security_sb_set_mnt_opts(s, &data->lsm_opts, 0, NULL);
 	if (error)
 		goto error_splat_root;
 
@@ -2602,7 +2602,7 @@ static int nfs4_remote_get_sb(struct file_system_type *fs_type,
 		goto error_splat_super;
 	}
 
-	error = security_sb_set_mnt_opts(s, &data->lsm_opts);
+	error = security_sb_set_mnt_opts(s, &data->lsm_opts, 0, NULL);
 	if (error)
 		goto error_splat_root;
 
diff --git a/include/linux/security.h b/include/linux/security.h
index 9597620..4bb5db7 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1509,7 +1509,9 @@ struct security_operations {
 	void (*sb_post_pivotroot) (struct path *old_path,
 				   struct path *new_path);
 	int (*sb_set_mnt_opts) (struct super_block *sb,
-				struct security_mnt_opts *opts);
+				struct security_mnt_opts *opts,
+				unsigned long kern_flags,
+				unsigned long *set_kern_flags);
 	void (*sb_clone_mnt_opts) (const struct super_block *oldsb,
 				   struct super_block *newsb);
 	int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts);
@@ -1807,7 +1809,8 @@ void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *d
 void security_sb_post_addmount(struct vfsmount *mnt, struct path *mountpoint);
 int security_sb_pivotroot(struct path *old_path, struct path *new_path);
 void security_sb_post_pivotroot(struct path *old_path, struct path *new_path);
-int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts);
+int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts, 
+				unsigned long kern_flags, unsigned long *set_kern_flags);
 void security_sb_clone_mnt_opts(const struct super_block *oldsb,
 				struct super_block *newsb);
 int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
@@ -2154,7 +2157,9 @@ static inline void security_sb_post_pivotroot(struct path *old_path,
 { }
 
 static inline int security_sb_set_mnt_opts(struct super_block *sb,
-					   struct security_mnt_opts *opts)
+					   struct security_mnt_opts *opts,
+					   unsigned long kern_flags,
+					   unsigned long *set_kern_flags)
 {
 	return 0;
 }
diff --git a/security/capability.c b/security/capability.c
index 0d8f7e9..46f5e78 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -117,7 +117,10 @@ static void cap_sb_post_pivotroot(struct path *old_path, struct path *new_path)
 }
 
 static int cap_sb_set_mnt_opts(struct super_block *sb,
-			       struct security_mnt_opts *opts)
+			       struct security_mnt_opts *opts,
+			       unsigned long kern_flags,
+			       unsigned long *set_kern_flags)
+
 {
 	if (unlikely(opts->num_mnt_opts))
 		return -EOPNOTSUPP;
diff --git a/security/security.c b/security/security.c
index 1f0765c..2246b5a 100644
--- a/security/security.c
+++ b/security/security.c
@@ -347,9 +347,11 @@ void security_sb_post_pivotroot(struct path *old_path, struct path *new_path)
 }
 
 int security_sb_set_mnt_opts(struct super_block *sb,
-				struct security_mnt_opts *opts)
+				struct security_mnt_opts *opts,
+				unsigned long kern_flags,
+				unsigned long *set_kern_flags)
 {
-	return security_ops->sb_set_mnt_opts(sb, opts);
+	return security_ops->sb_set_mnt_opts(sb, opts, kern_flags, set_kern_flags);
 }
 EXPORT_SYMBOL(security_sb_set_mnt_opts);
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8239f5c..d150fb4 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -591,7 +591,9 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
  * labeling information.
  */
 static int selinux_set_mnt_opts(struct super_block *sb,
-				struct security_mnt_opts *opts)
+				struct security_mnt_opts *opts,
+				unsigned long kern_flags,
+				unsigned long *set_kern_flags)
 {
 	const struct cred *cred = current_cred();
 	int rc = 0, i;
@@ -623,6 +625,12 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 			"before the security server is initialized\n");
 		goto out;
 	}
+	if (kern_flags && !set_kern_flags) {
+		/* Specifying internal flags without providing a place to 
+		 * place the results is not allowed */
+		rc = -EINVAL;
+		goto out;
+	}
 
 	/*
 	 * Binary mount data FS will come through this function twice.  Once
@@ -998,7 +1006,7 @@ static int superblock_doinit(struct super_block *sb, void *data)
 		goto out_err;
 
 out:
-	rc = selinux_set_mnt_opts(sb, &opts);
+	rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
 
 out_err:
 	security_free_mnt_opts(&opts);
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 03/10] LSM: Add flags field to security_sb_set_mnt_opts for in kernel mount data.
@ 2010-07-07 14:31   ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley

There is no way to differentiate if a text mount option is passed from user
space or the kernel. A flags field is being added to the
security_sb_set_mnt_opts hook to allow for in kernel security flags to be sent
to the LSM for processing in addition to the text options received from mount.
This patch also updated existing code to fix compilation errors.

Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/nfs/super.c           |    4 ++--
 include/linux/security.h |   11 ++++++++---
 security/capability.c    |    5 ++++-
 security/security.c      |    6 ++++--
 security/selinux/hooks.c |   12 ++++++++++--
 5 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index b4148fc..054bcaa 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2232,7 +2232,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 		goto error_splat_super;
 	}
 
-	error = security_sb_set_mnt_opts(s, &data->lsm_opts);
+	error = security_sb_set_mnt_opts(s, &data->lsm_opts, 0, NULL);
 	if (error)
 		goto error_splat_root;
 
@@ -2602,7 +2602,7 @@ static int nfs4_remote_get_sb(struct file_system_type *fs_type,
 		goto error_splat_super;
 	}
 
-	error = security_sb_set_mnt_opts(s, &data->lsm_opts);
+	error = security_sb_set_mnt_opts(s, &data->lsm_opts, 0, NULL);
 	if (error)
 		goto error_splat_root;
 
diff --git a/include/linux/security.h b/include/linux/security.h
index 9597620..4bb5db7 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1509,7 +1509,9 @@ struct security_operations {
 	void (*sb_post_pivotroot) (struct path *old_path,
 				   struct path *new_path);
 	int (*sb_set_mnt_opts) (struct super_block *sb,
-				struct security_mnt_opts *opts);
+				struct security_mnt_opts *opts,
+				unsigned long kern_flags,
+				unsigned long *set_kern_flags);
 	void (*sb_clone_mnt_opts) (const struct super_block *oldsb,
 				   struct super_block *newsb);
 	int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts);
@@ -1807,7 +1809,8 @@ void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *d
 void security_sb_post_addmount(struct vfsmount *mnt, struct path *mountpoint);
 int security_sb_pivotroot(struct path *old_path, struct path *new_path);
 void security_sb_post_pivotroot(struct path *old_path, struct path *new_path);
-int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts);
+int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts, 
+				unsigned long kern_flags, unsigned long *set_kern_flags);
 void security_sb_clone_mnt_opts(const struct super_block *oldsb,
 				struct super_block *newsb);
 int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
@@ -2154,7 +2157,9 @@ static inline void security_sb_post_pivotroot(struct path *old_path,
 { }
 
 static inline int security_sb_set_mnt_opts(struct super_block *sb,
-					   struct security_mnt_opts *opts)
+					   struct security_mnt_opts *opts,
+					   unsigned long kern_flags,
+					   unsigned long *set_kern_flags)
 {
 	return 0;
 }
diff --git a/security/capability.c b/security/capability.c
index 0d8f7e9..46f5e78 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -117,7 +117,10 @@ static void cap_sb_post_pivotroot(struct path *old_path, struct path *new_path)
 }
 
 static int cap_sb_set_mnt_opts(struct super_block *sb,
-			       struct security_mnt_opts *opts)
+			       struct security_mnt_opts *opts,
+			       unsigned long kern_flags,
+			       unsigned long *set_kern_flags)
+
 {
 	if (unlikely(opts->num_mnt_opts))
 		return -EOPNOTSUPP;
diff --git a/security/security.c b/security/security.c
index 1f0765c..2246b5a 100644
--- a/security/security.c
+++ b/security/security.c
@@ -347,9 +347,11 @@ void security_sb_post_pivotroot(struct path *old_path, struct path *new_path)
 }
 
 int security_sb_set_mnt_opts(struct super_block *sb,
-				struct security_mnt_opts *opts)
+				struct security_mnt_opts *opts,
+				unsigned long kern_flags,
+				unsigned long *set_kern_flags)
 {
-	return security_ops->sb_set_mnt_opts(sb, opts);
+	return security_ops->sb_set_mnt_opts(sb, opts, kern_flags, set_kern_flags);
 }
 EXPORT_SYMBOL(security_sb_set_mnt_opts);
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8239f5c..d150fb4 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -591,7 +591,9 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
  * labeling information.
  */
 static int selinux_set_mnt_opts(struct super_block *sb,
-				struct security_mnt_opts *opts)
+				struct security_mnt_opts *opts,
+				unsigned long kern_flags,
+				unsigned long *set_kern_flags)
 {
 	const struct cred *cred = current_cred();
 	int rc = 0, i;
@@ -623,6 +625,12 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 			"before the security server is initialized\n");
 		goto out;
 	}
+	if (kern_flags && !set_kern_flags) {
+		/* Specifying internal flags without providing a place to 
+		 * place the results is not allowed */
+		rc = -EINVAL;
+		goto out;
+	}
 
 	/*
 	 * Binary mount data FS will come through this function twice.  Once
@@ -998,7 +1006,7 @@ static int superblock_doinit(struct super_block *sb, void *data)
 		goto out_err;
 
 out:
-	rc = selinux_set_mnt_opts(sb, &opts);
+	rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
 
 out_err:
 	security_free_mnt_opts(&opts);
-- 
1.6.2.5


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 04/10] SELinux: Add new labeling type native labels
  2010-07-07 14:31 ` David P. Quigley
@ 2010-07-07 14:31   ` David P. Quigley
  -1 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

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>
---
 include/linux/security.h            |    3 +++
 security/selinux/hooks.c            |   30 +++++++++++++++++++++---------
 security/selinux/include/security.h |    2 ++
 security/selinux/ss/policydb.c      |    5 ++++-
 4 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 4bb5db7..d67c5d6 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -43,6 +43,9 @@
 #define SECURITY_CAP_NOAUDIT 0
 #define SECURITY_CAP_AUDIT 1
 
+/* LSM Agnostic defines for sb_set_mnt_opts */
+#define SECURITY_LSM_NATIVE_LABELS	1
+
 struct ctl_table;
 struct audit_krule;
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d150fb4..01edf80 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -77,6 +77,7 @@
 #include <linux/mutex.h>
 #include <linux/posix-timers.h>
 #include <linux/syslog.h>
+#include <linux/security.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -323,13 +324,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 labeling",
 };
 
 static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
@@ -721,14 +723,16 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 	if (strcmp(sb->s_type->name, "proc") == 0)
 		sbsec->flags |= SE_SBPROC;
 
-	/* Determine the labeling behavior to use for this filesystem type. */
-	rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid);
-	if (rc) {
-		printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
-		       __func__, sb->s_type->name, rc);
-		goto out;
+	if (!sbsec->behavior) {
+		/* Determine the labeling behavior to use for this filesystem type. */
+		rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, 
+					&sbsec->behavior, &sbsec->sid);
+		if (rc) {
+			printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
+					__func__, sb->s_type->name, rc);
+			goto out;
+		}
 	}
-
 	/* sets the context of the superblock for the fs being mounted. */
 	if (fscontext_sid) {
 		rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
@@ -743,6 +747,11 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 	 * sets the label used on all file below the mountpoint, and will set
 	 * the superblock context if not already set.
 	 */
+	if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
+		sbsec->behavior = SECURITY_FS_USE_NATIVE;
+		*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
+	}
+
 	if (context_sid) {
 		if (!fscontext_sid) {
 			rc = may_context_mount_sb_relabel(context_sid, sbsec,
@@ -774,7 +783,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 	}
 
 	if (defcontext_sid) {
-		if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
+		if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
+			sbsec->behavior != SECURITY_FS_USE_NATIVE) {
 			rc = -EINVAL;
 			printk(KERN_WARNING "SELinux: defcontext option is "
 			       "invalid for this filesystem type\n");
@@ -1251,6 +1261,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 	}
 
 	switch (sbsec->behavior) {
+	case SECURITY_FS_USE_NATIVE:
+		break;
 	case SECURITY_FS_USE_XATTR:
 		if (!inode->i_op->getxattr) {
 			isec->sid = sbsec->def_sid;
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 1f7c249..e4c5bd0 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -161,6 +161,8 @@ int security_get_allow_unknown(void);
 #define SECURITY_FS_USE_GENFS		4 /* use the genfs support */
 #define SECURITY_FS_USE_NONE		5 /* no labeling support */
 #define SECURITY_FS_USE_MNTPOINT	6 /* use mountpoint labeling */
+#define SECURITY_FS_USE_NATIVE		7 /* use native label support */
+#define SECURITY_FS_USE_MAX		7 /* Highest SECURITY_FS_USE_XXX */
 
 int security_fs_use(const char *fstype, unsigned int *behavior,
 	u32 *sid);
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 23c6e53..35e2b47 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -1996,7 +1996,10 @@ int policydb_read(struct policydb *p, void *fp)
 				if (rc < 0)
 					goto bad;
 				c->v.behavior = le32_to_cpu(buf[0]);
-				if (c->v.behavior > SECURITY_FS_USE_NONE)
+				/* Determined at runtime, not in policy DB. */
+				if (c->v.behavior == SECURITY_FS_USE_MNTPOINT)
+					goto bad;
+				if (c->v.behavior > SECURITY_FS_USE_MAX)
 					goto bad;
 				len = le32_to_cpu(buf[1]);
 				c->u.name = kmalloc(len + 1, GFP_KERNEL);
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 04/10] SELinux: Add new labeling type native labels
@ 2010-07-07 14:31   ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

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>
---
 include/linux/security.h            |    3 +++
 security/selinux/hooks.c            |   30 +++++++++++++++++++++---------
 security/selinux/include/security.h |    2 ++
 security/selinux/ss/policydb.c      |    5 ++++-
 4 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 4bb5db7..d67c5d6 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -43,6 +43,9 @@
 #define SECURITY_CAP_NOAUDIT 0
 #define SECURITY_CAP_AUDIT 1
 
+/* LSM Agnostic defines for sb_set_mnt_opts */
+#define SECURITY_LSM_NATIVE_LABELS	1
+
 struct ctl_table;
 struct audit_krule;
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d150fb4..01edf80 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -77,6 +77,7 @@
 #include <linux/mutex.h>
 #include <linux/posix-timers.h>
 #include <linux/syslog.h>
+#include <linux/security.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -323,13 +324,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 labeling",
 };
 
 static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
@@ -721,14 +723,16 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 	if (strcmp(sb->s_type->name, "proc") == 0)
 		sbsec->flags |= SE_SBPROC;
 
-	/* Determine the labeling behavior to use for this filesystem type. */
-	rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid);
-	if (rc) {
-		printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
-		       __func__, sb->s_type->name, rc);
-		goto out;
+	if (!sbsec->behavior) {
+		/* Determine the labeling behavior to use for this filesystem type. */
+		rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, 
+					&sbsec->behavior, &sbsec->sid);
+		if (rc) {
+			printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
+					__func__, sb->s_type->name, rc);
+			goto out;
+		}
 	}
-
 	/* sets the context of the superblock for the fs being mounted. */
 	if (fscontext_sid) {
 		rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
@@ -743,6 +747,11 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 	 * sets the label used on all file below the mountpoint, and will set
 	 * the superblock context if not already set.
 	 */
+	if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
+		sbsec->behavior = SECURITY_FS_USE_NATIVE;
+		*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
+	}
+
 	if (context_sid) {
 		if (!fscontext_sid) {
 			rc = may_context_mount_sb_relabel(context_sid, sbsec,
@@ -774,7 +783,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 	}
 
 	if (defcontext_sid) {
-		if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
+		if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
+			sbsec->behavior != SECURITY_FS_USE_NATIVE) {
 			rc = -EINVAL;
 			printk(KERN_WARNING "SELinux: defcontext option is "
 			       "invalid for this filesystem type\n");
@@ -1251,6 +1261,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 	}
 
 	switch (sbsec->behavior) {
+	case SECURITY_FS_USE_NATIVE:
+		break;
 	case SECURITY_FS_USE_XATTR:
 		if (!inode->i_op->getxattr) {
 			isec->sid = sbsec->def_sid;
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 1f7c249..e4c5bd0 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -161,6 +161,8 @@ int security_get_allow_unknown(void);
 #define SECURITY_FS_USE_GENFS		4 /* use the genfs support */
 #define SECURITY_FS_USE_NONE		5 /* no labeling support */
 #define SECURITY_FS_USE_MNTPOINT	6 /* use mountpoint labeling */
+#define SECURITY_FS_USE_NATIVE		7 /* use native label support */
+#define SECURITY_FS_USE_MAX		7 /* Highest SECURITY_FS_USE_XXX */
 
 int security_fs_use(const char *fstype, unsigned int *behavior,
 	u32 *sid);
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 23c6e53..35e2b47 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -1996,7 +1996,10 @@ int policydb_read(struct policydb *p, void *fp)
 				if (rc < 0)
 					goto bad;
 				c->v.behavior = le32_to_cpu(buf[0]);
-				if (c->v.behavior > SECURITY_FS_USE_NONE)
+				/* Determined at runtime, not in policy DB. */
+				if (c->v.behavior == SECURITY_FS_USE_MNTPOINT)
+					goto bad;
+				if (c->v.behavior > SECURITY_FS_USE_MAX)
 					goto bad;
 				len = le32_to_cpu(buf[1]);
 				c->u.name = kmalloc(len + 1, GFP_KERNEL);
-- 
1.6.2.5


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 05/10] KConfig: Add KConfig entries for Labeled NFS
  2010-07-07 14:31 ` David P. Quigley
@ 2010-07-07 14:31   ` David P. Quigley
  -1 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

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/nfs/Kconfig  |   16 ++++++++++++++++
 fs/nfsd/Kconfig |   13 +++++++++++++
 2 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index a43d07e..67b158c 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -83,6 +83,22 @@ config NFS_V4_1
 
 	  Unless you're an NFS developer, say N.
 
+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 enable fine-grained 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.
+	Without this an NFSv4 mount will have the same label on each file.
+
+	If you do not wish to enable fine-grained security labels SELinux or
+	Smack policies on NFSv4 files, say N.
+
+
+	  If unsure, say N.
+
 config ROOT_NFS
 	bool "Root file system on NFS"
 	depends on NFS_FS=y && IP_PNP
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index 503b9da..3a282f8 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -79,3 +79,16 @@ config NFSD_V4
 	  available from http://linux-nfs.org/.
 
 	  If unsure, say N.
+
+config NFSD_V4_SECURITY_LABEL
+	bool "Provide Security Label support for NFSv4 server"
+	depends on NFSD_V4 && SECURITY
+	help
+
+	Say Y here if you want enable fine-grained 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.
+	Without this an NFSv4 mount will have the same label on each file.
+
+	If you do not wish to enable fine-grained security labels SELinux or
+	Smack policies on NFSv4 files, say N.
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 05/10] KConfig: Add KConfig entries for Labeled NFS
@ 2010-07-07 14:31   ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

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/nfs/Kconfig  |   16 ++++++++++++++++
 fs/nfsd/Kconfig |   13 +++++++++++++
 2 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index a43d07e..67b158c 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -83,6 +83,22 @@ config NFS_V4_1
 
 	  Unless you're an NFS developer, say N.
 
+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 enable fine-grained 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.
+	Without this an NFSv4 mount will have the same label on each file.
+
+	If you do not wish to enable fine-grained security labels SELinux or
+	Smack policies on NFSv4 files, say N.
+
+
+	  If unsure, say N.
+
 config ROOT_NFS
 	bool "Root file system on NFS"
 	depends on NFS_FS=y && IP_PNP
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index 503b9da..3a282f8 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -79,3 +79,16 @@ config NFSD_V4
 	  available from http://linux-nfs.org/.
 
 	  If unsure, say N.
+
+config NFSD_V4_SECURITY_LABEL
+	bool "Provide Security Label support for NFSv4 server"
+	depends on NFSD_V4 && SECURITY
+	help
+
+	Say Y here if you want enable fine-grained 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.
+	Without this an NFSv4 mount will have the same label on each file.
+
+	If you do not wish to enable fine-grained security labels SELinux or
+	Smack policies on NFSv4 files, say N.
-- 
1.6.2.5


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
  2010-07-07 14:31 ` David P. Quigley
@ 2010-07-07 14:31   ` David P. Quigley
  -1 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

This patch adds a new recommended attribute named label into the NFSv4 file
attribute structure. It also adds several new flags to allow the NFS client and
server to determine if this attribute is supported and if it is being sent over
the wire.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/nfsd/nfsd.h              |    6 +++---
 include/linux/nfs4.h        |    2 ++
 include/linux/nfs_fs_sb.h   |    1 +
 include/linux/nfs_xdr.h     |    4 +++-
 include/linux/nfsd/export.h |    5 +++--
 5 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index e942a1a..ae20d51 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -277,8 +277,8 @@ extern struct timeval	nfssvc_boot;
  | FATTR4_WORD1_OWNER	        | FATTR4_WORD1_OWNER_GROUP  | FATTR4_WORD1_RAWDEV           \
  | FATTR4_WORD1_SPACE_AVAIL     | FATTR4_WORD1_SPACE_FREE   | FATTR4_WORD1_SPACE_TOTAL      \
  | FATTR4_WORD1_SPACE_USED      | FATTR4_WORD1_TIME_ACCESS  | FATTR4_WORD1_TIME_ACCESS_SET  \
- | FATTR4_WORD1_TIME_DELTA   | FATTR4_WORD1_TIME_METADATA    \
- | FATTR4_WORD1_TIME_MODIFY     | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID)
+ | FATTR4_WORD1_TIME_DELTA   	| FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY     \
+ | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID | FATTR4_WORD1_SECURITY_LABEL)
 
 #define NFSD4_SUPPORTED_ATTRS_WORD2 0
 
@@ -318,7 +318,7 @@ static inline u32 nfsd_suppattrs2(u32 minorversion)
 (FATTR4_WORD0_SIZE              | FATTR4_WORD0_ACL                                         )
 #define NFSD_WRITEABLE_ATTRS_WORD1                                                          \
 (FATTR4_WORD1_MODE              | FATTR4_WORD1_OWNER         | FATTR4_WORD1_OWNER_GROUP     \
- | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
+ | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_SECURITY_LABEL)
 #define NFSD_WRITEABLE_ATTRS_WORD2 0
 
 #define NFSD_SUPPATTR_EXCLCREAT_WORD0 \
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 9b8299a..a2abd1a 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -23,6 +23,7 @@
 #define NFS4_MAXNAMLEN		NAME_MAX
 #define NFS4_OPAQUE_LIMIT	1024
 #define NFS4_MAX_SESSIONID_LEN	16
+#define NFS4_MAXLABELLEN	4096
 
 #define NFS4_ACCESS_READ        0x0001
 #define NFS4_ACCESS_LOOKUP      0x0002
@@ -471,6 +472,7 @@ enum lock_type4 {
 #define FATTR4_WORD1_TIME_MODIFY        (1UL << 21)
 #define FATTR4_WORD1_TIME_MODIFY_SET    (1UL << 22)
 #define FATTR4_WORD1_MOUNTED_ON_FILEID  (1UL << 23)
+#define FATTR4_WORD1_SECURITY_LABEL     (1UL << 31)
 
 #define NFSPROC4_NULL 0
 #define NFSPROC4_COMPOUND 1
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index e82957a..aa95a22 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -177,6 +177,7 @@ struct nfs_server {
 #define NFS_CAP_CTIME		(1U << 12)
 #define NFS_CAP_MTIME		(1U << 13)
 #define NFS_CAP_POSIX_LOCK	(1U << 14)
+#define NFS_CAP_SECURITY_LABEL	(1U << 15)
 
 
 /* maximum number of slots to use */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 89b2881..28cde54 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -78,6 +78,7 @@ struct nfs_fattr {
 #define NFS_ATTR_FATTR_CHANGE		(1U << 17)
 #define NFS_ATTR_FATTR_PRECHANGE	(1U << 18)
 #define NFS_ATTR_FATTR_V4_REFERRAL	(1U << 19)	/* NFSv4 referral */
+#define NFS_ATTR_FATTR_V4_SECURITY_LABEL (1U << 20)	/* NFSv4 Security Labels */
 
 #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \
 		| NFS_ATTR_FATTR_MODE \
@@ -97,7 +98,8 @@ struct nfs_fattr {
 		| NFS_ATTR_FATTR_SPACE_USED)
 #define NFS_ATTR_FATTR_V4 (NFS_ATTR_FATTR \
 		| NFS_ATTR_FATTR_SPACE_USED \
-		| NFS_ATTR_FATTR_CHANGE)
+		| NFS_ATTR_FATTR_CHANGE \
+		| NFS_ATTR_FATTR_V4_SECURITY_LABEL)
 
 /*
  * Info on the file system
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 8ae78a6..72abeb6 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -31,7 +31,8 @@
 #define NFSEXP_ALLSQUASH	0x0008
 #define NFSEXP_ASYNC		0x0010
 #define NFSEXP_GATHERED_WRITES	0x0020
-/* 40 80 100 currently unused */
+#define NFSEXP_SECURITY_LABEL	0x0040  /* Support security label fattr4 */
+/* 80 100 currently unused */
 #define NFSEXP_NOHIDE		0x0200
 #define NFSEXP_NOSUBTREECHECK	0x0400
 #define	NFSEXP_NOAUTHNLM	0x0800		/* Don't authenticate NLM requests - just trust */
@@ -50,7 +51,7 @@
  */
 #define	NFSEXP_V4ROOT		0x10000
 /* All flags that we claim to support.  (Note we don't support NOACL.) */
-#define NFSEXP_ALLFLAGS		0x17E3F
+#define NFSEXP_ALLFLAGS		0x17E7F
 
 /* The flags that may vary depending on security flavor: */
 #define NFSEXP_SECINFO_FLAGS	(NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-07 14:31   ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

This patch adds a new recommended attribute named label into the NFSv4 file
attribute structure. It also adds several new flags to allow the NFS client and
server to determine if this attribute is supported and if it is being sent over
the wire.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/nfsd/nfsd.h              |    6 +++---
 include/linux/nfs4.h        |    2 ++
 include/linux/nfs_fs_sb.h   |    1 +
 include/linux/nfs_xdr.h     |    4 +++-
 include/linux/nfsd/export.h |    5 +++--
 5 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index e942a1a..ae20d51 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -277,8 +277,8 @@ extern struct timeval	nfssvc_boot;
  | FATTR4_WORD1_OWNER	        | FATTR4_WORD1_OWNER_GROUP  | FATTR4_WORD1_RAWDEV           \
  | FATTR4_WORD1_SPACE_AVAIL     | FATTR4_WORD1_SPACE_FREE   | FATTR4_WORD1_SPACE_TOTAL      \
  | FATTR4_WORD1_SPACE_USED      | FATTR4_WORD1_TIME_ACCESS  | FATTR4_WORD1_TIME_ACCESS_SET  \
- | FATTR4_WORD1_TIME_DELTA   | FATTR4_WORD1_TIME_METADATA    \
- | FATTR4_WORD1_TIME_MODIFY     | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID)
+ | FATTR4_WORD1_TIME_DELTA   	| FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY     \
+ | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID | FATTR4_WORD1_SECURITY_LABEL)
 
 #define NFSD4_SUPPORTED_ATTRS_WORD2 0
 
@@ -318,7 +318,7 @@ static inline u32 nfsd_suppattrs2(u32 minorversion)
 (FATTR4_WORD0_SIZE              | FATTR4_WORD0_ACL                                         )
 #define NFSD_WRITEABLE_ATTRS_WORD1                                                          \
 (FATTR4_WORD1_MODE              | FATTR4_WORD1_OWNER         | FATTR4_WORD1_OWNER_GROUP     \
- | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
+ | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_SECURITY_LABEL)
 #define NFSD_WRITEABLE_ATTRS_WORD2 0
 
 #define NFSD_SUPPATTR_EXCLCREAT_WORD0 \
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 9b8299a..a2abd1a 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -23,6 +23,7 @@
 #define NFS4_MAXNAMLEN		NAME_MAX
 #define NFS4_OPAQUE_LIMIT	1024
 #define NFS4_MAX_SESSIONID_LEN	16
+#define NFS4_MAXLABELLEN	4096
 
 #define NFS4_ACCESS_READ        0x0001
 #define NFS4_ACCESS_LOOKUP      0x0002
@@ -471,6 +472,7 @@ enum lock_type4 {
 #define FATTR4_WORD1_TIME_MODIFY        (1UL << 21)
 #define FATTR4_WORD1_TIME_MODIFY_SET    (1UL << 22)
 #define FATTR4_WORD1_MOUNTED_ON_FILEID  (1UL << 23)
+#define FATTR4_WORD1_SECURITY_LABEL     (1UL << 31)
 
 #define NFSPROC4_NULL 0
 #define NFSPROC4_COMPOUND 1
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index e82957a..aa95a22 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -177,6 +177,7 @@ struct nfs_server {
 #define NFS_CAP_CTIME		(1U << 12)
 #define NFS_CAP_MTIME		(1U << 13)
 #define NFS_CAP_POSIX_LOCK	(1U << 14)
+#define NFS_CAP_SECURITY_LABEL	(1U << 15)
 
 
 /* maximum number of slots to use */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 89b2881..28cde54 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -78,6 +78,7 @@ struct nfs_fattr {
 #define NFS_ATTR_FATTR_CHANGE		(1U << 17)
 #define NFS_ATTR_FATTR_PRECHANGE	(1U << 18)
 #define NFS_ATTR_FATTR_V4_REFERRAL	(1U << 19)	/* NFSv4 referral */
+#define NFS_ATTR_FATTR_V4_SECURITY_LABEL (1U << 20)	/* NFSv4 Security Labels */
 
 #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \
 		| NFS_ATTR_FATTR_MODE \
@@ -97,7 +98,8 @@ struct nfs_fattr {
 		| NFS_ATTR_FATTR_SPACE_USED)
 #define NFS_ATTR_FATTR_V4 (NFS_ATTR_FATTR \
 		| NFS_ATTR_FATTR_SPACE_USED \
-		| NFS_ATTR_FATTR_CHANGE)
+		| NFS_ATTR_FATTR_CHANGE \
+		| NFS_ATTR_FATTR_V4_SECURITY_LABEL)
 
 /*
  * Info on the file system
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 8ae78a6..72abeb6 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -31,7 +31,8 @@
 #define NFSEXP_ALLSQUASH	0x0008
 #define NFSEXP_ASYNC		0x0010
 #define NFSEXP_GATHERED_WRITES	0x0020
-/* 40 80 100 currently unused */
+#define NFSEXP_SECURITY_LABEL	0x0040  /* Support security label fattr4 */
+/* 80 100 currently unused */
 #define NFSEXP_NOHIDE		0x0200
 #define NFSEXP_NOSUBTREECHECK	0x0400
 #define	NFSEXP_NOAUTHNLM	0x0800		/* Don't authenticate NLM requests - just trust */
@@ -50,7 +51,7 @@
  */
 #define	NFSEXP_V4ROOT		0x10000
 /* All flags that we claim to support.  (Note we don't support NOACL.) */
-#define NFSEXP_ALLFLAGS		0x17E3F
+#define NFSEXP_ALLFLAGS		0x17E7F
 
 /* The flags that may vary depending on security flavor: */
 #define NFSEXP_SECINFO_FLAGS	(NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
-- 
1.6.2.5


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 07/10] NFSv4: Introduce new label structure
  2010-07-07 14:31 ` David P. Quigley
@ 2010-07-07 14:31   ` David P. Quigley
  -1 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

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>
---
 fs/nfs/nfs4proc.c       |   26 ++++++++++++++++++++++++++
 fs/nfsd/xdr4.h          |    3 +++
 include/linux/nfs4.h    |    7 +++++++
 include/linux/nfs_fs.h  |    7 +++++++
 include/linux/nfs_xdr.h |   22 ++++++++++++++++++++++
 5 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 071fced..71bb8da 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -148,6 +148,32 @@ const u32 nfs4_fs_locations_bitmap[2] = {
 	| FATTR4_WORD1_MOUNTED_ON_FILEID
 };
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+
+struct nfs4_label * nfs4_label_alloc (gfp_t flags)
+{
+	struct nfs4_label *label = NULL;
+
+	label = kzalloc(sizeof(struct nfs4_label) + NFS4_MAXLABELLEN, flags);
+	if (label == NULL)
+		return NULL;
+
+	label->label = (void *)(label + 1);
+	label->len = NFS4_MAXLABELLEN;
+	/* 0 is the null format meaning that the data is not to be translated */
+ 	label->lfs = 0;
+	return label;
+}
+
+void nfs4_label_free (struct nfs4_label *label)
+{
+	if (label)
+		kfree(label);
+	return;
+}
+
+#endif
+
 static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
 		struct nfs4_readdir_arg *readdir)
 {
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index efa3377..c217277 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -108,6 +108,7 @@ struct nfsd4_create {
 	struct iattr	cr_iattr;           /* request */
 	struct nfsd4_change_info  cr_cinfo; /* response */
 	struct nfs4_acl *cr_acl;
+	struct nfs4_label *cr_label;
 };
 #define cr_linklen	u.link.namelen
 #define cr_linkname	u.link.name
@@ -235,6 +236,7 @@ struct nfsd4_open {
 	int		op_truncate;        /* used during processing */
 	struct nfs4_stateowner *op_stateowner; /* used during processing */
 	struct nfs4_acl *op_acl;
+	struct nfs4_label *op_label;
 };
 #define op_iattr	iattr
 #define op_verf		verf
@@ -316,6 +318,7 @@ struct nfsd4_setattr {
 	u32		sa_bmval[3];        /* request */
 	struct iattr	sa_iattr;           /* request */
 	struct nfs4_acl *sa_acl;
+	struct nfs4_label *sa_label;
 };
 
 struct nfsd4_setclientid {
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index a2abd1a..c512a0c 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -167,6 +167,13 @@ struct nfs4_acl {
 	struct nfs4_ace	aces[0];
 };
 
+struct nfs4_label {
+	void		*label;
+	u32		len;
+	uint32_t	lfs;
+};
+
+
 typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
 typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
 
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 07ce460..2813b71 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -454,6 +454,13 @@ extern int nfs_mountpoint_expiry_timeout;
 extern void nfs_release_automount_timer(void);
 
 /*
+ * linux/fs/nfs/nfs4proc.c
+ */
+
+struct nfs4_label *	nfs4_label_alloc (gfp_t flags);
+void			nfs4_label_free (struct nfs4_label *);
+
+/*
  * linux/fs/nfs/unlink.c
  */
 extern int  nfs_async_unlink(struct inode *dir, struct dentry *dentry);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 28cde54..dc505e4 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -207,6 +207,7 @@ struct nfs_openargs {
 	const struct nfs_server *server;	 /* Needed for ID mapping */
 	const u32 *		bitmask;
 	__u32			claim;
+	const struct nfs4_label *label;
 	struct nfs4_sequence_args	seq_args;
 };
 
@@ -216,7 +217,9 @@ struct nfs_openres {
 	struct nfs4_change_info	cinfo;
 	__u32                   rflags;
 	struct nfs_fattr *      f_attr;
+	struct nfs4_label *	f_label;
 	struct nfs_fattr *      dir_attr;
+	struct nfs4_label *	dir_label;
 	struct nfs_seqid *	seqid;
 	const struct nfs_server *server;
 	fmode_t			delegation_type;
@@ -256,6 +259,7 @@ struct nfs_closeargs {
 struct nfs_closeres {
 	nfs4_stateid            stateid;
 	struct nfs_fattr *	fattr;
+	struct nfs4_label *	label;
 	struct nfs_seqid *	seqid;
 	const struct nfs_server *server;
 	struct nfs4_sequence_res	seq_res;
@@ -324,6 +328,7 @@ struct nfs4_delegreturnargs {
 
 struct nfs4_delegreturnres {
 	struct nfs_fattr * fattr;
+	struct nfs4_label * label;
 	const struct nfs_server *server;
 	struct nfs4_sequence_res	seq_res;
 };
@@ -343,6 +348,7 @@ struct nfs_readargs {
 
 struct nfs_readres {
 	struct nfs_fattr *	fattr;
+	struct nfs4_label *	label;
 	__u32			count;
 	int                     eof;
 	struct nfs4_sequence_res	seq_res;
@@ -390,6 +396,7 @@ struct nfs_removeres {
 	const struct nfs_server *server;
 	struct nfs4_change_info	cinfo;
 	struct nfs_fattr	dir_attr;
+	struct nfs4_label	*dir_label;
 	struct nfs4_sequence_res 	seq_res;
 };
 
@@ -405,6 +412,7 @@ struct nfs_entry {
 	int			eof;
 	struct nfs_fh *		fh;
 	struct nfs_fattr *	fattr;
+	struct nfs4_label *	label;
 };
 
 /*
@@ -443,6 +451,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 nfs4_sequence_args 	seq_args;
 };
 
@@ -473,6 +482,7 @@ struct nfs_getaclres {
 
 struct nfs_setattrres {
 	struct nfs_fattr *              fattr;
+	struct nfs4_label *		label;
 	const struct nfs_server *	server;
 	struct nfs4_sequence_res	seq_res;
 };
@@ -662,6 +672,7 @@ struct nfs4_accessargs {
 struct nfs4_accessres {
 	const struct nfs_server *	server;
 	struct nfs_fattr *		fattr;
+	struct nfs4_label *		label;
 	u32				supported;
 	u32				access;
 	struct nfs4_sequence_res	seq_res;
@@ -684,6 +695,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_sequence_args 	seq_args;
 };
 
@@ -691,8 +703,10 @@ struct nfs4_create_res {
 	const struct nfs_server *	server;
 	struct nfs_fh *			fh;
 	struct nfs_fattr *		fattr;
+	struct nfs4_label *		label;
 	struct nfs4_change_info		dir_cinfo;
 	struct nfs_fattr *		dir_fattr;
+	struct nfs4_label *		dir_label;
 	struct nfs4_sequence_res	seq_res;
 };
 
@@ -717,6 +731,7 @@ struct nfs4_getattr_res {
 	const struct nfs_server *	server;
 	struct nfs_fattr *		fattr;
 	struct nfs4_sequence_res	seq_res;
+	struct nfs4_label *		label;
 };
 
 struct nfs4_link_arg {
@@ -730,8 +745,10 @@ struct nfs4_link_arg {
 struct nfs4_link_res {
 	const struct nfs_server *	server;
 	struct nfs_fattr *		fattr;
+	struct nfs4_label *		label;
 	struct nfs4_change_info		cinfo;
 	struct nfs_fattr *		dir_attr;
+	struct nfs4_label *		dir_label;
 	struct nfs4_sequence_res	seq_res;
 };
 
@@ -747,6 +764,7 @@ struct nfs4_lookup_res {
 	const struct nfs_server *	server;
 	struct nfs_fattr *		fattr;
 	struct nfs_fh *			fh;
+	struct nfs4_label *		label;
 	struct nfs4_sequence_res	seq_res;
 };
 
@@ -800,6 +818,8 @@ struct nfs4_rename_arg {
 	const struct nfs_fh *		new_dir;
 	const struct qstr *		old_name;
 	const struct qstr *		new_name;
+	const struct nfs4_label *	old_label;
+	const struct nfs4_label *	new_label;
 	const u32 *			bitmask;
 	struct nfs4_sequence_args	seq_args;
 };
@@ -808,8 +828,10 @@ struct nfs4_rename_res {
 	const struct nfs_server *	server;
 	struct nfs4_change_info		old_cinfo;
 	struct nfs_fattr *		old_fattr;
+	struct nfs4_label *		old_label;
 	struct nfs4_change_info		new_cinfo;
 	struct nfs_fattr *		new_fattr;
+	struct nfs4_label *		new_label;
 	struct nfs4_sequence_res	seq_res;
 };
 
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 07/10] NFSv4: Introduce new label structure
@ 2010-07-07 14:31   ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

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>
---
 fs/nfs/nfs4proc.c       |   26 ++++++++++++++++++++++++++
 fs/nfsd/xdr4.h          |    3 +++
 include/linux/nfs4.h    |    7 +++++++
 include/linux/nfs_fs.h  |    7 +++++++
 include/linux/nfs_xdr.h |   22 ++++++++++++++++++++++
 5 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 071fced..71bb8da 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -148,6 +148,32 @@ const u32 nfs4_fs_locations_bitmap[2] = {
 	| FATTR4_WORD1_MOUNTED_ON_FILEID
 };
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+
+struct nfs4_label * nfs4_label_alloc (gfp_t flags)
+{
+	struct nfs4_label *label = NULL;
+
+	label = kzalloc(sizeof(struct nfs4_label) + NFS4_MAXLABELLEN, flags);
+	if (label == NULL)
+		return NULL;
+
+	label->label = (void *)(label + 1);
+	label->len = NFS4_MAXLABELLEN;
+	/* 0 is the null format meaning that the data is not to be translated */
+ 	label->lfs = 0;
+	return label;
+}
+
+void nfs4_label_free (struct nfs4_label *label)
+{
+	if (label)
+		kfree(label);
+	return;
+}
+
+#endif
+
 static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
 		struct nfs4_readdir_arg *readdir)
 {
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index efa3377..c217277 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -108,6 +108,7 @@ struct nfsd4_create {
 	struct iattr	cr_iattr;           /* request */
 	struct nfsd4_change_info  cr_cinfo; /* response */
 	struct nfs4_acl *cr_acl;
+	struct nfs4_label *cr_label;
 };
 #define cr_linklen	u.link.namelen
 #define cr_linkname	u.link.name
@@ -235,6 +236,7 @@ struct nfsd4_open {
 	int		op_truncate;        /* used during processing */
 	struct nfs4_stateowner *op_stateowner; /* used during processing */
 	struct nfs4_acl *op_acl;
+	struct nfs4_label *op_label;
 };
 #define op_iattr	iattr
 #define op_verf		verf
@@ -316,6 +318,7 @@ struct nfsd4_setattr {
 	u32		sa_bmval[3];        /* request */
 	struct iattr	sa_iattr;           /* request */
 	struct nfs4_acl *sa_acl;
+	struct nfs4_label *sa_label;
 };
 
 struct nfsd4_setclientid {
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index a2abd1a..c512a0c 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -167,6 +167,13 @@ struct nfs4_acl {
 	struct nfs4_ace	aces[0];
 };
 
+struct nfs4_label {
+	void		*label;
+	u32		len;
+	uint32_t	lfs;
+};
+
+
 typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
 typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
 
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 07ce460..2813b71 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -454,6 +454,13 @@ extern int nfs_mountpoint_expiry_timeout;
 extern void nfs_release_automount_timer(void);
 
 /*
+ * linux/fs/nfs/nfs4proc.c
+ */
+
+struct nfs4_label *	nfs4_label_alloc (gfp_t flags);
+void			nfs4_label_free (struct nfs4_label *);
+
+/*
  * linux/fs/nfs/unlink.c
  */
 extern int  nfs_async_unlink(struct inode *dir, struct dentry *dentry);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 28cde54..dc505e4 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -207,6 +207,7 @@ struct nfs_openargs {
 	const struct nfs_server *server;	 /* Needed for ID mapping */
 	const u32 *		bitmask;
 	__u32			claim;
+	const struct nfs4_label *label;
 	struct nfs4_sequence_args	seq_args;
 };
 
@@ -216,7 +217,9 @@ struct nfs_openres {
 	struct nfs4_change_info	cinfo;
 	__u32                   rflags;
 	struct nfs_fattr *      f_attr;
+	struct nfs4_label *	f_label;
 	struct nfs_fattr *      dir_attr;
+	struct nfs4_label *	dir_label;
 	struct nfs_seqid *	seqid;
 	const struct nfs_server *server;
 	fmode_t			delegation_type;
@@ -256,6 +259,7 @@ struct nfs_closeargs {
 struct nfs_closeres {
 	nfs4_stateid            stateid;
 	struct nfs_fattr *	fattr;
+	struct nfs4_label *	label;
 	struct nfs_seqid *	seqid;
 	const struct nfs_server *server;
 	struct nfs4_sequence_res	seq_res;
@@ -324,6 +328,7 @@ struct nfs4_delegreturnargs {
 
 struct nfs4_delegreturnres {
 	struct nfs_fattr * fattr;
+	struct nfs4_label * label;
 	const struct nfs_server *server;
 	struct nfs4_sequence_res	seq_res;
 };
@@ -343,6 +348,7 @@ struct nfs_readargs {
 
 struct nfs_readres {
 	struct nfs_fattr *	fattr;
+	struct nfs4_label *	label;
 	__u32			count;
 	int                     eof;
 	struct nfs4_sequence_res	seq_res;
@@ -390,6 +396,7 @@ struct nfs_removeres {
 	const struct nfs_server *server;
 	struct nfs4_change_info	cinfo;
 	struct nfs_fattr	dir_attr;
+	struct nfs4_label	*dir_label;
 	struct nfs4_sequence_res 	seq_res;
 };
 
@@ -405,6 +412,7 @@ struct nfs_entry {
 	int			eof;
 	struct nfs_fh *		fh;
 	struct nfs_fattr *	fattr;
+	struct nfs4_label *	label;
 };
 
 /*
@@ -443,6 +451,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 nfs4_sequence_args 	seq_args;
 };
 
@@ -473,6 +482,7 @@ struct nfs_getaclres {
 
 struct nfs_setattrres {
 	struct nfs_fattr *              fattr;
+	struct nfs4_label *		label;
 	const struct nfs_server *	server;
 	struct nfs4_sequence_res	seq_res;
 };
@@ -662,6 +672,7 @@ struct nfs4_accessargs {
 struct nfs4_accessres {
 	const struct nfs_server *	server;
 	struct nfs_fattr *		fattr;
+	struct nfs4_label *		label;
 	u32				supported;
 	u32				access;
 	struct nfs4_sequence_res	seq_res;
@@ -684,6 +695,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_sequence_args 	seq_args;
 };
 
@@ -691,8 +703,10 @@ struct nfs4_create_res {
 	const struct nfs_server *	server;
 	struct nfs_fh *			fh;
 	struct nfs_fattr *		fattr;
+	struct nfs4_label *		label;
 	struct nfs4_change_info		dir_cinfo;
 	struct nfs_fattr *		dir_fattr;
+	struct nfs4_label *		dir_label;
 	struct nfs4_sequence_res	seq_res;
 };
 
@@ -717,6 +731,7 @@ struct nfs4_getattr_res {
 	const struct nfs_server *	server;
 	struct nfs_fattr *		fattr;
 	struct nfs4_sequence_res	seq_res;
+	struct nfs4_label *		label;
 };
 
 struct nfs4_link_arg {
@@ -730,8 +745,10 @@ struct nfs4_link_arg {
 struct nfs4_link_res {
 	const struct nfs_server *	server;
 	struct nfs_fattr *		fattr;
+	struct nfs4_label *		label;
 	struct nfs4_change_info		cinfo;
 	struct nfs_fattr *		dir_attr;
+	struct nfs4_label *		dir_label;
 	struct nfs4_sequence_res	seq_res;
 };
 
@@ -747,6 +764,7 @@ struct nfs4_lookup_res {
 	const struct nfs_server *	server;
 	struct nfs_fattr *		fattr;
 	struct nfs_fh *			fh;
+	struct nfs4_label *		label;
 	struct nfs4_sequence_res	seq_res;
 };
 
@@ -800,6 +818,8 @@ struct nfs4_rename_arg {
 	const struct nfs_fh *		new_dir;
 	const struct qstr *		old_name;
 	const struct qstr *		new_name;
+	const struct nfs4_label *	old_label;
+	const struct nfs4_label *	new_label;
 	const u32 *			bitmask;
 	struct nfs4_sequence_args	seq_args;
 };
@@ -808,8 +828,10 @@ struct nfs4_rename_res {
 	const struct nfs_server *	server;
 	struct nfs4_change_info		old_cinfo;
 	struct nfs_fattr *		old_fattr;
+	struct nfs4_label *		old_label;
 	struct nfs4_change_info		new_cinfo;
 	struct nfs_fattr *		new_fattr;
+	struct nfs4_label *		new_label;
 	struct nfs4_sequence_res	seq_res;
 };
 
-- 
1.6.2.5


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 08/10] NFS: Client implementation of Labeled-NFS
  2010-07-07 14:31 ` David P. Quigley
@ 2010-07-07 14:31   ` David P. Quigley
  -1 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

This patch implements the client transport and handling support for labeled
NFS. The patch adds two functions to encode and decode the security label
recommended attribute which makes use of the LSM hooks added earlier. It also
adds code to grab the label from the file attribute structures and encode the
label to be sent back to the server.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/nfs/client.c           |    2 +-
 fs/nfs/dir.c              |   67 ++++--
 fs/nfs/getroot.c          |   32 +++-
 fs/nfs/inode.c            |   95 ++++++--
 fs/nfs/namespace.c        |    2 +-
 fs/nfs/nfs3acl.c          |    4 +-
 fs/nfs/nfs3proc.c         |   37 ++--
 fs/nfs/nfs4proc.c         |  591 +++++++++++++++++++++++++++++++++++++++------
 fs/nfs/nfs4xdr.c          |  133 ++++++++---
 fs/nfs/proc.c             |   15 +-
 fs/nfs/super.c            |   13 +-
 include/linux/nfs_fs.h    |   10 +-
 include/linux/nfs_fs_sb.h |    6 +
 include/linux/nfs_xdr.h   |    5 +-
 security/selinux/hooks.c  |    4 +
 15 files changed, 841 insertions(+), 175 deletions(-)

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index acc9c49..aa27229 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1078,7 +1078,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
 	}
 
 	if (!(fattr.valid & NFS_ATTR_FATTR)) {
-		error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
+		error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr, NULL);
 		if (error < 0) {
 			dprintk("nfs_create_server: getattr error = %d\n", -error);
 			goto error;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index a7bb5c6..d8590d6 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -557,6 +557,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 	my_entry.fh = &fh;
 	my_entry.fattr = &fattr;
 	nfs_fattr_init(&fattr);
+
 	desc->entry = &my_entry;
 
 	nfs_block_sillyrename(dentry);
@@ -776,9 +777,10 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 	struct inode *dir;
 	struct inode *inode;
 	struct dentry *parent;
-	int error;
+	int error = 0;
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr;
+	struct nfs4_label *label = NULL;
 
 	parent = dget_parent(dentry);
 	dir = parent->d_inode;
@@ -811,13 +813,26 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 	if (NFS_STALE(inode))
 		goto out_bad;
 
-	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		label = nfs4_label_alloc(GFP_NOWAIT);
+		if (label == NULL)
+			goto out_bad;
+	}
+#endif
+
+	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr, label);
 	if (error)
-		goto out_bad;
+		goto out_bad_free;
 	if (nfs_compare_fh(NFS_FH(inode), &fhandle))
-		goto out_bad;
-	if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
-		goto out_bad;
+		goto out_bad_free;
+	if ((error = nfs_refresh_inode(inode, &fattr, label)) != 0)
+		goto out_bad_free;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL))
+		nfs4_label_free(label);
+#endif
 
 out_set_verifier:
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
@@ -829,7 +844,7 @@ out_set_verifier:
 	return 1;
 out_zap_parent:
 	nfs_zap_caches(dir);
- out_bad:
+out_bad:
 	nfs_mark_for_revalidate(dir);
 	if (inode && S_ISDIR(inode->i_mode)) {
 		/* Purge readdir caches. */
@@ -847,6 +862,13 @@ out_zap_parent:
 			__func__, dentry->d_parent->d_name.name,
 			dentry->d_name.name);
 	return 0;
+
+out_bad_free:
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL))
+		nfs4_label_free(label);
+#endif
+	goto out_bad;
 }
 
 /*
@@ -911,9 +933,10 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
 	struct dentry *res;
 	struct dentry *parent;
 	struct inode *inode = NULL;
-	int error;
+	int error = 0;
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr;
+	struct nfs4_label *label = NULL;
 
 	dfprintk(VFS, "NFS: lookup(%s/%s)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -936,17 +959,26 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
 		goto out;
 	}
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		label = nfs4_label_alloc(GFP_NOWAIT);
+		if (label == NULL)
+			goto out;
+	}
+	/* XXX: should this move inside of nfs4_lookup() ? */
+#endif
+
 	parent = dentry->d_parent;
 	/* Protect against concurrent sillydeletes */
 	nfs_block_sillyrename(parent);
-	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
+	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr, label);
 	if (error == -ENOENT)
 		goto no_entry;
 	if (error < 0) {
 		res = ERR_PTR(error);
 		goto out_unblock_sillyrename;
 	}
-	inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
+	inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr, label);
 	res = (struct dentry *)inode;
 	if (IS_ERR(res))
 		goto out_unblock_sillyrename;
@@ -961,6 +993,10 @@ no_entry:
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 out_unblock_sillyrename:
 	nfs_unblock_sillyrename(parent);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL))
+		nfs4_label_free(label);
+#endif
 out:
 	return res;
 }
@@ -1149,7 +1185,7 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
 	if (dentry == NULL)
 		return NULL;
 	dentry->d_op = NFS_PROTO(dir)->dentry_ops;
-	inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr);
+	inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr, NULL);
 	if (IS_ERR(inode)) {
 		dput(dentry);
 		return NULL;
@@ -1172,7 +1208,8 @@ out_renew:
  * Code common to create, mkdir, and mknod.
  */
 int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
-				struct nfs_fattr *fattr)
+				struct nfs_fattr *fattr,
+				struct nfs4_label *label)
 {
 	struct dentry *parent = dget_parent(dentry);
 	struct inode *dir = parent->d_inode;
@@ -1185,18 +1222,18 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
 	if (dentry->d_inode)
 		goto out;
 	if (fhandle->size == 0) {
-		error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
+		error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, NULL);
 		if (error)
 			goto out_error;
 	}
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 	if (!(fattr->valid & NFS_ATTR_FATTR)) {
 		struct nfs_server *server = NFS_SB(dentry->d_sb);
-		error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr);
+		error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr, NULL);
 		if (error < 0)
 			goto out_error;
 	}
-	inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
+	inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label);
 	error = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out_error;
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index b35d2a6..7604f71 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -30,7 +30,6 @@
 #include <linux/nfs_idmap.h>
 #include <linux/vfs.h>
 #include <linux/namei.h>
-#include <linux/security.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -92,7 +91,7 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 		return ERR_PTR(error);
 	}
 
-	inode = nfs_fhget(sb, mntfh, fsinfo.fattr);
+	inode = nfs_fhget(sb, mntfh, fsinfo.fattr, NULL);
 	if (IS_ERR(inode)) {
 		dprintk("nfs_get_root: get root inode failed\n");
 		return ERR_CAST(inode);
@@ -242,6 +241,7 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 	struct nfs_fattr fattr;
 	struct dentry *mntroot;
 	struct inode *inode;
+	struct nfs4_label *label = NULL;
 	int error;
 
 	dprintk("--> nfs4_get_root()\n");
@@ -254,19 +254,43 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 		return ERR_PTR(error);
 	}
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		label = nfs4_label_alloc(GFP_KERNEL);
+		if (label == NULL) {
+			dprintk("nfs_get_root: nfs4_label_alloc error = %d\n",
+					error);
+			return ERR_PTR(-ENOMEM);
+		}
+	}
+#endif
+
 	/* get the actual root for this mount */
-	error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
+	error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr, label);
 	if (error < 0) {
 		dprintk("nfs_get_root: getattr error = %d\n", -error);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		if (server->caps & NFS_CAP_SECURITY_LABEL)
+			nfs4_label_free(label);
+#endif
 		return ERR_PTR(error);
 	}
 
-	inode = nfs_fhget(sb, mntfh, &fattr);
+	inode = nfs_fhget(sb, mntfh, &fattr, label);
 	if (IS_ERR(inode)) {
 		dprintk("nfs_get_root: get root inode failed\n");
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		if (server->caps & NFS_CAP_SECURITY_LABEL)
+			nfs4_label_free(label);
+#endif
 		return ERR_CAST(inode);
 	}
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL)
+		nfs4_label_free(label);
+#endif
+
 	error = nfs_superblock_set_dummy_root(sb, inode);
 	if (error != 0)
 		return ERR_PTR(error);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 50a56ed..88971d9 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -57,7 +57,7 @@
 static int enable_ino64 = NFS_64_BIT_INODE_NUMBERS_ENABLED;
 
 static void nfs_invalidate_inode(struct inode *);
-static int nfs_update_inode(struct inode *, struct nfs_fattr *);
+static int nfs_update_inode(struct inode *, struct nfs_fattr *, struct nfs4_label *);
 
 static struct kmem_cache * nfs_inode_cachep;
 
@@ -138,10 +138,13 @@ static void nfs_zap_caches_locked(struct inode *inode)
 	nfsi->attrtimeo_timestamp = jiffies;
 
 	memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
+	nfsi->cache_validity |= NFS_INO_INVALID_ATTR| \
+				NFS_INO_INVALID_LABEL| \
+				NFS_INO_INVALID_ACCESS| \
+				NFS_INO_INVALID_ACL| \
+				NFS_INO_REVAL_PAGECACHE;
 	if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
-		nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
-	else
-		nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
+		nfsi->cache_validity |= NFS_INO_INVALID_DATA;
 }
 
 void nfs_zap_caches(struct inode *inode)
@@ -230,12 +233,36 @@ nfs_init_locked(struct inode *inode, void *opaque)
 /* Don't use READDIRPLUS on directories that we believe are too large */
 #define NFS_LIMIT_READDIRPLUS (8*PAGE_SIZE)
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
+{
+	int error;
+
+/*	BUG_ON(!mutex_is_locked(&inode->i_mutex)); */
+
+	if ((fattr->valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL) &&
+		label && inode->i_security) {
+		error = security_inode_notifysecctx(inode, label->label,
+						   label->len);
+		if (error)
+			printk(KERN_ERR "%s() %s %d "
+				"security_inode_notifysecctx() %d\n",
+				__func__,
+				(char *)label->label, label->len, error);
+	}
+}
+#else
+void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
+{
+}
+#endif
+
 /*
  * This is our front-end to iget that looks up inodes by file handle
  * instead of inode number.
  */
 struct inode *
-nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
+nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct nfs_find_desc desc = {
 		.fh	= fh,
@@ -365,6 +392,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
 			 */
 			inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
 		}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		nfs_setsecurity(inode, fattr, label);
+#endif
 		nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
 		nfsi->attrtimeo_timestamp = now;
 		nfsi->access_cache = RB_ROOT;
@@ -373,7 +403,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
 
 		unlock_new_inode(inode);
 	} else
-		nfs_refresh_inode(inode, fattr);
+		nfs_refresh_inode(inode, fattr, label);
 	dprintk("NFS: nfs_fhget(%s/%Ld ct=%d)\n",
 		inode->i_sb->s_id,
 		(long long)NFS_FILEID(inode),
@@ -394,7 +424,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
 	struct inode *inode = dentry->d_inode;
 	struct nfs_fattr fattr;
-	int error;
+	int error = 0;
 
 	nfs_inc_stats(inode, NFSIOS_VFSSETATTR);
 
@@ -424,7 +454,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
 		nfs_inode_return_delegation(inode);
 	error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
 	if (error == 0)
-		nfs_refresh_inode(inode, &fattr);
+		nfs_refresh_inode(inode, &fattr, NULL);
 	return error;
 }
 
@@ -682,6 +712,7 @@ int
 __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 {
 	int		 status = -ESTALE;
+	struct nfs4_label *label = NULL;
 	struct nfs_fattr fattr;
 	struct nfs_inode *nfsi = NFS_I(inode);
 
@@ -694,7 +725,17 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 		goto out;
 
 	nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE);
-	status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr);
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) {
+		label = nfs4_label_alloc(GFP_KERNEL);
+		if (label == NULL) {
+			status = -ENOMEM;
+			goto out;
+		}
+	}
+#endif
+	status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr, label);
 	if (status != 0) {
 		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
 			 inode->i_sb->s_id,
@@ -707,7 +748,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 		goto out;
 	}
 
-	status = nfs_refresh_inode(inode, &fattr);
+	status = nfs_refresh_inode(inode, &fattr, label);
 	if (status) {
 		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",
 			 inode->i_sb->s_id,
@@ -723,6 +764,10 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 		(long long)NFS_FILEID(inode));
 
  out:
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL))
+		nfs4_label_free(label);
+#endif
 	return status;
 }
 
@@ -744,7 +789,7 @@ int nfs_attribute_timeout(struct inode *inode)
  */
 int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 {
-	if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR)
+	if (!(NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL))
 			&& !nfs_attribute_timeout(inode))
 		return NFS_STALE(inode) ? -ESTALE : 0;
 	return __nfs_revalidate_inode(server, inode);
@@ -945,10 +990,10 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n
 		((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0);
 }
 
-static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
+static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	if (nfs_inode_attrs_need_update(inode, fattr))
-		return nfs_update_inode(inode, fattr);
+		return nfs_update_inode(inode, fattr, label);
 	return nfs_check_inode_attributes(inode, fattr);
 }
 
@@ -962,20 +1007,20 @@ static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr
  * safe to do a full update of the inode attributes, or whether just to
  * call nfs_check_inode_attributes.
  */
-int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	int status;
 
 	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
 		return 0;
 	spin_lock(&inode->i_lock);
-	status = nfs_refresh_inode_locked(inode, fattr);
+	status = nfs_refresh_inode_locked(inode, fattr, label);
 	spin_unlock(&inode->i_lock);
 
 	return status;
 }
 
-static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
+static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 
@@ -984,7 +1029,7 @@ static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr
 		nfsi->cache_validity |= NFS_INO_INVALID_DATA;
 	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
 		return 0;
-	return nfs_refresh_inode_locked(inode, fattr);
+	return nfs_refresh_inode_locked(inode, fattr, label);
 }
 
 /**
@@ -1001,12 +1046,12 @@ static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr
  * are expected to change one or more attributes, to avoid
  * unnecessary NFS requests and trips through nfs_update_inode().
  */
-int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	int status;
 
 	spin_lock(&inode->i_lock);
-	status = nfs_post_op_update_inode_locked(inode, fattr);
+	status = nfs_post_op_update_inode_locked(inode, fattr, label);
 	spin_unlock(&inode->i_lock);
 	return status;
 }
@@ -1057,7 +1102,7 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa
 		fattr->valid |= NFS_ATTR_FATTR_PRESIZE;
 	}
 out_noforce:
-	status = nfs_post_op_update_inode_locked(inode, fattr);
+	status = nfs_post_op_update_inode_locked(inode, fattr, NULL);
 	spin_unlock(&inode->i_lock);
 	return status;
 }
@@ -1074,7 +1119,7 @@ out_noforce:
  *
  * A very similar scenario holds for the dir cache.
  */
-static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct nfs_server *server;
 	struct nfs_inode *nfsi = NFS_I(inode);
@@ -1226,6 +1271,11 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 				| NFS_INO_INVALID_ACL
 				| NFS_INO_REVAL_FORCED);
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label)
+		nfs_setsecurity(inode, fattr, label);
+#endif
+
 	if (fattr->valid & NFS_ATTR_FATTR_NLINK) {
 		if (inode->i_nlink != fattr->nlink) {
 			invalid |= NFS_INO_INVALID_ATTR;
@@ -1247,7 +1297,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 		inode->i_blocks = fattr->du.nfs2.blocks;
 
 	/* Update attrtimeo value if we're out of the unstable period */
-	if (invalid & NFS_INO_INVALID_ATTR) {
+	if (invalid & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) {
 		nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
 		nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
 		nfsi->attrtimeo_timestamp = now;
@@ -1260,6 +1310,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 		}
 	}
 	invalid &= ~NFS_INO_INVALID_ATTR;
+	invalid &= ~NFS_INO_INVALID_LABEL;
 	/* Don't invalidate the data if we were to blame */
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
 				|| S_ISLNK(inode->i_mode)))
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 7888cf3..252a764 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -123,7 +123,7 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
 	parent = dget_parent(nd->path.dentry);
 	err = server->nfs_client->rpc_ops->lookup(parent->d_inode,
 						  &nd->path.dentry->d_name,
-						  &fh, &fattr);
+						  &fh, &fattr, NULL);
 	dput(parent);
 	if (err != 0)
 		goto out_err;
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index d150ae0..20b44bf 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -238,7 +238,7 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
 
 	switch (status) {
 		case 0:
-			status = nfs_refresh_inode(inode, &fattr);
+			status = nfs_refresh_inode(inode, &fattr, NULL);
 			break;
 		case -EPFNOSUPPORT:
 		case -EPROTONOSUPPORT:
@@ -344,7 +344,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
 
 	switch (status) {
 		case 0:
-			status = nfs_refresh_inode(inode, &fattr);
+			status = nfs_refresh_inode(inode, &fattr, NULL);
 			nfs3_cache_acls(inode, acl, dfacl);
 			break;
 		case -EPFNOSUPPORT:
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index e701002..f58ce23 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -97,7 +97,7 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  */
 static int
 nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
-		struct nfs_fattr *fattr)
+		struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_GETATTR],
@@ -142,7 +142,8 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
 static int
 nfs3_proc_lookup(struct inode *dir, struct qstr *name,
-		 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+		 struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+		 struct nfs4_label *label)
 {
 	struct nfs_fattr	dir_attr;
 	struct nfs3_diropargs	arg = {
@@ -166,7 +167,7 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name,
 	nfs_fattr_init(&dir_attr);
 	nfs_fattr_init(fattr);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-	nfs_refresh_inode(dir, &dir_attr);
+	nfs_refresh_inode(dir, &dir_attr, NULL);
 	if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) {
 		msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
 		msg.rpc_argp = fhandle;
@@ -212,7 +213,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 	}
 	nfs_fattr_init(&fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
-	nfs_refresh_inode(inode, &fattr);
+	nfs_refresh_inode(inode, &fattr, NULL);
 	if (status == 0) {
 		entry->mask = 0;
 		if (res.access & NFS3_ACCESS_READ)
@@ -246,7 +247,7 @@ static int nfs3_proc_readlink(struct inode *inode, struct page *page,
 	dprintk("NFS call  readlink\n");
 	nfs_fattr_init(&fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
-	nfs_refresh_inode(inode, &fattr);
+	nfs_refresh_inode(inode, &fattr, NULL);
 	dprintk("NFS reply readlink: %d\n", status);
 	return status;
 }
@@ -287,9 +288,9 @@ static int nfs3_do_create(struct inode *dir, struct dentry *dentry, struct nfs3_
 	int status;
 
 	status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0);
-	nfs_post_op_update_inode(dir, data->res.dir_attr);
+	nfs_post_op_update_inode(dir, data->res.dir_attr, NULL);
 	if (status == 0)
-		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
+		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL);
 	return status;
 }
 
@@ -370,7 +371,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 		 * not sure this buys us anything (and I'd have
 		 * to revamp the NFSv3 XDR code) */
 		status = nfs3_proc_setattr(dentry, data->res.fattr, sattr);
-		nfs_post_op_update_inode(dentry->d_inode, data->res.fattr);
+		nfs_post_op_update_inode(dentry->d_inode, data->res.fattr, NULL);
 		dprintk("NFS reply setattr (post-create): %d\n", status);
 		if (status != 0)
 			goto out;
@@ -401,7 +402,7 @@ nfs3_proc_remove(struct inode *dir, struct qstr *name)
 	dprintk("NFS call  remove %s\n", name->name);
 	nfs_fattr_init(&res.dir_attr);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-	nfs_post_op_update_inode(dir, &res.dir_attr);
+	nfs_post_op_update_inode(dir, &res.dir_attr, NULL);
 	dprintk("NFS reply remove: %d\n", status);
 	return status;
 }
@@ -419,7 +420,7 @@ nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 	if (nfs3_async_handle_jukebox(task, dir))
 		return 0;
 	res = task->tk_msg.rpc_resp;
-	nfs_post_op_update_inode(dir, &res->dir_attr);
+	nfs_post_op_update_inode(dir, &res->dir_attr, NULL);
 	return 1;
 }
 
@@ -451,8 +452,8 @@ nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
 	nfs_fattr_init(&old_dir_attr);
 	nfs_fattr_init(&new_dir_attr);
 	status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
-	nfs_post_op_update_inode(old_dir, &old_dir_attr);
-	nfs_post_op_update_inode(new_dir, &new_dir_attr);
+	nfs_post_op_update_inode(old_dir, &old_dir_attr, NULL);
+	nfs_post_op_update_inode(new_dir, &new_dir_attr, NULL);
 	dprintk("NFS reply rename: %d\n", status);
 	return status;
 }
@@ -482,8 +483,8 @@ nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 	nfs_fattr_init(&dir_attr);
 	nfs_fattr_init(&fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
-	nfs_post_op_update_inode(dir, &dir_attr);
-	nfs_post_op_update_inode(inode, &fattr);
+	nfs_post_op_update_inode(dir, &dir_attr, NULL);
+	nfs_post_op_update_inode(inode, &fattr, NULL);
 	dprintk("NFS reply link: %d\n", status);
 	return status;
 }
@@ -570,7 +571,7 @@ nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
 	dprintk("NFS call  rmdir %s\n", name->name);
 	nfs_fattr_init(&dir_attr);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-	nfs_post_op_update_inode(dir, &dir_attr);
+	nfs_post_op_update_inode(dir, &dir_attr, NULL);
 	dprintk("NFS reply rmdir: %d\n", status);
 	return status;
 }
@@ -623,7 +624,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 
 	nfs_invalidate_atime(dir);
 
-	nfs_refresh_inode(dir, &dir_attr);
+	nfs_refresh_inode(dir, &dir_attr, NULL);
 	dprintk("NFS reply readdir: %d\n", status);
 	return status;
 }
@@ -756,7 +757,7 @@ static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data)
 		return -EAGAIN;
 
 	nfs_invalidate_atime(data->inode);
-	nfs_refresh_inode(data->inode, &data->fattr);
+	nfs_refresh_inode(data->inode, &data->fattr, NULL);
 	return 0;
 }
 
@@ -783,7 +784,7 @@ static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data)
 {
 	if (nfs3_async_handle_jukebox(task, data->inode))
 		return -EAGAIN;
-	nfs_refresh_inode(data->inode, data->res.fattr);
+	nfs_refresh_inode(data->inode, data->res.fattr, NULL);
 	return 0;
 }
 
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 71bb8da..e2b9010 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -68,8 +68,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data);
 static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
 static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
 static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *);
-static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
-static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
+static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label);
+static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label);
 
 /* Prevent leaks of NFSv4 errors into userland */
 static int nfs4_map_errors(int err)
@@ -105,6 +105,9 @@ const u32 nfs4_fattr_bitmap[2] = {
 	| FATTR4_WORD1_TIME_ACCESS
 	| FATTR4_WORD1_TIME_METADATA
 	| FATTR4_WORD1_TIME_MODIFY
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	| FATTR4_WORD1_SECURITY_LABEL
+#endif
 };
 
 const u32 nfs4_statfs_bitmap[2] = {
@@ -713,7 +716,9 @@ struct nfs4_opendata {
 	struct nfs_open_confirmargs c_arg;
 	struct nfs_open_confirmres c_res;
 	struct nfs_fattr f_attr;
+	struct nfs4_label *f_label;
 	struct nfs_fattr dir_attr;
+	struct nfs4_label *dir_label;
 	struct path path;
 	struct dentry *dir;
 	struct nfs4_state_owner *owner;
@@ -730,6 +735,8 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
 {
 	p->o_res.f_attr = &p->f_attr;
 	p->o_res.dir_attr = &p->dir_attr;
+	p->o_res.f_label = p->f_label;
+	p->o_res.dir_label = p->dir_label;
 	p->o_res.seqid = p->o_arg.seqid;
 	p->c_res.seqid = p->c_arg.seqid;
 	p->o_res.server = p->o_arg.server;
@@ -740,7 +747,7 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
 
 static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
 		struct nfs4_state_owner *sp, fmode_t fmode, int flags,
-		const struct iattr *attrs)
+		const struct iattr *attrs, struct nfs4_label *label)
 {
 	struct dentry *parent = dget_parent(path->dentry);
 	struct inode *dir = parent->d_inode;
@@ -750,9 +757,21 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
 	p = kzalloc(sizeof(*p), GFP_KERNEL);
 	if (p == NULL)
 		goto err;
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		p->f_label = nfs4_label_alloc(GFP_KERNEL);
+		if (p->f_label == NULL)
+			goto err_free_p;
+		p->dir_label = nfs4_label_alloc(GFP_KERNEL);
+		if (p->dir_label == NULL) {
+			nfs4_label_free(p->f_label);
+			goto err_free_p;
+		}
+	}
+#endif
 	p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
 	if (p->o_arg.seqid == NULL)
-		goto err_free;
+		goto err_free_label;
 	path_get(path);
 	p->path = *path;
 	p->dir = parent;
@@ -767,6 +786,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
 	p->o_arg.server = server;
 	p->o_arg.bitmask = server->attr_bitmask;
 	p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
+	p->o_arg.label = label;
 	if (flags & O_EXCL) {
 		if (nfs4_has_persistent_session(server->nfs_client)) {
 			/* GUARDED */
@@ -787,7 +807,15 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
 	nfs4_init_opendata_res(p);
 	kref_init(&p->kref);
 	return p;
-err_free:
+
+err_free_label:
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		nfs4_label_free(p->f_label);
+		nfs4_label_free(p->dir_label);
+	}
+#endif
+err_free_p:
 	kfree(p);
 err:
 	dput(parent);
@@ -803,6 +831,12 @@ static void nfs4_opendata_free(struct kref *kref)
 	if (p->state != NULL)
 		nfs4_put_open_state(p->state);
 	nfs4_put_state_owner(p->owner);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (p->o_arg.server->caps & NFS_CAP_SECURITY_LABEL) {
+		nfs4_label_free(p->f_label);
+		nfs4_label_free(p->dir_label);
+	}
+#endif
 	dput(p->dir);
 	path_put(&p->path);
 	kfree(p);
@@ -1028,7 +1062,7 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
 	ret = -EAGAIN;
 	if (!(data->f_attr.valid & NFS_ATTR_FATTR))
 		goto err;
-	inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr);
+	inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr, data->f_label);
 	ret = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto err;
@@ -1086,7 +1120,7 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context
 {
 	struct nfs4_opendata *opendata;
 
-	opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, 0, NULL);
+	opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, 0, NULL, NULL);
 	if (opendata == NULL)
 		return ERR_PTR(-ENOMEM);
 	opendata->state = state;
@@ -1518,7 +1552,7 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
 	if (status != 0 || !data->rpc_done)
 		return status;
 
-	nfs_refresh_inode(dir, o_res->dir_attr);
+	nfs_refresh_inode(dir, o_res->dir_attr, o_res->dir_label);
 
 	if (o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
 		status = _nfs4_proc_open_confirm(data);
@@ -1546,9 +1580,9 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
 
 	if (o_arg->open_flags & O_CREAT) {
 		update_changeattr(dir, &o_res->cinfo);
-		nfs_post_op_update_inode(dir, o_res->dir_attr);
+		nfs_post_op_update_inode(dir, o_res->dir_attr, o_res->dir_label);
 	} else
-		nfs_refresh_inode(dir, o_res->dir_attr);
+		nfs_refresh_inode(dir, o_res->dir_attr, o_res->dir_label);
 	if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
 		server->caps &= ~NFS_CAP_POSIX_LOCK;
 	if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
@@ -1557,7 +1591,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
 			return status;
 	}
 	if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
-		_nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr);
+		_nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, o_res->f_label);
 	return 0;
 }
 
@@ -1654,7 +1688,7 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct
 /*
  * Returns a referenced nfs4_state
  */
-static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
+static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, int flags, struct iattr *sattr, struct nfs4_label *label, struct rpc_cred *cred, struct nfs4_state **res)
 {
 	struct nfs4_state_owner  *sp;
 	struct nfs4_state     *state = NULL;
@@ -1674,7 +1708,7 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in
 	if (path->dentry->d_inode != NULL)
 		nfs4_return_incompatible_delegation(path->dentry->d_inode, fmode);
 	status = -ENOMEM;
-	opendata = nfs4_opendata_alloc(path, sp, fmode, flags, sattr);
+	opendata = nfs4_opendata_alloc(path, sp, fmode, flags, sattr, label);
 	if (opendata == NULL)
 		goto err_put_state_owner;
 
@@ -1708,14 +1742,14 @@ out_err:
 }
 
 
-static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred)
+static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, int flags, struct iattr *sattr, struct nfs4_label *label, struct rpc_cred *cred)
 {
 	struct nfs4_exception exception = { };
 	struct nfs4_state *res;
 	int status;
 
 	do {
-		status = _nfs4_do_open(dir, path, fmode, flags, sattr, cred, &res);
+		status = _nfs4_do_open(dir, path, fmode, flags, sattr, label, cred, &res);
 		if (status == 0)
 			break;
 		/* NOTE: BAD_SEQID means the server and client disagree about the
@@ -1759,17 +1793,20 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, fmo
 
 static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
 			    struct nfs_fattr *fattr, struct iattr *sattr,
-			    struct nfs4_state *state)
+			    struct nfs4_state *state, struct nfs4_label *ilabel,
+			    struct nfs4_label *olabel)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
         struct nfs_setattrargs  arg = {
                 .fh             = NFS_FH(inode),
                 .iap            = sattr,
 		.server		= server,
-		.bitmask = server->attr_bitmask,
+		.bitmask 	= server->attr_bitmask,
+		.label		= ilabel,
         };
         struct nfs_setattrres  res = {
 		.fattr		= fattr,
+		.label		= olabel,
 		.server		= server,
         };
         struct rpc_message msg = {
@@ -1781,6 +1818,11 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
 	unsigned long timestamp = jiffies;
 	int status;
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (ilabel == NULL || olabel == NULL)
+		arg.bitmask = server->attr_bitmask_nl;
+#endif
+
 	nfs_fattr_init(fattr);
 
 	if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) {
@@ -1797,15 +1839,16 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
 }
 
 static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
-			   struct nfs_fattr *fattr, struct iattr *sattr,
-			   struct nfs4_state *state)
+			    struct nfs_fattr *fattr, struct iattr *sattr,
+			    struct nfs4_state *state, struct nfs4_label *ilabel,
+			    struct nfs4_label *olabel)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(server,
-				_nfs4_do_setattr(inode, cred, fattr, sattr, state),
+				_nfs4_do_setattr(inode, cred, fattr, sattr, state, ilabel, olabel),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -1875,7 +1918,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
 				rpc_restart_call_prepare(task);
 	}
 	nfs_release_seqid(calldata->arg.seqid);
-	nfs_refresh_inode(calldata->inode, calldata->res.fattr);
+	nfs_refresh_inode(calldata->inode, calldata->res.fattr, NULL);
 }
 
 static void nfs4_close_prepare(struct rpc_task *task, void *data)
@@ -1969,9 +2012,9 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
 	/* Serialization for the sequence id */
 	calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
 	if (calldata->arg.seqid == NULL)
-		goto out_free_calldata;
+		goto out_free;
 	calldata->arg.fmode = 0;
-	calldata->arg.bitmask = server->cache_consistency_bitmask;
+	calldata->arg.bitmask = server->cache_consistency_bitmask_nl;
 	calldata->res.fattr = &calldata->fattr;
 	calldata->res.seqid = calldata->arg.seqid;
 	calldata->res.server = server;
@@ -1990,7 +2033,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
 		status = rpc_wait_for_completion_task(task);
 	rpc_put_task(task);
 	return status;
-out_free_calldata:
+out_free:
 	kfree(calldata);
 out:
 	nfs4_put_open_state(state);
@@ -2027,6 +2070,7 @@ out_close:
 struct dentry *
 nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+	struct nfs4_label l, *label = NULL;
 	struct path path = {
 		.mnt = nd->path.mnt,
 		.dentry = dentry,
@@ -2043,6 +2087,15 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 		attr.ia_valid = ATTR_MODE;
 		if (!IS_POSIXACL(dir))
 			attr.ia_mode &= ~current_umask();
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+			int error;
+			error = security_dentry_init_security(dentry,
+					attr.ia_mode, &l.label, &l.len);
+			if (error == 0)
+				label = &l;
+		}
+#endif
 	} else {
 		attr.ia_valid = 0;
 		BUG_ON(nd->intent.open.flags & O_CREAT);
@@ -2054,8 +2107,12 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 	parent = dentry->d_parent;
 	/* Protect against concurrent sillydeletes */
 	nfs_block_sillyrename(parent);
-	state = nfs4_do_open(dir, &path, fmode, nd->intent.open.flags, &attr, cred);
+	state = nfs4_do_open(dir, &path, fmode, nd->intent.open.flags, &attr, label, cred);
 	put_rpccred(cred);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label)
+		security_release_secctx(l.label, l.len);
+#endif
 	if (IS_ERR(state)) {
 		if (PTR_ERR(state) == -ENOENT) {
 			d_add(dentry, NULL);
@@ -2087,7 +2144,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
 	cred = rpc_lookup_cred();
 	if (IS_ERR(cred))
 		return PTR_ERR(cred);
-	state = nfs4_do_open(dir, &path, fmode, openflags, NULL, cred);
+	state = nfs4_do_open(dir, &path, fmode, openflags, NULL, NULL, cred);
 	put_rpccred(cred);
 	if (IS_ERR(state)) {
 		switch (PTR_ERR(state)) {
@@ -2145,6 +2202,17 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
 				NFS_CAP_CTIME|NFS_CAP_MTIME);
 		if (res.attr_bitmask[0] & FATTR4_WORD0_ACL)
 			server->caps |= NFS_CAP_ACLS;
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		if (res.attr_bitmask[1] & FATTR4_WORD1_SECURITY_LABEL) {
+			server->caps |= NFS_CAP_SECURITY_LABEL;
+		} else
+#endif
+			server->attr_bitmask[1] &= ~FATTR4_WORD1_SECURITY_LABEL;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		memcpy(server->attr_bitmask_nl, res.attr_bitmask, sizeof(server->attr_bitmask));
+		server->attr_bitmask_nl[1] &= ~FATTR4_WORD1_SECURITY_LABEL;
+#endif
 		if (res.has_links != 0)
 			server->caps |= NFS_CAP_HARDLINKS;
 		if (res.has_symlinks != 0)
@@ -2168,7 +2236,12 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
 
 		memcpy(server->cache_consistency_bitmask, res.attr_bitmask, sizeof(server->cache_consistency_bitmask));
 		server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE;
-		server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
+		server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA |
+							FATTR4_WORD1_TIME_MODIFY |
+							FATTR4_WORD1_SECURITY_LABEL;
+		memcpy(server->cache_consistency_bitmask_nl, server->cache_consistency_bitmask,
+						sizeof(server->cache_consistency_bitmask_nl));
+		server->cache_consistency_bitmask_nl[1] &= ~FATTR4_WORD1_SECURITY_LABEL;
 		server->acl_bitmask = res.acl_bitmask;
 	}
 
@@ -2190,8 +2263,9 @@ int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
 static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
 		struct nfs_fsinfo *info)
 {
+	u32 bitmask[2];
 	struct nfs4_lookup_root_arg args = {
-		.bitmask = nfs4_fattr_bitmap,
+		.bitmask = bitmask,
 	};
 	struct nfs4_lookup_res res = {
 		.server = server,
@@ -2203,6 +2277,8 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
 		.rpc_argp = &args,
 		.rpc_resp = &res,
 	};
+	bitmask[0] = nfs4_fattr_bitmap[0];
+	bitmask[1] = nfs4_fattr_bitmap[1] & ~FATTR4_WORD1_SECURITY_LABEL;
 
 	nfs_fattr_init(info->fattr);
 	return nfs4_call_sync(server, &msg, &args, &res, 0);
@@ -2278,7 +2354,8 @@ out:
 	return status;
 }
 
-static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+				struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct nfs4_getattr_arg args = {
 		.fh = fhandle,
@@ -2286,6 +2363,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 	};
 	struct nfs4_getattr_res res = {
 		.fattr = fattr,
+		.label = label,
 		.server = server,
 	};
 	struct rpc_message msg = {
@@ -2293,18 +2371,23 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 		.rpc_argp = &args,
 		.rpc_resp = &res,
 	};
-	
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (!label)
+		args.bitmask = server->attr_bitmask_nl;
+#endif
 	nfs_fattr_init(fattr);
 	return nfs4_call_sync(server, &msg, &args, &res, 0);
 }
 
-static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+				struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(server,
-				_nfs4_proc_getattr(server, fhandle, fattr),
+				_nfs4_proc_getattr(server, fhandle, fattr, label),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -2334,8 +2417,13 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 	struct inode *inode = dentry->d_inode;
 	struct rpc_cred *cred = NULL;
 	struct nfs4_state *state = NULL;
+	struct nfs4_label *olabel;
 	int status;
 
+	olabel = nfs4_label_alloc(GFP_KERNEL);
+	if (olabel == NULL)
+		return -ENOMEM;
+
 	nfs_fattr_init(fattr);
 	
 	/* Search for an existing open(O_WRITE) file */
@@ -2349,15 +2437,16 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 		}
 	}
 
-	status = nfs4_do_setattr(inode, cred, fattr, sattr, state);
-	if (status == 0)
+	status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, NULL);
+	if (status == 0) {
 		nfs_setattr_update_inode(inode, sattr);
+	}
 	return status;
 }
 
 static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *dirfh,
 		const struct qstr *name, struct nfs_fh *fhandle,
-		struct nfs_fattr *fattr)
+		struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	int		       status;
 	struct nfs4_lookup_arg args = {
@@ -2368,6 +2457,7 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d
 	struct nfs4_lookup_res res = {
 		.server = server,
 		.fattr = fattr,
+		.label = label,
 		.fh = fhandle,
 	};
 	struct rpc_message msg = {
@@ -2376,6 +2466,11 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d
 		.rpc_resp = &res,
 	};
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label == NULL)
+		args.bitmask = server->attr_bitmask_nl;
+#endif
+
 	nfs_fattr_init(fattr);
 
 	dprintk("NFS call  lookupfh %s\n", name->name);
@@ -2391,7 +2486,7 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
 	struct nfs4_exception exception = { };
 	int err;
 	do {
-		err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr);
+		err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr, NULL);
 		/* FIXME: !!!! */
 		if (err == -NFS4ERR_MOVED) {
 			err = -EREMOTE;
@@ -2403,25 +2498,27 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
 }
 
 static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name,
-		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+		struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+		struct nfs4_label *label)
 {
 	int status;
 	
 	dprintk("NFS call  lookup %s\n", name->name);
-	status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr);
+	status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr, label);
 	if (status == -NFS4ERR_MOVED)
 		status = nfs4_get_referral(dir, name, fattr, fhandle);
 	dprintk("NFS reply lookup: %d\n", status);
 	return status;
 }
 
-static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle,
+				struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
-				_nfs4_proc_lookup(dir, name, fhandle, fattr),
+				_nfs4_proc_lookup(dir, name, fhandle, fattr, label),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -2438,6 +2535,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
 	struct nfs4_accessres res = {
 		.server = server,
 		.fattr = &fattr,
+		.label = NULL,
 	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
@@ -2446,7 +2544,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
 		.rpc_cred = entry->cred,
 	};
 	int mode = entry->mask;
-	int status;
+	int status = 0;
 
 	/*
 	 * Determine which access bits we want to ask for...
@@ -2464,6 +2562,13 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
 		if (mode & MAY_EXEC)
 			args.access |= NFS4_ACCESS_EXECUTE;
 	}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		res.label = nfs4_label_alloc(GFP_KERNEL);
+		if (res.label == NULL)
+			return -ENOMEM;
+	}
+#endif
 	nfs_fattr_init(&fattr);
 	status = nfs4_call_sync(server, &msg, &args, &res, 0);
 	if (!status) {
@@ -2474,8 +2579,12 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
 			entry->mask |= MAY_WRITE;
 		if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE))
 			entry->mask |= MAY_EXEC;
-		nfs_refresh_inode(inode, &fattr);
+		nfs_refresh_inode(inode, &fattr, res.label);
 	}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL)
+		nfs4_label_free(res.label);
+#endif
 	return status;
 }
 
@@ -2566,6 +2675,7 @@ static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                  int flags, struct nameidata *nd)
 {
+	struct nfs4_label l, *ilabel = NULL, *olabel = NULL;
 	struct path path = {
 		.mnt = nd->path.mnt,
 		.dentry = dentry,
@@ -2580,7 +2690,27 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 		status = PTR_ERR(cred);
 		goto out;
 	}
-	state = nfs4_do_open(dir, &path, fmode, flags, sattr, cred);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (((nd->flags & LOOKUP_CREATE) != 0) &&
+			nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		status = security_dentry_init_security(dentry,
+				sattr->ia_mode, &l.label, &l.len);
+		/* XXX: should this be more fatal? */
+		if (status == 0)
+			ilabel = &l;
+	}
+
+	/* XXX: this conditional for the above too? */
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		olabel = nfs4_label_alloc(GFP_KERNEL);
+		if (olabel == NULL) {
+			status = -ENOMEM;
+			goto out;
+		}
+	}
+#endif
+
+	state = nfs4_do_open(dir, &path, fmode, flags, sattr, ilabel, cred);
 	d_drop(dentry);
 	if (IS_ERR(state)) {
 		status = PTR_ERR(state);
@@ -2590,10 +2720,12 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 	if (flags & O_EXCL) {
 		struct nfs_fattr fattr;
-		status = nfs4_do_setattr(state->inode, cred, &fattr, sattr, state);
-		if (status == 0)
+		status = nfs4_do_setattr(state->inode, cred, &fattr, sattr, state, ilabel, olabel);
+		if (status == 0) {
 			nfs_setattr_update_inode(state->inode, sattr);
-		nfs_post_op_update_inode(state->inode, &fattr);
+			nfs_post_op_update_inode(state->inode, &fattr, olabel);
+			nfs_setsecurity(state->inode, &fattr, olabel);
+		}
 	}
 	if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
 		status = nfs4_intent_set_file(nd, &path, state, fmode);
@@ -2602,6 +2734,12 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 out_putcred:
 	put_rpccred(cred);
 out:
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (ilabel)
+		security_release_secctx(ilabel->label, ilabel->len);
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL))
+		nfs4_label_free(olabel);
+#endif
 	return status;
 }
 
@@ -2622,14 +2760,26 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
 		.rpc_argp = &args,
 		.rpc_resp = &res,
 	};
-	int			status;
+	int	status = 0;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		res.dir_label = nfs4_label_alloc(GFP_NOWAIT);
+		if (res.dir_label == NULL)
+			return -ENOMEM;
+	}
+#endif
 
 	nfs_fattr_init(&res.dir_attr);
 	status = nfs4_call_sync(server, &msg, &args, &res, 1);
 	if (status == 0) {
 		update_changeattr(dir, &res.cinfo);
-		nfs_post_op_update_inode(dir, &res.dir_attr);
+		nfs_post_op_update_inode(dir, &res.dir_attr, res.dir_label);
 	}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL)
+		nfs4_label_free(res.dir_label);
+#endif
 	return status;
 }
 
@@ -2651,9 +2801,22 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
 	struct nfs_removeargs *args = msg->rpc_argp;
 	struct nfs_removeres *res = msg->rpc_resp;
 
-	args->bitmask = server->cache_consistency_bitmask;
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL)
+		res->dir_label = nfs4_label_alloc(GFP_NOWAIT);
+	else
+		res->dir_label = NULL;
+#endif
+
+	if (res->dir_label != NULL)
+		args->bitmask = server->cache_consistency_bitmask;
+	else
+		args->bitmask = server->cache_consistency_bitmask_nl;
+
 	res->server = server;
 	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
+
+	nfs_fattr_init(&res->dir_attr);
 }
 
 static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
@@ -2664,7 +2827,11 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 	if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
 		return 0;
 	update_changeattr(dir, &res->cinfo);
-	nfs_post_op_update_inode(dir, &res->dir_attr);
+	nfs_post_op_update_inode(dir, &res->dir_attr, res->dir_label);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (res->server->caps & NFS_CAP_SECURITY_LABEL)
+		nfs4_label_free(res->dir_label);
+#endif
 	return 1;
 }
 
@@ -2677,6 +2844,8 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 		.new_dir = NFS_FH(new_dir),
 		.old_name = old_name,
 		.new_name = new_name,
+		.old_label = NULL,
+		.new_label = NULL,
 		.bitmask = server->attr_bitmask,
 	};
 	struct nfs_fattr old_fattr, new_fattr;
@@ -2690,7 +2859,20 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 		.rpc_argp = &arg,
 		.rpc_resp = &res,
 	};
-	int			status;
+	int	status = 0;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		res.old_label = nfs4_label_alloc(GFP_NOWAIT);
+		if (res.old_label == NULL)
+			return -ENOMEM;
+		res.new_label = nfs4_label_alloc(GFP_NOWAIT);
+		if (res.new_label == NULL) {
+			nfs4_label_free(res.old_label);
+			return -ENOMEM;
+		}
+	}
+#endif
 	
 	nfs_fattr_init(res.old_fattr);
 	nfs_fattr_init(res.new_fattr);
@@ -2698,10 +2880,17 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 
 	if (!status) {
 		update_changeattr(old_dir, &res.old_cinfo);
-		nfs_post_op_update_inode(old_dir, res.old_fattr);
+		nfs_post_op_update_inode(old_dir, res.old_fattr, res.old_label);
 		update_changeattr(new_dir, &res.new_cinfo);
-		nfs_post_op_update_inode(new_dir, res.new_fattr);
+		nfs_post_op_update_inode(new_dir, res.new_fattr, res.new_label);
+	}
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		nfs4_label_free(res.old_label);
+		nfs4_label_free(res.new_label);
 	}
+#endif
 	return status;
 }
 
@@ -2732,23 +2921,44 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
 	struct nfs4_link_res res = {
 		.server = server,
 		.fattr = &fattr,
+		.label = NULL,
 		.dir_attr = &dir_attr,
+		.dir_label = NULL,
 	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
 		.rpc_argp = &arg,
 		.rpc_resp = &res,
 	};
-	int			status;
+	int	status = 0;
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		res.label = nfs4_label_alloc(GFP_KERNEL);
+		if (res.label == NULL)
+			return -ENOMEM;
+		res.dir_label = nfs4_label_alloc(GFP_KERNEL);
+		if (res.dir_label == NULL) {
+			nfs4_label_free(res.label);
+			return -ENOMEM;
+		}
+	}
+#endif
 	nfs_fattr_init(res.fattr);
 	nfs_fattr_init(res.dir_attr);
 	status = nfs4_call_sync(server, &msg, &arg, &res, 1);
 	if (!status) {
 		update_changeattr(dir, &res.cinfo);
-		nfs_post_op_update_inode(dir, res.dir_attr);
-		nfs_post_op_update_inode(inode, res.fattr);
+		nfs_post_op_update_inode(dir, res.dir_attr, res.dir_label);
+		nfs_post_op_update_inode(inode, res.fattr, res.label);
+	}
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		nfs4_label_free(res.label);
+		nfs4_label_free(res.dir_label);
 	}
+#endif
 
 	return status;
 }
@@ -2771,7 +2981,9 @@ struct nfs4_createdata {
 	struct nfs4_create_res res;
 	struct nfs_fh fh;
 	struct nfs_fattr fattr;
+	struct nfs4_label *label;
 	struct nfs_fattr dir_fattr;
+	struct nfs4_label *dir_label;
 };
 
 static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
@@ -2783,6 +2995,16 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
 	if (data != NULL) {
 		struct nfs_server *server = NFS_SERVER(dir);
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		if (server->caps & NFS_CAP_SECURITY_LABEL) {
+			data->label = nfs4_label_alloc(GFP_KERNEL);
+			if (data->label == NULL)
+				goto out_free;
+			data->dir_label = nfs4_label_alloc(GFP_KERNEL);
+			if (data->dir_label == NULL)
+				goto out_free;
+		}
+#endif
 		data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE];
 		data->msg.rpc_argp = &data->arg;
 		data->msg.rpc_resp = &data->res;
@@ -2795,11 +3017,17 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
 		data->res.server = server;
 		data->res.fh = &data->fh;
 		data->res.fattr = &data->fattr;
+		data->res.label = data->label;
 		data->res.dir_fattr = &data->dir_fattr;
+		data->res.dir_label = data->dir_label;
 		nfs_fattr_init(data->res.fattr);
 		nfs_fattr_init(data->res.dir_fattr);
 	}
 	return data;
+out_free:
+	kfree(data);
+	return NULL;
+
 }
 
 static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
@@ -2808,19 +3036,26 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_
 				    &data->arg, &data->res, 1);
 	if (status == 0) {
 		update_changeattr(dir, &data->res.dir_cinfo);
-		nfs_post_op_update_inode(dir, data->res.dir_fattr);
-		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
+		nfs_post_op_update_inode(dir, data->res.dir_fattr, data->res.dir_label);
+		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label);
 	}
 	return status;
 }
 
 static void nfs4_free_createdata(struct nfs4_createdata *data)
 {
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (data->arg.server->caps & NFS_CAP_SECURITY_LABEL) {
+		nfs4_label_free(data->label);
+		nfs4_label_free(data->dir_label);
+	}
+#endif
 	kfree(data);
 }
 
 static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
-		struct page *page, unsigned int len, struct iattr *sattr)
+		struct page *page, unsigned int len, struct iattr *sattr,
+		struct nfs4_label *label)
 {
 	struct nfs4_createdata *data;
 	int status = -ENAMETOOLONG;
@@ -2836,6 +3071,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
 	data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK];
 	data->arg.u.symlink.pages = &page;
 	data->arg.u.symlink.len = len;
+	data->arg.label = label;
 	
 	status = nfs4_do_create(dir, dentry, data);
 
@@ -2848,18 +3084,33 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
 		struct page *page, unsigned int len, struct iattr *sattr)
 {
 	struct nfs4_exception exception = { };
+	struct nfs4_label l, *label = NULL;
 	int err;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		err = security_dentry_init_security(dentry,
+				sattr->ia_mode, &l.label, &l.len);
+		if (err == 0)
+			label = &l;
+	}
+#endif
+
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
 				_nfs4_proc_symlink(dir, dentry, page,
-							len, sattr),
+							len, sattr, label),
 				&exception);
 	} while (exception.retry);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label)
+		security_release_secctx(l.label, l.len);
+#endif
 	return err;
 }
 
 static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
-		struct iattr *sattr)
+		struct iattr *sattr, struct nfs4_label *label)
 {
 	struct nfs4_createdata *data;
 	int status = -ENOMEM;
@@ -2868,6 +3119,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
 	if (data == NULL)
 		goto out;
 
+	data->arg.label = label;
 	status = nfs4_do_create(dir, dentry, data);
 
 	nfs4_free_createdata(data);
@@ -2879,12 +3131,27 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
 		struct iattr *sattr)
 {
 	struct nfs4_exception exception = { };
+	struct nfs4_label l, *label = NULL;
 	int err;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		err = security_dentry_init_security(dentry,
+				sattr->ia_mode, &l.label, &l.len);
+		if (err == 0)
+			label = &l;
+	}
+#endif
+
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
-				_nfs4_proc_mkdir(dir, dentry, sattr),
+				_nfs4_proc_mkdir(dir, dentry, sattr, label),
 				&exception);
 	} while (exception.retry);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label)
+		security_release_secctx(l.label, l.len);
+#endif
 	return err;
 }
 
@@ -2897,7 +3164,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 		.pages = &page,
 		.pgbase = 0,
 		.count = count,
-		.bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
+		.bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask_nl,
 	};
 	struct nfs4_readdir_res res;
 	struct rpc_message msg = {
@@ -2939,7 +3206,7 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 }
 
 static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
-		struct iattr *sattr, dev_t rdev)
+		struct iattr *sattr, struct nfs4_label *label, dev_t rdev)
 {
 	struct nfs4_createdata *data;
 	int mode = sattr->ia_mode;
@@ -2964,7 +3231,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
 		data->arg.u.device.specdata1 = MAJOR(rdev);
 		data->arg.u.device.specdata2 = MINOR(rdev);
 	}
-	
+	data->arg.label = label;
 	status = nfs4_do_create(dir, dentry, data);
 
 	nfs4_free_createdata(data);
@@ -2976,12 +3243,27 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
 		struct iattr *sattr, dev_t rdev)
 {
 	struct nfs4_exception exception = { };
+	struct nfs4_label l, *label = NULL;
 	int err;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		err = security_dentry_init_security(dentry,
+				sattr->ia_mode, &l.label, &l.len);
+		if (err == 0)
+			label = &l;
+	}
+#endif
+
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
-				_nfs4_proc_mknod(dir, dentry, sattr, rdev),
+				_nfs4_proc_mknod(dir, dentry, sattr, label, rdev),
 				&exception);
 	} while (exception.retry);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label)
+		security_release_secctx(l.label, l.len);
+#endif
 	return err;
 }
 
@@ -3142,7 +3424,11 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag
 {
 	struct nfs_server *server = NFS_SERVER(data->inode);
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	data->args.bitmask = server->cache_consistency_bitmask_nl;
+#else
 	data->args.bitmask = server->cache_consistency_bitmask;
+#endif
 	data->res.server = server;
 	data->timestamp   = jiffies;
 
@@ -3159,7 +3445,7 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
 		nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
 		return -EAGAIN;
 	}
-	nfs_refresh_inode(inode, data->res.fattr);
+	nfs_refresh_inode(inode, data->res.fattr, NULL);
 	return 0;
 }
 
@@ -3167,7 +3453,11 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_messa
 {
 	struct nfs_server *server = NFS_SERVER(data->inode);
 	
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	data->args.bitmask = server->cache_consistency_bitmask_nl;
+#else
 	data->args.bitmask = server->cache_consistency_bitmask;
+#endif
 	data->res.server = server;
 	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT];
 }
@@ -3514,6 +3804,169 @@ do_state_recovery:
 	return -EAGAIN;
 }
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+static int _nfs4_get_security_label(struct inode *inode, void *buf, size_t buflen)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs_fattr fattr;
+	struct nfs4_label label;
+	u32 bitmask[2] = { 0, FATTR4_WORD1_SECURITY_LABEL };
+	struct nfs4_getattr_arg args = {
+		.fh		= NFS_FH(inode),
+		.bitmask	= bitmask,
+	};
+	struct nfs4_getattr_res res = {
+		.fattr		= &fattr,
+		.label		= &label,
+		.server		= server,
+	};
+	struct rpc_message msg = {
+		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_GETATTR],
+		.rpc_argp	= &args,
+		.rpc_resp	= &res,
+	};
+	int ret;
+
+	label.label = buf;
+	label.len = buflen;
+	nfs_fattr_init(&fattr);
+
+	ret = rpc_call_sync(server->client, &msg, 0);
+	if (ret)
+		return ret;
+	if (!(fattr.valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL))
+		return -ENOENT;
+	if (buflen < label.len)
+		return -ERANGE;
+	return 0;
+}
+
+static int nfs4_get_security_label(struct inode *inode, void *buf, size_t buflen)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL))
+		return -EOPNOTSUPP;
+
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(inode),
+				_nfs4_get_security_label(inode, buf, buflen),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_do_set_security_label(struct inode *inode,
+				      struct nfs4_label *ilabel,
+				      struct nfs_fattr *fattr,
+				      struct nfs4_label *olabel,
+				      struct nfs4_state *state)
+{
+
+	struct iattr sattr;
+	struct nfs_server *server = NFS_SERVER(inode);
+	const u32 bitmask[2] = { 0, FATTR4_WORD1_SECURITY_LABEL };
+	struct nfs_setattrargs args = {
+		.fh             = NFS_FH(inode),
+		.iap            = &sattr,
+		.server		= server,
+		.bitmask	= bitmask,
+		.label		= ilabel,
+	};
+	struct nfs_setattrres res = {
+		.fattr		= fattr,
+		.label		= olabel,
+		.server		= server,
+	};
+	struct rpc_message msg = {
+		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
+		.rpc_argp       = &args,
+		.rpc_resp       = &res,
+	};
+	unsigned long timestamp = jiffies;
+	int status;
+
+	memset(&sattr, 0, sizeof(struct iattr));
+
+	if (nfs4_copy_delegation_stateid(&args.stateid, inode)) {
+		/* Use that stateid */
+	} else if (state != NULL) {
+		msg.rpc_cred = state->owner->so_cred;
+		nfs4_copy_stateid(&args.stateid, state, current->files);
+	} else
+		memcpy(&args.stateid, &zero_stateid, sizeof(args.stateid));
+
+	status = rpc_call_sync(server->client, &msg, 0);
+	if (status == 0 && state != NULL)
+		renew_lease(server, timestamp);
+	return status;
+}
+
+static int nfs4_do_set_security_label(struct inode *inode,
+				     struct nfs4_label *ilabel,
+				     struct nfs_fattr *fattr,
+				     struct nfs4_label *olabel,
+				     struct nfs4_state *state)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(inode),
+			_nfs4_do_set_security_label(inode, ilabel, fattr, olabel, state),
+			&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int
+nfs4_set_security_label(struct dentry *dentry, const void *buf, size_t buflen)
+{
+	struct nfs4_label ilabel, *olabel = NULL;
+	struct nfs_fattr fattr;
+	struct rpc_cred *cred;
+	struct nfs_open_context *ctx;
+	struct nfs4_state *state = NULL;
+	struct inode *inode = dentry->d_inode;
+	int status;
+
+	if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL))
+		return -EOPNOTSUPP;
+
+	nfs_fattr_init(&fattr);
+
+	ilabel.label = (char *)buf;
+	ilabel.len = buflen;
+
+	cred = rpc_lookup_cred();
+	if (IS_ERR(cred))
+		return PTR_ERR(cred);
+
+	olabel = nfs4_label_alloc(GFP_KERNEL);
+	if (olabel == NULL) {
+		status = -ENOMEM;
+		goto out;
+	}
+
+	/* Search for an existing open(O_WRITE) file */
+	ctx = nfs_find_open_context(inode, cred, FMODE_WRITE);
+	if (ctx != NULL)
+		state = ctx->state;
+
+	status = nfs4_do_set_security_label(inode, &ilabel, &fattr, olabel, state);
+	if (status == 0)
+		nfs_setsecurity(inode, &fattr, olabel);
+	if (ctx != NULL)
+		put_nfs_open_context(ctx);
+	nfs4_label_free(olabel);
+out:
+	put_rpccred(cred);
+	return status;
+}
+#endif	/* CONFIG_NFS_V4_SECURITY_LABEL */
+
+
 static int
 nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state)
 {
@@ -3698,7 +4151,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
 		return -ENOMEM;
 	data->args.fhandle = &data->fh;
 	data->args.stateid = &data->stateid;
-	data->args.bitmask = server->attr_bitmask;
+	data->args.bitmask = server->attr_bitmask_nl;
 	nfs_copy_fh(&data->fh, NFS_FH(inode));
 	memcpy(&data->stateid, stateid, sizeof(data->stateid));
 	data->res.fattr = &data->fattr;
@@ -3722,7 +4175,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
 	status = data->rpc_status;
 	if (status != 0)
 		goto out;
-	nfs_refresh_inode(inode, &data->fattr);
+	nfs_refresh_inode(inode, &data->fattr, NULL);
 out:
 	rpc_put_task(task);
 	return status;
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 38f3b58..61e0b47 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -95,9 +95,14 @@ static int nfs4_stat_to_errno(int);
 #define nfs4_path_maxsz		(1 + ((3 + NFS4_MAXPATHLEN) >> 2))
 #define nfs4_owner_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
 #define nfs4_group_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+#define	nfs4_label_maxsz	(4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN))
+#else
+#define	nfs4_label_maxsz	0
+#endif
 /* This is based on getfattr, which uses the most attributes: */
 #define nfs4_fattr_value_maxsz	(1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
-				3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz))
+				3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz + nfs4_label_maxsz))
 #define nfs4_fattr_maxsz	(nfs4_fattr_bitmap_maxsz + \
 				nfs4_fattr_value_maxsz)
 #define decode_getattr_maxsz    (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
@@ -105,6 +110,7 @@ static int nfs4_stat_to_errno(int);
 				 1 + 2 + 1 + \
 				nfs4_owner_maxsz + \
 				nfs4_group_maxsz + \
+				nfs4_label_maxsz + \
 				4 + 4)
 #define encode_savefh_maxsz     (op_encode_hdr_maxsz)
 #define decode_savefh_maxsz     (op_decode_hdr_maxsz)
@@ -775,7 +781,7 @@ static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *ve
 	xdr_encode_opaque_fixed(p, verf->data, NFS4_VERIFIER_SIZE);
 }
 
-static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server)
+static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs4_label *label, const struct nfs_server *server)
 {
 	char owner_name[IDMAP_NAMESZ];
 	char owner_group[IDMAP_NAMESZ];
@@ -824,6 +830,10 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
 		}
 		len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
 	}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label)
+		len += 4 + 4 + (XDR_QUADLEN(label->len) << 2);
+#endif
 	if (iap->ia_valid & ATTR_ATIME_SET)
 		len += 16;
 	else if (iap->ia_valid & ATTR_ATIME)
@@ -880,6 +890,14 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
 		bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
 		*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
 	}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label) {
+		bmval1 |= FATTR4_WORD1_SECURITY_LABEL;
+		*p++ = cpu_to_be32(label->lfs);
+		*p++ = cpu_to_be32(label->len);
+		p = xdr_encode_opaque_fixed(p, label->label, label->len);
+	}
+#endif
 
 	/*
 	 * Now we backfill the bitmap and the attribute buffer length.
@@ -961,7 +979,7 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *
 	hdr->nops++;
 	hdr->replen += decode_create_maxsz;
 
-	encode_attrs(xdr, create->attrs, create->server);
+	encode_attrs(xdr, create->attrs, create->label, create->server);
 }
 
 static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr)
@@ -1168,21 +1186,21 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op
 	switch(arg->open_flags & O_EXCL) {
 	case 0:
 		*p = cpu_to_be32(NFS4_CREATE_UNCHECKED);
-		encode_attrs(xdr, arg->u.attrs, arg->server);
+		encode_attrs(xdr, arg->u.attrs, arg->label, arg->server);
 		break;
 	default:
 		clp = arg->server->nfs_client;
 		if (clp->cl_minorversion > 0) {
 			if (nfs4_has_persistent_session(clp)) {
 				*p = cpu_to_be32(NFS4_CREATE_GUARDED);
-				encode_attrs(xdr, arg->u.attrs, arg->server);
+				encode_attrs(xdr, arg->u.attrs,arg->label,  arg->server);
 			} else {
 				struct iattr dummy;
 
 				*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
 				encode_nfs4_verifier(xdr, &arg->u.verifier);
 				dummy.ia_valid = 0;
-				encode_attrs(xdr, &dummy, arg->server);
+				encode_attrs(xdr, &dummy, arg->label, arg->server);
 			}
 		} else {
 			*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
@@ -1482,7 +1500,7 @@ static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs
 	xdr_encode_opaque_fixed(p, arg->stateid.data, NFS4_STATEID_SIZE);
 	hdr->nops++;
 	hdr->replen += decode_setattr_maxsz;
-	encode_attrs(xdr, arg->iap, server);
+	encode_attrs(xdr, arg->iap, arg->label, server);
 }
 
 static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr)
@@ -3495,6 +3513,58 @@ static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, str
 	return status;
 }
 
+static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_label *label)
+{
+	uint32_t lfs;
+	__u32 len;
+	__be32 *p;
+	int status = 0;
+
+	if (unlikely(bitmap[1] & (FATTR4_WORD1_SECURITY_LABEL - 1U)))
+		return -EIO;
+	if (likely(bitmap[1] & FATTR4_WORD1_SECURITY_LABEL)) {
+		p = xdr_inline_decode(xdr, 4);
+		if (unlikely(!p))
+			goto out_overflow;
+		lfs = be32_to_cpup(p++);
+		p = xdr_inline_decode(xdr, 4);
+		if (unlikely(!p))
+			goto out_overflow;
+		len = be32_to_cpup(p++);
+		p = xdr_inline_decode(xdr, len);
+		if (unlikely(!p))
+			goto out_overflow;
+		if (len < XDR_MAX_NETOBJ) {
+			if (label) {
+				if (label->len < len) {
+					printk(KERN_ERR
+						"%s(): label->len %d < len %d\n",
+						__func__, label->len, len);
+				} else {
+					memcpy(label->label, p, len);
+					label->len = len;
+					label->lfs = lfs;
+					status = NFS_ATTR_FATTR_V4_SECURITY_LABEL;
+				}
+			} else {
+				printk("%s(): NULL label.\n", __func__);
+				dump_stack();
+			}
+			bitmap[1] &= ~FATTR4_WORD1_SECURITY_LABEL;
+		} else
+			printk(KERN_WARNING "%s: label too long (%u)!\n",
+					__FUNCTION__, len);
+	}
+	if(label && label->label)
+		dprintk("%s: label=%s, len=%d\n", __func__,
+				 label->label, label->len);
+	return status;
+
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+	return -EIO;
+}
+
 static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen)
 {
 	unsigned int attrwords = XDR_QUADLEN(attrlen);
@@ -3701,7 +3771,8 @@ xdr_error:
 }
 
 static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
-		const struct nfs_server *server, int may_sleep)
+		struct nfs4_label *label, const struct nfs_server *server,
+		int may_sleep)
 {
 	__be32 *savep;
 	uint32_t attrlen,
@@ -3817,6 +3888,10 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
 		fattr->fileid = fileid;
 		fattr->valid |= status;
 	}
+	status = decode_attr_security_label(xdr, bitmap, label);
+	if (status < 0)
+		goto xdr_error;
+	fattr->valid |= status;
 
 	status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
@@ -4708,7 +4783,7 @@ static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, __be32 *p, struct
 	status = decode_open_downgrade(&xdr, res);
 	if (status != 0)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4736,7 +4811,7 @@ static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_ac
 	status = decode_access(&xdr, res);
 	if (status != 0)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4764,7 +4839,7 @@ static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lo
 		goto out;
 	if ((status = decode_getfh(&xdr, res->fh)) != 0)
 		goto out;
-	status = decode_getfattr(&xdr, res->fattr, res->server
+	status = decode_getfattr(&xdr, res->fattr, res->label, res->server
 			,!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4789,7 +4864,7 @@ static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, __be32 *p, struct nf
 	if ((status = decode_putrootfh(&xdr)) != 0)
 		goto out;
 	if ((status = decode_getfh(&xdr, res->fh)) == 0)
-		status = decode_getfattr(&xdr, res->fattr, res->server,
+		status = decode_getfattr(&xdr, res->fattr, res->label, res->server,
 				!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4815,7 +4890,7 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs_rem
 		goto out;
 	if ((status = decode_remove(&xdr, &res->cinfo)) != 0)
 		goto out;
-	decode_getfattr(&xdr, &res->dir_attr, res->server,
+	decode_getfattr(&xdr, &res->dir_attr, res->dir_label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4846,12 +4921,12 @@ static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_re
 	if ((status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo)) != 0)
 		goto out;
 	/* Current FH is target directory */
-	if (decode_getfattr(&xdr, res->new_fattr, res->server,
+	if (decode_getfattr(&xdr, res->new_fattr, res->new_label, res->server,
 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
 		goto out;
 	if ((status = decode_restorefh(&xdr)) != 0)
 		goto out;
-	decode_getfattr(&xdr, res->old_fattr, res->server,
+	decode_getfattr(&xdr, res->old_fattr, res->old_label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4885,12 +4960,12 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_link
 	 * Note order: OP_LINK leaves the directory as the current
 	 *             filehandle.
 	 */
-	if (decode_getfattr(&xdr, res->dir_attr, res->server,
+	if (decode_getfattr(&xdr, res->dir_attr, res->dir_label, res->server,
 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
 		goto out;
 	if ((status = decode_restorefh(&xdr)) != 0)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4920,12 +4995,12 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_cr
 		goto out;
 	if ((status = decode_getfh(&xdr, res->fh)) != 0)
 		goto out;
-	if (decode_getfattr(&xdr, res->fattr, res->server,
+	if (decode_getfattr(&xdr, res->fattr, res->label, res->server,
 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
 		goto out;
 	if ((status = decode_restorefh(&xdr)) != 0)
 		goto out;
-	decode_getfattr(&xdr, res->dir_fattr, res->server,
+	decode_getfattr(&xdr, res->dir_fattr, res->dir_label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4958,7 +5033,7 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_g
 	status = decode_putfh(&xdr);
 	if (status)
 		goto out;
-	status = decode_getfattr(&xdr, res->fattr, res->server,
+	status = decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5066,7 +5141,7 @@ static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p, struct nfs_clos
 	 * 	an ESTALE error. Shouldn't be a problem,
 	 * 	though, since fattr->valid will remain unset.
 	 */
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5099,12 +5174,12 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openr
 		goto out;
 	if (decode_getfh(&xdr, &res->fh) != 0)
 		goto out;
-	if (decode_getfattr(&xdr, res->f_attr, res->server,
+	if (decode_getfattr(&xdr, res->f_attr, res->f_label, res->server,
 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
 		goto out;
 	if (decode_restorefh(&xdr) != 0)
 		goto out;
-	decode_getfattr(&xdr, res->dir_attr, res->server,
+	decode_getfattr(&xdr, res->dir_attr, res->dir_label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5153,7 +5228,7 @@ static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p, struct nf
 	status = decode_open(&xdr, res);
 	if (status)
 		goto out;
-	decode_getfattr(&xdr, res->f_attr, res->server,
+	decode_getfattr(&xdr, res->f_attr, NULL, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5181,7 +5256,7 @@ static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_se
 	status = decode_setattr(&xdr);
 	if (status)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5356,7 +5431,7 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writ
 	status = decode_write(&xdr, res);
 	if (status)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, NULL, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 	if (!status)
 		status = res->count;
@@ -5386,7 +5461,7 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_wri
 	status = decode_commit(&xdr, res);
 	if (status)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, NULL, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5553,7 +5628,7 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nf
 	status = decode_delegreturn(&xdr);
 	if (status != 0)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5581,7 +5656,7 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p,
 	if ((status = decode_lookup(&xdr)) != 0)
 		goto out;
 	xdr_enter_page(&xdr, PAGE_SIZE);
-	status = decode_getfattr(&xdr, &res->fs_locations->fattr,
+	status = decode_getfattr(&xdr, &res->fs_locations->fattr, NULL,
 				 res->fs_locations->server,
 				 !RPC_IS_ASYNC(req->rq_task));
 out:
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 0288be8..acdc92d 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -130,7 +130,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  */
 static int
 nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
-		struct nfs_fattr *fattr)
+		struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs_procedures[NFSPROC_GETATTR],
@@ -178,7 +178,8 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
 static int
 nfs_proc_lookup(struct inode *dir, struct qstr *name,
-		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+		struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+		struct nfs4_label *label)
 {
 	struct nfs_diropargs	arg = {
 		.fh		= NFS_FH(dir),
@@ -252,7 +253,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	nfs_mark_for_revalidate(dir);
 	if (status == 0)
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, NULL);
 	dprintk("NFS reply create: %d\n", status);
 	return status;
 }
@@ -304,7 +305,7 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 		status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	}
 	if (status == 0)
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, NULL);
 	dprintk("NFS reply mknod: %d\n", status);
 	return status;
 }
@@ -430,7 +431,7 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
 	if (status == 0) {
 		nfs_fattr_init(&fattr);
 		fhandle.size = 0;
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, NULL);
 	}
 
 	dprintk("NFS reply symlink: %d\n", status);
@@ -464,7 +465,7 @@ nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	nfs_mark_for_revalidate(dir);
 	if (status == 0)
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, NULL);
 	dprintk("NFS reply mkdir: %d\n", status);
 	return status;
 }
@@ -599,7 +600,7 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
 
 	nfs_invalidate_atime(data->inode);
 	if (task->tk_status >= 0) {
-		nfs_refresh_inode(data->inode, data->res.fattr);
+		nfs_refresh_inode(data->inode, data->res.fattr, data->res.label);
 		/* Emulate the eof flag, which isn't normally needed in NFSv2
 		 * as it is guaranteed to always return the file attributes
 		 */
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 054bcaa..8135838 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2551,6 +2551,7 @@ static int nfs4_remote_get_sb(struct file_system_type *fs_type,
 	struct nfs_fh *mntfh;
 	struct dentry *mntroot;
 	int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
+	unsigned long kflags = 0, kflags_out = 0;
 	struct nfs_sb_mountdata sb_mntdata = {
 		.mntflags = flags,
 	};
@@ -2602,10 +2603,20 @@ static int nfs4_remote_get_sb(struct file_system_type *fs_type,
 		goto error_splat_super;
 	}
 
-	error = security_sb_set_mnt_opts(s, &data->lsm_opts, 0, NULL);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL)
+		kflags |= SECURITY_LSM_NATIVE_LABELS;
+#endif
+
+	error = security_sb_set_mnt_opts(s, &data->lsm_opts, kflags, &kflags_out);
 	if (error)
 		goto error_splat_root;
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL && !(kflags_out & SECURITY_LSM_NATIVE_LABELS))
+		server->caps &= ~NFS_CAP_SECURITY_LABEL;
+#endif
+
 	s->s_flags |= MS_ACTIVE;
 	mnt->mnt_sb = s;
 	mnt->mnt_root = mntroot;
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 2813b71..753294d 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -198,6 +198,7 @@ struct nfs_inode {
 #define NFS_INO_INVALID_ACL	0x0010		/* cached acls are invalid */
 #define NFS_INO_REVAL_PAGECACHE	0x0020		/* must revalidate pagecache */
 #define NFS_INO_REVAL_FORCED	0x0040		/* force revalidation ignoring a delegation */
+#define NFS_INO_INVALID_LABEL	0x0080		/* cached label is invalid */
 
 /*
  * Bit offsets in flags field
@@ -336,9 +337,9 @@ extern void nfs_zap_mapping(struct inode *inode, struct address_space *mapping);
 extern void nfs_zap_caches(struct inode *);
 extern void nfs_invalidate_atime(struct inode *);
 extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
-				struct nfs_fattr *);
-extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
-extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
+				struct nfs_fattr *, struct nfs4_label *);
+extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *, struct nfs4_label *);
+extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *);
 extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr);
 extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int nfs_permission(struct inode *, int);
@@ -350,6 +351,7 @@ extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
 extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
 extern int nfs_setattr(struct dentry *, struct iattr *);
 extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
+extern void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label);
 extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
 extern void put_nfs_open_context(struct nfs_open_context *ctx);
 extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
@@ -425,7 +427,7 @@ extern const struct file_operations nfs_dir_operations;
 extern const struct dentry_operations nfs_dentry_operations;
 
 extern void nfs_force_lookup_revalidate(struct inode *dir);
-extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr);
+extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr, struct nfs4_label *label);
 extern int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags);
 extern void nfs_access_zap_cache(struct inode *inode);
 
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index aa95a22..86895ee 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -140,11 +140,17 @@ struct nfs_server {
 	u32			attr_bitmask[2];/* V4 bitmask representing the set
 						   of attributes supported on this
 						   filesystem */
+	u32			attr_bitmask_nl[2]; /* V4 bitmask representing the set
+							of attributes supported on this
+							filesystem excluding the label
+							support bit. */
 	u32			cache_consistency_bitmask[2];
 						/* V4 bitmask representing the subset
 						   of change attribute, size, ctime
 						   and mtime attributes supported by
 						   the server */
+	u32			cache_consistency_bitmask_nl[2];
+						/* As above, excluding label. */
 	u32			acl_bitmask;	/* V4 bitmask representing the ACEs
 						   that are supported on this
 						   filesystem */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index dc505e4..bc87a58 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1034,11 +1034,12 @@ struct nfs_rpc_ops {
 			    struct qstr *, struct nfs_fh *,
 			    struct nfs_fattr *);
 	int	(*getattr) (struct nfs_server *, struct nfs_fh *,
-			    struct nfs_fattr *);
+			    struct nfs_fattr *, struct nfs4_label *);
 	int	(*setattr) (struct dentry *, struct nfs_fattr *,
 			    struct iattr *);
 	int	(*lookup)  (struct inode *, struct qstr *,
-			    struct nfs_fh *, struct nfs_fattr *);
+			    struct nfs_fh *, struct nfs_fattr *,
+			    struct nfs4_label *);
 	int	(*access)  (struct inode *, struct nfs_access_entry *);
 	int	(*readlink)(struct inode *, struct page *, unsigned int,
 			    unsigned int);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 01edf80..6c1e2fa 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2883,7 +2883,10 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
 		return;
 	}
 
+	isec->sclass = inode_mode_to_security_class(inode->i_mode);
 	isec->sid = newsid;
+	isec->initialized = 1;
+
 	return;
 }
 
@@ -2971,6 +2974,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
 	if (rc)
 		return rc;
 
+	isec->sclass = inode_mode_to_security_class(inode->i_mode);
 	isec->sid = newsid;
 	isec->initialized = 1;
 	return 0;
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 08/10] NFS: Client implementation of Labeled-NFS
@ 2010-07-07 14:31   ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

This patch implements the client transport and handling support for labeled
NFS. The patch adds two functions to encode and decode the security label
recommended attribute which makes use of the LSM hooks added earlier. It also
adds code to grab the label from the file attribute structures and encode the
label to be sent back to the server.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/nfs/client.c           |    2 +-
 fs/nfs/dir.c              |   67 ++++--
 fs/nfs/getroot.c          |   32 +++-
 fs/nfs/inode.c            |   95 ++++++--
 fs/nfs/namespace.c        |    2 +-
 fs/nfs/nfs3acl.c          |    4 +-
 fs/nfs/nfs3proc.c         |   37 ++--
 fs/nfs/nfs4proc.c         |  591 +++++++++++++++++++++++++++++++++++++++------
 fs/nfs/nfs4xdr.c          |  133 ++++++++---
 fs/nfs/proc.c             |   15 +-
 fs/nfs/super.c            |   13 +-
 include/linux/nfs_fs.h    |   10 +-
 include/linux/nfs_fs_sb.h |    6 +
 include/linux/nfs_xdr.h   |    5 +-
 security/selinux/hooks.c  |    4 +
 15 files changed, 841 insertions(+), 175 deletions(-)

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index acc9c49..aa27229 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1078,7 +1078,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
 	}
 
 	if (!(fattr.valid & NFS_ATTR_FATTR)) {
-		error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
+		error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr, NULL);
 		if (error < 0) {
 			dprintk("nfs_create_server: getattr error = %d\n", -error);
 			goto error;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index a7bb5c6..d8590d6 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -557,6 +557,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 	my_entry.fh = &fh;
 	my_entry.fattr = &fattr;
 	nfs_fattr_init(&fattr);
+
 	desc->entry = &my_entry;
 
 	nfs_block_sillyrename(dentry);
@@ -776,9 +777,10 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 	struct inode *dir;
 	struct inode *inode;
 	struct dentry *parent;
-	int error;
+	int error = 0;
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr;
+	struct nfs4_label *label = NULL;
 
 	parent = dget_parent(dentry);
 	dir = parent->d_inode;
@@ -811,13 +813,26 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 	if (NFS_STALE(inode))
 		goto out_bad;
 
-	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		label = nfs4_label_alloc(GFP_NOWAIT);
+		if (label == NULL)
+			goto out_bad;
+	}
+#endif
+
+	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr, label);
 	if (error)
-		goto out_bad;
+		goto out_bad_free;
 	if (nfs_compare_fh(NFS_FH(inode), &fhandle))
-		goto out_bad;
-	if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
-		goto out_bad;
+		goto out_bad_free;
+	if ((error = nfs_refresh_inode(inode, &fattr, label)) != 0)
+		goto out_bad_free;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL))
+		nfs4_label_free(label);
+#endif
 
 out_set_verifier:
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
@@ -829,7 +844,7 @@ out_set_verifier:
 	return 1;
 out_zap_parent:
 	nfs_zap_caches(dir);
- out_bad:
+out_bad:
 	nfs_mark_for_revalidate(dir);
 	if (inode && S_ISDIR(inode->i_mode)) {
 		/* Purge readdir caches. */
@@ -847,6 +862,13 @@ out_zap_parent:
 			__func__, dentry->d_parent->d_name.name,
 			dentry->d_name.name);
 	return 0;
+
+out_bad_free:
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL))
+		nfs4_label_free(label);
+#endif
+	goto out_bad;
 }
 
 /*
@@ -911,9 +933,10 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
 	struct dentry *res;
 	struct dentry *parent;
 	struct inode *inode = NULL;
-	int error;
+	int error = 0;
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr;
+	struct nfs4_label *label = NULL;
 
 	dfprintk(VFS, "NFS: lookup(%s/%s)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -936,17 +959,26 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
 		goto out;
 	}
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		label = nfs4_label_alloc(GFP_NOWAIT);
+		if (label == NULL)
+			goto out;
+	}
+	/* XXX: should this move inside of nfs4_lookup() ? */
+#endif
+
 	parent = dentry->d_parent;
 	/* Protect against concurrent sillydeletes */
 	nfs_block_sillyrename(parent);
-	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
+	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr, label);
 	if (error == -ENOENT)
 		goto no_entry;
 	if (error < 0) {
 		res = ERR_PTR(error);
 		goto out_unblock_sillyrename;
 	}
-	inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
+	inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr, label);
 	res = (struct dentry *)inode;
 	if (IS_ERR(res))
 		goto out_unblock_sillyrename;
@@ -961,6 +993,10 @@ no_entry:
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 out_unblock_sillyrename:
 	nfs_unblock_sillyrename(parent);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL))
+		nfs4_label_free(label);
+#endif
 out:
 	return res;
 }
@@ -1149,7 +1185,7 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
 	if (dentry == NULL)
 		return NULL;
 	dentry->d_op = NFS_PROTO(dir)->dentry_ops;
-	inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr);
+	inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr, NULL);
 	if (IS_ERR(inode)) {
 		dput(dentry);
 		return NULL;
@@ -1172,7 +1208,8 @@ out_renew:
  * Code common to create, mkdir, and mknod.
  */
 int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
-				struct nfs_fattr *fattr)
+				struct nfs_fattr *fattr,
+				struct nfs4_label *label)
 {
 	struct dentry *parent = dget_parent(dentry);
 	struct inode *dir = parent->d_inode;
@@ -1185,18 +1222,18 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
 	if (dentry->d_inode)
 		goto out;
 	if (fhandle->size == 0) {
-		error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
+		error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, NULL);
 		if (error)
 			goto out_error;
 	}
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 	if (!(fattr->valid & NFS_ATTR_FATTR)) {
 		struct nfs_server *server = NFS_SB(dentry->d_sb);
-		error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr);
+		error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr, NULL);
 		if (error < 0)
 			goto out_error;
 	}
-	inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
+	inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label);
 	error = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out_error;
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index b35d2a6..7604f71 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -30,7 +30,6 @@
 #include <linux/nfs_idmap.h>
 #include <linux/vfs.h>
 #include <linux/namei.h>
-#include <linux/security.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -92,7 +91,7 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 		return ERR_PTR(error);
 	}
 
-	inode = nfs_fhget(sb, mntfh, fsinfo.fattr);
+	inode = nfs_fhget(sb, mntfh, fsinfo.fattr, NULL);
 	if (IS_ERR(inode)) {
 		dprintk("nfs_get_root: get root inode failed\n");
 		return ERR_CAST(inode);
@@ -242,6 +241,7 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 	struct nfs_fattr fattr;
 	struct dentry *mntroot;
 	struct inode *inode;
+	struct nfs4_label *label = NULL;
 	int error;
 
 	dprintk("--> nfs4_get_root()\n");
@@ -254,19 +254,43 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 		return ERR_PTR(error);
 	}
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		label = nfs4_label_alloc(GFP_KERNEL);
+		if (label == NULL) {
+			dprintk("nfs_get_root: nfs4_label_alloc error = %d\n",
+					error);
+			return ERR_PTR(-ENOMEM);
+		}
+	}
+#endif
+
 	/* get the actual root for this mount */
-	error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
+	error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr, label);
 	if (error < 0) {
 		dprintk("nfs_get_root: getattr error = %d\n", -error);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		if (server->caps & NFS_CAP_SECURITY_LABEL)
+			nfs4_label_free(label);
+#endif
 		return ERR_PTR(error);
 	}
 
-	inode = nfs_fhget(sb, mntfh, &fattr);
+	inode = nfs_fhget(sb, mntfh, &fattr, label);
 	if (IS_ERR(inode)) {
 		dprintk("nfs_get_root: get root inode failed\n");
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		if (server->caps & NFS_CAP_SECURITY_LABEL)
+			nfs4_label_free(label);
+#endif
 		return ERR_CAST(inode);
 	}
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL)
+		nfs4_label_free(label);
+#endif
+
 	error = nfs_superblock_set_dummy_root(sb, inode);
 	if (error != 0)
 		return ERR_PTR(error);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 50a56ed..88971d9 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -57,7 +57,7 @@
 static int enable_ino64 = NFS_64_BIT_INODE_NUMBERS_ENABLED;
 
 static void nfs_invalidate_inode(struct inode *);
-static int nfs_update_inode(struct inode *, struct nfs_fattr *);
+static int nfs_update_inode(struct inode *, struct nfs_fattr *, struct nfs4_label *);
 
 static struct kmem_cache * nfs_inode_cachep;
 
@@ -138,10 +138,13 @@ static void nfs_zap_caches_locked(struct inode *inode)
 	nfsi->attrtimeo_timestamp = jiffies;
 
 	memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
+	nfsi->cache_validity |= NFS_INO_INVALID_ATTR| \
+				NFS_INO_INVALID_LABEL| \
+				NFS_INO_INVALID_ACCESS| \
+				NFS_INO_INVALID_ACL| \
+				NFS_INO_REVAL_PAGECACHE;
 	if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
-		nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
-	else
-		nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
+		nfsi->cache_validity |= NFS_INO_INVALID_DATA;
 }
 
 void nfs_zap_caches(struct inode *inode)
@@ -230,12 +233,36 @@ nfs_init_locked(struct inode *inode, void *opaque)
 /* Don't use READDIRPLUS on directories that we believe are too large */
 #define NFS_LIMIT_READDIRPLUS (8*PAGE_SIZE)
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
+{
+	int error;
+
+/*	BUG_ON(!mutex_is_locked(&inode->i_mutex)); */
+
+	if ((fattr->valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL) &&
+		label && inode->i_security) {
+		error = security_inode_notifysecctx(inode, label->label,
+						   label->len);
+		if (error)
+			printk(KERN_ERR "%s() %s %d "
+				"security_inode_notifysecctx() %d\n",
+				__func__,
+				(char *)label->label, label->len, error);
+	}
+}
+#else
+void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
+{
+}
+#endif
+
 /*
  * This is our front-end to iget that looks up inodes by file handle
  * instead of inode number.
  */
 struct inode *
-nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
+nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct nfs_find_desc desc = {
 		.fh	= fh,
@@ -365,6 +392,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
 			 */
 			inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
 		}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		nfs_setsecurity(inode, fattr, label);
+#endif
 		nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
 		nfsi->attrtimeo_timestamp = now;
 		nfsi->access_cache = RB_ROOT;
@@ -373,7 +403,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
 
 		unlock_new_inode(inode);
 	} else
-		nfs_refresh_inode(inode, fattr);
+		nfs_refresh_inode(inode, fattr, label);
 	dprintk("NFS: nfs_fhget(%s/%Ld ct=%d)\n",
 		inode->i_sb->s_id,
 		(long long)NFS_FILEID(inode),
@@ -394,7 +424,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
 	struct inode *inode = dentry->d_inode;
 	struct nfs_fattr fattr;
-	int error;
+	int error = 0;
 
 	nfs_inc_stats(inode, NFSIOS_VFSSETATTR);
 
@@ -424,7 +454,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
 		nfs_inode_return_delegation(inode);
 	error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
 	if (error == 0)
-		nfs_refresh_inode(inode, &fattr);
+		nfs_refresh_inode(inode, &fattr, NULL);
 	return error;
 }
 
@@ -682,6 +712,7 @@ int
 __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 {
 	int		 status = -ESTALE;
+	struct nfs4_label *label = NULL;
 	struct nfs_fattr fattr;
 	struct nfs_inode *nfsi = NFS_I(inode);
 
@@ -694,7 +725,17 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 		goto out;
 
 	nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE);
-	status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr);
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) {
+		label = nfs4_label_alloc(GFP_KERNEL);
+		if (label == NULL) {
+			status = -ENOMEM;
+			goto out;
+		}
+	}
+#endif
+	status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr, label);
 	if (status != 0) {
 		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
 			 inode->i_sb->s_id,
@@ -707,7 +748,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 		goto out;
 	}
 
-	status = nfs_refresh_inode(inode, &fattr);
+	status = nfs_refresh_inode(inode, &fattr, label);
 	if (status) {
 		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",
 			 inode->i_sb->s_id,
@@ -723,6 +764,10 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 		(long long)NFS_FILEID(inode));
 
  out:
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL))
+		nfs4_label_free(label);
+#endif
 	return status;
 }
 
@@ -744,7 +789,7 @@ int nfs_attribute_timeout(struct inode *inode)
  */
 int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 {
-	if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR)
+	if (!(NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL))
 			&& !nfs_attribute_timeout(inode))
 		return NFS_STALE(inode) ? -ESTALE : 0;
 	return __nfs_revalidate_inode(server, inode);
@@ -945,10 +990,10 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n
 		((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0);
 }
 
-static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
+static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	if (nfs_inode_attrs_need_update(inode, fattr))
-		return nfs_update_inode(inode, fattr);
+		return nfs_update_inode(inode, fattr, label);
 	return nfs_check_inode_attributes(inode, fattr);
 }
 
@@ -962,20 +1007,20 @@ static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr
  * safe to do a full update of the inode attributes, or whether just to
  * call nfs_check_inode_attributes.
  */
-int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	int status;
 
 	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
 		return 0;
 	spin_lock(&inode->i_lock);
-	status = nfs_refresh_inode_locked(inode, fattr);
+	status = nfs_refresh_inode_locked(inode, fattr, label);
 	spin_unlock(&inode->i_lock);
 
 	return status;
 }
 
-static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
+static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 
@@ -984,7 +1029,7 @@ static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr
 		nfsi->cache_validity |= NFS_INO_INVALID_DATA;
 	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
 		return 0;
-	return nfs_refresh_inode_locked(inode, fattr);
+	return nfs_refresh_inode_locked(inode, fattr, label);
 }
 
 /**
@@ -1001,12 +1046,12 @@ static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr
  * are expected to change one or more attributes, to avoid
  * unnecessary NFS requests and trips through nfs_update_inode().
  */
-int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	int status;
 
 	spin_lock(&inode->i_lock);
-	status = nfs_post_op_update_inode_locked(inode, fattr);
+	status = nfs_post_op_update_inode_locked(inode, fattr, label);
 	spin_unlock(&inode->i_lock);
 	return status;
 }
@@ -1057,7 +1102,7 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa
 		fattr->valid |= NFS_ATTR_FATTR_PRESIZE;
 	}
 out_noforce:
-	status = nfs_post_op_update_inode_locked(inode, fattr);
+	status = nfs_post_op_update_inode_locked(inode, fattr, NULL);
 	spin_unlock(&inode->i_lock);
 	return status;
 }
@@ -1074,7 +1119,7 @@ out_noforce:
  *
  * A very similar scenario holds for the dir cache.
  */
-static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct nfs_server *server;
 	struct nfs_inode *nfsi = NFS_I(inode);
@@ -1226,6 +1271,11 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 				| NFS_INO_INVALID_ACL
 				| NFS_INO_REVAL_FORCED);
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label)
+		nfs_setsecurity(inode, fattr, label);
+#endif
+
 	if (fattr->valid & NFS_ATTR_FATTR_NLINK) {
 		if (inode->i_nlink != fattr->nlink) {
 			invalid |= NFS_INO_INVALID_ATTR;
@@ -1247,7 +1297,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 		inode->i_blocks = fattr->du.nfs2.blocks;
 
 	/* Update attrtimeo value if we're out of the unstable period */
-	if (invalid & NFS_INO_INVALID_ATTR) {
+	if (invalid & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) {
 		nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
 		nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
 		nfsi->attrtimeo_timestamp = now;
@@ -1260,6 +1310,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 		}
 	}
 	invalid &= ~NFS_INO_INVALID_ATTR;
+	invalid &= ~NFS_INO_INVALID_LABEL;
 	/* Don't invalidate the data if we were to blame */
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
 				|| S_ISLNK(inode->i_mode)))
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 7888cf3..252a764 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -123,7 +123,7 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
 	parent = dget_parent(nd->path.dentry);
 	err = server->nfs_client->rpc_ops->lookup(parent->d_inode,
 						  &nd->path.dentry->d_name,
-						  &fh, &fattr);
+						  &fh, &fattr, NULL);
 	dput(parent);
 	if (err != 0)
 		goto out_err;
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index d150ae0..20b44bf 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -238,7 +238,7 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
 
 	switch (status) {
 		case 0:
-			status = nfs_refresh_inode(inode, &fattr);
+			status = nfs_refresh_inode(inode, &fattr, NULL);
 			break;
 		case -EPFNOSUPPORT:
 		case -EPROTONOSUPPORT:
@@ -344,7 +344,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
 
 	switch (status) {
 		case 0:
-			status = nfs_refresh_inode(inode, &fattr);
+			status = nfs_refresh_inode(inode, &fattr, NULL);
 			nfs3_cache_acls(inode, acl, dfacl);
 			break;
 		case -EPFNOSUPPORT:
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index e701002..f58ce23 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -97,7 +97,7 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  */
 static int
 nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
-		struct nfs_fattr *fattr)
+		struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_GETATTR],
@@ -142,7 +142,8 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
 static int
 nfs3_proc_lookup(struct inode *dir, struct qstr *name,
-		 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+		 struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+		 struct nfs4_label *label)
 {
 	struct nfs_fattr	dir_attr;
 	struct nfs3_diropargs	arg = {
@@ -166,7 +167,7 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name,
 	nfs_fattr_init(&dir_attr);
 	nfs_fattr_init(fattr);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-	nfs_refresh_inode(dir, &dir_attr);
+	nfs_refresh_inode(dir, &dir_attr, NULL);
 	if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) {
 		msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
 		msg.rpc_argp = fhandle;
@@ -212,7 +213,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 	}
 	nfs_fattr_init(&fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
-	nfs_refresh_inode(inode, &fattr);
+	nfs_refresh_inode(inode, &fattr, NULL);
 	if (status == 0) {
 		entry->mask = 0;
 		if (res.access & NFS3_ACCESS_READ)
@@ -246,7 +247,7 @@ static int nfs3_proc_readlink(struct inode *inode, struct page *page,
 	dprintk("NFS call  readlink\n");
 	nfs_fattr_init(&fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
-	nfs_refresh_inode(inode, &fattr);
+	nfs_refresh_inode(inode, &fattr, NULL);
 	dprintk("NFS reply readlink: %d\n", status);
 	return status;
 }
@@ -287,9 +288,9 @@ static int nfs3_do_create(struct inode *dir, struct dentry *dentry, struct nfs3_
 	int status;
 
 	status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0);
-	nfs_post_op_update_inode(dir, data->res.dir_attr);
+	nfs_post_op_update_inode(dir, data->res.dir_attr, NULL);
 	if (status == 0)
-		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
+		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL);
 	return status;
 }
 
@@ -370,7 +371,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 		 * not sure this buys us anything (and I'd have
 		 * to revamp the NFSv3 XDR code) */
 		status = nfs3_proc_setattr(dentry, data->res.fattr, sattr);
-		nfs_post_op_update_inode(dentry->d_inode, data->res.fattr);
+		nfs_post_op_update_inode(dentry->d_inode, data->res.fattr, NULL);
 		dprintk("NFS reply setattr (post-create): %d\n", status);
 		if (status != 0)
 			goto out;
@@ -401,7 +402,7 @@ nfs3_proc_remove(struct inode *dir, struct qstr *name)
 	dprintk("NFS call  remove %s\n", name->name);
 	nfs_fattr_init(&res.dir_attr);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-	nfs_post_op_update_inode(dir, &res.dir_attr);
+	nfs_post_op_update_inode(dir, &res.dir_attr, NULL);
 	dprintk("NFS reply remove: %d\n", status);
 	return status;
 }
@@ -419,7 +420,7 @@ nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 	if (nfs3_async_handle_jukebox(task, dir))
 		return 0;
 	res = task->tk_msg.rpc_resp;
-	nfs_post_op_update_inode(dir, &res->dir_attr);
+	nfs_post_op_update_inode(dir, &res->dir_attr, NULL);
 	return 1;
 }
 
@@ -451,8 +452,8 @@ nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
 	nfs_fattr_init(&old_dir_attr);
 	nfs_fattr_init(&new_dir_attr);
 	status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
-	nfs_post_op_update_inode(old_dir, &old_dir_attr);
-	nfs_post_op_update_inode(new_dir, &new_dir_attr);
+	nfs_post_op_update_inode(old_dir, &old_dir_attr, NULL);
+	nfs_post_op_update_inode(new_dir, &new_dir_attr, NULL);
 	dprintk("NFS reply rename: %d\n", status);
 	return status;
 }
@@ -482,8 +483,8 @@ nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 	nfs_fattr_init(&dir_attr);
 	nfs_fattr_init(&fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
-	nfs_post_op_update_inode(dir, &dir_attr);
-	nfs_post_op_update_inode(inode, &fattr);
+	nfs_post_op_update_inode(dir, &dir_attr, NULL);
+	nfs_post_op_update_inode(inode, &fattr, NULL);
 	dprintk("NFS reply link: %d\n", status);
 	return status;
 }
@@ -570,7 +571,7 @@ nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
 	dprintk("NFS call  rmdir %s\n", name->name);
 	nfs_fattr_init(&dir_attr);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-	nfs_post_op_update_inode(dir, &dir_attr);
+	nfs_post_op_update_inode(dir, &dir_attr, NULL);
 	dprintk("NFS reply rmdir: %d\n", status);
 	return status;
 }
@@ -623,7 +624,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 
 	nfs_invalidate_atime(dir);
 
-	nfs_refresh_inode(dir, &dir_attr);
+	nfs_refresh_inode(dir, &dir_attr, NULL);
 	dprintk("NFS reply readdir: %d\n", status);
 	return status;
 }
@@ -756,7 +757,7 @@ static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data)
 		return -EAGAIN;
 
 	nfs_invalidate_atime(data->inode);
-	nfs_refresh_inode(data->inode, &data->fattr);
+	nfs_refresh_inode(data->inode, &data->fattr, NULL);
 	return 0;
 }
 
@@ -783,7 +784,7 @@ static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data)
 {
 	if (nfs3_async_handle_jukebox(task, data->inode))
 		return -EAGAIN;
-	nfs_refresh_inode(data->inode, data->res.fattr);
+	nfs_refresh_inode(data->inode, data->res.fattr, NULL);
 	return 0;
 }
 
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 71bb8da..e2b9010 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -68,8 +68,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data);
 static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
 static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
 static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *);
-static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
-static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
+static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label);
+static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label);
 
 /* Prevent leaks of NFSv4 errors into userland */
 static int nfs4_map_errors(int err)
@@ -105,6 +105,9 @@ const u32 nfs4_fattr_bitmap[2] = {
 	| FATTR4_WORD1_TIME_ACCESS
 	| FATTR4_WORD1_TIME_METADATA
 	| FATTR4_WORD1_TIME_MODIFY
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	| FATTR4_WORD1_SECURITY_LABEL
+#endif
 };
 
 const u32 nfs4_statfs_bitmap[2] = {
@@ -713,7 +716,9 @@ struct nfs4_opendata {
 	struct nfs_open_confirmargs c_arg;
 	struct nfs_open_confirmres c_res;
 	struct nfs_fattr f_attr;
+	struct nfs4_label *f_label;
 	struct nfs_fattr dir_attr;
+	struct nfs4_label *dir_label;
 	struct path path;
 	struct dentry *dir;
 	struct nfs4_state_owner *owner;
@@ -730,6 +735,8 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
 {
 	p->o_res.f_attr = &p->f_attr;
 	p->o_res.dir_attr = &p->dir_attr;
+	p->o_res.f_label = p->f_label;
+	p->o_res.dir_label = p->dir_label;
 	p->o_res.seqid = p->o_arg.seqid;
 	p->c_res.seqid = p->c_arg.seqid;
 	p->o_res.server = p->o_arg.server;
@@ -740,7 +747,7 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
 
 static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
 		struct nfs4_state_owner *sp, fmode_t fmode, int flags,
-		const struct iattr *attrs)
+		const struct iattr *attrs, struct nfs4_label *label)
 {
 	struct dentry *parent = dget_parent(path->dentry);
 	struct inode *dir = parent->d_inode;
@@ -750,9 +757,21 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
 	p = kzalloc(sizeof(*p), GFP_KERNEL);
 	if (p == NULL)
 		goto err;
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		p->f_label = nfs4_label_alloc(GFP_KERNEL);
+		if (p->f_label == NULL)
+			goto err_free_p;
+		p->dir_label = nfs4_label_alloc(GFP_KERNEL);
+		if (p->dir_label == NULL) {
+			nfs4_label_free(p->f_label);
+			goto err_free_p;
+		}
+	}
+#endif
 	p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
 	if (p->o_arg.seqid == NULL)
-		goto err_free;
+		goto err_free_label;
 	path_get(path);
 	p->path = *path;
 	p->dir = parent;
@@ -767,6 +786,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
 	p->o_arg.server = server;
 	p->o_arg.bitmask = server->attr_bitmask;
 	p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
+	p->o_arg.label = label;
 	if (flags & O_EXCL) {
 		if (nfs4_has_persistent_session(server->nfs_client)) {
 			/* GUARDED */
@@ -787,7 +807,15 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
 	nfs4_init_opendata_res(p);
 	kref_init(&p->kref);
 	return p;
-err_free:
+
+err_free_label:
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		nfs4_label_free(p->f_label);
+		nfs4_label_free(p->dir_label);
+	}
+#endif
+err_free_p:
 	kfree(p);
 err:
 	dput(parent);
@@ -803,6 +831,12 @@ static void nfs4_opendata_free(struct kref *kref)
 	if (p->state != NULL)
 		nfs4_put_open_state(p->state);
 	nfs4_put_state_owner(p->owner);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (p->o_arg.server->caps & NFS_CAP_SECURITY_LABEL) {
+		nfs4_label_free(p->f_label);
+		nfs4_label_free(p->dir_label);
+	}
+#endif
 	dput(p->dir);
 	path_put(&p->path);
 	kfree(p);
@@ -1028,7 +1062,7 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
 	ret = -EAGAIN;
 	if (!(data->f_attr.valid & NFS_ATTR_FATTR))
 		goto err;
-	inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr);
+	inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr, data->f_label);
 	ret = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto err;
@@ -1086,7 +1120,7 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context
 {
 	struct nfs4_opendata *opendata;
 
-	opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, 0, NULL);
+	opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, 0, NULL, NULL);
 	if (opendata == NULL)
 		return ERR_PTR(-ENOMEM);
 	opendata->state = state;
@@ -1518,7 +1552,7 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
 	if (status != 0 || !data->rpc_done)
 		return status;
 
-	nfs_refresh_inode(dir, o_res->dir_attr);
+	nfs_refresh_inode(dir, o_res->dir_attr, o_res->dir_label);
 
 	if (o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
 		status = _nfs4_proc_open_confirm(data);
@@ -1546,9 +1580,9 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
 
 	if (o_arg->open_flags & O_CREAT) {
 		update_changeattr(dir, &o_res->cinfo);
-		nfs_post_op_update_inode(dir, o_res->dir_attr);
+		nfs_post_op_update_inode(dir, o_res->dir_attr, o_res->dir_label);
 	} else
-		nfs_refresh_inode(dir, o_res->dir_attr);
+		nfs_refresh_inode(dir, o_res->dir_attr, o_res->dir_label);
 	if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
 		server->caps &= ~NFS_CAP_POSIX_LOCK;
 	if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
@@ -1557,7 +1591,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
 			return status;
 	}
 	if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
-		_nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr);
+		_nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, o_res->f_label);
 	return 0;
 }
 
@@ -1654,7 +1688,7 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct
 /*
  * Returns a referenced nfs4_state
  */
-static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
+static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, int flags, struct iattr *sattr, struct nfs4_label *label, struct rpc_cred *cred, struct nfs4_state **res)
 {
 	struct nfs4_state_owner  *sp;
 	struct nfs4_state     *state = NULL;
@@ -1674,7 +1708,7 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in
 	if (path->dentry->d_inode != NULL)
 		nfs4_return_incompatible_delegation(path->dentry->d_inode, fmode);
 	status = -ENOMEM;
-	opendata = nfs4_opendata_alloc(path, sp, fmode, flags, sattr);
+	opendata = nfs4_opendata_alloc(path, sp, fmode, flags, sattr, label);
 	if (opendata == NULL)
 		goto err_put_state_owner;
 
@@ -1708,14 +1742,14 @@ out_err:
 }
 
 
-static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred)
+static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, int flags, struct iattr *sattr, struct nfs4_label *label, struct rpc_cred *cred)
 {
 	struct nfs4_exception exception = { };
 	struct nfs4_state *res;
 	int status;
 
 	do {
-		status = _nfs4_do_open(dir, path, fmode, flags, sattr, cred, &res);
+		status = _nfs4_do_open(dir, path, fmode, flags, sattr, label, cred, &res);
 		if (status == 0)
 			break;
 		/* NOTE: BAD_SEQID means the server and client disagree about the
@@ -1759,17 +1793,20 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, fmo
 
 static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
 			    struct nfs_fattr *fattr, struct iattr *sattr,
-			    struct nfs4_state *state)
+			    struct nfs4_state *state, struct nfs4_label *ilabel,
+			    struct nfs4_label *olabel)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
         struct nfs_setattrargs  arg = {
                 .fh             = NFS_FH(inode),
                 .iap            = sattr,
 		.server		= server,
-		.bitmask = server->attr_bitmask,
+		.bitmask 	= server->attr_bitmask,
+		.label		= ilabel,
         };
         struct nfs_setattrres  res = {
 		.fattr		= fattr,
+		.label		= olabel,
 		.server		= server,
         };
         struct rpc_message msg = {
@@ -1781,6 +1818,11 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
 	unsigned long timestamp = jiffies;
 	int status;
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (ilabel == NULL || olabel == NULL)
+		arg.bitmask = server->attr_bitmask_nl;
+#endif
+
 	nfs_fattr_init(fattr);
 
 	if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) {
@@ -1797,15 +1839,16 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
 }
 
 static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
-			   struct nfs_fattr *fattr, struct iattr *sattr,
-			   struct nfs4_state *state)
+			    struct nfs_fattr *fattr, struct iattr *sattr,
+			    struct nfs4_state *state, struct nfs4_label *ilabel,
+			    struct nfs4_label *olabel)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(server,
-				_nfs4_do_setattr(inode, cred, fattr, sattr, state),
+				_nfs4_do_setattr(inode, cred, fattr, sattr, state, ilabel, olabel),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -1875,7 +1918,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
 				rpc_restart_call_prepare(task);
 	}
 	nfs_release_seqid(calldata->arg.seqid);
-	nfs_refresh_inode(calldata->inode, calldata->res.fattr);
+	nfs_refresh_inode(calldata->inode, calldata->res.fattr, NULL);
 }
 
 static void nfs4_close_prepare(struct rpc_task *task, void *data)
@@ -1969,9 +2012,9 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
 	/* Serialization for the sequence id */
 	calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
 	if (calldata->arg.seqid == NULL)
-		goto out_free_calldata;
+		goto out_free;
 	calldata->arg.fmode = 0;
-	calldata->arg.bitmask = server->cache_consistency_bitmask;
+	calldata->arg.bitmask = server->cache_consistency_bitmask_nl;
 	calldata->res.fattr = &calldata->fattr;
 	calldata->res.seqid = calldata->arg.seqid;
 	calldata->res.server = server;
@@ -1990,7 +2033,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
 		status = rpc_wait_for_completion_task(task);
 	rpc_put_task(task);
 	return status;
-out_free_calldata:
+out_free:
 	kfree(calldata);
 out:
 	nfs4_put_open_state(state);
@@ -2027,6 +2070,7 @@ out_close:
 struct dentry *
 nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+	struct nfs4_label l, *label = NULL;
 	struct path path = {
 		.mnt = nd->path.mnt,
 		.dentry = dentry,
@@ -2043,6 +2087,15 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 		attr.ia_valid = ATTR_MODE;
 		if (!IS_POSIXACL(dir))
 			attr.ia_mode &= ~current_umask();
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+			int error;
+			error = security_dentry_init_security(dentry,
+					attr.ia_mode, &l.label, &l.len);
+			if (error == 0)
+				label = &l;
+		}
+#endif
 	} else {
 		attr.ia_valid = 0;
 		BUG_ON(nd->intent.open.flags & O_CREAT);
@@ -2054,8 +2107,12 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 	parent = dentry->d_parent;
 	/* Protect against concurrent sillydeletes */
 	nfs_block_sillyrename(parent);
-	state = nfs4_do_open(dir, &path, fmode, nd->intent.open.flags, &attr, cred);
+	state = nfs4_do_open(dir, &path, fmode, nd->intent.open.flags, &attr, label, cred);
 	put_rpccred(cred);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label)
+		security_release_secctx(l.label, l.len);
+#endif
 	if (IS_ERR(state)) {
 		if (PTR_ERR(state) == -ENOENT) {
 			d_add(dentry, NULL);
@@ -2087,7 +2144,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
 	cred = rpc_lookup_cred();
 	if (IS_ERR(cred))
 		return PTR_ERR(cred);
-	state = nfs4_do_open(dir, &path, fmode, openflags, NULL, cred);
+	state = nfs4_do_open(dir, &path, fmode, openflags, NULL, NULL, cred);
 	put_rpccred(cred);
 	if (IS_ERR(state)) {
 		switch (PTR_ERR(state)) {
@@ -2145,6 +2202,17 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
 				NFS_CAP_CTIME|NFS_CAP_MTIME);
 		if (res.attr_bitmask[0] & FATTR4_WORD0_ACL)
 			server->caps |= NFS_CAP_ACLS;
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		if (res.attr_bitmask[1] & FATTR4_WORD1_SECURITY_LABEL) {
+			server->caps |= NFS_CAP_SECURITY_LABEL;
+		} else
+#endif
+			server->attr_bitmask[1] &= ~FATTR4_WORD1_SECURITY_LABEL;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		memcpy(server->attr_bitmask_nl, res.attr_bitmask, sizeof(server->attr_bitmask));
+		server->attr_bitmask_nl[1] &= ~FATTR4_WORD1_SECURITY_LABEL;
+#endif
 		if (res.has_links != 0)
 			server->caps |= NFS_CAP_HARDLINKS;
 		if (res.has_symlinks != 0)
@@ -2168,7 +2236,12 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
 
 		memcpy(server->cache_consistency_bitmask, res.attr_bitmask, sizeof(server->cache_consistency_bitmask));
 		server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE;
-		server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
+		server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA |
+							FATTR4_WORD1_TIME_MODIFY |
+							FATTR4_WORD1_SECURITY_LABEL;
+		memcpy(server->cache_consistency_bitmask_nl, server->cache_consistency_bitmask,
+						sizeof(server->cache_consistency_bitmask_nl));
+		server->cache_consistency_bitmask_nl[1] &= ~FATTR4_WORD1_SECURITY_LABEL;
 		server->acl_bitmask = res.acl_bitmask;
 	}
 
@@ -2190,8 +2263,9 @@ int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
 static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
 		struct nfs_fsinfo *info)
 {
+	u32 bitmask[2];
 	struct nfs4_lookup_root_arg args = {
-		.bitmask = nfs4_fattr_bitmap,
+		.bitmask = bitmask,
 	};
 	struct nfs4_lookup_res res = {
 		.server = server,
@@ -2203,6 +2277,8 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
 		.rpc_argp = &args,
 		.rpc_resp = &res,
 	};
+	bitmask[0] = nfs4_fattr_bitmap[0];
+	bitmask[1] = nfs4_fattr_bitmap[1] & ~FATTR4_WORD1_SECURITY_LABEL;
 
 	nfs_fattr_init(info->fattr);
 	return nfs4_call_sync(server, &msg, &args, &res, 0);
@@ -2278,7 +2354,8 @@ out:
 	return status;
 }
 
-static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+				struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct nfs4_getattr_arg args = {
 		.fh = fhandle,
@@ -2286,6 +2363,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 	};
 	struct nfs4_getattr_res res = {
 		.fattr = fattr,
+		.label = label,
 		.server = server,
 	};
 	struct rpc_message msg = {
@@ -2293,18 +2371,23 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 		.rpc_argp = &args,
 		.rpc_resp = &res,
 	};
-	
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (!label)
+		args.bitmask = server->attr_bitmask_nl;
+#endif
 	nfs_fattr_init(fattr);
 	return nfs4_call_sync(server, &msg, &args, &res, 0);
 }
 
-static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+				struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(server,
-				_nfs4_proc_getattr(server, fhandle, fattr),
+				_nfs4_proc_getattr(server, fhandle, fattr, label),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -2334,8 +2417,13 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 	struct inode *inode = dentry->d_inode;
 	struct rpc_cred *cred = NULL;
 	struct nfs4_state *state = NULL;
+	struct nfs4_label *olabel;
 	int status;
 
+	olabel = nfs4_label_alloc(GFP_KERNEL);
+	if (olabel == NULL)
+		return -ENOMEM;
+
 	nfs_fattr_init(fattr);
 	
 	/* Search for an existing open(O_WRITE) file */
@@ -2349,15 +2437,16 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 		}
 	}
 
-	status = nfs4_do_setattr(inode, cred, fattr, sattr, state);
-	if (status == 0)
+	status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, NULL);
+	if (status == 0) {
 		nfs_setattr_update_inode(inode, sattr);
+	}
 	return status;
 }
 
 static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *dirfh,
 		const struct qstr *name, struct nfs_fh *fhandle,
-		struct nfs_fattr *fattr)
+		struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	int		       status;
 	struct nfs4_lookup_arg args = {
@@ -2368,6 +2457,7 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d
 	struct nfs4_lookup_res res = {
 		.server = server,
 		.fattr = fattr,
+		.label = label,
 		.fh = fhandle,
 	};
 	struct rpc_message msg = {
@@ -2376,6 +2466,11 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d
 		.rpc_resp = &res,
 	};
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label == NULL)
+		args.bitmask = server->attr_bitmask_nl;
+#endif
+
 	nfs_fattr_init(fattr);
 
 	dprintk("NFS call  lookupfh %s\n", name->name);
@@ -2391,7 +2486,7 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
 	struct nfs4_exception exception = { };
 	int err;
 	do {
-		err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr);
+		err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr, NULL);
 		/* FIXME: !!!! */
 		if (err == -NFS4ERR_MOVED) {
 			err = -EREMOTE;
@@ -2403,25 +2498,27 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
 }
 
 static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name,
-		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+		struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+		struct nfs4_label *label)
 {
 	int status;
 	
 	dprintk("NFS call  lookup %s\n", name->name);
-	status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr);
+	status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr, label);
 	if (status == -NFS4ERR_MOVED)
 		status = nfs4_get_referral(dir, name, fattr, fhandle);
 	dprintk("NFS reply lookup: %d\n", status);
 	return status;
 }
 
-static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle,
+				struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
-				_nfs4_proc_lookup(dir, name, fhandle, fattr),
+				_nfs4_proc_lookup(dir, name, fhandle, fattr, label),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -2438,6 +2535,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
 	struct nfs4_accessres res = {
 		.server = server,
 		.fattr = &fattr,
+		.label = NULL,
 	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
@@ -2446,7 +2544,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
 		.rpc_cred = entry->cred,
 	};
 	int mode = entry->mask;
-	int status;
+	int status = 0;
 
 	/*
 	 * Determine which access bits we want to ask for...
@@ -2464,6 +2562,13 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
 		if (mode & MAY_EXEC)
 			args.access |= NFS4_ACCESS_EXECUTE;
 	}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		res.label = nfs4_label_alloc(GFP_KERNEL);
+		if (res.label == NULL)
+			return -ENOMEM;
+	}
+#endif
 	nfs_fattr_init(&fattr);
 	status = nfs4_call_sync(server, &msg, &args, &res, 0);
 	if (!status) {
@@ -2474,8 +2579,12 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
 			entry->mask |= MAY_WRITE;
 		if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE))
 			entry->mask |= MAY_EXEC;
-		nfs_refresh_inode(inode, &fattr);
+		nfs_refresh_inode(inode, &fattr, res.label);
 	}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL)
+		nfs4_label_free(res.label);
+#endif
 	return status;
 }
 
@@ -2566,6 +2675,7 @@ static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                  int flags, struct nameidata *nd)
 {
+	struct nfs4_label l, *ilabel = NULL, *olabel = NULL;
 	struct path path = {
 		.mnt = nd->path.mnt,
 		.dentry = dentry,
@@ -2580,7 +2690,27 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 		status = PTR_ERR(cred);
 		goto out;
 	}
-	state = nfs4_do_open(dir, &path, fmode, flags, sattr, cred);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (((nd->flags & LOOKUP_CREATE) != 0) &&
+			nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		status = security_dentry_init_security(dentry,
+				sattr->ia_mode, &l.label, &l.len);
+		/* XXX: should this be more fatal? */
+		if (status == 0)
+			ilabel = &l;
+	}
+
+	/* XXX: this conditional for the above too? */
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		olabel = nfs4_label_alloc(GFP_KERNEL);
+		if (olabel == NULL) {
+			status = -ENOMEM;
+			goto out;
+		}
+	}
+#endif
+
+	state = nfs4_do_open(dir, &path, fmode, flags, sattr, ilabel, cred);
 	d_drop(dentry);
 	if (IS_ERR(state)) {
 		status = PTR_ERR(state);
@@ -2590,10 +2720,12 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 	if (flags & O_EXCL) {
 		struct nfs_fattr fattr;
-		status = nfs4_do_setattr(state->inode, cred, &fattr, sattr, state);
-		if (status == 0)
+		status = nfs4_do_setattr(state->inode, cred, &fattr, sattr, state, ilabel, olabel);
+		if (status == 0) {
 			nfs_setattr_update_inode(state->inode, sattr);
-		nfs_post_op_update_inode(state->inode, &fattr);
+			nfs_post_op_update_inode(state->inode, &fattr, olabel);
+			nfs_setsecurity(state->inode, &fattr, olabel);
+		}
 	}
 	if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
 		status = nfs4_intent_set_file(nd, &path, state, fmode);
@@ -2602,6 +2734,12 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 out_putcred:
 	put_rpccred(cred);
 out:
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (ilabel)
+		security_release_secctx(ilabel->label, ilabel->len);
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL))
+		nfs4_label_free(olabel);
+#endif
 	return status;
 }
 
@@ -2622,14 +2760,26 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
 		.rpc_argp = &args,
 		.rpc_resp = &res,
 	};
-	int			status;
+	int	status = 0;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		res.dir_label = nfs4_label_alloc(GFP_NOWAIT);
+		if (res.dir_label == NULL)
+			return -ENOMEM;
+	}
+#endif
 
 	nfs_fattr_init(&res.dir_attr);
 	status = nfs4_call_sync(server, &msg, &args, &res, 1);
 	if (status == 0) {
 		update_changeattr(dir, &res.cinfo);
-		nfs_post_op_update_inode(dir, &res.dir_attr);
+		nfs_post_op_update_inode(dir, &res.dir_attr, res.dir_label);
 	}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL)
+		nfs4_label_free(res.dir_label);
+#endif
 	return status;
 }
 
@@ -2651,9 +2801,22 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
 	struct nfs_removeargs *args = msg->rpc_argp;
 	struct nfs_removeres *res = msg->rpc_resp;
 
-	args->bitmask = server->cache_consistency_bitmask;
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL)
+		res->dir_label = nfs4_label_alloc(GFP_NOWAIT);
+	else
+		res->dir_label = NULL;
+#endif
+
+	if (res->dir_label != NULL)
+		args->bitmask = server->cache_consistency_bitmask;
+	else
+		args->bitmask = server->cache_consistency_bitmask_nl;
+
 	res->server = server;
 	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
+
+	nfs_fattr_init(&res->dir_attr);
 }
 
 static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
@@ -2664,7 +2827,11 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 	if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
 		return 0;
 	update_changeattr(dir, &res->cinfo);
-	nfs_post_op_update_inode(dir, &res->dir_attr);
+	nfs_post_op_update_inode(dir, &res->dir_attr, res->dir_label);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (res->server->caps & NFS_CAP_SECURITY_LABEL)
+		nfs4_label_free(res->dir_label);
+#endif
 	return 1;
 }
 
@@ -2677,6 +2844,8 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 		.new_dir = NFS_FH(new_dir),
 		.old_name = old_name,
 		.new_name = new_name,
+		.old_label = NULL,
+		.new_label = NULL,
 		.bitmask = server->attr_bitmask,
 	};
 	struct nfs_fattr old_fattr, new_fattr;
@@ -2690,7 +2859,20 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 		.rpc_argp = &arg,
 		.rpc_resp = &res,
 	};
-	int			status;
+	int	status = 0;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		res.old_label = nfs4_label_alloc(GFP_NOWAIT);
+		if (res.old_label == NULL)
+			return -ENOMEM;
+		res.new_label = nfs4_label_alloc(GFP_NOWAIT);
+		if (res.new_label == NULL) {
+			nfs4_label_free(res.old_label);
+			return -ENOMEM;
+		}
+	}
+#endif
 	
 	nfs_fattr_init(res.old_fattr);
 	nfs_fattr_init(res.new_fattr);
@@ -2698,10 +2880,17 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 
 	if (!status) {
 		update_changeattr(old_dir, &res.old_cinfo);
-		nfs_post_op_update_inode(old_dir, res.old_fattr);
+		nfs_post_op_update_inode(old_dir, res.old_fattr, res.old_label);
 		update_changeattr(new_dir, &res.new_cinfo);
-		nfs_post_op_update_inode(new_dir, res.new_fattr);
+		nfs_post_op_update_inode(new_dir, res.new_fattr, res.new_label);
+	}
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		nfs4_label_free(res.old_label);
+		nfs4_label_free(res.new_label);
 	}
+#endif
 	return status;
 }
 
@@ -2732,23 +2921,44 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
 	struct nfs4_link_res res = {
 		.server = server,
 		.fattr = &fattr,
+		.label = NULL,
 		.dir_attr = &dir_attr,
+		.dir_label = NULL,
 	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
 		.rpc_argp = &arg,
 		.rpc_resp = &res,
 	};
-	int			status;
+	int	status = 0;
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		res.label = nfs4_label_alloc(GFP_KERNEL);
+		if (res.label == NULL)
+			return -ENOMEM;
+		res.dir_label = nfs4_label_alloc(GFP_KERNEL);
+		if (res.dir_label == NULL) {
+			nfs4_label_free(res.label);
+			return -ENOMEM;
+		}
+	}
+#endif
 	nfs_fattr_init(res.fattr);
 	nfs_fattr_init(res.dir_attr);
 	status = nfs4_call_sync(server, &msg, &arg, &res, 1);
 	if (!status) {
 		update_changeattr(dir, &res.cinfo);
-		nfs_post_op_update_inode(dir, res.dir_attr);
-		nfs_post_op_update_inode(inode, res.fattr);
+		nfs_post_op_update_inode(dir, res.dir_attr, res.dir_label);
+		nfs_post_op_update_inode(inode, res.fattr, res.label);
+	}
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL) {
+		nfs4_label_free(res.label);
+		nfs4_label_free(res.dir_label);
 	}
+#endif
 
 	return status;
 }
@@ -2771,7 +2981,9 @@ struct nfs4_createdata {
 	struct nfs4_create_res res;
 	struct nfs_fh fh;
 	struct nfs_fattr fattr;
+	struct nfs4_label *label;
 	struct nfs_fattr dir_fattr;
+	struct nfs4_label *dir_label;
 };
 
 static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
@@ -2783,6 +2995,16 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
 	if (data != NULL) {
 		struct nfs_server *server = NFS_SERVER(dir);
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+		if (server->caps & NFS_CAP_SECURITY_LABEL) {
+			data->label = nfs4_label_alloc(GFP_KERNEL);
+			if (data->label == NULL)
+				goto out_free;
+			data->dir_label = nfs4_label_alloc(GFP_KERNEL);
+			if (data->dir_label == NULL)
+				goto out_free;
+		}
+#endif
 		data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE];
 		data->msg.rpc_argp = &data->arg;
 		data->msg.rpc_resp = &data->res;
@@ -2795,11 +3017,17 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
 		data->res.server = server;
 		data->res.fh = &data->fh;
 		data->res.fattr = &data->fattr;
+		data->res.label = data->label;
 		data->res.dir_fattr = &data->dir_fattr;
+		data->res.dir_label = data->dir_label;
 		nfs_fattr_init(data->res.fattr);
 		nfs_fattr_init(data->res.dir_fattr);
 	}
 	return data;
+out_free:
+	kfree(data);
+	return NULL;
+
 }
 
 static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
@@ -2808,19 +3036,26 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_
 				    &data->arg, &data->res, 1);
 	if (status == 0) {
 		update_changeattr(dir, &data->res.dir_cinfo);
-		nfs_post_op_update_inode(dir, data->res.dir_fattr);
-		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
+		nfs_post_op_update_inode(dir, data->res.dir_fattr, data->res.dir_label);
+		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label);
 	}
 	return status;
 }
 
 static void nfs4_free_createdata(struct nfs4_createdata *data)
 {
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (data->arg.server->caps & NFS_CAP_SECURITY_LABEL) {
+		nfs4_label_free(data->label);
+		nfs4_label_free(data->dir_label);
+	}
+#endif
 	kfree(data);
 }
 
 static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
-		struct page *page, unsigned int len, struct iattr *sattr)
+		struct page *page, unsigned int len, struct iattr *sattr,
+		struct nfs4_label *label)
 {
 	struct nfs4_createdata *data;
 	int status = -ENAMETOOLONG;
@@ -2836,6 +3071,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
 	data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK];
 	data->arg.u.symlink.pages = &page;
 	data->arg.u.symlink.len = len;
+	data->arg.label = label;
 	
 	status = nfs4_do_create(dir, dentry, data);
 
@@ -2848,18 +3084,33 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
 		struct page *page, unsigned int len, struct iattr *sattr)
 {
 	struct nfs4_exception exception = { };
+	struct nfs4_label l, *label = NULL;
 	int err;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		err = security_dentry_init_security(dentry,
+				sattr->ia_mode, &l.label, &l.len);
+		if (err == 0)
+			label = &l;
+	}
+#endif
+
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
 				_nfs4_proc_symlink(dir, dentry, page,
-							len, sattr),
+							len, sattr, label),
 				&exception);
 	} while (exception.retry);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label)
+		security_release_secctx(l.label, l.len);
+#endif
 	return err;
 }
 
 static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
-		struct iattr *sattr)
+		struct iattr *sattr, struct nfs4_label *label)
 {
 	struct nfs4_createdata *data;
 	int status = -ENOMEM;
@@ -2868,6 +3119,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
 	if (data == NULL)
 		goto out;
 
+	data->arg.label = label;
 	status = nfs4_do_create(dir, dentry, data);
 
 	nfs4_free_createdata(data);
@@ -2879,12 +3131,27 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
 		struct iattr *sattr)
 {
 	struct nfs4_exception exception = { };
+	struct nfs4_label l, *label = NULL;
 	int err;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		err = security_dentry_init_security(dentry,
+				sattr->ia_mode, &l.label, &l.len);
+		if (err == 0)
+			label = &l;
+	}
+#endif
+
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
-				_nfs4_proc_mkdir(dir, dentry, sattr),
+				_nfs4_proc_mkdir(dir, dentry, sattr, label),
 				&exception);
 	} while (exception.retry);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label)
+		security_release_secctx(l.label, l.len);
+#endif
 	return err;
 }
 
@@ -2897,7 +3164,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 		.pages = &page,
 		.pgbase = 0,
 		.count = count,
-		.bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
+		.bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask_nl,
 	};
 	struct nfs4_readdir_res res;
 	struct rpc_message msg = {
@@ -2939,7 +3206,7 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 }
 
 static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
-		struct iattr *sattr, dev_t rdev)
+		struct iattr *sattr, struct nfs4_label *label, dev_t rdev)
 {
 	struct nfs4_createdata *data;
 	int mode = sattr->ia_mode;
@@ -2964,7 +3231,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
 		data->arg.u.device.specdata1 = MAJOR(rdev);
 		data->arg.u.device.specdata2 = MINOR(rdev);
 	}
-	
+	data->arg.label = label;
 	status = nfs4_do_create(dir, dentry, data);
 
 	nfs4_free_createdata(data);
@@ -2976,12 +3243,27 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
 		struct iattr *sattr, dev_t rdev)
 {
 	struct nfs4_exception exception = { };
+	struct nfs4_label l, *label = NULL;
 	int err;
+
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+		err = security_dentry_init_security(dentry,
+				sattr->ia_mode, &l.label, &l.len);
+		if (err == 0)
+			label = &l;
+	}
+#endif
+
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
-				_nfs4_proc_mknod(dir, dentry, sattr, rdev),
+				_nfs4_proc_mknod(dir, dentry, sattr, label, rdev),
 				&exception);
 	} while (exception.retry);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label)
+		security_release_secctx(l.label, l.len);
+#endif
 	return err;
 }
 
@@ -3142,7 +3424,11 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag
 {
 	struct nfs_server *server = NFS_SERVER(data->inode);
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	data->args.bitmask = server->cache_consistency_bitmask_nl;
+#else
 	data->args.bitmask = server->cache_consistency_bitmask;
+#endif
 	data->res.server = server;
 	data->timestamp   = jiffies;
 
@@ -3159,7 +3445,7 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
 		nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
 		return -EAGAIN;
 	}
-	nfs_refresh_inode(inode, data->res.fattr);
+	nfs_refresh_inode(inode, data->res.fattr, NULL);
 	return 0;
 }
 
@@ -3167,7 +3453,11 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_messa
 {
 	struct nfs_server *server = NFS_SERVER(data->inode);
 	
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	data->args.bitmask = server->cache_consistency_bitmask_nl;
+#else
 	data->args.bitmask = server->cache_consistency_bitmask;
+#endif
 	data->res.server = server;
 	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT];
 }
@@ -3514,6 +3804,169 @@ do_state_recovery:
 	return -EAGAIN;
 }
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+static int _nfs4_get_security_label(struct inode *inode, void *buf, size_t buflen)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs_fattr fattr;
+	struct nfs4_label label;
+	u32 bitmask[2] = { 0, FATTR4_WORD1_SECURITY_LABEL };
+	struct nfs4_getattr_arg args = {
+		.fh		= NFS_FH(inode),
+		.bitmask	= bitmask,
+	};
+	struct nfs4_getattr_res res = {
+		.fattr		= &fattr,
+		.label		= &label,
+		.server		= server,
+	};
+	struct rpc_message msg = {
+		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_GETATTR],
+		.rpc_argp	= &args,
+		.rpc_resp	= &res,
+	};
+	int ret;
+
+	label.label = buf;
+	label.len = buflen;
+	nfs_fattr_init(&fattr);
+
+	ret = rpc_call_sync(server->client, &msg, 0);
+	if (ret)
+		return ret;
+	if (!(fattr.valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL))
+		return -ENOENT;
+	if (buflen < label.len)
+		return -ERANGE;
+	return 0;
+}
+
+static int nfs4_get_security_label(struct inode *inode, void *buf, size_t buflen)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL))
+		return -EOPNOTSUPP;
+
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(inode),
+				_nfs4_get_security_label(inode, buf, buflen),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_do_set_security_label(struct inode *inode,
+				      struct nfs4_label *ilabel,
+				      struct nfs_fattr *fattr,
+				      struct nfs4_label *olabel,
+				      struct nfs4_state *state)
+{
+
+	struct iattr sattr;
+	struct nfs_server *server = NFS_SERVER(inode);
+	const u32 bitmask[2] = { 0, FATTR4_WORD1_SECURITY_LABEL };
+	struct nfs_setattrargs args = {
+		.fh             = NFS_FH(inode),
+		.iap            = &sattr,
+		.server		= server,
+		.bitmask	= bitmask,
+		.label		= ilabel,
+	};
+	struct nfs_setattrres res = {
+		.fattr		= fattr,
+		.label		= olabel,
+		.server		= server,
+	};
+	struct rpc_message msg = {
+		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
+		.rpc_argp       = &args,
+		.rpc_resp       = &res,
+	};
+	unsigned long timestamp = jiffies;
+	int status;
+
+	memset(&sattr, 0, sizeof(struct iattr));
+
+	if (nfs4_copy_delegation_stateid(&args.stateid, inode)) {
+		/* Use that stateid */
+	} else if (state != NULL) {
+		msg.rpc_cred = state->owner->so_cred;
+		nfs4_copy_stateid(&args.stateid, state, current->files);
+	} else
+		memcpy(&args.stateid, &zero_stateid, sizeof(args.stateid));
+
+	status = rpc_call_sync(server->client, &msg, 0);
+	if (status == 0 && state != NULL)
+		renew_lease(server, timestamp);
+	return status;
+}
+
+static int nfs4_do_set_security_label(struct inode *inode,
+				     struct nfs4_label *ilabel,
+				     struct nfs_fattr *fattr,
+				     struct nfs4_label *olabel,
+				     struct nfs4_state *state)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(inode),
+			_nfs4_do_set_security_label(inode, ilabel, fattr, olabel, state),
+			&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int
+nfs4_set_security_label(struct dentry *dentry, const void *buf, size_t buflen)
+{
+	struct nfs4_label ilabel, *olabel = NULL;
+	struct nfs_fattr fattr;
+	struct rpc_cred *cred;
+	struct nfs_open_context *ctx;
+	struct nfs4_state *state = NULL;
+	struct inode *inode = dentry->d_inode;
+	int status;
+
+	if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL))
+		return -EOPNOTSUPP;
+
+	nfs_fattr_init(&fattr);
+
+	ilabel.label = (char *)buf;
+	ilabel.len = buflen;
+
+	cred = rpc_lookup_cred();
+	if (IS_ERR(cred))
+		return PTR_ERR(cred);
+
+	olabel = nfs4_label_alloc(GFP_KERNEL);
+	if (olabel == NULL) {
+		status = -ENOMEM;
+		goto out;
+	}
+
+	/* Search for an existing open(O_WRITE) file */
+	ctx = nfs_find_open_context(inode, cred, FMODE_WRITE);
+	if (ctx != NULL)
+		state = ctx->state;
+
+	status = nfs4_do_set_security_label(inode, &ilabel, &fattr, olabel, state);
+	if (status == 0)
+		nfs_setsecurity(inode, &fattr, olabel);
+	if (ctx != NULL)
+		put_nfs_open_context(ctx);
+	nfs4_label_free(olabel);
+out:
+	put_rpccred(cred);
+	return status;
+}
+#endif	/* CONFIG_NFS_V4_SECURITY_LABEL */
+
+
 static int
 nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state)
 {
@@ -3698,7 +4151,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
 		return -ENOMEM;
 	data->args.fhandle = &data->fh;
 	data->args.stateid = &data->stateid;
-	data->args.bitmask = server->attr_bitmask;
+	data->args.bitmask = server->attr_bitmask_nl;
 	nfs_copy_fh(&data->fh, NFS_FH(inode));
 	memcpy(&data->stateid, stateid, sizeof(data->stateid));
 	data->res.fattr = &data->fattr;
@@ -3722,7 +4175,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
 	status = data->rpc_status;
 	if (status != 0)
 		goto out;
-	nfs_refresh_inode(inode, &data->fattr);
+	nfs_refresh_inode(inode, &data->fattr, NULL);
 out:
 	rpc_put_task(task);
 	return status;
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 38f3b58..61e0b47 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -95,9 +95,14 @@ static int nfs4_stat_to_errno(int);
 #define nfs4_path_maxsz		(1 + ((3 + NFS4_MAXPATHLEN) >> 2))
 #define nfs4_owner_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
 #define nfs4_group_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+#define	nfs4_label_maxsz	(4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN))
+#else
+#define	nfs4_label_maxsz	0
+#endif
 /* This is based on getfattr, which uses the most attributes: */
 #define nfs4_fattr_value_maxsz	(1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
-				3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz))
+				3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz + nfs4_label_maxsz))
 #define nfs4_fattr_maxsz	(nfs4_fattr_bitmap_maxsz + \
 				nfs4_fattr_value_maxsz)
 #define decode_getattr_maxsz    (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
@@ -105,6 +110,7 @@ static int nfs4_stat_to_errno(int);
 				 1 + 2 + 1 + \
 				nfs4_owner_maxsz + \
 				nfs4_group_maxsz + \
+				nfs4_label_maxsz + \
 				4 + 4)
 #define encode_savefh_maxsz     (op_encode_hdr_maxsz)
 #define decode_savefh_maxsz     (op_decode_hdr_maxsz)
@@ -775,7 +781,7 @@ static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *ve
 	xdr_encode_opaque_fixed(p, verf->data, NFS4_VERIFIER_SIZE);
 }
 
-static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server)
+static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs4_label *label, const struct nfs_server *server)
 {
 	char owner_name[IDMAP_NAMESZ];
 	char owner_group[IDMAP_NAMESZ];
@@ -824,6 +830,10 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
 		}
 		len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
 	}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label)
+		len += 4 + 4 + (XDR_QUADLEN(label->len) << 2);
+#endif
 	if (iap->ia_valid & ATTR_ATIME_SET)
 		len += 16;
 	else if (iap->ia_valid & ATTR_ATIME)
@@ -880,6 +890,14 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
 		bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
 		*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
 	}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (label) {
+		bmval1 |= FATTR4_WORD1_SECURITY_LABEL;
+		*p++ = cpu_to_be32(label->lfs);
+		*p++ = cpu_to_be32(label->len);
+		p = xdr_encode_opaque_fixed(p, label->label, label->len);
+	}
+#endif
 
 	/*
 	 * Now we backfill the bitmap and the attribute buffer length.
@@ -961,7 +979,7 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *
 	hdr->nops++;
 	hdr->replen += decode_create_maxsz;
 
-	encode_attrs(xdr, create->attrs, create->server);
+	encode_attrs(xdr, create->attrs, create->label, create->server);
 }
 
 static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr)
@@ -1168,21 +1186,21 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op
 	switch(arg->open_flags & O_EXCL) {
 	case 0:
 		*p = cpu_to_be32(NFS4_CREATE_UNCHECKED);
-		encode_attrs(xdr, arg->u.attrs, arg->server);
+		encode_attrs(xdr, arg->u.attrs, arg->label, arg->server);
 		break;
 	default:
 		clp = arg->server->nfs_client;
 		if (clp->cl_minorversion > 0) {
 			if (nfs4_has_persistent_session(clp)) {
 				*p = cpu_to_be32(NFS4_CREATE_GUARDED);
-				encode_attrs(xdr, arg->u.attrs, arg->server);
+				encode_attrs(xdr, arg->u.attrs,arg->label,  arg->server);
 			} else {
 				struct iattr dummy;
 
 				*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
 				encode_nfs4_verifier(xdr, &arg->u.verifier);
 				dummy.ia_valid = 0;
-				encode_attrs(xdr, &dummy, arg->server);
+				encode_attrs(xdr, &dummy, arg->label, arg->server);
 			}
 		} else {
 			*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
@@ -1482,7 +1500,7 @@ static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs
 	xdr_encode_opaque_fixed(p, arg->stateid.data, NFS4_STATEID_SIZE);
 	hdr->nops++;
 	hdr->replen += decode_setattr_maxsz;
-	encode_attrs(xdr, arg->iap, server);
+	encode_attrs(xdr, arg->iap, arg->label, server);
 }
 
 static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr)
@@ -3495,6 +3513,58 @@ static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, str
 	return status;
 }
 
+static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_label *label)
+{
+	uint32_t lfs;
+	__u32 len;
+	__be32 *p;
+	int status = 0;
+
+	if (unlikely(bitmap[1] & (FATTR4_WORD1_SECURITY_LABEL - 1U)))
+		return -EIO;
+	if (likely(bitmap[1] & FATTR4_WORD1_SECURITY_LABEL)) {
+		p = xdr_inline_decode(xdr, 4);
+		if (unlikely(!p))
+			goto out_overflow;
+		lfs = be32_to_cpup(p++);
+		p = xdr_inline_decode(xdr, 4);
+		if (unlikely(!p))
+			goto out_overflow;
+		len = be32_to_cpup(p++);
+		p = xdr_inline_decode(xdr, len);
+		if (unlikely(!p))
+			goto out_overflow;
+		if (len < XDR_MAX_NETOBJ) {
+			if (label) {
+				if (label->len < len) {
+					printk(KERN_ERR
+						"%s(): label->len %d < len %d\n",
+						__func__, label->len, len);
+				} else {
+					memcpy(label->label, p, len);
+					label->len = len;
+					label->lfs = lfs;
+					status = NFS_ATTR_FATTR_V4_SECURITY_LABEL;
+				}
+			} else {
+				printk("%s(): NULL label.\n", __func__);
+				dump_stack();
+			}
+			bitmap[1] &= ~FATTR4_WORD1_SECURITY_LABEL;
+		} else
+			printk(KERN_WARNING "%s: label too long (%u)!\n",
+					__FUNCTION__, len);
+	}
+	if(label && label->label)
+		dprintk("%s: label=%s, len=%d\n", __func__,
+				 label->label, label->len);
+	return status;
+
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+	return -EIO;
+}
+
 static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen)
 {
 	unsigned int attrwords = XDR_QUADLEN(attrlen);
@@ -3701,7 +3771,8 @@ xdr_error:
 }
 
 static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
-		const struct nfs_server *server, int may_sleep)
+		struct nfs4_label *label, const struct nfs_server *server,
+		int may_sleep)
 {
 	__be32 *savep;
 	uint32_t attrlen,
@@ -3817,6 +3888,10 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
 		fattr->fileid = fileid;
 		fattr->valid |= status;
 	}
+	status = decode_attr_security_label(xdr, bitmap, label);
+	if (status < 0)
+		goto xdr_error;
+	fattr->valid |= status;
 
 	status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
@@ -4708,7 +4783,7 @@ static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, __be32 *p, struct
 	status = decode_open_downgrade(&xdr, res);
 	if (status != 0)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4736,7 +4811,7 @@ static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_ac
 	status = decode_access(&xdr, res);
 	if (status != 0)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4764,7 +4839,7 @@ static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lo
 		goto out;
 	if ((status = decode_getfh(&xdr, res->fh)) != 0)
 		goto out;
-	status = decode_getfattr(&xdr, res->fattr, res->server
+	status = decode_getfattr(&xdr, res->fattr, res->label, res->server
 			,!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4789,7 +4864,7 @@ static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, __be32 *p, struct nf
 	if ((status = decode_putrootfh(&xdr)) != 0)
 		goto out;
 	if ((status = decode_getfh(&xdr, res->fh)) == 0)
-		status = decode_getfattr(&xdr, res->fattr, res->server,
+		status = decode_getfattr(&xdr, res->fattr, res->label, res->server,
 				!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4815,7 +4890,7 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs_rem
 		goto out;
 	if ((status = decode_remove(&xdr, &res->cinfo)) != 0)
 		goto out;
-	decode_getfattr(&xdr, &res->dir_attr, res->server,
+	decode_getfattr(&xdr, &res->dir_attr, res->dir_label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4846,12 +4921,12 @@ static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_re
 	if ((status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo)) != 0)
 		goto out;
 	/* Current FH is target directory */
-	if (decode_getfattr(&xdr, res->new_fattr, res->server,
+	if (decode_getfattr(&xdr, res->new_fattr, res->new_label, res->server,
 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
 		goto out;
 	if ((status = decode_restorefh(&xdr)) != 0)
 		goto out;
-	decode_getfattr(&xdr, res->old_fattr, res->server,
+	decode_getfattr(&xdr, res->old_fattr, res->old_label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4885,12 +4960,12 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_link
 	 * Note order: OP_LINK leaves the directory as the current
 	 *             filehandle.
 	 */
-	if (decode_getfattr(&xdr, res->dir_attr, res->server,
+	if (decode_getfattr(&xdr, res->dir_attr, res->dir_label, res->server,
 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
 		goto out;
 	if ((status = decode_restorefh(&xdr)) != 0)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4920,12 +4995,12 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_cr
 		goto out;
 	if ((status = decode_getfh(&xdr, res->fh)) != 0)
 		goto out;
-	if (decode_getfattr(&xdr, res->fattr, res->server,
+	if (decode_getfattr(&xdr, res->fattr, res->label, res->server,
 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
 		goto out;
 	if ((status = decode_restorefh(&xdr)) != 0)
 		goto out;
-	decode_getfattr(&xdr, res->dir_fattr, res->server,
+	decode_getfattr(&xdr, res->dir_fattr, res->dir_label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -4958,7 +5033,7 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_g
 	status = decode_putfh(&xdr);
 	if (status)
 		goto out;
-	status = decode_getfattr(&xdr, res->fattr, res->server,
+	status = decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5066,7 +5141,7 @@ static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p, struct nfs_clos
 	 * 	an ESTALE error. Shouldn't be a problem,
 	 * 	though, since fattr->valid will remain unset.
 	 */
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5099,12 +5174,12 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openr
 		goto out;
 	if (decode_getfh(&xdr, &res->fh) != 0)
 		goto out;
-	if (decode_getfattr(&xdr, res->f_attr, res->server,
+	if (decode_getfattr(&xdr, res->f_attr, res->f_label, res->server,
 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
 		goto out;
 	if (decode_restorefh(&xdr) != 0)
 		goto out;
-	decode_getfattr(&xdr, res->dir_attr, res->server,
+	decode_getfattr(&xdr, res->dir_attr, res->dir_label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5153,7 +5228,7 @@ static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p, struct nf
 	status = decode_open(&xdr, res);
 	if (status)
 		goto out;
-	decode_getfattr(&xdr, res->f_attr, res->server,
+	decode_getfattr(&xdr, res->f_attr, NULL, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5181,7 +5256,7 @@ static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_se
 	status = decode_setattr(&xdr);
 	if (status)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5356,7 +5431,7 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writ
 	status = decode_write(&xdr, res);
 	if (status)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, NULL, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 	if (!status)
 		status = res->count;
@@ -5386,7 +5461,7 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_wri
 	status = decode_commit(&xdr, res);
 	if (status)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, NULL, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5553,7 +5628,7 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nf
 	status = decode_delegreturn(&xdr);
 	if (status != 0)
 		goto out;
-	decode_getfattr(&xdr, res->fattr, res->server,
+	decode_getfattr(&xdr, res->fattr, res->label, res->server,
 			!RPC_IS_ASYNC(rqstp->rq_task));
 out:
 	return status;
@@ -5581,7 +5656,7 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p,
 	if ((status = decode_lookup(&xdr)) != 0)
 		goto out;
 	xdr_enter_page(&xdr, PAGE_SIZE);
-	status = decode_getfattr(&xdr, &res->fs_locations->fattr,
+	status = decode_getfattr(&xdr, &res->fs_locations->fattr, NULL,
 				 res->fs_locations->server,
 				 !RPC_IS_ASYNC(req->rq_task));
 out:
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 0288be8..acdc92d 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -130,7 +130,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  */
 static int
 nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
-		struct nfs_fattr *fattr)
+		struct nfs_fattr *fattr, struct nfs4_label *label)
 {
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs_procedures[NFSPROC_GETATTR],
@@ -178,7 +178,8 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
 static int
 nfs_proc_lookup(struct inode *dir, struct qstr *name,
-		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+		struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+		struct nfs4_label *label)
 {
 	struct nfs_diropargs	arg = {
 		.fh		= NFS_FH(dir),
@@ -252,7 +253,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	nfs_mark_for_revalidate(dir);
 	if (status == 0)
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, NULL);
 	dprintk("NFS reply create: %d\n", status);
 	return status;
 }
@@ -304,7 +305,7 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 		status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	}
 	if (status == 0)
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, NULL);
 	dprintk("NFS reply mknod: %d\n", status);
 	return status;
 }
@@ -430,7 +431,7 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
 	if (status == 0) {
 		nfs_fattr_init(&fattr);
 		fhandle.size = 0;
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, NULL);
 	}
 
 	dprintk("NFS reply symlink: %d\n", status);
@@ -464,7 +465,7 @@ nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	nfs_mark_for_revalidate(dir);
 	if (status == 0)
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, NULL);
 	dprintk("NFS reply mkdir: %d\n", status);
 	return status;
 }
@@ -599,7 +600,7 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
 
 	nfs_invalidate_atime(data->inode);
 	if (task->tk_status >= 0) {
-		nfs_refresh_inode(data->inode, data->res.fattr);
+		nfs_refresh_inode(data->inode, data->res.fattr, data->res.label);
 		/* Emulate the eof flag, which isn't normally needed in NFSv2
 		 * as it is guaranteed to always return the file attributes
 		 */
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 054bcaa..8135838 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2551,6 +2551,7 @@ static int nfs4_remote_get_sb(struct file_system_type *fs_type,
 	struct nfs_fh *mntfh;
 	struct dentry *mntroot;
 	int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
+	unsigned long kflags = 0, kflags_out = 0;
 	struct nfs_sb_mountdata sb_mntdata = {
 		.mntflags = flags,
 	};
@@ -2602,10 +2603,20 @@ static int nfs4_remote_get_sb(struct file_system_type *fs_type,
 		goto error_splat_super;
 	}
 
-	error = security_sb_set_mnt_opts(s, &data->lsm_opts, 0, NULL);
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL)
+		kflags |= SECURITY_LSM_NATIVE_LABELS;
+#endif
+
+	error = security_sb_set_mnt_opts(s, &data->lsm_opts, kflags, &kflags_out);
 	if (error)
 		goto error_splat_root;
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (server->caps & NFS_CAP_SECURITY_LABEL && !(kflags_out & SECURITY_LSM_NATIVE_LABELS))
+		server->caps &= ~NFS_CAP_SECURITY_LABEL;
+#endif
+
 	s->s_flags |= MS_ACTIVE;
 	mnt->mnt_sb = s;
 	mnt->mnt_root = mntroot;
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 2813b71..753294d 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -198,6 +198,7 @@ struct nfs_inode {
 #define NFS_INO_INVALID_ACL	0x0010		/* cached acls are invalid */
 #define NFS_INO_REVAL_PAGECACHE	0x0020		/* must revalidate pagecache */
 #define NFS_INO_REVAL_FORCED	0x0040		/* force revalidation ignoring a delegation */
+#define NFS_INO_INVALID_LABEL	0x0080		/* cached label is invalid */
 
 /*
  * Bit offsets in flags field
@@ -336,9 +337,9 @@ extern void nfs_zap_mapping(struct inode *inode, struct address_space *mapping);
 extern void nfs_zap_caches(struct inode *);
 extern void nfs_invalidate_atime(struct inode *);
 extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
-				struct nfs_fattr *);
-extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
-extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
+				struct nfs_fattr *, struct nfs4_label *);
+extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *, struct nfs4_label *);
+extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *);
 extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr);
 extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int nfs_permission(struct inode *, int);
@@ -350,6 +351,7 @@ extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
 extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
 extern int nfs_setattr(struct dentry *, struct iattr *);
 extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
+extern void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label);
 extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
 extern void put_nfs_open_context(struct nfs_open_context *ctx);
 extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
@@ -425,7 +427,7 @@ extern const struct file_operations nfs_dir_operations;
 extern const struct dentry_operations nfs_dentry_operations;
 
 extern void nfs_force_lookup_revalidate(struct inode *dir);
-extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr);
+extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr, struct nfs4_label *label);
 extern int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags);
 extern void nfs_access_zap_cache(struct inode *inode);
 
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index aa95a22..86895ee 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -140,11 +140,17 @@ struct nfs_server {
 	u32			attr_bitmask[2];/* V4 bitmask representing the set
 						   of attributes supported on this
 						   filesystem */
+	u32			attr_bitmask_nl[2]; /* V4 bitmask representing the set
+							of attributes supported on this
+							filesystem excluding the label
+							support bit. */
 	u32			cache_consistency_bitmask[2];
 						/* V4 bitmask representing the subset
 						   of change attribute, size, ctime
 						   and mtime attributes supported by
 						   the server */
+	u32			cache_consistency_bitmask_nl[2];
+						/* As above, excluding label. */
 	u32			acl_bitmask;	/* V4 bitmask representing the ACEs
 						   that are supported on this
 						   filesystem */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index dc505e4..bc87a58 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1034,11 +1034,12 @@ struct nfs_rpc_ops {
 			    struct qstr *, struct nfs_fh *,
 			    struct nfs_fattr *);
 	int	(*getattr) (struct nfs_server *, struct nfs_fh *,
-			    struct nfs_fattr *);
+			    struct nfs_fattr *, struct nfs4_label *);
 	int	(*setattr) (struct dentry *, struct nfs_fattr *,
 			    struct iattr *);
 	int	(*lookup)  (struct inode *, struct qstr *,
-			    struct nfs_fh *, struct nfs_fattr *);
+			    struct nfs_fh *, struct nfs_fattr *,
+			    struct nfs4_label *);
 	int	(*access)  (struct inode *, struct nfs_access_entry *);
 	int	(*readlink)(struct inode *, struct page *, unsigned int,
 			    unsigned int);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 01edf80..6c1e2fa 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2883,7 +2883,10 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
 		return;
 	}
 
+	isec->sclass = inode_mode_to_security_class(inode->i_mode);
 	isec->sid = newsid;
+	isec->initialized = 1;
+
 	return;
 }
 
@@ -2971,6 +2974,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
 	if (rc)
 		return rc;
 
+	isec->sclass = inode_mode_to_security_class(inode->i_mode);
 	isec->sid = newsid;
 	isec->initialized = 1;
 	return 0;
-- 
1.6.2.5


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 09/10] NFS: Extend NFS xattr handlers to accept the security namespace
  2010-07-07 14:31 ` David P. Quigley
@ 2010-07-07 14:31   ` David P. Quigley
  -1 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

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   |   48 +++++++++++++++++++++++++++++++++++++-----------
 security/security.c |    1 +
 2 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index e2b9010..7eac20b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4870,10 +4870,13 @@ 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)
+		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,
@@ -4885,22 +4888,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) + 1;
+	size_t len = 0, l;
+	char *p;
 
-	if (!nfs4_server_supports_acls(NFS_SERVER(dentry->d_inode)))
+	if (nfs4_server_supports_acls(NFS_SERVER(dentry->d_inode)))
+		len += strlen(XATTR_NAME_NFSV4_ACL) + 1;
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dentry->d_inode, NFS_CAP_SECURITY_LABEL))
+		len += security_inode_listsecurity(dentry->d_inode, NULL, 0);
+#endif
+	if (!len)
 		return 0;
 	if (buf && buflen < len)
 		return -ERANGE;
-	if (buf)
-		memcpy(buf, XATTR_NAME_NFSV4_ACL, len);
+	if (!buf)
+		return len;
+
+	p = buf;
+	if (nfs4_server_supports_acls(NFS_SERVER(dentry->d_inode))) {
+		l = strlen(XATTR_NAME_NFSV4_ACL) + 1;
+		memcpy(p, XATTR_NAME_NFSV4_ACL, l);
+		p += l;
+	}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dentry->d_inode, NFS_CAP_SECURITY_LABEL))
+		p += security_inode_listsecurity(dentry->d_inode, p,
+			buflen - (p - buf));
+#endif
 	return len;
 }
 
diff --git a/security/security.c b/security/security.c
index 2246b5a..1f88c4a 100644
--- a/security/security.c
+++ b/security/security.c
@@ -663,6 +663,7 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
 		return 0;
 	return security_ops->inode_listsecurity(inode, buffer, buffer_size);
 }
+EXPORT_SYMBOL(security_inode_listsecurity);
 
 void security_inode_getsecid(const struct inode *inode, u32 *secid)
 {
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 09/10] NFS: Extend NFS xattr handlers to accept the security namespace
@ 2010-07-07 14:31   ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

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   |   48 +++++++++++++++++++++++++++++++++++++-----------
 security/security.c |    1 +
 2 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index e2b9010..7eac20b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4870,10 +4870,13 @@ 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)
+		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,
@@ -4885,22 +4888,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) + 1;
+	size_t len = 0, l;
+	char *p;
 
-	if (!nfs4_server_supports_acls(NFS_SERVER(dentry->d_inode)))
+	if (nfs4_server_supports_acls(NFS_SERVER(dentry->d_inode)))
+		len += strlen(XATTR_NAME_NFSV4_ACL) + 1;
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dentry->d_inode, NFS_CAP_SECURITY_LABEL))
+		len += security_inode_listsecurity(dentry->d_inode, NULL, 0);
+#endif
+	if (!len)
 		return 0;
 	if (buf && buflen < len)
 		return -ERANGE;
-	if (buf)
-		memcpy(buf, XATTR_NAME_NFSV4_ACL, len);
+	if (!buf)
+		return len;
+
+	p = buf;
+	if (nfs4_server_supports_acls(NFS_SERVER(dentry->d_inode))) {
+		l = strlen(XATTR_NAME_NFSV4_ACL) + 1;
+		memcpy(p, XATTR_NAME_NFSV4_ACL, l);
+		p += l;
+	}
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+	if (nfs_server_capable(dentry->d_inode, NFS_CAP_SECURITY_LABEL))
+		p += security_inode_listsecurity(dentry->d_inode, p,
+			buflen - (p - buf));
+#endif
 	return len;
 }
 
diff --git a/security/security.c b/security/security.c
index 2246b5a..1f88c4a 100644
--- a/security/security.c
+++ b/security/security.c
@@ -663,6 +663,7 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
 		return 0;
 	return security_ops->inode_listsecurity(inode, buffer, buffer_size);
 }
+EXPORT_SYMBOL(security_inode_listsecurity);
 
 void security_inode_getsecid(const struct inode *inode, u32 *secid)
 {
-- 
1.6.2.5


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 10/10] NFSD: Server implementation of MAC Labeling
  2010-07-07 14:31 ` David P. Quigley
@ 2010-07-07 14:31   ` David P. Quigley
  -1 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

This patch adds the ability to encode and decode file labels on the server for
the purpose of sending them to the client and also to process label change
requests from the client.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/nfsd/export.c   |    3 +
 fs/nfsd/nfs4proc.c |   33 ++++++++++++++
 fs/nfsd/nfs4xdr.c  |  125 +++++++++++++++++++++++++++++++++++++++++++++++++---
 fs/nfsd/vfs.c      |   30 ++++++++++++
 fs/nfsd/vfs.h      |    2 +
 5 files changed, 187 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 872a5ef..39cd1f7 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -1422,6 +1422,9 @@ static struct flags {
 	{ NFSEXP_ALLSQUASH, {"all_squash", ""}},
 	{ NFSEXP_ASYNC, {"async", "sync"}},
 	{ NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}},
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+	{ NFSEXP_SECURITY_LABEL, {"security_label", ""}},
+#endif
 	{ NFSEXP_NOHIDE, {"nohide", ""}},
 	{ NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
 	{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 2ab9e85..8ce1704 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -39,6 +39,10 @@
 #include "xdr4.h"
 #include "vfs.h"
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+#include <linux/security.h>
+#endif
+
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
 static u32 nfsd_attrmask[] = {
@@ -204,6 +208,18 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
 					(u32 *)open->op_verf.data,
 					&open->op_truncate, &created);
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+		if (!status && open->op_label != NULL) {
+			struct inode *inode = resfh.fh_dentry->d_inode;
+
+			mutex_lock(&inode->i_mutex);
+			/* Is it appropriate to just kick back an error? */
+			status = security_inode_setsecctx(resfh.fh_dentry,
+					open->op_label->label, open->op_label->len);
+			mutex_unlock(&inode->i_mutex);
+		}
+#endif
+
 		/*
 		 * Following rfc 3530 14.2.16, use the returned bitmask
 		 * to indicate which attributes we used to store the
@@ -553,6 +569,18 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		status = nfserr_badtype;
 	}
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+	if (!status && create->cr_label != NULL) {
+		struct inode *inode = resfh.fh_dentry->d_inode;
+
+		mutex_lock(&inode->i_mutex);
+		/* Is it appropriate to just kick back an error? */
+		status = security_inode_setsecctx(resfh.fh_dentry,
+				create->cr_label->label, create->cr_label->len);
+		mutex_unlock(&inode->i_mutex);
+	}
+#endif
+
 	if (status)
 		goto out;
 
@@ -803,6 +831,11 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 					    setattr->sa_acl);
 	if (status)
 		goto out;
+	if (setattr->sa_label != NULL)
+		status = nfsd4_set_nfs4_label(rqstp, &cstate->current_fh,
+					    setattr->sa_label);
+	if (status)
+		goto out;
 	status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
 				0, (time_t)0);
 out:
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 34ccf81..7e16b41 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -51,6 +51,10 @@
 #include "xdr4.h"
 #include "vfs.h"
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+#include <linux/security.h>
+#endif
+
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
 
 /*
@@ -239,7 +243,8 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
 
 static __be32
 nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
-		   struct iattr *iattr, struct nfs4_acl **acl)
+		   struct iattr *iattr, struct nfs4_acl **acl,
+		   struct nfs4_label **label)
 {
 	int expected_len, len = 0;
 	u32 dummy32;
@@ -383,6 +388,45 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 			goto xdr_error;
 		}
 	}
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+	if (bmval[1] & FATTR4_WORD1_SECURITY_LABEL) {
+		uint32_t lfs;
+
+		READ_BUF(4);
+		len += 4;
+		READ32(lfs);
+		READ_BUF(4);
+		len += 4;
+		READ32(dummy32);
+		READ_BUF(dummy32);
+		len += (XDR_QUADLEN(dummy32) << 2);
+		READMEM(buf, dummy32);
+
+		if (dummy32 > NFS4_MAXLABELLEN)
+			return nfserr_resource;
+
+		*label = kzalloc(sizeof(struct nfs4_label), GFP_KERNEL);
+		if (*label == NULL) {
+			host_err = -ENOMEM;
+			goto out_nfserr;
+		}
+
+		(*label)->label = kmalloc(dummy32 + 1, GFP_KERNEL);
+		if ((*label)->label == NULL) {
+			host_err = -ENOMEM;
+			kfree(*label);
+			goto out_nfserr;
+		}
+
+		(*label)->len = dummy32;
+		memcpy((*label)->label, buf, dummy32);
+		((char *)(*label)->label)[dummy32] = '\0';
+		(*label)->lfs = lfs;
+
+		defer_free(argp, kfree, (*label)->label);
+		defer_free(argp, kfree, *label);
+	}
+#endif
 	if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
 	    || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
 	    || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2)
@@ -481,7 +525,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
 		return status;
 
 	status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
-				    &create->cr_acl);
+				    &create->cr_acl, &create->cr_label);
 	if (status)
 		goto out;
 
@@ -644,7 +688,8 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 		case NFS4_CREATE_UNCHECKED:
 		case NFS4_CREATE_GUARDED:
 			status = nfsd4_decode_fattr(argp, open->op_bmval,
-				&open->op_iattr, &open->op_acl);
+				&open->op_iattr, &open->op_acl,
+				&open->op_label);
 			if (status)
 				goto out;
 			break;
@@ -658,7 +703,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 			READ_BUF(8);
 			COPYMEM(open->op_verf.data, 8);
 			status = nfsd4_decode_fattr(argp, open->op_bmval,
-				&open->op_iattr, &open->op_acl);
+				&open->op_iattr, &open->op_acl, &open->op_label);
 			if (status)
 				goto out;
 			break;
@@ -855,7 +900,7 @@ nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *seta
 	if (status)
 		return status;
 	return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
-				  &setattr->sa_acl);
+				  &setattr->sa_acl, &setattr->sa_label);
 }
 
 static __be32
@@ -918,7 +963,7 @@ nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify
 	 * nfsd4_proc_verify; however we still decode here just to return
 	 * correct error in case of bad xdr. */
 #if 0
-	status = nfsd4_decode_fattr(ve_bmval, &ve_iattr, &ve_acl);
+	status = nfsd4_decode_fattr(ve_bmval, &ve_iattr, &ve_acl, &ve_label);
 	if (status == nfserr_inval) {
 		status = nfserrno(status);
 		goto out;
@@ -1696,6 +1741,44 @@ nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
 	return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
 }
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+static inline __be32
+nfsd4_encode_security_label(struct svc_rqst *rqstp, struct dentry *dentry, __be32 **pp, int *buflen)
+{
+	void *context;
+	int err;
+	int len;
+	uint32_t lfs = 0;
+	__be32 *p = *pp;
+
+	err = 0;
+	(void)security_inode_getsecctx(dentry->d_inode, &context, &len);
+	if (len < 0)
+		return nfserrno(len);
+
+	if (*buflen < ((XDR_QUADLEN(len) << 2) + 4 +4)) {
+		err = nfserr_resource;
+		goto out;
+	}
+
+	/* XXX: A call to the translation code should be placed here
+	 * for now send 0  until we have that to indicate the null
+	 * translation */ 
+
+	if ((*buflen -= 4) < 0)
+                return nfserr_resource;
+	WRITE32(lfs);
+	p = xdr_encode_opaque(p, context, len);
+	*buflen -= (XDR_QUADLEN(len) << 2) + 4;
+	BUG_ON(*buflen < 0);
+	
+	*pp = p;
+out:
+	security_release_secctx(context, len);
+	return err;
+}
+#endif
+
 #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
 			      FATTR4_WORD0_RDATTR_ERROR)
 #define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
@@ -1791,6 +1874,18 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 				goto out_nfserr;
 		}
 	}
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+	if (bmval1 & FATTR4_WORD1_SECURITY_LABEL) {
+		/* XXX: This is not a good way to handle this. We need
+		 * a better way to determine if the system has labeling support
+		 * turned on here.
+		 */
+		if (/* XXX !selinux_enabled */ 0)
+			bmval1 &= ~FATTR4_WORD1_SECURITY_LABEL;
+	}
+#else
+	bmval1 &= ~FATTR4_WORD1_SECURITY_LABEL;
+#endif
 	if ((buflen -= 16) < 0)
 		goto out_resource;
 
@@ -1818,6 +1913,14 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 			goto out_resource;
 		if (!aclsupport)
 			word0 &= ~FATTR4_WORD0_ACL;
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+		if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
+			word1 |= FATTR4_WORD1_SECURITY_LABEL;
+		else
+			word1 &= ~FATTR4_WORD1_SECURITY_LABEL;
+#else
+		word1 &= ~FATTR4_WORD1_SECURITY_LABEL;
+#endif
 		if (!word2) {
 			WRITE32(2);
 			WRITE32(word0);
@@ -2136,6 +2239,16 @@ out_acl:
 		}
 		WRITE64(stat.ino);
 	}
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+	if (bmval1 & FATTR4_WORD1_SECURITY_LABEL) {
+		status = nfsd4_encode_security_label(rqstp, dentry,
+				&p, &buflen);
+		if (status == nfserr_resource)
+			goto out_resource;
+		if (status)
+			goto out;
+	}
+#endif
 	if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
 		WRITE32(3);
 		WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 6dd5f19..f08ed68 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -29,6 +29,7 @@
 #include <asm/uaccess.h>
 #include <linux/exportfs.h>
 #include <linux/writeback.h>
+#include <linux/security.h>
 
 #ifdef CONFIG_NFSD_V3
 #include "xdr3.h"
@@ -605,6 +606,35 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac
 	return error;
 }
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+__be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
+    struct nfs4_label *label)
+{
+	__be32 error;
+	int host_error;
+	struct dentry *dentry;
+
+	/* Get inode */
+	/* XXX: should we have a MAY_SSECCTX? */
+	error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, NFSD_MAY_SATTR);
+	if (error)
+		return error;
+
+	dentry = fhp->fh_dentry;
+
+	mutex_lock(&dentry->d_inode->i_mutex);
+	host_error = security_inode_setsecctx(dentry, label->label, label->len);
+	mutex_unlock(&dentry->d_inode->i_mutex);
+	return nfserrno(host_error);
+}
+#else
+__be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
+    struct nfs4_label *label)
+{
+	return -EOPNOTSUPP;
+}
+#endif
+
 #endif /* defined(CONFIG_NFS_V4) */
 
 #ifdef CONFIG_NFSD_V3
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index 4b1de0a..a20814f 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -47,6 +47,8 @@ int nfsd_mountpoint(struct dentry *, struct svc_export *);
 __be32          nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
                     struct nfs4_acl *);
 int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
+__be32          nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
+		    struct nfs4_label *);
 #endif /* CONFIG_NFSD_V4 */
 __be32		nfsd_create(struct svc_rqst *, struct svc_fh *,
 				char *name, int len, struct iattr *attrs,
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 10/10] NFSD: Server implementation of MAC Labeling
@ 2010-07-07 14:31   ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 14:31 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs, David P. Quigley, Matthew N. Dodd

This patch adds the ability to encode and decode file labels on the server for
the purpose of sending them to the client and also to process label change
requests from the client.

Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/nfsd/export.c   |    3 +
 fs/nfsd/nfs4proc.c |   33 ++++++++++++++
 fs/nfsd/nfs4xdr.c  |  125 +++++++++++++++++++++++++++++++++++++++++++++++++---
 fs/nfsd/vfs.c      |   30 ++++++++++++
 fs/nfsd/vfs.h      |    2 +
 5 files changed, 187 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 872a5ef..39cd1f7 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -1422,6 +1422,9 @@ static struct flags {
 	{ NFSEXP_ALLSQUASH, {"all_squash", ""}},
 	{ NFSEXP_ASYNC, {"async", "sync"}},
 	{ NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}},
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+	{ NFSEXP_SECURITY_LABEL, {"security_label", ""}},
+#endif
 	{ NFSEXP_NOHIDE, {"nohide", ""}},
 	{ NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
 	{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 2ab9e85..8ce1704 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -39,6 +39,10 @@
 #include "xdr4.h"
 #include "vfs.h"
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+#include <linux/security.h>
+#endif
+
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
 static u32 nfsd_attrmask[] = {
@@ -204,6 +208,18 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
 					(u32 *)open->op_verf.data,
 					&open->op_truncate, &created);
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+		if (!status && open->op_label != NULL) {
+			struct inode *inode = resfh.fh_dentry->d_inode;
+
+			mutex_lock(&inode->i_mutex);
+			/* Is it appropriate to just kick back an error? */
+			status = security_inode_setsecctx(resfh.fh_dentry,
+					open->op_label->label, open->op_label->len);
+			mutex_unlock(&inode->i_mutex);
+		}
+#endif
+
 		/*
 		 * Following rfc 3530 14.2.16, use the returned bitmask
 		 * to indicate which attributes we used to store the
@@ -553,6 +569,18 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		status = nfserr_badtype;
 	}
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+	if (!status && create->cr_label != NULL) {
+		struct inode *inode = resfh.fh_dentry->d_inode;
+
+		mutex_lock(&inode->i_mutex);
+		/* Is it appropriate to just kick back an error? */
+		status = security_inode_setsecctx(resfh.fh_dentry,
+				create->cr_label->label, create->cr_label->len);
+		mutex_unlock(&inode->i_mutex);
+	}
+#endif
+
 	if (status)
 		goto out;
 
@@ -803,6 +831,11 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 					    setattr->sa_acl);
 	if (status)
 		goto out;
+	if (setattr->sa_label != NULL)
+		status = nfsd4_set_nfs4_label(rqstp, &cstate->current_fh,
+					    setattr->sa_label);
+	if (status)
+		goto out;
 	status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
 				0, (time_t)0);
 out:
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 34ccf81..7e16b41 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -51,6 +51,10 @@
 #include "xdr4.h"
 #include "vfs.h"
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+#include <linux/security.h>
+#endif
+
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
 
 /*
@@ -239,7 +243,8 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
 
 static __be32
 nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
-		   struct iattr *iattr, struct nfs4_acl **acl)
+		   struct iattr *iattr, struct nfs4_acl **acl,
+		   struct nfs4_label **label)
 {
 	int expected_len, len = 0;
 	u32 dummy32;
@@ -383,6 +388,45 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 			goto xdr_error;
 		}
 	}
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+	if (bmval[1] & FATTR4_WORD1_SECURITY_LABEL) {
+		uint32_t lfs;
+
+		READ_BUF(4);
+		len += 4;
+		READ32(lfs);
+		READ_BUF(4);
+		len += 4;
+		READ32(dummy32);
+		READ_BUF(dummy32);
+		len += (XDR_QUADLEN(dummy32) << 2);
+		READMEM(buf, dummy32);
+
+		if (dummy32 > NFS4_MAXLABELLEN)
+			return nfserr_resource;
+
+		*label = kzalloc(sizeof(struct nfs4_label), GFP_KERNEL);
+		if (*label == NULL) {
+			host_err = -ENOMEM;
+			goto out_nfserr;
+		}
+
+		(*label)->label = kmalloc(dummy32 + 1, GFP_KERNEL);
+		if ((*label)->label == NULL) {
+			host_err = -ENOMEM;
+			kfree(*label);
+			goto out_nfserr;
+		}
+
+		(*label)->len = dummy32;
+		memcpy((*label)->label, buf, dummy32);
+		((char *)(*label)->label)[dummy32] = '\0';
+		(*label)->lfs = lfs;
+
+		defer_free(argp, kfree, (*label)->label);
+		defer_free(argp, kfree, *label);
+	}
+#endif
 	if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
 	    || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
 	    || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2)
@@ -481,7 +525,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
 		return status;
 
 	status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
-				    &create->cr_acl);
+				    &create->cr_acl, &create->cr_label);
 	if (status)
 		goto out;
 
@@ -644,7 +688,8 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 		case NFS4_CREATE_UNCHECKED:
 		case NFS4_CREATE_GUARDED:
 			status = nfsd4_decode_fattr(argp, open->op_bmval,
-				&open->op_iattr, &open->op_acl);
+				&open->op_iattr, &open->op_acl,
+				&open->op_label);
 			if (status)
 				goto out;
 			break;
@@ -658,7 +703,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 			READ_BUF(8);
 			COPYMEM(open->op_verf.data, 8);
 			status = nfsd4_decode_fattr(argp, open->op_bmval,
-				&open->op_iattr, &open->op_acl);
+				&open->op_iattr, &open->op_acl, &open->op_label);
 			if (status)
 				goto out;
 			break;
@@ -855,7 +900,7 @@ nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *seta
 	if (status)
 		return status;
 	return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
-				  &setattr->sa_acl);
+				  &setattr->sa_acl, &setattr->sa_label);
 }
 
 static __be32
@@ -918,7 +963,7 @@ nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify
 	 * nfsd4_proc_verify; however we still decode here just to return
 	 * correct error in case of bad xdr. */
 #if 0
-	status = nfsd4_decode_fattr(ve_bmval, &ve_iattr, &ve_acl);
+	status = nfsd4_decode_fattr(ve_bmval, &ve_iattr, &ve_acl, &ve_label);
 	if (status == nfserr_inval) {
 		status = nfserrno(status);
 		goto out;
@@ -1696,6 +1741,44 @@ nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
 	return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
 }
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+static inline __be32
+nfsd4_encode_security_label(struct svc_rqst *rqstp, struct dentry *dentry, __be32 **pp, int *buflen)
+{
+	void *context;
+	int err;
+	int len;
+	uint32_t lfs = 0;
+	__be32 *p = *pp;
+
+	err = 0;
+	(void)security_inode_getsecctx(dentry->d_inode, &context, &len);
+	if (len < 0)
+		return nfserrno(len);
+
+	if (*buflen < ((XDR_QUADLEN(len) << 2) + 4 +4)) {
+		err = nfserr_resource;
+		goto out;
+	}
+
+	/* XXX: A call to the translation code should be placed here
+	 * for now send 0  until we have that to indicate the null
+	 * translation */ 
+
+	if ((*buflen -= 4) < 0)
+                return nfserr_resource;
+	WRITE32(lfs);
+	p = xdr_encode_opaque(p, context, len);
+	*buflen -= (XDR_QUADLEN(len) << 2) + 4;
+	BUG_ON(*buflen < 0);
+	
+	*pp = p;
+out:
+	security_release_secctx(context, len);
+	return err;
+}
+#endif
+
 #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
 			      FATTR4_WORD0_RDATTR_ERROR)
 #define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
@@ -1791,6 +1874,18 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 				goto out_nfserr;
 		}
 	}
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+	if (bmval1 & FATTR4_WORD1_SECURITY_LABEL) {
+		/* XXX: This is not a good way to handle this. We need
+		 * a better way to determine if the system has labeling support
+		 * turned on here.
+		 */
+		if (/* XXX !selinux_enabled */ 0)
+			bmval1 &= ~FATTR4_WORD1_SECURITY_LABEL;
+	}
+#else
+	bmval1 &= ~FATTR4_WORD1_SECURITY_LABEL;
+#endif
 	if ((buflen -= 16) < 0)
 		goto out_resource;
 
@@ -1818,6 +1913,14 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 			goto out_resource;
 		if (!aclsupport)
 			word0 &= ~FATTR4_WORD0_ACL;
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+		if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
+			word1 |= FATTR4_WORD1_SECURITY_LABEL;
+		else
+			word1 &= ~FATTR4_WORD1_SECURITY_LABEL;
+#else
+		word1 &= ~FATTR4_WORD1_SECURITY_LABEL;
+#endif
 		if (!word2) {
 			WRITE32(2);
 			WRITE32(word0);
@@ -2136,6 +2239,16 @@ out_acl:
 		}
 		WRITE64(stat.ino);
 	}
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+	if (bmval1 & FATTR4_WORD1_SECURITY_LABEL) {
+		status = nfsd4_encode_security_label(rqstp, dentry,
+				&p, &buflen);
+		if (status == nfserr_resource)
+			goto out_resource;
+		if (status)
+			goto out;
+	}
+#endif
 	if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
 		WRITE32(3);
 		WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 6dd5f19..f08ed68 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -29,6 +29,7 @@
 #include <asm/uaccess.h>
 #include <linux/exportfs.h>
 #include <linux/writeback.h>
+#include <linux/security.h>
 
 #ifdef CONFIG_NFSD_V3
 #include "xdr3.h"
@@ -605,6 +606,35 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac
 	return error;
 }
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+__be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
+    struct nfs4_label *label)
+{
+	__be32 error;
+	int host_error;
+	struct dentry *dentry;
+
+	/* Get inode */
+	/* XXX: should we have a MAY_SSECCTX? */
+	error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, NFSD_MAY_SATTR);
+	if (error)
+		return error;
+
+	dentry = fhp->fh_dentry;
+
+	mutex_lock(&dentry->d_inode->i_mutex);
+	host_error = security_inode_setsecctx(dentry, label->label, label->len);
+	mutex_unlock(&dentry->d_inode->i_mutex);
+	return nfserrno(host_error);
+}
+#else
+__be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
+    struct nfs4_label *label)
+{
+	return -EOPNOTSUPP;
+}
+#endif
+
 #endif /* defined(CONFIG_NFS_V4) */
 
 #ifdef CONFIG_NFSD_V3
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index 4b1de0a..a20814f 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -47,6 +47,8 @@ int nfsd_mountpoint(struct dentry *, struct svc_export *);
 __be32          nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
                     struct nfs4_acl *);
 int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
+__be32          nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
+		    struct nfs4_label *);
 #endif /* CONFIG_NFSD_V4 */
 __be32		nfsd_create(struct svc_rqst *, struct svc_fh *,
 				char *name, int len, struct iattr *attrs,
-- 
1.6.2.5


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
  2010-07-07 14:31   ` David P. Quigley
  (?)
@ 2010-07-07 16:01   ` Chuck Lever
  2010-07-07 16:21       ` Casey Schaufler
  2010-07-07 16:22       ` David P. Quigley
  -1 siblings, 2 replies; 95+ messages in thread
From: Chuck Lever @ 2010-07-07 16:01 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

My comments below apply to the other NFS client patches as well.  This 
seemed like the right one to use for code examples.

On 07/ 7/10 10:31 AM, David P. Quigley wrote:
> 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>
> ---
>   fs/nfs/nfs4proc.c       |   26 ++++++++++++++++++++++++++
>   fs/nfsd/xdr4.h          |    3 +++
>   include/linux/nfs4.h    |    7 +++++++
>   include/linux/nfs_fs.h  |    7 +++++++
>   include/linux/nfs_xdr.h |   22 ++++++++++++++++++++++
>   5 files changed, 65 insertions(+), 0 deletions(-)
>
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 071fced..71bb8da 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -148,6 +148,32 @@ const u32 nfs4_fs_locations_bitmap[2] = {
>   	| FATTR4_WORD1_MOUNTED_ON_FILEID
>   };
>
> +#ifdef CONFIG_NFS_V4_SECURITY_LABEL
> +
> +struct nfs4_label * nfs4_label_alloc (gfp_t flags)

Style: have you run these patches through scripts/checkpatch.pl?  Kernel 
coding style likes "struct foo *function(args)", without the spaces.

> +{
> +	struct nfs4_label *label = NULL;
> +
> +	label = kzalloc(sizeof(struct nfs4_label) + NFS4_MAXLABELLEN, flags);
> +	if (label == NULL)
> +		return NULL;

Instead of NULL, you could return an ERR_PTR.  NULL could then be used 
to signal that labels aren't supported.  See below.

> +
> +	label->label = (void *)(label + 1);
> +	label->len = NFS4_MAXLABELLEN;
> +	/* 0 is the null format meaning that the data is not to be translated */
> + 	label->lfs = 0;
> +	return label;
> +}
> +
> +void nfs4_label_free (struct nfs4_label *label)
> +{
> +	if (label)
> +		kfree(label);

Style: kfree() already checks for a NULL pointer, so you shouldn't.  At 
one point recently, all such checks were removed from the kernel in 
favor of using the one already in kfree().

Also, you check the server capabilities before calling this function, 
nearly every time.  Is that really needed?  If there's a label data 
structure, it should be freed whether the server supports it or not.

That capabilities check is probably going to be more complex if you want 
to have NFSv3 label support as well.  Would it make sense to provide a 
function that can check for NFSv3 (eventually) or NFSv4 label support?

Or, fold such checks into your allocator?  Hiding the capabilities check 
here would allow easy expansion in the future to include other NFS 
versions, and cause less clutter in all callers.

> +	return;
> +}
> +
> +#endif

Style: Generally speaking, we like to keep "#ifdef CONFIG_BAR" noise 
down to a dull roar.  So, this is the right place to keep it, and the 
generic functions (like nfs_lookup() and nfs_readdir()) is generally not.

Usually we accomplish this by having functions like nfs4_label_free() 
always be available, but if CONFIG_NFS_V4_SECURITY_LABEL isn't set, the 
function call is a no-op.

> +
>   static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
>   		struct nfs4_readdir_arg *readdir)
>   {
> diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
> index efa3377..c217277 100644
> --- a/fs/nfsd/xdr4.h
> +++ b/fs/nfsd/xdr4.h
> @@ -108,6 +108,7 @@ struct nfsd4_create {
>   	struct iattr	cr_iattr;           /* request */
>   	struct nfsd4_change_info  cr_cinfo; /* response */
>   	struct nfs4_acl *cr_acl;
> +	struct nfs4_label *cr_label;
>   };
>   #define cr_linklen	u.link.namelen
>   #define cr_linkname	u.link.name
> @@ -235,6 +236,7 @@ struct nfsd4_open {
>   	int		op_truncate;        /* used during processing */
>   	struct nfs4_stateowner *op_stateowner; /* used during processing */
>   	struct nfs4_acl *op_acl;
> +	struct nfs4_label *op_label;
>   };
>   #define op_iattr	iattr
>   #define op_verf		verf
> @@ -316,6 +318,7 @@ struct nfsd4_setattr {
>   	u32		sa_bmval[3];        /* request */
>   	struct iattr	sa_iattr;           /* request */
>   	struct nfs4_acl *sa_acl;
> +	struct nfs4_label *sa_label;
>   };
>
>   struct nfsd4_setclientid {
> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
> index a2abd1a..c512a0c 100644
> --- a/include/linux/nfs4.h
> +++ b/include/linux/nfs4.h
> @@ -167,6 +167,13 @@ struct nfs4_acl {
>   	struct nfs4_ace	aces[0];
>   };
>
> +struct nfs4_label {
> +	void		*label;
> +	u32		len;
> +	uint32_t	lfs;
> +};

If we have support for NFS labels in NFSv3, would we also use struct 
nfs4_label?

It seems to me you want something more generic, just like nfs_fh or 
nfs_fattr, to represent these.  Over time, I'm guessing label support 
won't be tied to a specific NFS version.  And, you are passing these 
around in the generic NFS functions (for post-op updates and inode 
revalidation, and what not).

Can I recommend "struct nfs_seclabel" instead?  Then have 
nfs_seclabel_alloc() and nfs_seclabel_free().

Does it make sense to deduplicate these in the client's memory?  It 
seems to me that you could have hundreds or thousands that all contain 
the same label information.

> +
> +
>   typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
>   typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
>
> diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
> index 07ce460..2813b71 100644
> --- a/include/linux/nfs_fs.h
> +++ b/include/linux/nfs_fs.h
> @@ -454,6 +454,13 @@ extern int nfs_mountpoint_expiry_timeout;
>   extern void nfs_release_automount_timer(void);
>
>   /*
> + * linux/fs/nfs/nfs4proc.c
> + */
> +
> +struct nfs4_label *	nfs4_label_alloc (gfp_t flags);
> +void			nfs4_label_free (struct nfs4_label *);
> +
> +/*
>    * linux/fs/nfs/unlink.c
>    */
>   extern int  nfs_async_unlink(struct inode *dir, struct dentry *dentry);
> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> index 28cde54..dc505e4 100644
> --- a/include/linux/nfs_xdr.h
> +++ b/include/linux/nfs_xdr.h
> @@ -207,6 +207,7 @@ struct nfs_openargs {
>   	const struct nfs_server *server;	 /* Needed for ID mapping */
>   	const u32 *		bitmask;
>   	__u32			claim;
> +	const struct nfs4_label *label;
>   	struct nfs4_sequence_args	seq_args;
>   };
>
> @@ -216,7 +217,9 @@ struct nfs_openres {
>   	struct nfs4_change_info	cinfo;
>   	__u32                   rflags;
>   	struct nfs_fattr *      f_attr;
> +	struct nfs4_label *	f_label;
>   	struct nfs_fattr *      dir_attr;
> +	struct nfs4_label *	dir_label;
>   	struct nfs_seqid *	seqid;
>   	const struct nfs_server *server;
>   	fmode_t			delegation_type;
> @@ -256,6 +259,7 @@ struct nfs_closeargs {
>   struct nfs_closeres {
>   	nfs4_stateid            stateid;
>   	struct nfs_fattr *	fattr;
> +	struct nfs4_label *	label;
>   	struct nfs_seqid *	seqid;
>   	const struct nfs_server *server;
>   	struct nfs4_sequence_res	seq_res;
> @@ -324,6 +328,7 @@ struct nfs4_delegreturnargs {
>
>   struct nfs4_delegreturnres {
>   	struct nfs_fattr * fattr;
> +	struct nfs4_label * label;
>   	const struct nfs_server *server;
>   	struct nfs4_sequence_res	seq_res;
>   };
> @@ -343,6 +348,7 @@ struct nfs_readargs {
>
>   struct nfs_readres {
>   	struct nfs_fattr *	fattr;
> +	struct nfs4_label *	label;
>   	__u32			count;
>   	int                     eof;
>   	struct nfs4_sequence_res	seq_res;
> @@ -390,6 +396,7 @@ struct nfs_removeres {
>   	const struct nfs_server *server;
>   	struct nfs4_change_info	cinfo;
>   	struct nfs_fattr	dir_attr;
> +	struct nfs4_label	*dir_label;
>   	struct nfs4_sequence_res 	seq_res;
>   };
>
> @@ -405,6 +412,7 @@ struct nfs_entry {
>   	int			eof;
>   	struct nfs_fh *		fh;
>   	struct nfs_fattr *	fattr;
> +	struct nfs4_label *	label;
>   };
>
>   /*
> @@ -443,6 +451,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 nfs4_sequence_args 	seq_args;
>   };
>
> @@ -473,6 +482,7 @@ struct nfs_getaclres {
>
>   struct nfs_setattrres {
>   	struct nfs_fattr *              fattr;
> +	struct nfs4_label *		label;
>   	const struct nfs_server *	server;
>   	struct nfs4_sequence_res	seq_res;
>   };
> @@ -662,6 +672,7 @@ struct nfs4_accessargs {
>   struct nfs4_accessres {
>   	const struct nfs_server *	server;
>   	struct nfs_fattr *		fattr;
> +	struct nfs4_label *		label;
>   	u32				supported;
>   	u32				access;
>   	struct nfs4_sequence_res	seq_res;
> @@ -684,6 +695,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_sequence_args 	seq_args;
>   };
>
> @@ -691,8 +703,10 @@ struct nfs4_create_res {
>   	const struct nfs_server *	server;
>   	struct nfs_fh *			fh;
>   	struct nfs_fattr *		fattr;
> +	struct nfs4_label *		label;
>   	struct nfs4_change_info		dir_cinfo;
>   	struct nfs_fattr *		dir_fattr;
> +	struct nfs4_label *		dir_label;
>   	struct nfs4_sequence_res	seq_res;
>   };
>
> @@ -717,6 +731,7 @@ struct nfs4_getattr_res {
>   	const struct nfs_server *	server;
>   	struct nfs_fattr *		fattr;
>   	struct nfs4_sequence_res	seq_res;
> +	struct nfs4_label *		label;
>   };
>
>   struct nfs4_link_arg {
> @@ -730,8 +745,10 @@ struct nfs4_link_arg {
>   struct nfs4_link_res {
>   	const struct nfs_server *	server;
>   	struct nfs_fattr *		fattr;
> +	struct nfs4_label *		label;
>   	struct nfs4_change_info		cinfo;
>   	struct nfs_fattr *		dir_attr;
> +	struct nfs4_label *		dir_label;
>   	struct nfs4_sequence_res	seq_res;
>   };
>
> @@ -747,6 +764,7 @@ struct nfs4_lookup_res {
>   	const struct nfs_server *	server;
>   	struct nfs_fattr *		fattr;
>   	struct nfs_fh *			fh;
> +	struct nfs4_label *		label;
>   	struct nfs4_sequence_res	seq_res;
>   };
>
> @@ -800,6 +818,8 @@ struct nfs4_rename_arg {
>   	const struct nfs_fh *		new_dir;
>   	const struct qstr *		old_name;
>   	const struct qstr *		new_name;
> +	const struct nfs4_label *	old_label;
> +	const struct nfs4_label *	new_label;
>   	const u32 *			bitmask;
>   	struct nfs4_sequence_args	seq_args;
>   };
> @@ -808,8 +828,10 @@ struct nfs4_rename_res {
>   	const struct nfs_server *	server;
>   	struct nfs4_change_info		old_cinfo;
>   	struct nfs_fattr *		old_fattr;
> +	struct nfs4_label *		old_label;
>   	struct nfs4_change_info		new_cinfo;
>   	struct nfs_fattr *		new_fattr;
> +	struct nfs4_label *		new_label;
>   	struct nfs4_sequence_res	seq_res;
>   };
>


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
@ 2010-07-07 16:21       ` Casey Schaufler
  0 siblings, 0 replies; 95+ messages in thread
From: Casey Schaufler @ 2010-07-07 16:21 UTC (permalink / raw)
  To: Chuck Lever
  Cc: David P. Quigley, hch, viro, sds, matthew.dodd, trond.myklebust,
	bfields, linux-kernel, linux-fsdevel, linux-security-module,
	selinux, linux-nfs

Chuck Lever wrote:
> My comments below apply to the other NFS client patches as well.  This
> seemed like the right one to use for code examples.
>
> On 07/ 7/10 10:31 AM, David P. Quigley wrote:
>> 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>
>> ---
>>   fs/nfs/nfs4proc.c       |   26 ++++++++++++++++++++++++++
>>   fs/nfsd/xdr4.h          |    3 +++
>>   include/linux/nfs4.h    |    7 +++++++
>>   include/linux/nfs_fs.h  |    7 +++++++
>>   include/linux/nfs_xdr.h |   22 ++++++++++++++++++++++
>>   5 files changed, 65 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
>> index 071fced..71bb8da 100644
>> --- a/fs/nfs/nfs4proc.c
>> +++ b/fs/nfs/nfs4proc.c
>> @@ -148,6 +148,32 @@ const u32 nfs4_fs_locations_bitmap[2] = {
>>       | FATTR4_WORD1_MOUNTED_ON_FILEID
>>   };
>>
>> +#ifdef CONFIG_NFS_V4_SECURITY_LABEL
>> +
>> +struct nfs4_label * nfs4_label_alloc (gfp_t flags)
>
> Style: have you run these patches through scripts/checkpatch.pl? 
> Kernel coding style likes "struct foo *function(args)", without the
> spaces.
>
>> +{
>> +    struct nfs4_label *label = NULL;
>> +
>> +    label = kzalloc(sizeof(struct nfs4_label) + NFS4_MAXLABELLEN,
>> flags);
>> +    if (label == NULL)
>> +        return NULL;
>
> Instead of NULL, you could return an ERR_PTR.  NULL could then be used
> to signal that labels aren't supported.  See below.
>
>> +
>> +    label->label = (void *)(label + 1);
>> +    label->len = NFS4_MAXLABELLEN;
>> +    /* 0 is the null format meaning that the data is not to be
>> translated */
>> +     label->lfs = 0;
>> +    return label;
>> +}
>> +
>> +void nfs4_label_free (struct nfs4_label *label)
>> +{
>> +    if (label)
>> +        kfree(label);
>
> Style: kfree() already checks for a NULL pointer, so you shouldn't. 
> At one point recently, all such checks were removed from the kernel in
> favor of using the one already in kfree().
>
> Also, you check the server capabilities before calling this function,
> nearly every time.  Is that really needed?  If there's a label data
> structure, it should be freed whether the server supports it or not.
>
> That capabilities check is probably going to be more complex if you
> want to have NFSv3 label support as well.  Would it make sense to
> provide a function that can check for NFSv3 (eventually) or NFSv4
> label support?
>
> Or, fold such checks into your allocator?  Hiding the capabilities
> check here would allow easy expansion in the future to include other
> NFS versions, and cause less clutter in all callers.
>
>> +    return;
>> +}
>> +
>> +#endif
>
> Style: Generally speaking, we like to keep "#ifdef CONFIG_BAR" noise
> down to a dull roar.  So, this is the right place to keep it, and the
> generic functions (like nfs_lookup() and nfs_readdir()) is generally not.
>
> Usually we accomplish this by having functions like nfs4_label_free()
> always be available, but if CONFIG_NFS_V4_SECURITY_LABEL isn't set,
> the function call is a no-op.
>
>> +
>>   static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct
>> dentry *dentry,
>>           struct nfs4_readdir_arg *readdir)
>>   {
>> diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
>> index efa3377..c217277 100644
>> --- a/fs/nfsd/xdr4.h
>> +++ b/fs/nfsd/xdr4.h
>> @@ -108,6 +108,7 @@ struct nfsd4_create {
>>       struct iattr    cr_iattr;           /* request */
>>       struct nfsd4_change_info  cr_cinfo; /* response */
>>       struct nfs4_acl *cr_acl;
>> +    struct nfs4_label *cr_label;
>>   };
>>   #define cr_linklen    u.link.namelen
>>   #define cr_linkname    u.link.name
>> @@ -235,6 +236,7 @@ struct nfsd4_open {
>>       int        op_truncate;        /* used during processing */
>>       struct nfs4_stateowner *op_stateowner; /* used during
>> processing */
>>       struct nfs4_acl *op_acl;
>> +    struct nfs4_label *op_label;
>>   };
>>   #define op_iattr    iattr
>>   #define op_verf        verf
>> @@ -316,6 +318,7 @@ struct nfsd4_setattr {
>>       u32        sa_bmval[3];        /* request */
>>       struct iattr    sa_iattr;           /* request */
>>       struct nfs4_acl *sa_acl;
>> +    struct nfs4_label *sa_label;
>>   };
>>
>>   struct nfsd4_setclientid {
>> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
>> index a2abd1a..c512a0c 100644
>> --- a/include/linux/nfs4.h
>> +++ b/include/linux/nfs4.h
>> @@ -167,6 +167,13 @@ struct nfs4_acl {
>>       struct nfs4_ace    aces[0];
>>   };
>>
>> +struct nfs4_label {
>> +    void        *label;
>> +    u32        len;
>> +    uint32_t    lfs;
>> +};
>
> If we have support for NFS labels in NFSv3, would we also use struct
> nfs4_label?
>
> It seems to me you want something more generic, just like nfs_fh or
> nfs_fattr, to represent these.  Over time, I'm guessing label support
> won't be tied to a specific NFS version.  And, you are passing these
> around in the generic NFS functions (for post-op updates and inode
> revalidation, and what not).
>
> Can I recommend "struct nfs_seclabel" instead?  Then have
> nfs_seclabel_alloc() and nfs_seclabel_free().

Security has been the primary consumer of labels to date, but
the xattr concept has always been envisioned as useful in many
ways. That, and people have so many different views on what is
and isn't security and whether it is good or evil that you are
asking to limit the value if you tie "security" to the names.
Plus, it adds unnecessary characters.

>
> Does it make sense to deduplicate these in the client's memory?  It
> seems to me that you could have hundreds or thousands that all contain
> the same label information.

That would be easy enough to do. Look at smack_import() for a
worked example.

>
>> +
>> +
>>   typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
>>   typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
>>
>> diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
>> index 07ce460..2813b71 100644
>> --- a/include/linux/nfs_fs.h
>> +++ b/include/linux/nfs_fs.h
>> @@ -454,6 +454,13 @@ extern int nfs_mountpoint_expiry_timeout;
>>   extern void nfs_release_automount_timer(void);
>>
>>   /*
>> + * linux/fs/nfs/nfs4proc.c
>> + */
>> +
>> +struct nfs4_label *    nfs4_label_alloc (gfp_t flags);
>> +void            nfs4_label_free (struct nfs4_label *);
>> +
>> +/*
>>    * linux/fs/nfs/unlink.c
>>    */
>>   extern int  nfs_async_unlink(struct inode *dir, struct dentry
>> *dentry);
>> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
>> index 28cde54..dc505e4 100644
>> --- a/include/linux/nfs_xdr.h
>> +++ b/include/linux/nfs_xdr.h
>> @@ -207,6 +207,7 @@ struct nfs_openargs {
>>       const struct nfs_server *server;     /* Needed for ID mapping */
>>       const u32 *        bitmask;
>>       __u32            claim;
>> +    const struct nfs4_label *label;
>>       struct nfs4_sequence_args    seq_args;
>>   };
>>
>> @@ -216,7 +217,9 @@ struct nfs_openres {
>>       struct nfs4_change_info    cinfo;
>>       __u32                   rflags;
>>       struct nfs_fattr *      f_attr;
>> +    struct nfs4_label *    f_label;
>>       struct nfs_fattr *      dir_attr;
>> +    struct nfs4_label *    dir_label;
>>       struct nfs_seqid *    seqid;
>>       const struct nfs_server *server;
>>       fmode_t            delegation_type;
>> @@ -256,6 +259,7 @@ struct nfs_closeargs {
>>   struct nfs_closeres {
>>       nfs4_stateid            stateid;
>>       struct nfs_fattr *    fattr;
>> +    struct nfs4_label *    label;
>>       struct nfs_seqid *    seqid;
>>       const struct nfs_server *server;
>>       struct nfs4_sequence_res    seq_res;
>> @@ -324,6 +328,7 @@ struct nfs4_delegreturnargs {
>>
>>   struct nfs4_delegreturnres {
>>       struct nfs_fattr * fattr;
>> +    struct nfs4_label * label;
>>       const struct nfs_server *server;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>> @@ -343,6 +348,7 @@ struct nfs_readargs {
>>
>>   struct nfs_readres {
>>       struct nfs_fattr *    fattr;
>> +    struct nfs4_label *    label;
>>       __u32            count;
>>       int                     eof;
>>       struct nfs4_sequence_res    seq_res;
>> @@ -390,6 +396,7 @@ struct nfs_removeres {
>>       const struct nfs_server *server;
>>       struct nfs4_change_info    cinfo;
>>       struct nfs_fattr    dir_attr;
>> +    struct nfs4_label    *dir_label;
>>       struct nfs4_sequence_res     seq_res;
>>   };
>>
>> @@ -405,6 +412,7 @@ struct nfs_entry {
>>       int            eof;
>>       struct nfs_fh *        fh;
>>       struct nfs_fattr *    fattr;
>> +    struct nfs4_label *    label;
>>   };
>>
>>   /*
>> @@ -443,6 +451,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 nfs4_sequence_args     seq_args;
>>   };
>>
>> @@ -473,6 +482,7 @@ struct nfs_getaclres {
>>
>>   struct nfs_setattrres {
>>       struct nfs_fattr *              fattr;
>> +    struct nfs4_label *        label;
>>       const struct nfs_server *    server;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>> @@ -662,6 +672,7 @@ struct nfs4_accessargs {
>>   struct nfs4_accessres {
>>       const struct nfs_server *    server;
>>       struct nfs_fattr *        fattr;
>> +    struct nfs4_label *        label;
>>       u32                supported;
>>       u32                access;
>>       struct nfs4_sequence_res    seq_res;
>> @@ -684,6 +695,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_sequence_args     seq_args;
>>   };
>>
>> @@ -691,8 +703,10 @@ struct nfs4_create_res {
>>       const struct nfs_server *    server;
>>       struct nfs_fh *            fh;
>>       struct nfs_fattr *        fattr;
>> +    struct nfs4_label *        label;
>>       struct nfs4_change_info        dir_cinfo;
>>       struct nfs_fattr *        dir_fattr;
>> +    struct nfs4_label *        dir_label;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>>
>> @@ -717,6 +731,7 @@ struct nfs4_getattr_res {
>>       const struct nfs_server *    server;
>>       struct nfs_fattr *        fattr;
>>       struct nfs4_sequence_res    seq_res;
>> +    struct nfs4_label *        label;
>>   };
>>
>>   struct nfs4_link_arg {
>> @@ -730,8 +745,10 @@ struct nfs4_link_arg {
>>   struct nfs4_link_res {
>>       const struct nfs_server *    server;
>>       struct nfs_fattr *        fattr;
>> +    struct nfs4_label *        label;
>>       struct nfs4_change_info        cinfo;
>>       struct nfs_fattr *        dir_attr;
>> +    struct nfs4_label *        dir_label;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>>
>> @@ -747,6 +764,7 @@ struct nfs4_lookup_res {
>>       const struct nfs_server *    server;
>>       struct nfs_fattr *        fattr;
>>       struct nfs_fh *            fh;
>> +    struct nfs4_label *        label;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>>
>> @@ -800,6 +818,8 @@ struct nfs4_rename_arg {
>>       const struct nfs_fh *        new_dir;
>>       const struct qstr *        old_name;
>>       const struct qstr *        new_name;
>> +    const struct nfs4_label *    old_label;
>> +    const struct nfs4_label *    new_label;
>>       const u32 *            bitmask;
>>       struct nfs4_sequence_args    seq_args;
>>   };
>> @@ -808,8 +828,10 @@ struct nfs4_rename_res {
>>       const struct nfs_server *    server;
>>       struct nfs4_change_info        old_cinfo;
>>       struct nfs_fattr *        old_fattr;
>> +    struct nfs4_label *        old_label;
>>       struct nfs4_change_info        new_cinfo;
>>       struct nfs_fattr *        new_fattr;
>> +    struct nfs4_label *        new_label;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>>
>
>


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
@ 2010-07-07 16:21       ` Casey Schaufler
  0 siblings, 0 replies; 95+ messages in thread
From: Casey Schaufler @ 2010-07-07 16:21 UTC (permalink / raw)
  To: Chuck Lever
  Cc: David P. Quigley, hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	sds-+05T5uksL2qpZYMLLGbcSA, matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	bfields-uC3wQj2KruNg9hUCZPvPmw,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

Chuck Lever wrote:
> My comments below apply to the other NFS client patches as well.  This
> seemed like the right one to use for code examples.
>
> On 07/ 7/10 10:31 AM, David P. Quigley wrote:
>> 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-DABiIiYg7OfQT0dZR+AlfA@public.gmane.org>
>> Signed-off-by: David P. Quigley<dpquigl-+05T5uksL2qpZYMLLGbcSA@public.gmane.org>
>> ---
>>   fs/nfs/nfs4proc.c       |   26 ++++++++++++++++++++++++++
>>   fs/nfsd/xdr4.h          |    3 +++
>>   include/linux/nfs4.h    |    7 +++++++
>>   include/linux/nfs_fs.h  |    7 +++++++
>>   include/linux/nfs_xdr.h |   22 ++++++++++++++++++++++
>>   5 files changed, 65 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
>> index 071fced..71bb8da 100644
>> --- a/fs/nfs/nfs4proc.c
>> +++ b/fs/nfs/nfs4proc.c
>> @@ -148,6 +148,32 @@ const u32 nfs4_fs_locations_bitmap[2] = {
>>       | FATTR4_WORD1_MOUNTED_ON_FILEID
>>   };
>>
>> +#ifdef CONFIG_NFS_V4_SECURITY_LABEL
>> +
>> +struct nfs4_label * nfs4_label_alloc (gfp_t flags)
>
> Style: have you run these patches through scripts/checkpatch.pl? 
> Kernel coding style likes "struct foo *function(args)", without the
> spaces.
>
>> +{
>> +    struct nfs4_label *label = NULL;
>> +
>> +    label = kzalloc(sizeof(struct nfs4_label) + NFS4_MAXLABELLEN,
>> flags);
>> +    if (label == NULL)
>> +        return NULL;
>
> Instead of NULL, you could return an ERR_PTR.  NULL could then be used
> to signal that labels aren't supported.  See below.
>
>> +
>> +    label->label = (void *)(label + 1);
>> +    label->len = NFS4_MAXLABELLEN;
>> +    /* 0 is the null format meaning that the data is not to be
>> translated */
>> +     label->lfs = 0;
>> +    return label;
>> +}
>> +
>> +void nfs4_label_free (struct nfs4_label *label)
>> +{
>> +    if (label)
>> +        kfree(label);
>
> Style: kfree() already checks for a NULL pointer, so you shouldn't. 
> At one point recently, all such checks were removed from the kernel in
> favor of using the one already in kfree().
>
> Also, you check the server capabilities before calling this function,
> nearly every time.  Is that really needed?  If there's a label data
> structure, it should be freed whether the server supports it or not.
>
> That capabilities check is probably going to be more complex if you
> want to have NFSv3 label support as well.  Would it make sense to
> provide a function that can check for NFSv3 (eventually) or NFSv4
> label support?
>
> Or, fold such checks into your allocator?  Hiding the capabilities
> check here would allow easy expansion in the future to include other
> NFS versions, and cause less clutter in all callers.
>
>> +    return;
>> +}
>> +
>> +#endif
>
> Style: Generally speaking, we like to keep "#ifdef CONFIG_BAR" noise
> down to a dull roar.  So, this is the right place to keep it, and the
> generic functions (like nfs_lookup() and nfs_readdir()) is generally not.
>
> Usually we accomplish this by having functions like nfs4_label_free()
> always be available, but if CONFIG_NFS_V4_SECURITY_LABEL isn't set,
> the function call is a no-op.
>
>> +
>>   static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct
>> dentry *dentry,
>>           struct nfs4_readdir_arg *readdir)
>>   {
>> diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
>> index efa3377..c217277 100644
>> --- a/fs/nfsd/xdr4.h
>> +++ b/fs/nfsd/xdr4.h
>> @@ -108,6 +108,7 @@ struct nfsd4_create {
>>       struct iattr    cr_iattr;           /* request */
>>       struct nfsd4_change_info  cr_cinfo; /* response */
>>       struct nfs4_acl *cr_acl;
>> +    struct nfs4_label *cr_label;
>>   };
>>   #define cr_linklen    u.link.namelen
>>   #define cr_linkname    u.link.name
>> @@ -235,6 +236,7 @@ struct nfsd4_open {
>>       int        op_truncate;        /* used during processing */
>>       struct nfs4_stateowner *op_stateowner; /* used during
>> processing */
>>       struct nfs4_acl *op_acl;
>> +    struct nfs4_label *op_label;
>>   };
>>   #define op_iattr    iattr
>>   #define op_verf        verf
>> @@ -316,6 +318,7 @@ struct nfsd4_setattr {
>>       u32        sa_bmval[3];        /* request */
>>       struct iattr    sa_iattr;           /* request */
>>       struct nfs4_acl *sa_acl;
>> +    struct nfs4_label *sa_label;
>>   };
>>
>>   struct nfsd4_setclientid {
>> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
>> index a2abd1a..c512a0c 100644
>> --- a/include/linux/nfs4.h
>> +++ b/include/linux/nfs4.h
>> @@ -167,6 +167,13 @@ struct nfs4_acl {
>>       struct nfs4_ace    aces[0];
>>   };
>>
>> +struct nfs4_label {
>> +    void        *label;
>> +    u32        len;
>> +    uint32_t    lfs;
>> +};
>
> If we have support for NFS labels in NFSv3, would we also use struct
> nfs4_label?
>
> It seems to me you want something more generic, just like nfs_fh or
> nfs_fattr, to represent these.  Over time, I'm guessing label support
> won't be tied to a specific NFS version.  And, you are passing these
> around in the generic NFS functions (for post-op updates and inode
> revalidation, and what not).
>
> Can I recommend "struct nfs_seclabel" instead?  Then have
> nfs_seclabel_alloc() and nfs_seclabel_free().

Security has been the primary consumer of labels to date, but
the xattr concept has always been envisioned as useful in many
ways. That, and people have so many different views on what is
and isn't security and whether it is good or evil that you are
asking to limit the value if you tie "security" to the names.
Plus, it adds unnecessary characters.

>
> Does it make sense to deduplicate these in the client's memory?  It
> seems to me that you could have hundreds or thousands that all contain
> the same label information.

That would be easy enough to do. Look at smack_import() for a
worked example.

>
>> +
>> +
>>   typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
>>   typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
>>
>> diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
>> index 07ce460..2813b71 100644
>> --- a/include/linux/nfs_fs.h
>> +++ b/include/linux/nfs_fs.h
>> @@ -454,6 +454,13 @@ extern int nfs_mountpoint_expiry_timeout;
>>   extern void nfs_release_automount_timer(void);
>>
>>   /*
>> + * linux/fs/nfs/nfs4proc.c
>> + */
>> +
>> +struct nfs4_label *    nfs4_label_alloc (gfp_t flags);
>> +void            nfs4_label_free (struct nfs4_label *);
>> +
>> +/*
>>    * linux/fs/nfs/unlink.c
>>    */
>>   extern int  nfs_async_unlink(struct inode *dir, struct dentry
>> *dentry);
>> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
>> index 28cde54..dc505e4 100644
>> --- a/include/linux/nfs_xdr.h
>> +++ b/include/linux/nfs_xdr.h
>> @@ -207,6 +207,7 @@ struct nfs_openargs {
>>       const struct nfs_server *server;     /* Needed for ID mapping */
>>       const u32 *        bitmask;
>>       __u32            claim;
>> +    const struct nfs4_label *label;
>>       struct nfs4_sequence_args    seq_args;
>>   };
>>
>> @@ -216,7 +217,9 @@ struct nfs_openres {
>>       struct nfs4_change_info    cinfo;
>>       __u32                   rflags;
>>       struct nfs_fattr *      f_attr;
>> +    struct nfs4_label *    f_label;
>>       struct nfs_fattr *      dir_attr;
>> +    struct nfs4_label *    dir_label;
>>       struct nfs_seqid *    seqid;
>>       const struct nfs_server *server;
>>       fmode_t            delegation_type;
>> @@ -256,6 +259,7 @@ struct nfs_closeargs {
>>   struct nfs_closeres {
>>       nfs4_stateid            stateid;
>>       struct nfs_fattr *    fattr;
>> +    struct nfs4_label *    label;
>>       struct nfs_seqid *    seqid;
>>       const struct nfs_server *server;
>>       struct nfs4_sequence_res    seq_res;
>> @@ -324,6 +328,7 @@ struct nfs4_delegreturnargs {
>>
>>   struct nfs4_delegreturnres {
>>       struct nfs_fattr * fattr;
>> +    struct nfs4_label * label;
>>       const struct nfs_server *server;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>> @@ -343,6 +348,7 @@ struct nfs_readargs {
>>
>>   struct nfs_readres {
>>       struct nfs_fattr *    fattr;
>> +    struct nfs4_label *    label;
>>       __u32            count;
>>       int                     eof;
>>       struct nfs4_sequence_res    seq_res;
>> @@ -390,6 +396,7 @@ struct nfs_removeres {
>>       const struct nfs_server *server;
>>       struct nfs4_change_info    cinfo;
>>       struct nfs_fattr    dir_attr;
>> +    struct nfs4_label    *dir_label;
>>       struct nfs4_sequence_res     seq_res;
>>   };
>>
>> @@ -405,6 +412,7 @@ struct nfs_entry {
>>       int            eof;
>>       struct nfs_fh *        fh;
>>       struct nfs_fattr *    fattr;
>> +    struct nfs4_label *    label;
>>   };
>>
>>   /*
>> @@ -443,6 +451,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 nfs4_sequence_args     seq_args;
>>   };
>>
>> @@ -473,6 +482,7 @@ struct nfs_getaclres {
>>
>>   struct nfs_setattrres {
>>       struct nfs_fattr *              fattr;
>> +    struct nfs4_label *        label;
>>       const struct nfs_server *    server;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>> @@ -662,6 +672,7 @@ struct nfs4_accessargs {
>>   struct nfs4_accessres {
>>       const struct nfs_server *    server;
>>       struct nfs_fattr *        fattr;
>> +    struct nfs4_label *        label;
>>       u32                supported;
>>       u32                access;
>>       struct nfs4_sequence_res    seq_res;
>> @@ -684,6 +695,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_sequence_args     seq_args;
>>   };
>>
>> @@ -691,8 +703,10 @@ struct nfs4_create_res {
>>       const struct nfs_server *    server;
>>       struct nfs_fh *            fh;
>>       struct nfs_fattr *        fattr;
>> +    struct nfs4_label *        label;
>>       struct nfs4_change_info        dir_cinfo;
>>       struct nfs_fattr *        dir_fattr;
>> +    struct nfs4_label *        dir_label;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>>
>> @@ -717,6 +731,7 @@ struct nfs4_getattr_res {
>>       const struct nfs_server *    server;
>>       struct nfs_fattr *        fattr;
>>       struct nfs4_sequence_res    seq_res;
>> +    struct nfs4_label *        label;
>>   };
>>
>>   struct nfs4_link_arg {
>> @@ -730,8 +745,10 @@ struct nfs4_link_arg {
>>   struct nfs4_link_res {
>>       const struct nfs_server *    server;
>>       struct nfs_fattr *        fattr;
>> +    struct nfs4_label *        label;
>>       struct nfs4_change_info        cinfo;
>>       struct nfs_fattr *        dir_attr;
>> +    struct nfs4_label *        dir_label;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>>
>> @@ -747,6 +764,7 @@ struct nfs4_lookup_res {
>>       const struct nfs_server *    server;
>>       struct nfs_fattr *        fattr;
>>       struct nfs_fh *            fh;
>> +    struct nfs4_label *        label;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>>
>> @@ -800,6 +818,8 @@ struct nfs4_rename_arg {
>>       const struct nfs_fh *        new_dir;
>>       const struct qstr *        old_name;
>>       const struct qstr *        new_name;
>> +    const struct nfs4_label *    old_label;
>> +    const struct nfs4_label *    new_label;
>>       const u32 *            bitmask;
>>       struct nfs4_sequence_args    seq_args;
>>   };
>> @@ -808,8 +828,10 @@ struct nfs4_rename_res {
>>       const struct nfs_server *    server;
>>       struct nfs4_change_info        old_cinfo;
>>       struct nfs_fattr *        old_fattr;
>> +    struct nfs4_label *        old_label;
>>       struct nfs4_change_info        new_cinfo;
>>       struct nfs_fattr *        new_fattr;
>> +    struct nfs4_label *        new_label;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>>
>
>

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
@ 2010-07-07 16:21       ` Casey Schaufler
  0 siblings, 0 replies; 95+ messages in thread
From: Casey Schaufler @ 2010-07-07 16:21 UTC (permalink / raw)
  To: Chuck Lever
  Cc: David P. Quigley, hch, viro, sds, matthew.dodd, trond.myklebust,
	bfields, linux-kernel, linux-fsdevel, linux-security-module,
	selinux, linux-nfs

Chuck Lever wrote:
> My comments below apply to the other NFS client patches as well.  This
> seemed like the right one to use for code examples.
>
> On 07/ 7/10 10:31 AM, David P. Quigley wrote:
>> 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>
>> ---
>>   fs/nfs/nfs4proc.c       |   26 ++++++++++++++++++++++++++
>>   fs/nfsd/xdr4.h          |    3 +++
>>   include/linux/nfs4.h    |    7 +++++++
>>   include/linux/nfs_fs.h  |    7 +++++++
>>   include/linux/nfs_xdr.h |   22 ++++++++++++++++++++++
>>   5 files changed, 65 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
>> index 071fced..71bb8da 100644
>> --- a/fs/nfs/nfs4proc.c
>> +++ b/fs/nfs/nfs4proc.c
>> @@ -148,6 +148,32 @@ const u32 nfs4_fs_locations_bitmap[2] = {
>>       | FATTR4_WORD1_MOUNTED_ON_FILEID
>>   };
>>
>> +#ifdef CONFIG_NFS_V4_SECURITY_LABEL
>> +
>> +struct nfs4_label * nfs4_label_alloc (gfp_t flags)
>
> Style: have you run these patches through scripts/checkpatch.pl? 
> Kernel coding style likes "struct foo *function(args)", without the
> spaces.
>
>> +{
>> +    struct nfs4_label *label = NULL;
>> +
>> +    label = kzalloc(sizeof(struct nfs4_label) + NFS4_MAXLABELLEN,
>> flags);
>> +    if (label == NULL)
>> +        return NULL;
>
> Instead of NULL, you could return an ERR_PTR.  NULL could then be used
> to signal that labels aren't supported.  See below.
>
>> +
>> +    label->label = (void *)(label + 1);
>> +    label->len = NFS4_MAXLABELLEN;
>> +    /* 0 is the null format meaning that the data is not to be
>> translated */
>> +     label->lfs = 0;
>> +    return label;
>> +}
>> +
>> +void nfs4_label_free (struct nfs4_label *label)
>> +{
>> +    if (label)
>> +        kfree(label);
>
> Style: kfree() already checks for a NULL pointer, so you shouldn't. 
> At one point recently, all such checks were removed from the kernel in
> favor of using the one already in kfree().
>
> Also, you check the server capabilities before calling this function,
> nearly every time.  Is that really needed?  If there's a label data
> structure, it should be freed whether the server supports it or not.
>
> That capabilities check is probably going to be more complex if you
> want to have NFSv3 label support as well.  Would it make sense to
> provide a function that can check for NFSv3 (eventually) or NFSv4
> label support?
>
> Or, fold such checks into your allocator?  Hiding the capabilities
> check here would allow easy expansion in the future to include other
> NFS versions, and cause less clutter in all callers.
>
>> +    return;
>> +}
>> +
>> +#endif
>
> Style: Generally speaking, we like to keep "#ifdef CONFIG_BAR" noise
> down to a dull roar.  So, this is the right place to keep it, and the
> generic functions (like nfs_lookup() and nfs_readdir()) is generally not.
>
> Usually we accomplish this by having functions like nfs4_label_free()
> always be available, but if CONFIG_NFS_V4_SECURITY_LABEL isn't set,
> the function call is a no-op.
>
>> +
>>   static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct
>> dentry *dentry,
>>           struct nfs4_readdir_arg *readdir)
>>   {
>> diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
>> index efa3377..c217277 100644
>> --- a/fs/nfsd/xdr4.h
>> +++ b/fs/nfsd/xdr4.h
>> @@ -108,6 +108,7 @@ struct nfsd4_create {
>>       struct iattr    cr_iattr;           /* request */
>>       struct nfsd4_change_info  cr_cinfo; /* response */
>>       struct nfs4_acl *cr_acl;
>> +    struct nfs4_label *cr_label;
>>   };
>>   #define cr_linklen    u.link.namelen
>>   #define cr_linkname    u.link.name
>> @@ -235,6 +236,7 @@ struct nfsd4_open {
>>       int        op_truncate;        /* used during processing */
>>       struct nfs4_stateowner *op_stateowner; /* used during
>> processing */
>>       struct nfs4_acl *op_acl;
>> +    struct nfs4_label *op_label;
>>   };
>>   #define op_iattr    iattr
>>   #define op_verf        verf
>> @@ -316,6 +318,7 @@ struct nfsd4_setattr {
>>       u32        sa_bmval[3];        /* request */
>>       struct iattr    sa_iattr;           /* request */
>>       struct nfs4_acl *sa_acl;
>> +    struct nfs4_label *sa_label;
>>   };
>>
>>   struct nfsd4_setclientid {
>> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
>> index a2abd1a..c512a0c 100644
>> --- a/include/linux/nfs4.h
>> +++ b/include/linux/nfs4.h
>> @@ -167,6 +167,13 @@ struct nfs4_acl {
>>       struct nfs4_ace    aces[0];
>>   };
>>
>> +struct nfs4_label {
>> +    void        *label;
>> +    u32        len;
>> +    uint32_t    lfs;
>> +};
>
> If we have support for NFS labels in NFSv3, would we also use struct
> nfs4_label?
>
> It seems to me you want something more generic, just like nfs_fh or
> nfs_fattr, to represent these.  Over time, I'm guessing label support
> won't be tied to a specific NFS version.  And, you are passing these
> around in the generic NFS functions (for post-op updates and inode
> revalidation, and what not).
>
> Can I recommend "struct nfs_seclabel" instead?  Then have
> nfs_seclabel_alloc() and nfs_seclabel_free().

Security has been the primary consumer of labels to date, but
the xattr concept has always been envisioned as useful in many
ways. That, and people have so many different views on what is
and isn't security and whether it is good or evil that you are
asking to limit the value if you tie "security" to the names.
Plus, it adds unnecessary characters.

>
> Does it make sense to deduplicate these in the client's memory?  It
> seems to me that you could have hundreds or thousands that all contain
> the same label information.

That would be easy enough to do. Look at smack_import() for a
worked example.

>
>> +
>> +
>>   typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
>>   typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
>>
>> diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
>> index 07ce460..2813b71 100644
>> --- a/include/linux/nfs_fs.h
>> +++ b/include/linux/nfs_fs.h
>> @@ -454,6 +454,13 @@ extern int nfs_mountpoint_expiry_timeout;
>>   extern void nfs_release_automount_timer(void);
>>
>>   /*
>> + * linux/fs/nfs/nfs4proc.c
>> + */
>> +
>> +struct nfs4_label *    nfs4_label_alloc (gfp_t flags);
>> +void            nfs4_label_free (struct nfs4_label *);
>> +
>> +/*
>>    * linux/fs/nfs/unlink.c
>>    */
>>   extern int  nfs_async_unlink(struct inode *dir, struct dentry
>> *dentry);
>> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
>> index 28cde54..dc505e4 100644
>> --- a/include/linux/nfs_xdr.h
>> +++ b/include/linux/nfs_xdr.h
>> @@ -207,6 +207,7 @@ struct nfs_openargs {
>>       const struct nfs_server *server;     /* Needed for ID mapping */
>>       const u32 *        bitmask;
>>       __u32            claim;
>> +    const struct nfs4_label *label;
>>       struct nfs4_sequence_args    seq_args;
>>   };
>>
>> @@ -216,7 +217,9 @@ struct nfs_openres {
>>       struct nfs4_change_info    cinfo;
>>       __u32                   rflags;
>>       struct nfs_fattr *      f_attr;
>> +    struct nfs4_label *    f_label;
>>       struct nfs_fattr *      dir_attr;
>> +    struct nfs4_label *    dir_label;
>>       struct nfs_seqid *    seqid;
>>       const struct nfs_server *server;
>>       fmode_t            delegation_type;
>> @@ -256,6 +259,7 @@ struct nfs_closeargs {
>>   struct nfs_closeres {
>>       nfs4_stateid            stateid;
>>       struct nfs_fattr *    fattr;
>> +    struct nfs4_label *    label;
>>       struct nfs_seqid *    seqid;
>>       const struct nfs_server *server;
>>       struct nfs4_sequence_res    seq_res;
>> @@ -324,6 +328,7 @@ struct nfs4_delegreturnargs {
>>
>>   struct nfs4_delegreturnres {
>>       struct nfs_fattr * fattr;
>> +    struct nfs4_label * label;
>>       const struct nfs_server *server;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>> @@ -343,6 +348,7 @@ struct nfs_readargs {
>>
>>   struct nfs_readres {
>>       struct nfs_fattr *    fattr;
>> +    struct nfs4_label *    label;
>>       __u32            count;
>>       int                     eof;
>>       struct nfs4_sequence_res    seq_res;
>> @@ -390,6 +396,7 @@ struct nfs_removeres {
>>       const struct nfs_server *server;
>>       struct nfs4_change_info    cinfo;
>>       struct nfs_fattr    dir_attr;
>> +    struct nfs4_label    *dir_label;
>>       struct nfs4_sequence_res     seq_res;
>>   };
>>
>> @@ -405,6 +412,7 @@ struct nfs_entry {
>>       int            eof;
>>       struct nfs_fh *        fh;
>>       struct nfs_fattr *    fattr;
>> +    struct nfs4_label *    label;
>>   };
>>
>>   /*
>> @@ -443,6 +451,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 nfs4_sequence_args     seq_args;
>>   };
>>
>> @@ -473,6 +482,7 @@ struct nfs_getaclres {
>>
>>   struct nfs_setattrres {
>>       struct nfs_fattr *              fattr;
>> +    struct nfs4_label *        label;
>>       const struct nfs_server *    server;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>> @@ -662,6 +672,7 @@ struct nfs4_accessargs {
>>   struct nfs4_accessres {
>>       const struct nfs_server *    server;
>>       struct nfs_fattr *        fattr;
>> +    struct nfs4_label *        label;
>>       u32                supported;
>>       u32                access;
>>       struct nfs4_sequence_res    seq_res;
>> @@ -684,6 +695,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_sequence_args     seq_args;
>>   };
>>
>> @@ -691,8 +703,10 @@ struct nfs4_create_res {
>>       const struct nfs_server *    server;
>>       struct nfs_fh *            fh;
>>       struct nfs_fattr *        fattr;
>> +    struct nfs4_label *        label;
>>       struct nfs4_change_info        dir_cinfo;
>>       struct nfs_fattr *        dir_fattr;
>> +    struct nfs4_label *        dir_label;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>>
>> @@ -717,6 +731,7 @@ struct nfs4_getattr_res {
>>       const struct nfs_server *    server;
>>       struct nfs_fattr *        fattr;
>>       struct nfs4_sequence_res    seq_res;
>> +    struct nfs4_label *        label;
>>   };
>>
>>   struct nfs4_link_arg {
>> @@ -730,8 +745,10 @@ struct nfs4_link_arg {
>>   struct nfs4_link_res {
>>       const struct nfs_server *    server;
>>       struct nfs_fattr *        fattr;
>> +    struct nfs4_label *        label;
>>       struct nfs4_change_info        cinfo;
>>       struct nfs_fattr *        dir_attr;
>> +    struct nfs4_label *        dir_label;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>>
>> @@ -747,6 +764,7 @@ struct nfs4_lookup_res {
>>       const struct nfs_server *    server;
>>       struct nfs_fattr *        fattr;
>>       struct nfs_fh *            fh;
>> +    struct nfs4_label *        label;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>>
>> @@ -800,6 +818,8 @@ struct nfs4_rename_arg {
>>       const struct nfs_fh *        new_dir;
>>       const struct qstr *        old_name;
>>       const struct qstr *        new_name;
>> +    const struct nfs4_label *    old_label;
>> +    const struct nfs4_label *    new_label;
>>       const u32 *            bitmask;
>>       struct nfs4_sequence_args    seq_args;
>>   };
>> @@ -808,8 +828,10 @@ struct nfs4_rename_res {
>>       const struct nfs_server *    server;
>>       struct nfs4_change_info        old_cinfo;
>>       struct nfs_fattr *        old_fattr;
>> +    struct nfs4_label *        old_label;
>>       struct nfs4_change_info        new_cinfo;
>>       struct nfs_fattr *        new_fattr;
>> +    struct nfs4_label *        new_label;
>>       struct nfs4_sequence_res    seq_res;
>>   };
>>
>
>


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
@ 2010-07-07 16:22       ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 16:22 UTC (permalink / raw)
  To: Chuck Lever
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

Hello Chuck,
   Thank you for the comments. I'll go through and address them inline
(Sorry for the top post).

On Wed, 2010-07-07 at 12:01 -0400, Chuck Lever wrote:
> My comments below apply to the other NFS client patches as well.  This 
> seemed like the right one to use for code examples.
> 
> On 07/ 7/10 10:31 AM, David P. Quigley wrote:
> > 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>
> > ---
> >   fs/nfs/nfs4proc.c       |   26 ++++++++++++++++++++++++++
> >   fs/nfsd/xdr4.h          |    3 +++
> >   include/linux/nfs4.h    |    7 +++++++
> >   include/linux/nfs_fs.h  |    7 +++++++
> >   include/linux/nfs_xdr.h |   22 ++++++++++++++++++++++
> >   5 files changed, 65 insertions(+), 0 deletions(-)
> >
> > diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> > index 071fced..71bb8da 100644
> > --- a/fs/nfs/nfs4proc.c
> > +++ b/fs/nfs/nfs4proc.c
> > @@ -148,6 +148,32 @@ const u32 nfs4_fs_locations_bitmap[2] = {
> >   	| FATTR4_WORD1_MOUNTED_ON_FILEID
> >   };
> >
> > +#ifdef CONFIG_NFS_V4_SECURITY_LABEL
> > +
> > +struct nfs4_label * nfs4_label_alloc (gfp_t flags)
> 
> Style: have you run these patches through scripts/checkpatch.pl?  Kernel 
> coding style likes "struct foo *function(args)", without the spaces.

I haven't run them through checkpatch in a while. I will make sure that
I do that soon and apply all of the style complaints from that.

> 
> > +{
> > +	struct nfs4_label *label = NULL;
> > +
> > +	label = kzalloc(sizeof(struct nfs4_label) + NFS4_MAXLABELLEN, flags);
> > +	if (label == NULL)
> > +		return NULL;
> 
> Instead of NULL, you could return an ERR_PTR.  NULL could then be used 
> to signal that labels aren't supported.  See below.

Is it possible for kzalloc to fail with something other than NULL
though?

> 
> > +
> > +	label->label = (void *)(label + 1);
> > +	label->len = NFS4_MAXLABELLEN;
> > +	/* 0 is the null format meaning that the data is not to be translated */
> > + 	label->lfs = 0;
> > +	return label;
> > +}
> > +
> > +void nfs4_label_free (struct nfs4_label *label)
> > +{
> > +	if (label)
> > +		kfree(label);
> 
> Style: kfree() already checks for a NULL pointer, so you shouldn't.  At 
> one point recently, all such checks were removed from the kernel in 
> favor of using the one already in kfree().

Thats a good point. I'll go through and clean these up.

> 
> Also, you check the server capabilities before calling this function, 
> nearly every time.  Is that really needed?  If there's a label data 
> structure, it should be freed whether the server supports it or not.

We should free the structure regardless of server support. We moved to
this code a long time ago so I don't quite remember if we will ever see
an allocated label data structure when the server does not support
labeling.

> 
> That capabilities check is probably going to be more complex if you want 
> to have NFSv3 label support as well.  Would it make sense to provide a 
> function that can check for NFSv3 (eventually) or NFSv4 label support?

I'm not sure about what James intends to do about NFSv3 security label
support but if it is what I think it might be then it is a different
beast than what I am doing for NFSv4. If anything James will probably
use the normal xattr method for security labels on NFSv3 because that is
the mechanism he is proposing. On NFSv3 this wont be a capability check
on the server for whether it supports security labels but instead would
be a capability check for if it supports xattrs (even then I don't think
it is since the xattr protocol is a sideband protocol). 

> 
> Or, fold such checks into your allocator?  Hiding the capabilities check 
> here would allow easy expansion in the future to include other NFS 
> versions, and cause less clutter in all callers.
> 
> > +	return;
> > +}
> > +
> > +#endif
> 
> Style: Generally speaking, we like to keep "#ifdef CONFIG_BAR" noise 
> down to a dull roar.  So, this is the right place to keep it, and the 
> generic functions (like nfs_lookup() and nfs_readdir()) is generally not.
> 
> Usually we accomplish this by having functions like nfs4_label_free() 
> always be available, but if CONFIG_NFS_V4_SECURITY_LABEL isn't set, the 
> function call is a no-op.

Hmm I could have sworn I got this comment before and fixed it. I'll go
back and make sure that this is the case in the patches. Looking at
patch 7 alone it doesn't seem like we do this but I will go about
checking and fixing it just to be sure.

> 
> > +
> >   static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
> >   		struct nfs4_readdir_arg *readdir)
> >   {
> > diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
> > index efa3377..c217277 100644
> > --- a/fs/nfsd/xdr4.h
> > +++ b/fs/nfsd/xdr4.h
> > @@ -108,6 +108,7 @@ struct nfsd4_create {
> >   	struct iattr	cr_iattr;           /* request */
> >   	struct nfsd4_change_info  cr_cinfo; /* response */
> >   	struct nfs4_acl *cr_acl;
> > +	struct nfs4_label *cr_label;
> >   };
> >   #define cr_linklen	u.link.namelen
> >   #define cr_linkname	u.link.name
> > @@ -235,6 +236,7 @@ struct nfsd4_open {
> >   	int		op_truncate;        /* used during processing */
> >   	struct nfs4_stateowner *op_stateowner; /* used during processing */
> >   	struct nfs4_acl *op_acl;
> > +	struct nfs4_label *op_label;
> >   };
> >   #define op_iattr	iattr
> >   #define op_verf		verf
> > @@ -316,6 +318,7 @@ struct nfsd4_setattr {
> >   	u32		sa_bmval[3];        /* request */
> >   	struct iattr	sa_iattr;           /* request */
> >   	struct nfs4_acl *sa_acl;
> > +	struct nfs4_label *sa_label;
> >   };
> >
> >   struct nfsd4_setclientid {
> > diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
> > index a2abd1a..c512a0c 100644
> > --- a/include/linux/nfs4.h
> > +++ b/include/linux/nfs4.h
> > @@ -167,6 +167,13 @@ struct nfs4_acl {
> >   	struct nfs4_ace	aces[0];
> >   };
> >
> > +struct nfs4_label {
> > +	void		*label;
> > +	u32		len;
> > +	uint32_t	lfs;
> > +};
> 
> If we have support for NFS labels in NFSv3, would we also use struct 
> nfs4_label?

I don't believe this is the case. NFSv3 label support won't come in the
form of file attribute. Instead it will use James' out of band xattr
protocol. At that point the changes for getting the label into the inode
are very different. The reason we have to do all of this is because we
are getting the security label in NFSv4 from the fattr structure. This
structure contains what I'd call first class inode attributes. In Linux
security labels are handled through the xattr interface instead. Initial
I tried modifying the iattr structure which would have made it easier to
apply the fattr attributes to the inode including the security label.
This got pushback from Christoph since xattrs are the interface for
security labels. Also this wasn't a good solution because I needed a
dentry for the setxattr and getxattr calls and that wasn't available at
that point.

> 
> It seems to me you want something more generic, just like nfs_fh or 
> nfs_fattr, to represent these.  Over time, I'm guessing label support 
> won't be tied to a specific NFS version.  And, you are passing these 
> around in the generic NFS functions (for post-op updates and inode 
> revalidation, and what not).
> 
> Can I recommend "struct nfs_seclabel" instead?  Then have 
> nfs_seclabel_alloc() and nfs_seclabel_free().

I can definitely rename them to be more generic. I don't see anything
else besides NFSv4 using them but its fine with me to rename them. The
reason we call them nfs4_label is because we modeled it after the NFSv4
acl support code. I spoke with Christoph a long time ago and he
suggested that it should be handled the same way that the NFSv4 ACLs are
handled as opposed to the iattr thing we were trying. 

> 
> Does it make sense to deduplicate these in the client's memory?  It 
> seems to me that you could have hundreds or thousands that all contain 
> the same label information.

I don't think it is worth the effort. We are only using these structures
until the security label is crammed into the inode. Once that happens
they get freed. You shouldn't have them sitting around for very long.
They will be pulled again when the inode attributes expire and need to
be revalidated. For things like SELinux you could argue that the LSM
might benefit from this (and it might already do it but I'm not sure)
but I think that is something to be handled by the LSM itself or the
credentials code (since it already supports COW credentials it should be
possible). 

> 
> > +
> > +
> >   typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
> >   typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
> >
> > diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
> > index 07ce460..2813b71 100644
> > --- a/include/linux/nfs_fs.h
> > +++ b/include/linux/nfs_fs.h
> > @@ -454,6 +454,13 @@ extern int nfs_mountpoint_expiry_timeout;
> >   extern void nfs_release_automount_timer(void);
> >
> >   /*
> > + * linux/fs/nfs/nfs4proc.c
> > + */
> > +
> > +struct nfs4_label *	nfs4_label_alloc (gfp_t flags);
> > +void			nfs4_label_free (struct nfs4_label *);
> > +
> > +/*
> >    * linux/fs/nfs/unlink.c
> >    */
> >   extern int  nfs_async_unlink(struct inode *dir, struct dentry *dentry);
> > diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> > index 28cde54..dc505e4 100644
> > --- a/include/linux/nfs_xdr.h
> > +++ b/include/linux/nfs_xdr.h
> > @@ -207,6 +207,7 @@ struct nfs_openargs {
> >   	const struct nfs_server *server;	 /* Needed for ID mapping */
> >   	const u32 *		bitmask;
> >   	__u32			claim;
> > +	const struct nfs4_label *label;
> >   	struct nfs4_sequence_args	seq_args;
> >   };
> >
> > @@ -216,7 +217,9 @@ struct nfs_openres {
> >   	struct nfs4_change_info	cinfo;
> >   	__u32                   rflags;
> >   	struct nfs_fattr *      f_attr;
> > +	struct nfs4_label *	f_label;
> >   	struct nfs_fattr *      dir_attr;
> > +	struct nfs4_label *	dir_label;
> >   	struct nfs_seqid *	seqid;
> >   	const struct nfs_server *server;
> >   	fmode_t			delegation_type;
> > @@ -256,6 +259,7 @@ struct nfs_closeargs {
> >   struct nfs_closeres {
> >   	nfs4_stateid            stateid;
> >   	struct nfs_fattr *	fattr;
> > +	struct nfs4_label *	label;
> >   	struct nfs_seqid *	seqid;
> >   	const struct nfs_server *server;
> >   	struct nfs4_sequence_res	seq_res;
> > @@ -324,6 +328,7 @@ struct nfs4_delegreturnargs {
> >
> >   struct nfs4_delegreturnres {
> >   	struct nfs_fattr * fattr;
> > +	struct nfs4_label * label;
> >   	const struct nfs_server *server;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> > @@ -343,6 +348,7 @@ struct nfs_readargs {
> >
> >   struct nfs_readres {
> >   	struct nfs_fattr *	fattr;
> > +	struct nfs4_label *	label;
> >   	__u32			count;
> >   	int                     eof;
> >   	struct nfs4_sequence_res	seq_res;
> > @@ -390,6 +396,7 @@ struct nfs_removeres {
> >   	const struct nfs_server *server;
> >   	struct nfs4_change_info	cinfo;
> >   	struct nfs_fattr	dir_attr;
> > +	struct nfs4_label	*dir_label;
> >   	struct nfs4_sequence_res 	seq_res;
> >   };
> >
> > @@ -405,6 +412,7 @@ struct nfs_entry {
> >   	int			eof;
> >   	struct nfs_fh *		fh;
> >   	struct nfs_fattr *	fattr;
> > +	struct nfs4_label *	label;
> >   };
> >
> >   /*
> > @@ -443,6 +451,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 nfs4_sequence_args 	seq_args;
> >   };
> >
> > @@ -473,6 +482,7 @@ struct nfs_getaclres {
> >
> >   struct nfs_setattrres {
> >   	struct nfs_fattr *              fattr;
> > +	struct nfs4_label *		label;
> >   	const struct nfs_server *	server;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> > @@ -662,6 +672,7 @@ struct nfs4_accessargs {
> >   struct nfs4_accessres {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fattr *		fattr;
> > +	struct nfs4_label *		label;
> >   	u32				supported;
> >   	u32				access;
> >   	struct nfs4_sequence_res	seq_res;
> > @@ -684,6 +695,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_sequence_args 	seq_args;
> >   };
> >
> > @@ -691,8 +703,10 @@ struct nfs4_create_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fh *			fh;
> >   	struct nfs_fattr *		fattr;
> > +	struct nfs4_label *		label;
> >   	struct nfs4_change_info		dir_cinfo;
> >   	struct nfs_fattr *		dir_fattr;
> > +	struct nfs4_label *		dir_label;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> >
> > @@ -717,6 +731,7 @@ struct nfs4_getattr_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fattr *		fattr;
> >   	struct nfs4_sequence_res	seq_res;
> > +	struct nfs4_label *		label;
> >   };
> >
> >   struct nfs4_link_arg {
> > @@ -730,8 +745,10 @@ struct nfs4_link_arg {
> >   struct nfs4_link_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fattr *		fattr;
> > +	struct nfs4_label *		label;
> >   	struct nfs4_change_info		cinfo;
> >   	struct nfs_fattr *		dir_attr;
> > +	struct nfs4_label *		dir_label;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> >
> > @@ -747,6 +764,7 @@ struct nfs4_lookup_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fattr *		fattr;
> >   	struct nfs_fh *			fh;
> > +	struct nfs4_label *		label;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> >
> > @@ -800,6 +818,8 @@ struct nfs4_rename_arg {
> >   	const struct nfs_fh *		new_dir;
> >   	const struct qstr *		old_name;
> >   	const struct qstr *		new_name;
> > +	const struct nfs4_label *	old_label;
> > +	const struct nfs4_label *	new_label;
> >   	const u32 *			bitmask;
> >   	struct nfs4_sequence_args	seq_args;
> >   };
> > @@ -808,8 +828,10 @@ struct nfs4_rename_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs4_change_info		old_cinfo;
> >   	struct nfs_fattr *		old_fattr;
> > +	struct nfs4_label *		old_label;
> >   	struct nfs4_change_info		new_cinfo;
> >   	struct nfs_fattr *		new_fattr;
> > +	struct nfs4_label *		new_label;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> >


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
@ 2010-07-07 16:22       ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 16:22 UTC (permalink / raw)
  To: Chuck Lever
  Cc: hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	casey-iSGtlc1asvQWG2LlvL+J4A, sds-+05T5uksL2qpZYMLLGbcSA,
	matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	bfields-uC3wQj2KruNg9hUCZPvPmw,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

Hello Chuck,
   Thank you for the comments. I'll go through and address them inline
(Sorry for the top post).

On Wed, 2010-07-07 at 12:01 -0400, Chuck Lever wrote:
> My comments below apply to the other NFS client patches as well.  This 
> seemed like the right one to use for code examples.
> 
> On 07/ 7/10 10:31 AM, David P. Quigley wrote:
> > 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-DABiIiYg7OfQT0dZR+AlfA@public.gmane.org>
> > Signed-off-by: David P. Quigley<dpquigl-+05T5uksL2qpZYMLLGbcSA@public.gmane.org>
> > ---
> >   fs/nfs/nfs4proc.c       |   26 ++++++++++++++++++++++++++
> >   fs/nfsd/xdr4.h          |    3 +++
> >   include/linux/nfs4.h    |    7 +++++++
> >   include/linux/nfs_fs.h  |    7 +++++++
> >   include/linux/nfs_xdr.h |   22 ++++++++++++++++++++++
> >   5 files changed, 65 insertions(+), 0 deletions(-)
> >
> > diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> > index 071fced..71bb8da 100644
> > --- a/fs/nfs/nfs4proc.c
> > +++ b/fs/nfs/nfs4proc.c
> > @@ -148,6 +148,32 @@ const u32 nfs4_fs_locations_bitmap[2] = {
> >   	| FATTR4_WORD1_MOUNTED_ON_FILEID
> >   };
> >
> > +#ifdef CONFIG_NFS_V4_SECURITY_LABEL
> > +
> > +struct nfs4_label * nfs4_label_alloc (gfp_t flags)
> 
> Style: have you run these patches through scripts/checkpatch.pl?  Kernel 
> coding style likes "struct foo *function(args)", without the spaces.

I haven't run them through checkpatch in a while. I will make sure that
I do that soon and apply all of the style complaints from that.

> 
> > +{
> > +	struct nfs4_label *label = NULL;
> > +
> > +	label = kzalloc(sizeof(struct nfs4_label) + NFS4_MAXLABELLEN, flags);
> > +	if (label == NULL)
> > +		return NULL;
> 
> Instead of NULL, you could return an ERR_PTR.  NULL could then be used 
> to signal that labels aren't supported.  See below.

Is it possible for kzalloc to fail with something other than NULL
though?

> 
> > +
> > +	label->label = (void *)(label + 1);
> > +	label->len = NFS4_MAXLABELLEN;
> > +	/* 0 is the null format meaning that the data is not to be translated */
> > + 	label->lfs = 0;
> > +	return label;
> > +}
> > +
> > +void nfs4_label_free (struct nfs4_label *label)
> > +{
> > +	if (label)
> > +		kfree(label);
> 
> Style: kfree() already checks for a NULL pointer, so you shouldn't.  At 
> one point recently, all such checks were removed from the kernel in 
> favor of using the one already in kfree().

Thats a good point. I'll go through and clean these up.

> 
> Also, you check the server capabilities before calling this function, 
> nearly every time.  Is that really needed?  If there's a label data 
> structure, it should be freed whether the server supports it or not.

We should free the structure regardless of server support. We moved to
this code a long time ago so I don't quite remember if we will ever see
an allocated label data structure when the server does not support
labeling.

> 
> That capabilities check is probably going to be more complex if you want 
> to have NFSv3 label support as well.  Would it make sense to provide a 
> function that can check for NFSv3 (eventually) or NFSv4 label support?

I'm not sure about what James intends to do about NFSv3 security label
support but if it is what I think it might be then it is a different
beast than what I am doing for NFSv4. If anything James will probably
use the normal xattr method for security labels on NFSv3 because that is
the mechanism he is proposing. On NFSv3 this wont be a capability check
on the server for whether it supports security labels but instead would
be a capability check for if it supports xattrs (even then I don't think
it is since the xattr protocol is a sideband protocol). 

> 
> Or, fold such checks into your allocator?  Hiding the capabilities check 
> here would allow easy expansion in the future to include other NFS 
> versions, and cause less clutter in all callers.
> 
> > +	return;
> > +}
> > +
> > +#endif
> 
> Style: Generally speaking, we like to keep "#ifdef CONFIG_BAR" noise 
> down to a dull roar.  So, this is the right place to keep it, and the 
> generic functions (like nfs_lookup() and nfs_readdir()) is generally not.
> 
> Usually we accomplish this by having functions like nfs4_label_free() 
> always be available, but if CONFIG_NFS_V4_SECURITY_LABEL isn't set, the 
> function call is a no-op.

Hmm I could have sworn I got this comment before and fixed it. I'll go
back and make sure that this is the case in the patches. Looking at
patch 7 alone it doesn't seem like we do this but I will go about
checking and fixing it just to be sure.

> 
> > +
> >   static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
> >   		struct nfs4_readdir_arg *readdir)
> >   {
> > diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
> > index efa3377..c217277 100644
> > --- a/fs/nfsd/xdr4.h
> > +++ b/fs/nfsd/xdr4.h
> > @@ -108,6 +108,7 @@ struct nfsd4_create {
> >   	struct iattr	cr_iattr;           /* request */
> >   	struct nfsd4_change_info  cr_cinfo; /* response */
> >   	struct nfs4_acl *cr_acl;
> > +	struct nfs4_label *cr_label;
> >   };
> >   #define cr_linklen	u.link.namelen
> >   #define cr_linkname	u.link.name
> > @@ -235,6 +236,7 @@ struct nfsd4_open {
> >   	int		op_truncate;        /* used during processing */
> >   	struct nfs4_stateowner *op_stateowner; /* used during processing */
> >   	struct nfs4_acl *op_acl;
> > +	struct nfs4_label *op_label;
> >   };
> >   #define op_iattr	iattr
> >   #define op_verf		verf
> > @@ -316,6 +318,7 @@ struct nfsd4_setattr {
> >   	u32		sa_bmval[3];        /* request */
> >   	struct iattr	sa_iattr;           /* request */
> >   	struct nfs4_acl *sa_acl;
> > +	struct nfs4_label *sa_label;
> >   };
> >
> >   struct nfsd4_setclientid {
> > diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
> > index a2abd1a..c512a0c 100644
> > --- a/include/linux/nfs4.h
> > +++ b/include/linux/nfs4.h
> > @@ -167,6 +167,13 @@ struct nfs4_acl {
> >   	struct nfs4_ace	aces[0];
> >   };
> >
> > +struct nfs4_label {
> > +	void		*label;
> > +	u32		len;
> > +	uint32_t	lfs;
> > +};
> 
> If we have support for NFS labels in NFSv3, would we also use struct 
> nfs4_label?

I don't believe this is the case. NFSv3 label support won't come in the
form of file attribute. Instead it will use James' out of band xattr
protocol. At that point the changes for getting the label into the inode
are very different. The reason we have to do all of this is because we
are getting the security label in NFSv4 from the fattr structure. This
structure contains what I'd call first class inode attributes. In Linux
security labels are handled through the xattr interface instead. Initial
I tried modifying the iattr structure which would have made it easier to
apply the fattr attributes to the inode including the security label.
This got pushback from Christoph since xattrs are the interface for
security labels. Also this wasn't a good solution because I needed a
dentry for the setxattr and getxattr calls and that wasn't available at
that point.

> 
> It seems to me you want something more generic, just like nfs_fh or 
> nfs_fattr, to represent these.  Over time, I'm guessing label support 
> won't be tied to a specific NFS version.  And, you are passing these 
> around in the generic NFS functions (for post-op updates and inode 
> revalidation, and what not).
> 
> Can I recommend "struct nfs_seclabel" instead?  Then have 
> nfs_seclabel_alloc() and nfs_seclabel_free().

I can definitely rename them to be more generic. I don't see anything
else besides NFSv4 using them but its fine with me to rename them. The
reason we call them nfs4_label is because we modeled it after the NFSv4
acl support code. I spoke with Christoph a long time ago and he
suggested that it should be handled the same way that the NFSv4 ACLs are
handled as opposed to the iattr thing we were trying. 

> 
> Does it make sense to deduplicate these in the client's memory?  It 
> seems to me that you could have hundreds or thousands that all contain 
> the same label information.

I don't think it is worth the effort. We are only using these structures
until the security label is crammed into the inode. Once that happens
they get freed. You shouldn't have them sitting around for very long.
They will be pulled again when the inode attributes expire and need to
be revalidated. For things like SELinux you could argue that the LSM
might benefit from this (and it might already do it but I'm not sure)
but I think that is something to be handled by the LSM itself or the
credentials code (since it already supports COW credentials it should be
possible). 

> 
> > +
> > +
> >   typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
> >   typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
> >
> > diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
> > index 07ce460..2813b71 100644
> > --- a/include/linux/nfs_fs.h
> > +++ b/include/linux/nfs_fs.h
> > @@ -454,6 +454,13 @@ extern int nfs_mountpoint_expiry_timeout;
> >   extern void nfs_release_automount_timer(void);
> >
> >   /*
> > + * linux/fs/nfs/nfs4proc.c
> > + */
> > +
> > +struct nfs4_label *	nfs4_label_alloc (gfp_t flags);
> > +void			nfs4_label_free (struct nfs4_label *);
> > +
> > +/*
> >    * linux/fs/nfs/unlink.c
> >    */
> >   extern int  nfs_async_unlink(struct inode *dir, struct dentry *dentry);
> > diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> > index 28cde54..dc505e4 100644
> > --- a/include/linux/nfs_xdr.h
> > +++ b/include/linux/nfs_xdr.h
> > @@ -207,6 +207,7 @@ struct nfs_openargs {
> >   	const struct nfs_server *server;	 /* Needed for ID mapping */
> >   	const u32 *		bitmask;
> >   	__u32			claim;
> > +	const struct nfs4_label *label;
> >   	struct nfs4_sequence_args	seq_args;
> >   };
> >
> > @@ -216,7 +217,9 @@ struct nfs_openres {
> >   	struct nfs4_change_info	cinfo;
> >   	__u32                   rflags;
> >   	struct nfs_fattr *      f_attr;
> > +	struct nfs4_label *	f_label;
> >   	struct nfs_fattr *      dir_attr;
> > +	struct nfs4_label *	dir_label;
> >   	struct nfs_seqid *	seqid;
> >   	const struct nfs_server *server;
> >   	fmode_t			delegation_type;
> > @@ -256,6 +259,7 @@ struct nfs_closeargs {
> >   struct nfs_closeres {
> >   	nfs4_stateid            stateid;
> >   	struct nfs_fattr *	fattr;
> > +	struct nfs4_label *	label;
> >   	struct nfs_seqid *	seqid;
> >   	const struct nfs_server *server;
> >   	struct nfs4_sequence_res	seq_res;
> > @@ -324,6 +328,7 @@ struct nfs4_delegreturnargs {
> >
> >   struct nfs4_delegreturnres {
> >   	struct nfs_fattr * fattr;
> > +	struct nfs4_label * label;
> >   	const struct nfs_server *server;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> > @@ -343,6 +348,7 @@ struct nfs_readargs {
> >
> >   struct nfs_readres {
> >   	struct nfs_fattr *	fattr;
> > +	struct nfs4_label *	label;
> >   	__u32			count;
> >   	int                     eof;
> >   	struct nfs4_sequence_res	seq_res;
> > @@ -390,6 +396,7 @@ struct nfs_removeres {
> >   	const struct nfs_server *server;
> >   	struct nfs4_change_info	cinfo;
> >   	struct nfs_fattr	dir_attr;
> > +	struct nfs4_label	*dir_label;
> >   	struct nfs4_sequence_res 	seq_res;
> >   };
> >
> > @@ -405,6 +412,7 @@ struct nfs_entry {
> >   	int			eof;
> >   	struct nfs_fh *		fh;
> >   	struct nfs_fattr *	fattr;
> > +	struct nfs4_label *	label;
> >   };
> >
> >   /*
> > @@ -443,6 +451,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 nfs4_sequence_args 	seq_args;
> >   };
> >
> > @@ -473,6 +482,7 @@ struct nfs_getaclres {
> >
> >   struct nfs_setattrres {
> >   	struct nfs_fattr *              fattr;
> > +	struct nfs4_label *		label;
> >   	const struct nfs_server *	server;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> > @@ -662,6 +672,7 @@ struct nfs4_accessargs {
> >   struct nfs4_accessres {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fattr *		fattr;
> > +	struct nfs4_label *		label;
> >   	u32				supported;
> >   	u32				access;
> >   	struct nfs4_sequence_res	seq_res;
> > @@ -684,6 +695,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_sequence_args 	seq_args;
> >   };
> >
> > @@ -691,8 +703,10 @@ struct nfs4_create_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fh *			fh;
> >   	struct nfs_fattr *		fattr;
> > +	struct nfs4_label *		label;
> >   	struct nfs4_change_info		dir_cinfo;
> >   	struct nfs_fattr *		dir_fattr;
> > +	struct nfs4_label *		dir_label;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> >
> > @@ -717,6 +731,7 @@ struct nfs4_getattr_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fattr *		fattr;
> >   	struct nfs4_sequence_res	seq_res;
> > +	struct nfs4_label *		label;
> >   };
> >
> >   struct nfs4_link_arg {
> > @@ -730,8 +745,10 @@ struct nfs4_link_arg {
> >   struct nfs4_link_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fattr *		fattr;
> > +	struct nfs4_label *		label;
> >   	struct nfs4_change_info		cinfo;
> >   	struct nfs_fattr *		dir_attr;
> > +	struct nfs4_label *		dir_label;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> >
> > @@ -747,6 +764,7 @@ struct nfs4_lookup_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fattr *		fattr;
> >   	struct nfs_fh *			fh;
> > +	struct nfs4_label *		label;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> >
> > @@ -800,6 +818,8 @@ struct nfs4_rename_arg {
> >   	const struct nfs_fh *		new_dir;
> >   	const struct qstr *		old_name;
> >   	const struct qstr *		new_name;
> > +	const struct nfs4_label *	old_label;
> > +	const struct nfs4_label *	new_label;
> >   	const u32 *			bitmask;
> >   	struct nfs4_sequence_args	seq_args;
> >   };
> > @@ -808,8 +828,10 @@ struct nfs4_rename_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs4_change_info		old_cinfo;
> >   	struct nfs_fattr *		old_fattr;
> > +	struct nfs4_label *		old_label;
> >   	struct nfs4_change_info		new_cinfo;
> >   	struct nfs_fattr *		new_fattr;
> > +	struct nfs4_label *		new_label;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> >

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
@ 2010-07-07 16:22       ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 16:22 UTC (permalink / raw)
  To: Chuck Lever
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

Hello Chuck,
   Thank you for the comments. I'll go through and address them inline
(Sorry for the top post).

On Wed, 2010-07-07 at 12:01 -0400, Chuck Lever wrote:
> My comments below apply to the other NFS client patches as well.  This 
> seemed like the right one to use for code examples.
> 
> On 07/ 7/10 10:31 AM, David P. Quigley wrote:
> > 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>
> > ---
> >   fs/nfs/nfs4proc.c       |   26 ++++++++++++++++++++++++++
> >   fs/nfsd/xdr4.h          |    3 +++
> >   include/linux/nfs4.h    |    7 +++++++
> >   include/linux/nfs_fs.h  |    7 +++++++
> >   include/linux/nfs_xdr.h |   22 ++++++++++++++++++++++
> >   5 files changed, 65 insertions(+), 0 deletions(-)
> >
> > diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> > index 071fced..71bb8da 100644
> > --- a/fs/nfs/nfs4proc.c
> > +++ b/fs/nfs/nfs4proc.c
> > @@ -148,6 +148,32 @@ const u32 nfs4_fs_locations_bitmap[2] = {
> >   	| FATTR4_WORD1_MOUNTED_ON_FILEID
> >   };
> >
> > +#ifdef CONFIG_NFS_V4_SECURITY_LABEL
> > +
> > +struct nfs4_label * nfs4_label_alloc (gfp_t flags)
> 
> Style: have you run these patches through scripts/checkpatch.pl?  Kernel 
> coding style likes "struct foo *function(args)", without the spaces.

I haven't run them through checkpatch in a while. I will make sure that
I do that soon and apply all of the style complaints from that.

> 
> > +{
> > +	struct nfs4_label *label = NULL;
> > +
> > +	label = kzalloc(sizeof(struct nfs4_label) + NFS4_MAXLABELLEN, flags);
> > +	if (label == NULL)
> > +		return NULL;
> 
> Instead of NULL, you could return an ERR_PTR.  NULL could then be used 
> to signal that labels aren't supported.  See below.

Is it possible for kzalloc to fail with something other than NULL
though?

> 
> > +
> > +	label->label = (void *)(label + 1);
> > +	label->len = NFS4_MAXLABELLEN;
> > +	/* 0 is the null format meaning that the data is not to be translated */
> > + 	label->lfs = 0;
> > +	return label;
> > +}
> > +
> > +void nfs4_label_free (struct nfs4_label *label)
> > +{
> > +	if (label)
> > +		kfree(label);
> 
> Style: kfree() already checks for a NULL pointer, so you shouldn't.  At 
> one point recently, all such checks were removed from the kernel in 
> favor of using the one already in kfree().

Thats a good point. I'll go through and clean these up.

> 
> Also, you check the server capabilities before calling this function, 
> nearly every time.  Is that really needed?  If there's a label data 
> structure, it should be freed whether the server supports it or not.

We should free the structure regardless of server support. We moved to
this code a long time ago so I don't quite remember if we will ever see
an allocated label data structure when the server does not support
labeling.

> 
> That capabilities check is probably going to be more complex if you want 
> to have NFSv3 label support as well.  Would it make sense to provide a 
> function that can check for NFSv3 (eventually) or NFSv4 label support?

I'm not sure about what James intends to do about NFSv3 security label
support but if it is what I think it might be then it is a different
beast than what I am doing for NFSv4. If anything James will probably
use the normal xattr method for security labels on NFSv3 because that is
the mechanism he is proposing. On NFSv3 this wont be a capability check
on the server for whether it supports security labels but instead would
be a capability check for if it supports xattrs (even then I don't think
it is since the xattr protocol is a sideband protocol). 

> 
> Or, fold such checks into your allocator?  Hiding the capabilities check 
> here would allow easy expansion in the future to include other NFS 
> versions, and cause less clutter in all callers.
> 
> > +	return;
> > +}
> > +
> > +#endif
> 
> Style: Generally speaking, we like to keep "#ifdef CONFIG_BAR" noise 
> down to a dull roar.  So, this is the right place to keep it, and the 
> generic functions (like nfs_lookup() and nfs_readdir()) is generally not.
> 
> Usually we accomplish this by having functions like nfs4_label_free() 
> always be available, but if CONFIG_NFS_V4_SECURITY_LABEL isn't set, the 
> function call is a no-op.

Hmm I could have sworn I got this comment before and fixed it. I'll go
back and make sure that this is the case in the patches. Looking at
patch 7 alone it doesn't seem like we do this but I will go about
checking and fixing it just to be sure.

> 
> > +
> >   static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
> >   		struct nfs4_readdir_arg *readdir)
> >   {
> > diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
> > index efa3377..c217277 100644
> > --- a/fs/nfsd/xdr4.h
> > +++ b/fs/nfsd/xdr4.h
> > @@ -108,6 +108,7 @@ struct nfsd4_create {
> >   	struct iattr	cr_iattr;           /* request */
> >   	struct nfsd4_change_info  cr_cinfo; /* response */
> >   	struct nfs4_acl *cr_acl;
> > +	struct nfs4_label *cr_label;
> >   };
> >   #define cr_linklen	u.link.namelen
> >   #define cr_linkname	u.link.name
> > @@ -235,6 +236,7 @@ struct nfsd4_open {
> >   	int		op_truncate;        /* used during processing */
> >   	struct nfs4_stateowner *op_stateowner; /* used during processing */
> >   	struct nfs4_acl *op_acl;
> > +	struct nfs4_label *op_label;
> >   };
> >   #define op_iattr	iattr
> >   #define op_verf		verf
> > @@ -316,6 +318,7 @@ struct nfsd4_setattr {
> >   	u32		sa_bmval[3];        /* request */
> >   	struct iattr	sa_iattr;           /* request */
> >   	struct nfs4_acl *sa_acl;
> > +	struct nfs4_label *sa_label;
> >   };
> >
> >   struct nfsd4_setclientid {
> > diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
> > index a2abd1a..c512a0c 100644
> > --- a/include/linux/nfs4.h
> > +++ b/include/linux/nfs4.h
> > @@ -167,6 +167,13 @@ struct nfs4_acl {
> >   	struct nfs4_ace	aces[0];
> >   };
> >
> > +struct nfs4_label {
> > +	void		*label;
> > +	u32		len;
> > +	uint32_t	lfs;
> > +};
> 
> If we have support for NFS labels in NFSv3, would we also use struct 
> nfs4_label?

I don't believe this is the case. NFSv3 label support won't come in the
form of file attribute. Instead it will use James' out of band xattr
protocol. At that point the changes for getting the label into the inode
are very different. The reason we have to do all of this is because we
are getting the security label in NFSv4 from the fattr structure. This
structure contains what I'd call first class inode attributes. In Linux
security labels are handled through the xattr interface instead. Initial
I tried modifying the iattr structure which would have made it easier to
apply the fattr attributes to the inode including the security label.
This got pushback from Christoph since xattrs are the interface for
security labels. Also this wasn't a good solution because I needed a
dentry for the setxattr and getxattr calls and that wasn't available at
that point.

> 
> It seems to me you want something more generic, just like nfs_fh or 
> nfs_fattr, to represent these.  Over time, I'm guessing label support 
> won't be tied to a specific NFS version.  And, you are passing these 
> around in the generic NFS functions (for post-op updates and inode 
> revalidation, and what not).
> 
> Can I recommend "struct nfs_seclabel" instead?  Then have 
> nfs_seclabel_alloc() and nfs_seclabel_free().

I can definitely rename them to be more generic. I don't see anything
else besides NFSv4 using them but its fine with me to rename them. The
reason we call them nfs4_label is because we modeled it after the NFSv4
acl support code. I spoke with Christoph a long time ago and he
suggested that it should be handled the same way that the NFSv4 ACLs are
handled as opposed to the iattr thing we were trying. 

> 
> Does it make sense to deduplicate these in the client's memory?  It 
> seems to me that you could have hundreds or thousands that all contain 
> the same label information.

I don't think it is worth the effort. We are only using these structures
until the security label is crammed into the inode. Once that happens
they get freed. You shouldn't have them sitting around for very long.
They will be pulled again when the inode attributes expire and need to
be revalidated. For things like SELinux you could argue that the LSM
might benefit from this (and it might already do it but I'm not sure)
but I think that is something to be handled by the LSM itself or the
credentials code (since it already supports COW credentials it should be
possible). 

> 
> > +
> > +
> >   typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
> >   typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
> >
> > diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
> > index 07ce460..2813b71 100644
> > --- a/include/linux/nfs_fs.h
> > +++ b/include/linux/nfs_fs.h
> > @@ -454,6 +454,13 @@ extern int nfs_mountpoint_expiry_timeout;
> >   extern void nfs_release_automount_timer(void);
> >
> >   /*
> > + * linux/fs/nfs/nfs4proc.c
> > + */
> > +
> > +struct nfs4_label *	nfs4_label_alloc (gfp_t flags);
> > +void			nfs4_label_free (struct nfs4_label *);
> > +
> > +/*
> >    * linux/fs/nfs/unlink.c
> >    */
> >   extern int  nfs_async_unlink(struct inode *dir, struct dentry *dentry);
> > diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> > index 28cde54..dc505e4 100644
> > --- a/include/linux/nfs_xdr.h
> > +++ b/include/linux/nfs_xdr.h
> > @@ -207,6 +207,7 @@ struct nfs_openargs {
> >   	const struct nfs_server *server;	 /* Needed for ID mapping */
> >   	const u32 *		bitmask;
> >   	__u32			claim;
> > +	const struct nfs4_label *label;
> >   	struct nfs4_sequence_args	seq_args;
> >   };
> >
> > @@ -216,7 +217,9 @@ struct nfs_openres {
> >   	struct nfs4_change_info	cinfo;
> >   	__u32                   rflags;
> >   	struct nfs_fattr *      f_attr;
> > +	struct nfs4_label *	f_label;
> >   	struct nfs_fattr *      dir_attr;
> > +	struct nfs4_label *	dir_label;
> >   	struct nfs_seqid *	seqid;
> >   	const struct nfs_server *server;
> >   	fmode_t			delegation_type;
> > @@ -256,6 +259,7 @@ struct nfs_closeargs {
> >   struct nfs_closeres {
> >   	nfs4_stateid            stateid;
> >   	struct nfs_fattr *	fattr;
> > +	struct nfs4_label *	label;
> >   	struct nfs_seqid *	seqid;
> >   	const struct nfs_server *server;
> >   	struct nfs4_sequence_res	seq_res;
> > @@ -324,6 +328,7 @@ struct nfs4_delegreturnargs {
> >
> >   struct nfs4_delegreturnres {
> >   	struct nfs_fattr * fattr;
> > +	struct nfs4_label * label;
> >   	const struct nfs_server *server;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> > @@ -343,6 +348,7 @@ struct nfs_readargs {
> >
> >   struct nfs_readres {
> >   	struct nfs_fattr *	fattr;
> > +	struct nfs4_label *	label;
> >   	__u32			count;
> >   	int                     eof;
> >   	struct nfs4_sequence_res	seq_res;
> > @@ -390,6 +396,7 @@ struct nfs_removeres {
> >   	const struct nfs_server *server;
> >   	struct nfs4_change_info	cinfo;
> >   	struct nfs_fattr	dir_attr;
> > +	struct nfs4_label	*dir_label;
> >   	struct nfs4_sequence_res 	seq_res;
> >   };
> >
> > @@ -405,6 +412,7 @@ struct nfs_entry {
> >   	int			eof;
> >   	struct nfs_fh *		fh;
> >   	struct nfs_fattr *	fattr;
> > +	struct nfs4_label *	label;
> >   };
> >
> >   /*
> > @@ -443,6 +451,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 nfs4_sequence_args 	seq_args;
> >   };
> >
> > @@ -473,6 +482,7 @@ struct nfs_getaclres {
> >
> >   struct nfs_setattrres {
> >   	struct nfs_fattr *              fattr;
> > +	struct nfs4_label *		label;
> >   	const struct nfs_server *	server;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> > @@ -662,6 +672,7 @@ struct nfs4_accessargs {
> >   struct nfs4_accessres {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fattr *		fattr;
> > +	struct nfs4_label *		label;
> >   	u32				supported;
> >   	u32				access;
> >   	struct nfs4_sequence_res	seq_res;
> > @@ -684,6 +695,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_sequence_args 	seq_args;
> >   };
> >
> > @@ -691,8 +703,10 @@ struct nfs4_create_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fh *			fh;
> >   	struct nfs_fattr *		fattr;
> > +	struct nfs4_label *		label;
> >   	struct nfs4_change_info		dir_cinfo;
> >   	struct nfs_fattr *		dir_fattr;
> > +	struct nfs4_label *		dir_label;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> >
> > @@ -717,6 +731,7 @@ struct nfs4_getattr_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fattr *		fattr;
> >   	struct nfs4_sequence_res	seq_res;
> > +	struct nfs4_label *		label;
> >   };
> >
> >   struct nfs4_link_arg {
> > @@ -730,8 +745,10 @@ struct nfs4_link_arg {
> >   struct nfs4_link_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fattr *		fattr;
> > +	struct nfs4_label *		label;
> >   	struct nfs4_change_info		cinfo;
> >   	struct nfs_fattr *		dir_attr;
> > +	struct nfs4_label *		dir_label;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> >
> > @@ -747,6 +764,7 @@ struct nfs4_lookup_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs_fattr *		fattr;
> >   	struct nfs_fh *			fh;
> > +	struct nfs4_label *		label;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> >
> > @@ -800,6 +818,8 @@ struct nfs4_rename_arg {
> >   	const struct nfs_fh *		new_dir;
> >   	const struct qstr *		old_name;
> >   	const struct qstr *		new_name;
> > +	const struct nfs4_label *	old_label;
> > +	const struct nfs4_label *	new_label;
> >   	const u32 *			bitmask;
> >   	struct nfs4_sequence_args	seq_args;
> >   };
> > @@ -808,8 +828,10 @@ struct nfs4_rename_res {
> >   	const struct nfs_server *	server;
> >   	struct nfs4_change_info		old_cinfo;
> >   	struct nfs_fattr *		old_fattr;
> > +	struct nfs4_label *		old_label;
> >   	struct nfs4_change_info		new_cinfo;
> >   	struct nfs_fattr *		new_fattr;
> > +	struct nfs4_label *		new_label;
> >   	struct nfs4_sequence_res	seq_res;
> >   };
> >


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
@ 2010-07-07 16:24         ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 16:24 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Chuck Lever, hch, viro, sds, matthew.dodd, trond.myklebust,
	bfields, linux-kernel, linux-fsdevel, linux-security-module,
	selinux, linux-nfs

On Wed, 2010-07-07 at 09:21 -0700, Casey Schaufler wrote:
> Chuck Lever wrote:
> > My comments below apply to the other NFS client patches as well.  This
> > seemed like the right one to use for code examples.
> >
> > On 07/ 7/10 10:31 AM, David P. Quigley wrote:
> >> 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>
> >> ---
> >>   fs/nfs/nfs4proc.c       |   26 ++++++++++++++++++++++++++
> >>   fs/nfsd/xdr4.h          |    3 +++
> >>   include/linux/nfs4.h    |    7 +++++++
> >>   include/linux/nfs_fs.h  |    7 +++++++
> >>   include/linux/nfs_xdr.h |   22 ++++++++++++++++++++++
> >>   5 files changed, 65 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> >> index 071fced..71bb8da 100644
> >> --- a/fs/nfs/nfs4proc.c
> >> +++ b/fs/nfs/nfs4proc.c
> >> @@ -148,6 +148,32 @@ const u32 nfs4_fs_locations_bitmap[2] = {
> >>       | FATTR4_WORD1_MOUNTED_ON_FILEID
> >>   };
> >>
> >> +#ifdef CONFIG_NFS_V4_SECURITY_LABEL
> >> +
> >> +struct nfs4_label * nfs4_label_alloc (gfp_t flags)
> >
> > Style: have you run these patches through scripts/checkpatch.pl? 
> > Kernel coding style likes "struct foo *function(args)", without the
> > spaces.
> >
> >> +{
> >> +    struct nfs4_label *label = NULL;
> >> +
> >> +    label = kzalloc(sizeof(struct nfs4_label) + NFS4_MAXLABELLEN,
> >> flags);
> >> +    if (label == NULL)
> >> +        return NULL;
> >
> > Instead of NULL, you could return an ERR_PTR.  NULL could then be used
> > to signal that labels aren't supported.  See below.
> >
> >> +
> >> +    label->label = (void *)(label + 1);
> >> +    label->len = NFS4_MAXLABELLEN;
> >> +    /* 0 is the null format meaning that the data is not to be
> >> translated */
> >> +     label->lfs = 0;
> >> +    return label;
> >> +}
> >> +
> >> +void nfs4_label_free (struct nfs4_label *label)
> >> +{
> >> +    if (label)
> >> +        kfree(label);
> >
> > Style: kfree() already checks for a NULL pointer, so you shouldn't. 
> > At one point recently, all such checks were removed from the kernel in
> > favor of using the one already in kfree().
> >
> > Also, you check the server capabilities before calling this function,
> > nearly every time.  Is that really needed?  If there's a label data
> > structure, it should be freed whether the server supports it or not.
> >
> > That capabilities check is probably going to be more complex if you
> > want to have NFSv3 label support as well.  Would it make sense to
> > provide a function that can check for NFSv3 (eventually) or NFSv4
> > label support?
> >
> > Or, fold such checks into your allocator?  Hiding the capabilities
> > check here would allow easy expansion in the future to include other
> > NFS versions, and cause less clutter in all callers.
> >
> >> +    return;
> >> +}
> >> +
> >> +#endif
> >
> > Style: Generally speaking, we like to keep "#ifdef CONFIG_BAR" noise
> > down to a dull roar.  So, this is the right place to keep it, and the
> > generic functions (like nfs_lookup() and nfs_readdir()) is generally not.
> >
> > Usually we accomplish this by having functions like nfs4_label_free()
> > always be available, but if CONFIG_NFS_V4_SECURITY_LABEL isn't set,
> > the function call is a no-op.
> >
> >> +
> >>   static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct
> >> dentry *dentry,
> >>           struct nfs4_readdir_arg *readdir)
> >>   {
> >> diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
> >> index efa3377..c217277 100644
> >> --- a/fs/nfsd/xdr4.h
> >> +++ b/fs/nfsd/xdr4.h
> >> @@ -108,6 +108,7 @@ struct nfsd4_create {
> >>       struct iattr    cr_iattr;           /* request */
> >>       struct nfsd4_change_info  cr_cinfo; /* response */
> >>       struct nfs4_acl *cr_acl;
> >> +    struct nfs4_label *cr_label;
> >>   };
> >>   #define cr_linklen    u.link.namelen
> >>   #define cr_linkname    u.link.name
> >> @@ -235,6 +236,7 @@ struct nfsd4_open {
> >>       int        op_truncate;        /* used during processing */
> >>       struct nfs4_stateowner *op_stateowner; /* used during
> >> processing */
> >>       struct nfs4_acl *op_acl;
> >> +    struct nfs4_label *op_label;
> >>   };
> >>   #define op_iattr    iattr
> >>   #define op_verf        verf
> >> @@ -316,6 +318,7 @@ struct nfsd4_setattr {
> >>       u32        sa_bmval[3];        /* request */
> >>       struct iattr    sa_iattr;           /* request */
> >>       struct nfs4_acl *sa_acl;
> >> +    struct nfs4_label *sa_label;
> >>   };
> >>
> >>   struct nfsd4_setclientid {
> >> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
> >> index a2abd1a..c512a0c 100644
> >> --- a/include/linux/nfs4.h
> >> +++ b/include/linux/nfs4.h
> >> @@ -167,6 +167,13 @@ struct nfs4_acl {
> >>       struct nfs4_ace    aces[0];
> >>   };
> >>
> >> +struct nfs4_label {
> >> +    void        *label;
> >> +    u32        len;
> >> +    uint32_t    lfs;
> >> +};
> >
> > If we have support for NFS labels in NFSv3, would we also use struct
> > nfs4_label?
> >
> > It seems to me you want something more generic, just like nfs_fh or
> > nfs_fattr, to represent these.  Over time, I'm guessing label support
> > won't be tied to a specific NFS version.  And, you are passing these
> > around in the generic NFS functions (for post-op updates and inode
> > revalidation, and what not).
> >
> > Can I recommend "struct nfs_seclabel" instead?  Then have
> > nfs_seclabel_alloc() and nfs_seclabel_free().
> 
> Security has been the primary consumer of labels to date, but
> the xattr concept has always been envisioned as useful in many
> ways. That, and people have so many different views on what is
> and isn't security and whether it is good or evil that you are
> asking to limit the value if you tie "security" to the names.
> Plus, it adds unnecessary characters.

I agree that xattrs are useful in other ways but this NFSv4 attribute's
purpose is security labels. This is definitely not meant to be anything
like an xattr.

> 
> >
> > Does it make sense to deduplicate these in the client's memory?  It
> > seems to me that you could have hundreds or thousands that all contain
> > the same label information.
> 
> That would be easy enough to do. Look at smack_import() for a
> worked example.
> 

I'm not sure its worth it. These structures don't stay around for long.
Its purpose is just to get the info up the stack to a point where we can
put it in the inode proper. 

> >
> >> +
> >> +
> >>   typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
> >>   typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
> >>
> >> diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
> >> index 07ce460..2813b71 100644
> >> --- a/include/linux/nfs_fs.h
> >> +++ b/include/linux/nfs_fs.h
> >> @@ -454,6 +454,13 @@ extern int nfs_mountpoint_expiry_timeout;
> >>   extern void nfs_release_automount_timer(void);
> >>
> >>   /*
> >> + * linux/fs/nfs/nfs4proc.c
> >> + */
> >> +
> >> +struct nfs4_label *    nfs4_label_alloc (gfp_t flags);
> >> +void            nfs4_label_free (struct nfs4_label *);
> >> +
> >> +/*
> >>    * linux/fs/nfs/unlink.c
> >>    */
> >>   extern int  nfs_async_unlink(struct inode *dir, struct dentry
> >> *dentry);
> >> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> >> index 28cde54..dc505e4 100644
> >> --- a/include/linux/nfs_xdr.h
> >> +++ b/include/linux/nfs_xdr.h
> >> @@ -207,6 +207,7 @@ struct nfs_openargs {
> >>       const struct nfs_server *server;     /* Needed for ID mapping */
> >>       const u32 *        bitmask;
> >>       __u32            claim;
> >> +    const struct nfs4_label *label;
> >>       struct nfs4_sequence_args    seq_args;
> >>   };
> >>
> >> @@ -216,7 +217,9 @@ struct nfs_openres {
> >>       struct nfs4_change_info    cinfo;
> >>       __u32                   rflags;
> >>       struct nfs_fattr *      f_attr;
> >> +    struct nfs4_label *    f_label;
> >>       struct nfs_fattr *      dir_attr;
> >> +    struct nfs4_label *    dir_label;
> >>       struct nfs_seqid *    seqid;
> >>       const struct nfs_server *server;
> >>       fmode_t            delegation_type;
> >> @@ -256,6 +259,7 @@ struct nfs_closeargs {
> >>   struct nfs_closeres {
> >>       nfs4_stateid            stateid;
> >>       struct nfs_fattr *    fattr;
> >> +    struct nfs4_label *    label;
> >>       struct nfs_seqid *    seqid;
> >>       const struct nfs_server *server;
> >>       struct nfs4_sequence_res    seq_res;
> >> @@ -324,6 +328,7 @@ struct nfs4_delegreturnargs {
> >>
> >>   struct nfs4_delegreturnres {
> >>       struct nfs_fattr * fattr;
> >> +    struct nfs4_label * label;
> >>       const struct nfs_server *server;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >> @@ -343,6 +348,7 @@ struct nfs_readargs {
> >>
> >>   struct nfs_readres {
> >>       struct nfs_fattr *    fattr;
> >> +    struct nfs4_label *    label;
> >>       __u32            count;
> >>       int                     eof;
> >>       struct nfs4_sequence_res    seq_res;
> >> @@ -390,6 +396,7 @@ struct nfs_removeres {
> >>       const struct nfs_server *server;
> >>       struct nfs4_change_info    cinfo;
> >>       struct nfs_fattr    dir_attr;
> >> +    struct nfs4_label    *dir_label;
> >>       struct nfs4_sequence_res     seq_res;
> >>   };
> >>
> >> @@ -405,6 +412,7 @@ struct nfs_entry {
> >>       int            eof;
> >>       struct nfs_fh *        fh;
> >>       struct nfs_fattr *    fattr;
> >> +    struct nfs4_label *    label;
> >>   };
> >>
> >>   /*
> >> @@ -443,6 +451,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 nfs4_sequence_args     seq_args;
> >>   };
> >>
> >> @@ -473,6 +482,7 @@ struct nfs_getaclres {
> >>
> >>   struct nfs_setattrres {
> >>       struct nfs_fattr *              fattr;
> >> +    struct nfs4_label *        label;
> >>       const struct nfs_server *    server;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >> @@ -662,6 +672,7 @@ struct nfs4_accessargs {
> >>   struct nfs4_accessres {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fattr *        fattr;
> >> +    struct nfs4_label *        label;
> >>       u32                supported;
> >>       u32                access;
> >>       struct nfs4_sequence_res    seq_res;
> >> @@ -684,6 +695,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_sequence_args     seq_args;
> >>   };
> >>
> >> @@ -691,8 +703,10 @@ struct nfs4_create_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fh *            fh;
> >>       struct nfs_fattr *        fattr;
> >> +    struct nfs4_label *        label;
> >>       struct nfs4_change_info        dir_cinfo;
> >>       struct nfs_fattr *        dir_fattr;
> >> +    struct nfs4_label *        dir_label;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >>
> >> @@ -717,6 +731,7 @@ struct nfs4_getattr_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fattr *        fattr;
> >>       struct nfs4_sequence_res    seq_res;
> >> +    struct nfs4_label *        label;
> >>   };
> >>
> >>   struct nfs4_link_arg {
> >> @@ -730,8 +745,10 @@ struct nfs4_link_arg {
> >>   struct nfs4_link_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fattr *        fattr;
> >> +    struct nfs4_label *        label;
> >>       struct nfs4_change_info        cinfo;
> >>       struct nfs_fattr *        dir_attr;
> >> +    struct nfs4_label *        dir_label;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >>
> >> @@ -747,6 +764,7 @@ struct nfs4_lookup_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fattr *        fattr;
> >>       struct nfs_fh *            fh;
> >> +    struct nfs4_label *        label;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >>
> >> @@ -800,6 +818,8 @@ struct nfs4_rename_arg {
> >>       const struct nfs_fh *        new_dir;
> >>       const struct qstr *        old_name;
> >>       const struct qstr *        new_name;
> >> +    const struct nfs4_label *    old_label;
> >> +    const struct nfs4_label *    new_label;
> >>       const u32 *            bitmask;
> >>       struct nfs4_sequence_args    seq_args;
> >>   };
> >> @@ -808,8 +828,10 @@ struct nfs4_rename_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs4_change_info        old_cinfo;
> >>       struct nfs_fattr *        old_fattr;
> >> +    struct nfs4_label *        old_label;
> >>       struct nfs4_change_info        new_cinfo;
> >>       struct nfs_fattr *        new_fattr;
> >> +    struct nfs4_label *        new_label;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >>
> >
> >


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
@ 2010-07-07 16:24         ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 16:24 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Chuck Lever, hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	sds-+05T5uksL2qpZYMLLGbcSA, matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	bfields-uC3wQj2KruNg9hUCZPvPmw,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

On Wed, 2010-07-07 at 09:21 -0700, Casey Schaufler wrote:
> Chuck Lever wrote:
> > My comments below apply to the other NFS client patches as well.  This
> > seemed like the right one to use for code examples.
> >
> > On 07/ 7/10 10:31 AM, David P. Quigley wrote:
> >> 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-DABiIiYg7OfQT0dZR+AlfA@public.gmane.org>
> >> Signed-off-by: David P. Quigley<dpquigl-+05T5uksL2qpZYMLLGbcSA@public.gmane.org>
> >> ---
> >>   fs/nfs/nfs4proc.c       |   26 ++++++++++++++++++++++++++
> >>   fs/nfsd/xdr4.h          |    3 +++
> >>   include/linux/nfs4.h    |    7 +++++++
> >>   include/linux/nfs_fs.h  |    7 +++++++
> >>   include/linux/nfs_xdr.h |   22 ++++++++++++++++++++++
> >>   5 files changed, 65 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> >> index 071fced..71bb8da 100644
> >> --- a/fs/nfs/nfs4proc.c
> >> +++ b/fs/nfs/nfs4proc.c
> >> @@ -148,6 +148,32 @@ const u32 nfs4_fs_locations_bitmap[2] = {
> >>       | FATTR4_WORD1_MOUNTED_ON_FILEID
> >>   };
> >>
> >> +#ifdef CONFIG_NFS_V4_SECURITY_LABEL
> >> +
> >> +struct nfs4_label * nfs4_label_alloc (gfp_t flags)
> >
> > Style: have you run these patches through scripts/checkpatch.pl? 
> > Kernel coding style likes "struct foo *function(args)", without the
> > spaces.
> >
> >> +{
> >> +    struct nfs4_label *label = NULL;
> >> +
> >> +    label = kzalloc(sizeof(struct nfs4_label) + NFS4_MAXLABELLEN,
> >> flags);
> >> +    if (label == NULL)
> >> +        return NULL;
> >
> > Instead of NULL, you could return an ERR_PTR.  NULL could then be used
> > to signal that labels aren't supported.  See below.
> >
> >> +
> >> +    label->label = (void *)(label + 1);
> >> +    label->len = NFS4_MAXLABELLEN;
> >> +    /* 0 is the null format meaning that the data is not to be
> >> translated */
> >> +     label->lfs = 0;
> >> +    return label;
> >> +}
> >> +
> >> +void nfs4_label_free (struct nfs4_label *label)
> >> +{
> >> +    if (label)
> >> +        kfree(label);
> >
> > Style: kfree() already checks for a NULL pointer, so you shouldn't. 
> > At one point recently, all such checks were removed from the kernel in
> > favor of using the one already in kfree().
> >
> > Also, you check the server capabilities before calling this function,
> > nearly every time.  Is that really needed?  If there's a label data
> > structure, it should be freed whether the server supports it or not.
> >
> > That capabilities check is probably going to be more complex if you
> > want to have NFSv3 label support as well.  Would it make sense to
> > provide a function that can check for NFSv3 (eventually) or NFSv4
> > label support?
> >
> > Or, fold such checks into your allocator?  Hiding the capabilities
> > check here would allow easy expansion in the future to include other
> > NFS versions, and cause less clutter in all callers.
> >
> >> +    return;
> >> +}
> >> +
> >> +#endif
> >
> > Style: Generally speaking, we like to keep "#ifdef CONFIG_BAR" noise
> > down to a dull roar.  So, this is the right place to keep it, and the
> > generic functions (like nfs_lookup() and nfs_readdir()) is generally not.
> >
> > Usually we accomplish this by having functions like nfs4_label_free()
> > always be available, but if CONFIG_NFS_V4_SECURITY_LABEL isn't set,
> > the function call is a no-op.
> >
> >> +
> >>   static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct
> >> dentry *dentry,
> >>           struct nfs4_readdir_arg *readdir)
> >>   {
> >> diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
> >> index efa3377..c217277 100644
> >> --- a/fs/nfsd/xdr4.h
> >> +++ b/fs/nfsd/xdr4.h
> >> @@ -108,6 +108,7 @@ struct nfsd4_create {
> >>       struct iattr    cr_iattr;           /* request */
> >>       struct nfsd4_change_info  cr_cinfo; /* response */
> >>       struct nfs4_acl *cr_acl;
> >> +    struct nfs4_label *cr_label;
> >>   };
> >>   #define cr_linklen    u.link.namelen
> >>   #define cr_linkname    u.link.name
> >> @@ -235,6 +236,7 @@ struct nfsd4_open {
> >>       int        op_truncate;        /* used during processing */
> >>       struct nfs4_stateowner *op_stateowner; /* used during
> >> processing */
> >>       struct nfs4_acl *op_acl;
> >> +    struct nfs4_label *op_label;
> >>   };
> >>   #define op_iattr    iattr
> >>   #define op_verf        verf
> >> @@ -316,6 +318,7 @@ struct nfsd4_setattr {
> >>       u32        sa_bmval[3];        /* request */
> >>       struct iattr    sa_iattr;           /* request */
> >>       struct nfs4_acl *sa_acl;
> >> +    struct nfs4_label *sa_label;
> >>   };
> >>
> >>   struct nfsd4_setclientid {
> >> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
> >> index a2abd1a..c512a0c 100644
> >> --- a/include/linux/nfs4.h
> >> +++ b/include/linux/nfs4.h
> >> @@ -167,6 +167,13 @@ struct nfs4_acl {
> >>       struct nfs4_ace    aces[0];
> >>   };
> >>
> >> +struct nfs4_label {
> >> +    void        *label;
> >> +    u32        len;
> >> +    uint32_t    lfs;
> >> +};
> >
> > If we have support for NFS labels in NFSv3, would we also use struct
> > nfs4_label?
> >
> > It seems to me you want something more generic, just like nfs_fh or
> > nfs_fattr, to represent these.  Over time, I'm guessing label support
> > won't be tied to a specific NFS version.  And, you are passing these
> > around in the generic NFS functions (for post-op updates and inode
> > revalidation, and what not).
> >
> > Can I recommend "struct nfs_seclabel" instead?  Then have
> > nfs_seclabel_alloc() and nfs_seclabel_free().
> 
> Security has been the primary consumer of labels to date, but
> the xattr concept has always been envisioned as useful in many
> ways. That, and people have so many different views on what is
> and isn't security and whether it is good or evil that you are
> asking to limit the value if you tie "security" to the names.
> Plus, it adds unnecessary characters.

I agree that xattrs are useful in other ways but this NFSv4 attribute's
purpose is security labels. This is definitely not meant to be anything
like an xattr.

> 
> >
> > Does it make sense to deduplicate these in the client's memory?  It
> > seems to me that you could have hundreds or thousands that all contain
> > the same label information.
> 
> That would be easy enough to do. Look at smack_import() for a
> worked example.
> 

I'm not sure its worth it. These structures don't stay around for long.
Its purpose is just to get the info up the stack to a point where we can
put it in the inode proper. 

> >
> >> +
> >> +
> >>   typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
> >>   typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
> >>
> >> diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
> >> index 07ce460..2813b71 100644
> >> --- a/include/linux/nfs_fs.h
> >> +++ b/include/linux/nfs_fs.h
> >> @@ -454,6 +454,13 @@ extern int nfs_mountpoint_expiry_timeout;
> >>   extern void nfs_release_automount_timer(void);
> >>
> >>   /*
> >> + * linux/fs/nfs/nfs4proc.c
> >> + */
> >> +
> >> +struct nfs4_label *    nfs4_label_alloc (gfp_t flags);
> >> +void            nfs4_label_free (struct nfs4_label *);
> >> +
> >> +/*
> >>    * linux/fs/nfs/unlink.c
> >>    */
> >>   extern int  nfs_async_unlink(struct inode *dir, struct dentry
> >> *dentry);
> >> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> >> index 28cde54..dc505e4 100644
> >> --- a/include/linux/nfs_xdr.h
> >> +++ b/include/linux/nfs_xdr.h
> >> @@ -207,6 +207,7 @@ struct nfs_openargs {
> >>       const struct nfs_server *server;     /* Needed for ID mapping */
> >>       const u32 *        bitmask;
> >>       __u32            claim;
> >> +    const struct nfs4_label *label;
> >>       struct nfs4_sequence_args    seq_args;
> >>   };
> >>
> >> @@ -216,7 +217,9 @@ struct nfs_openres {
> >>       struct nfs4_change_info    cinfo;
> >>       __u32                   rflags;
> >>       struct nfs_fattr *      f_attr;
> >> +    struct nfs4_label *    f_label;
> >>       struct nfs_fattr *      dir_attr;
> >> +    struct nfs4_label *    dir_label;
> >>       struct nfs_seqid *    seqid;
> >>       const struct nfs_server *server;
> >>       fmode_t            delegation_type;
> >> @@ -256,6 +259,7 @@ struct nfs_closeargs {
> >>   struct nfs_closeres {
> >>       nfs4_stateid            stateid;
> >>       struct nfs_fattr *    fattr;
> >> +    struct nfs4_label *    label;
> >>       struct nfs_seqid *    seqid;
> >>       const struct nfs_server *server;
> >>       struct nfs4_sequence_res    seq_res;
> >> @@ -324,6 +328,7 @@ struct nfs4_delegreturnargs {
> >>
> >>   struct nfs4_delegreturnres {
> >>       struct nfs_fattr * fattr;
> >> +    struct nfs4_label * label;
> >>       const struct nfs_server *server;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >> @@ -343,6 +348,7 @@ struct nfs_readargs {
> >>
> >>   struct nfs_readres {
> >>       struct nfs_fattr *    fattr;
> >> +    struct nfs4_label *    label;
> >>       __u32            count;
> >>       int                     eof;
> >>       struct nfs4_sequence_res    seq_res;
> >> @@ -390,6 +396,7 @@ struct nfs_removeres {
> >>       const struct nfs_server *server;
> >>       struct nfs4_change_info    cinfo;
> >>       struct nfs_fattr    dir_attr;
> >> +    struct nfs4_label    *dir_label;
> >>       struct nfs4_sequence_res     seq_res;
> >>   };
> >>
> >> @@ -405,6 +412,7 @@ struct nfs_entry {
> >>       int            eof;
> >>       struct nfs_fh *        fh;
> >>       struct nfs_fattr *    fattr;
> >> +    struct nfs4_label *    label;
> >>   };
> >>
> >>   /*
> >> @@ -443,6 +451,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 nfs4_sequence_args     seq_args;
> >>   };
> >>
> >> @@ -473,6 +482,7 @@ struct nfs_getaclres {
> >>
> >>   struct nfs_setattrres {
> >>       struct nfs_fattr *              fattr;
> >> +    struct nfs4_label *        label;
> >>       const struct nfs_server *    server;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >> @@ -662,6 +672,7 @@ struct nfs4_accessargs {
> >>   struct nfs4_accessres {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fattr *        fattr;
> >> +    struct nfs4_label *        label;
> >>       u32                supported;
> >>       u32                access;
> >>       struct nfs4_sequence_res    seq_res;
> >> @@ -684,6 +695,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_sequence_args     seq_args;
> >>   };
> >>
> >> @@ -691,8 +703,10 @@ struct nfs4_create_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fh *            fh;
> >>       struct nfs_fattr *        fattr;
> >> +    struct nfs4_label *        label;
> >>       struct nfs4_change_info        dir_cinfo;
> >>       struct nfs_fattr *        dir_fattr;
> >> +    struct nfs4_label *        dir_label;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >>
> >> @@ -717,6 +731,7 @@ struct nfs4_getattr_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fattr *        fattr;
> >>       struct nfs4_sequence_res    seq_res;
> >> +    struct nfs4_label *        label;
> >>   };
> >>
> >>   struct nfs4_link_arg {
> >> @@ -730,8 +745,10 @@ struct nfs4_link_arg {
> >>   struct nfs4_link_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fattr *        fattr;
> >> +    struct nfs4_label *        label;
> >>       struct nfs4_change_info        cinfo;
> >>       struct nfs_fattr *        dir_attr;
> >> +    struct nfs4_label *        dir_label;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >>
> >> @@ -747,6 +764,7 @@ struct nfs4_lookup_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fattr *        fattr;
> >>       struct nfs_fh *            fh;
> >> +    struct nfs4_label *        label;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >>
> >> @@ -800,6 +818,8 @@ struct nfs4_rename_arg {
> >>       const struct nfs_fh *        new_dir;
> >>       const struct qstr *        old_name;
> >>       const struct qstr *        new_name;
> >> +    const struct nfs4_label *    old_label;
> >> +    const struct nfs4_label *    new_label;
> >>       const u32 *            bitmask;
> >>       struct nfs4_sequence_args    seq_args;
> >>   };
> >> @@ -808,8 +828,10 @@ struct nfs4_rename_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs4_change_info        old_cinfo;
> >>       struct nfs_fattr *        old_fattr;
> >> +    struct nfs4_label *        old_label;
> >>       struct nfs4_change_info        new_cinfo;
> >>       struct nfs_fattr *        new_fattr;
> >> +    struct nfs4_label *        new_label;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >>
> >
> >

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
@ 2010-07-07 16:24         ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 16:24 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Chuck Lever, hch, viro, sds, matthew.dodd, trond.myklebust,
	bfields, linux-kernel, linux-fsdevel, linux-security-module,
	selinux, linux-nfs

On Wed, 2010-07-07 at 09:21 -0700, Casey Schaufler wrote:
> Chuck Lever wrote:
> > My comments below apply to the other NFS client patches as well.  This
> > seemed like the right one to use for code examples.
> >
> > On 07/ 7/10 10:31 AM, David P. Quigley wrote:
> >> 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>
> >> ---
> >>   fs/nfs/nfs4proc.c       |   26 ++++++++++++++++++++++++++
> >>   fs/nfsd/xdr4.h          |    3 +++
> >>   include/linux/nfs4.h    |    7 +++++++
> >>   include/linux/nfs_fs.h  |    7 +++++++
> >>   include/linux/nfs_xdr.h |   22 ++++++++++++++++++++++
> >>   5 files changed, 65 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> >> index 071fced..71bb8da 100644
> >> --- a/fs/nfs/nfs4proc.c
> >> +++ b/fs/nfs/nfs4proc.c
> >> @@ -148,6 +148,32 @@ const u32 nfs4_fs_locations_bitmap[2] = {
> >>       | FATTR4_WORD1_MOUNTED_ON_FILEID
> >>   };
> >>
> >> +#ifdef CONFIG_NFS_V4_SECURITY_LABEL
> >> +
> >> +struct nfs4_label * nfs4_label_alloc (gfp_t flags)
> >
> > Style: have you run these patches through scripts/checkpatch.pl? 
> > Kernel coding style likes "struct foo *function(args)", without the
> > spaces.
> >
> >> +{
> >> +    struct nfs4_label *label = NULL;
> >> +
> >> +    label = kzalloc(sizeof(struct nfs4_label) + NFS4_MAXLABELLEN,
> >> flags);
> >> +    if (label == NULL)
> >> +        return NULL;
> >
> > Instead of NULL, you could return an ERR_PTR.  NULL could then be used
> > to signal that labels aren't supported.  See below.
> >
> >> +
> >> +    label->label = (void *)(label + 1);
> >> +    label->len = NFS4_MAXLABELLEN;
> >> +    /* 0 is the null format meaning that the data is not to be
> >> translated */
> >> +     label->lfs = 0;
> >> +    return label;
> >> +}
> >> +
> >> +void nfs4_label_free (struct nfs4_label *label)
> >> +{
> >> +    if (label)
> >> +        kfree(label);
> >
> > Style: kfree() already checks for a NULL pointer, so you shouldn't. 
> > At one point recently, all such checks were removed from the kernel in
> > favor of using the one already in kfree().
> >
> > Also, you check the server capabilities before calling this function,
> > nearly every time.  Is that really needed?  If there's a label data
> > structure, it should be freed whether the server supports it or not.
> >
> > That capabilities check is probably going to be more complex if you
> > want to have NFSv3 label support as well.  Would it make sense to
> > provide a function that can check for NFSv3 (eventually) or NFSv4
> > label support?
> >
> > Or, fold such checks into your allocator?  Hiding the capabilities
> > check here would allow easy expansion in the future to include other
> > NFS versions, and cause less clutter in all callers.
> >
> >> +    return;
> >> +}
> >> +
> >> +#endif
> >
> > Style: Generally speaking, we like to keep "#ifdef CONFIG_BAR" noise
> > down to a dull roar.  So, this is the right place to keep it, and the
> > generic functions (like nfs_lookup() and nfs_readdir()) is generally not.
> >
> > Usually we accomplish this by having functions like nfs4_label_free()
> > always be available, but if CONFIG_NFS_V4_SECURITY_LABEL isn't set,
> > the function call is a no-op.
> >
> >> +
> >>   static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct
> >> dentry *dentry,
> >>           struct nfs4_readdir_arg *readdir)
> >>   {
> >> diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
> >> index efa3377..c217277 100644
> >> --- a/fs/nfsd/xdr4.h
> >> +++ b/fs/nfsd/xdr4.h
> >> @@ -108,6 +108,7 @@ struct nfsd4_create {
> >>       struct iattr    cr_iattr;           /* request */
> >>       struct nfsd4_change_info  cr_cinfo; /* response */
> >>       struct nfs4_acl *cr_acl;
> >> +    struct nfs4_label *cr_label;
> >>   };
> >>   #define cr_linklen    u.link.namelen
> >>   #define cr_linkname    u.link.name
> >> @@ -235,6 +236,7 @@ struct nfsd4_open {
> >>       int        op_truncate;        /* used during processing */
> >>       struct nfs4_stateowner *op_stateowner; /* used during
> >> processing */
> >>       struct nfs4_acl *op_acl;
> >> +    struct nfs4_label *op_label;
> >>   };
> >>   #define op_iattr    iattr
> >>   #define op_verf        verf
> >> @@ -316,6 +318,7 @@ struct nfsd4_setattr {
> >>       u32        sa_bmval[3];        /* request */
> >>       struct iattr    sa_iattr;           /* request */
> >>       struct nfs4_acl *sa_acl;
> >> +    struct nfs4_label *sa_label;
> >>   };
> >>
> >>   struct nfsd4_setclientid {
> >> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
> >> index a2abd1a..c512a0c 100644
> >> --- a/include/linux/nfs4.h
> >> +++ b/include/linux/nfs4.h
> >> @@ -167,6 +167,13 @@ struct nfs4_acl {
> >>       struct nfs4_ace    aces[0];
> >>   };
> >>
> >> +struct nfs4_label {
> >> +    void        *label;
> >> +    u32        len;
> >> +    uint32_t    lfs;
> >> +};
> >
> > If we have support for NFS labels in NFSv3, would we also use struct
> > nfs4_label?
> >
> > It seems to me you want something more generic, just like nfs_fh or
> > nfs_fattr, to represent these.  Over time, I'm guessing label support
> > won't be tied to a specific NFS version.  And, you are passing these
> > around in the generic NFS functions (for post-op updates and inode
> > revalidation, and what not).
> >
> > Can I recommend "struct nfs_seclabel" instead?  Then have
> > nfs_seclabel_alloc() and nfs_seclabel_free().
> 
> Security has been the primary consumer of labels to date, but
> the xattr concept has always been envisioned as useful in many
> ways. That, and people have so many different views on what is
> and isn't security and whether it is good or evil that you are
> asking to limit the value if you tie "security" to the names.
> Plus, it adds unnecessary characters.

I agree that xattrs are useful in other ways but this NFSv4 attribute's
purpose is security labels. This is definitely not meant to be anything
like an xattr.

> 
> >
> > Does it make sense to deduplicate these in the client's memory?  It
> > seems to me that you could have hundreds or thousands that all contain
> > the same label information.
> 
> That would be easy enough to do. Look at smack_import() for a
> worked example.
> 

I'm not sure its worth it. These structures don't stay around for long.
Its purpose is just to get the info up the stack to a point where we can
put it in the inode proper. 

> >
> >> +
> >> +
> >>   typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
> >>   typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
> >>
> >> diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
> >> index 07ce460..2813b71 100644
> >> --- a/include/linux/nfs_fs.h
> >> +++ b/include/linux/nfs_fs.h
> >> @@ -454,6 +454,13 @@ extern int nfs_mountpoint_expiry_timeout;
> >>   extern void nfs_release_automount_timer(void);
> >>
> >>   /*
> >> + * linux/fs/nfs/nfs4proc.c
> >> + */
> >> +
> >> +struct nfs4_label *    nfs4_label_alloc (gfp_t flags);
> >> +void            nfs4_label_free (struct nfs4_label *);
> >> +
> >> +/*
> >>    * linux/fs/nfs/unlink.c
> >>    */
> >>   extern int  nfs_async_unlink(struct inode *dir, struct dentry
> >> *dentry);
> >> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> >> index 28cde54..dc505e4 100644
> >> --- a/include/linux/nfs_xdr.h
> >> +++ b/include/linux/nfs_xdr.h
> >> @@ -207,6 +207,7 @@ struct nfs_openargs {
> >>       const struct nfs_server *server;     /* Needed for ID mapping */
> >>       const u32 *        bitmask;
> >>       __u32            claim;
> >> +    const struct nfs4_label *label;
> >>       struct nfs4_sequence_args    seq_args;
> >>   };
> >>
> >> @@ -216,7 +217,9 @@ struct nfs_openres {
> >>       struct nfs4_change_info    cinfo;
> >>       __u32                   rflags;
> >>       struct nfs_fattr *      f_attr;
> >> +    struct nfs4_label *    f_label;
> >>       struct nfs_fattr *      dir_attr;
> >> +    struct nfs4_label *    dir_label;
> >>       struct nfs_seqid *    seqid;
> >>       const struct nfs_server *server;
> >>       fmode_t            delegation_type;
> >> @@ -256,6 +259,7 @@ struct nfs_closeargs {
> >>   struct nfs_closeres {
> >>       nfs4_stateid            stateid;
> >>       struct nfs_fattr *    fattr;
> >> +    struct nfs4_label *    label;
> >>       struct nfs_seqid *    seqid;
> >>       const struct nfs_server *server;
> >>       struct nfs4_sequence_res    seq_res;
> >> @@ -324,6 +328,7 @@ struct nfs4_delegreturnargs {
> >>
> >>   struct nfs4_delegreturnres {
> >>       struct nfs_fattr * fattr;
> >> +    struct nfs4_label * label;
> >>       const struct nfs_server *server;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >> @@ -343,6 +348,7 @@ struct nfs_readargs {
> >>
> >>   struct nfs_readres {
> >>       struct nfs_fattr *    fattr;
> >> +    struct nfs4_label *    label;
> >>       __u32            count;
> >>       int                     eof;
> >>       struct nfs4_sequence_res    seq_res;
> >> @@ -390,6 +396,7 @@ struct nfs_removeres {
> >>       const struct nfs_server *server;
> >>       struct nfs4_change_info    cinfo;
> >>       struct nfs_fattr    dir_attr;
> >> +    struct nfs4_label    *dir_label;
> >>       struct nfs4_sequence_res     seq_res;
> >>   };
> >>
> >> @@ -405,6 +412,7 @@ struct nfs_entry {
> >>       int            eof;
> >>       struct nfs_fh *        fh;
> >>       struct nfs_fattr *    fattr;
> >> +    struct nfs4_label *    label;
> >>   };
> >>
> >>   /*
> >> @@ -443,6 +451,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 nfs4_sequence_args     seq_args;
> >>   };
> >>
> >> @@ -473,6 +482,7 @@ struct nfs_getaclres {
> >>
> >>   struct nfs_setattrres {
> >>       struct nfs_fattr *              fattr;
> >> +    struct nfs4_label *        label;
> >>       const struct nfs_server *    server;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >> @@ -662,6 +672,7 @@ struct nfs4_accessargs {
> >>   struct nfs4_accessres {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fattr *        fattr;
> >> +    struct nfs4_label *        label;
> >>       u32                supported;
> >>       u32                access;
> >>       struct nfs4_sequence_res    seq_res;
> >> @@ -684,6 +695,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_sequence_args     seq_args;
> >>   };
> >>
> >> @@ -691,8 +703,10 @@ struct nfs4_create_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fh *            fh;
> >>       struct nfs_fattr *        fattr;
> >> +    struct nfs4_label *        label;
> >>       struct nfs4_change_info        dir_cinfo;
> >>       struct nfs_fattr *        dir_fattr;
> >> +    struct nfs4_label *        dir_label;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >>
> >> @@ -717,6 +731,7 @@ struct nfs4_getattr_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fattr *        fattr;
> >>       struct nfs4_sequence_res    seq_res;
> >> +    struct nfs4_label *        label;
> >>   };
> >>
> >>   struct nfs4_link_arg {
> >> @@ -730,8 +745,10 @@ struct nfs4_link_arg {
> >>   struct nfs4_link_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fattr *        fattr;
> >> +    struct nfs4_label *        label;
> >>       struct nfs4_change_info        cinfo;
> >>       struct nfs_fattr *        dir_attr;
> >> +    struct nfs4_label *        dir_label;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >>
> >> @@ -747,6 +764,7 @@ struct nfs4_lookup_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs_fattr *        fattr;
> >>       struct nfs_fh *            fh;
> >> +    struct nfs4_label *        label;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >>
> >> @@ -800,6 +818,8 @@ struct nfs4_rename_arg {
> >>       const struct nfs_fh *        new_dir;
> >>       const struct qstr *        old_name;
> >>       const struct qstr *        new_name;
> >> +    const struct nfs4_label *    old_label;
> >> +    const struct nfs4_label *    new_label;
> >>       const u32 *            bitmask;
> >>       struct nfs4_sequence_args    seq_args;
> >>   };
> >> @@ -808,8 +828,10 @@ struct nfs4_rename_res {
> >>       const struct nfs_server *    server;
> >>       struct nfs4_change_info        old_cinfo;
> >>       struct nfs_fattr *        old_fattr;
> >> +    struct nfs4_label *        old_label;
> >>       struct nfs4_change_info        new_cinfo;
> >>       struct nfs_fattr *        new_fattr;
> >> +    struct nfs4_label *        new_label;
> >>       struct nfs4_sequence_res    seq_res;
> >>   };
> >>
> >
> >


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 02/10] Security: Add Hook to test if the particular xattr is part of a MAC model.
@ 2010-07-07 16:49     ` J. Bruce Fields
  0 siblings, 0 replies; 95+ messages in thread
From: J. Bruce Fields @ 2010-07-07 16:49 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, Jul 07, 2010 at 10:31:18AM -0400, David P. Quigley wrote:
> There are areas in the Labeled NFS code where where we need to test if the
> attribute being requested exhibits the semantics of a MAC model.

I have no idea what that means....

> + * @ismaclabel:
> + * 	Check if the extended attribute specified by @name represents a MAC label.

Is this what you mean to say?

--b.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 02/10] Security: Add Hook to test if the particular xattr is part of a MAC model.
@ 2010-07-07 16:49     ` J. Bruce Fields
  0 siblings, 0 replies; 95+ messages in thread
From: J. Bruce Fields @ 2010-07-07 16:49 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	casey-iSGtlc1asvQWG2LlvL+J4A, sds-+05T5uksL2qpZYMLLGbcSA,
	matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

On Wed, Jul 07, 2010 at 10:31:18AM -0400, David P. Quigley wrote:
> There are areas in the Labeled NFS code where where we need to test if the
> attribute being requested exhibits the semantics of a MAC model.

I have no idea what that means....

> + * @ismaclabel:
> + * 	Check if the extended attribute specified by @name represents a MAC label.

Is this what you mean to say?

--b.
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 05/10] KConfig: Add KConfig entries for Labeled NFS
@ 2010-07-07 16:56     ` J. Bruce Fields
  0 siblings, 0 replies; 95+ messages in thread
From: J. Bruce Fields @ 2010-07-07 16:56 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, Jul 07, 2010 at 10:31:21AM -0400, David P. Quigley wrote:
> 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.

Will there also be some way to turn these on and off at run-time (maybe
for particular exports or filesystems?)

And if so, will there be any reason not to have this on all the time?  I
don't think we'll want a config option for every future possible NFSv4.x
feature.

--b.

> 
> Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
> Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
> ---
>  fs/nfs/Kconfig  |   16 ++++++++++++++++
>  fs/nfsd/Kconfig |   13 +++++++++++++
>  2 files changed, 29 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
> index a43d07e..67b158c 100644
> --- a/fs/nfs/Kconfig
> +++ b/fs/nfs/Kconfig
> @@ -83,6 +83,22 @@ config NFS_V4_1
>  
>  	  Unless you're an NFS developer, say N.
>  
> +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 enable fine-grained 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.
> +	Without this an NFSv4 mount will have the same label on each file.
> +
> +	If you do not wish to enable fine-grained security labels SELinux or
> +	Smack policies on NFSv4 files, say N.
> +
> +
> +	  If unsure, say N.
> +
>  config ROOT_NFS
>  	bool "Root file system on NFS"
>  	depends on NFS_FS=y && IP_PNP
> diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
> index 503b9da..3a282f8 100644
> --- a/fs/nfsd/Kconfig
> +++ b/fs/nfsd/Kconfig
> @@ -79,3 +79,16 @@ config NFSD_V4
>  	  available from http://linux-nfs.org/.
>  
>  	  If unsure, say N.
> +
> +config NFSD_V4_SECURITY_LABEL
> +	bool "Provide Security Label support for NFSv4 server"
> +	depends on NFSD_V4 && SECURITY
> +	help
> +
> +	Say Y here if you want enable fine-grained 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.
> +	Without this an NFSv4 mount will have the same label on each file.
> +
> +	If you do not wish to enable fine-grained security labels SELinux or
> +	Smack policies on NFSv4 files, say N.
> -- 
> 1.6.2.5
> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 05/10] KConfig: Add KConfig entries for Labeled NFS
@ 2010-07-07 16:56     ` J. Bruce Fields
  0 siblings, 0 replies; 95+ messages in thread
From: J. Bruce Fields @ 2010-07-07 16:56 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	casey-iSGtlc1asvQWG2LlvL+J4A, sds-+05T5uksL2qpZYMLLGbcSA,
	matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

On Wed, Jul 07, 2010 at 10:31:21AM -0400, David P. Quigley wrote:
> 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.

Will there also be some way to turn these on and off at run-time (maybe
for particular exports or filesystems?)

And if so, will there be any reason not to have this on all the time?  I
don't think we'll want a config option for every future possible NFSv4.x
feature.

--b.

> 
> Signed-off-by: Matthew N. Dodd <Matthew.Dodd-DABiIiYg7OfQT0dZR+AlfA@public.gmane.org>
> Signed-off-by: David P. Quigley <dpquigl-+05T5uksL2qpZYMLLGbcSA@public.gmane.org>
> ---
>  fs/nfs/Kconfig  |   16 ++++++++++++++++
>  fs/nfsd/Kconfig |   13 +++++++++++++
>  2 files changed, 29 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
> index a43d07e..67b158c 100644
> --- a/fs/nfs/Kconfig
> +++ b/fs/nfs/Kconfig
> @@ -83,6 +83,22 @@ config NFS_V4_1
>  
>  	  Unless you're an NFS developer, say N.
>  
> +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 enable fine-grained 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.
> +	Without this an NFSv4 mount will have the same label on each file.
> +
> +	If you do not wish to enable fine-grained security labels SELinux or
> +	Smack policies on NFSv4 files, say N.
> +
> +
> +	  If unsure, say N.
> +
>  config ROOT_NFS
>  	bool "Root file system on NFS"
>  	depends on NFS_FS=y && IP_PNP
> diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
> index 503b9da..3a282f8 100644
> --- a/fs/nfsd/Kconfig
> +++ b/fs/nfsd/Kconfig
> @@ -79,3 +79,16 @@ config NFSD_V4
>  	  available from http://linux-nfs.org/.
>  
>  	  If unsure, say N.
> +
> +config NFSD_V4_SECURITY_LABEL
> +	bool "Provide Security Label support for NFSv4 server"
> +	depends on NFSD_V4 && SECURITY
> +	help
> +
> +	Say Y here if you want enable fine-grained 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.
> +	Without this an NFSv4 mount will have the same label on each file.
> +
> +	If you do not wish to enable fine-grained security labels SELinux or
> +	Smack policies on NFSv4 files, say N.
> -- 
> 1.6.2.5
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
  2010-07-07 14:31   ` David P. Quigley
  (?)
@ 2010-07-07 17:00   ` J. Bruce Fields
  2010-07-07 23:30       ` James Morris
  -1 siblings, 1 reply; 95+ messages in thread
From: J. Bruce Fields @ 2010-07-07 17:00 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, Jul 07, 2010 at 10:31:22AM -0400, David P. Quigley wrote:
> This patch adds a new recommended attribute named label into the NFSv4 file

Make that '... recommended attribute named "security_label"' ?

> +#define NFS4_MAXLABELLEN	4096

Idle curiosity--why 4096?  (Why couldn't it be 16?  And how do we know
people will never want 8192?)

> +#define NFSEXP_SECURITY_LABEL	0x0040  /* Support security label fattr4 */

I guess that answers my earlier question.

--b.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 05/10] KConfig: Add KConfig entries for Labeled NFS
@ 2010-07-07 17:05       ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 17:05 UTC (permalink / raw)
  To: J. Bruce Fields
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, 2010-07-07 at 12:56 -0400, J. Bruce Fields wrote:
> On Wed, Jul 07, 2010 at 10:31:21AM -0400, David P. Quigley wrote:
> > 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.
> 
> Will there also be some way to turn these on and off at run-time (maybe
> for particular exports or filesystems?)
> 
> And if so, will there be any reason not to have this on all the time?  I
> don't think we'll want a config option for every future possible NFSv4.x
> feature.

The way the code currently works is if you want security labeling on an
export you need to put the sec_label option on your export line (we have
a modified nfs-utils to accept that option). This will set the
particular capability flag for security labeling support on the server.
After that it works like any other capability. I don't think there is a
need to turn it on/off without reexporting the file system especially
since I'm not sure if there is a way to regrab the server capabilities
after the initial mount. I don't see why we couldn't not have this on at
all times from a kconfig perspective. I can make sure that the code is
prepared to always be there and handle when there is no need for it to
be used.

A little bit of a background on how SELinux will handle this (other LSMs
are welcome to do what they like).

If you want to turn security labeling on/off on a per export basis we
have the sec_label export option for that. If you have a file system
that is exported with sec_label and you don't want to use security
labels from the server SELinux provides a capability called context
mounts. It allows us to set the label for every file on that mount point
regardless of whether the file system provides other labeling
capabilities. So if we have a server exporting /www with security labels
and we don't want to trust it I would use a mount command like the one
below to set the security label for the entire mount

mount -t nfs4 -o context="system_u:object_r:httpd_sys_content_t:s0"
localhost:/www /mnt/www

Dave




^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 05/10] KConfig: Add KConfig entries for Labeled NFS
@ 2010-07-07 17:05       ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 17:05 UTC (permalink / raw)
  To: J. Bruce Fields
  Cc: hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	casey-iSGtlc1asvQWG2LlvL+J4A, sds-+05T5uksL2qpZYMLLGbcSA,
	matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

On Wed, 2010-07-07 at 12:56 -0400, J. Bruce Fields wrote:
> On Wed, Jul 07, 2010 at 10:31:21AM -0400, David P. Quigley wrote:
> > 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.
> 
> Will there also be some way to turn these on and off at run-time (maybe
> for particular exports or filesystems?)
> 
> And if so, will there be any reason not to have this on all the time?  I
> don't think we'll want a config option for every future possible NFSv4.x
> feature.

The way the code currently works is if you want security labeling on an
export you need to put the sec_label option on your export line (we have
a modified nfs-utils to accept that option). This will set the
particular capability flag for security labeling support on the server.
After that it works like any other capability. I don't think there is a
need to turn it on/off without reexporting the file system especially
since I'm not sure if there is a way to regrab the server capabilities
after the initial mount. I don't see why we couldn't not have this on at
all times from a kconfig perspective. I can make sure that the code is
prepared to always be there and handle when there is no need for it to
be used.

A little bit of a background on how SELinux will handle this (other LSMs
are welcome to do what they like).

If you want to turn security labeling on/off on a per export basis we
have the sec_label export option for that. If you have a file system
that is exported with sec_label and you don't want to use security
labels from the server SELinux provides a capability called context
mounts. It allows us to set the label for every file on that mount point
regardless of whether the file system provides other labeling
capabilities. So if we have a server exporting /www with security labels
and we don't want to trust it I would use a mount command like the one
below to set the security label for the entire mount

mount -t nfs4 -o context="system_u:object_r:httpd_sys_content_t:s0"
localhost:/www /mnt/www

Dave



--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 05/10] KConfig: Add KConfig entries for Labeled NFS
@ 2010-07-07 17:05       ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 17:05 UTC (permalink / raw)
  To: J. Bruce Fields
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, 2010-07-07 at 12:56 -0400, J. Bruce Fields wrote:
> On Wed, Jul 07, 2010 at 10:31:21AM -0400, David P. Quigley wrote:
> > 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.
> 
> Will there also be some way to turn these on and off at run-time (maybe
> for particular exports or filesystems?)
> 
> And if so, will there be any reason not to have this on all the time?  I
> don't think we'll want a config option for every future possible NFSv4.x
> feature.

The way the code currently works is if you want security labeling on an
export you need to put the sec_label option on your export line (we have
a modified nfs-utils to accept that option). This will set the
particular capability flag for security labeling support on the server.
After that it works like any other capability. I don't think there is a
need to turn it on/off without reexporting the file system especially
since I'm not sure if there is a way to regrab the server capabilities
after the initial mount. I don't see why we couldn't not have this on at
all times from a kconfig perspective. I can make sure that the code is
prepared to always be there and handle when there is no need for it to
be used.

A little bit of a background on how SELinux will handle this (other LSMs
are welcome to do what they like).

If you want to turn security labeling on/off on a per export basis we
have the sec_label export option for that. If you have a file system
that is exported with sec_label and you don't want to use security
labels from the server SELinux provides a capability called context
mounts. It allows us to set the label for every file on that mount point
regardless of whether the file system provides other labeling
capabilities. So if we have a server exporting /www with security labels
and we don't want to trust it I would use a mount command like the one
below to set the security label for the entire mount

mount -t nfs4 -o context="system_u:object_r:httpd_sys_content_t:s0"
localhost:/www /mnt/www

Dave




--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 10/10] NFSD: Server implementation of MAC Labeling
  2010-07-07 14:31   ` David P. Quigley
  (?)
@ 2010-07-07 17:21   ` J. Bruce Fields
  2010-07-07 18:03       ` David P. Quigley
  -1 siblings, 1 reply; 95+ messages in thread
From: J. Bruce Fields @ 2010-07-07 17:21 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, Jul 07, 2010 at 10:31:26AM -0400, David P. Quigley wrote:
> This patch adds the ability to encode and decode file labels on the server for
>  static __be32
>  nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
> -		   struct iattr *iattr, struct nfs4_acl **acl)
> +		   struct iattr *iattr, struct nfs4_acl **acl,
> +		   struct nfs4_label **label)

As we add more arguments, I wonder if at some point it becomes worth
creating something like

	struct nfsd4_attrs {
		struct iattr iattr;
		struct nfs4_acl *acl;
		...
	}

and passing that instead?

> +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
> +	if (bmval[1] & FATTR4_WORD1_SECURITY_LABEL) {
> +		uint32_t lfs;
> +
> +		READ_BUF(4);
> +		len += 4;
> +		READ32(lfs);
> +		READ_BUF(4);
> +		len += 4;
> +		READ32(dummy32);
> +		READ_BUF(dummy32);
> +		len += (XDR_QUADLEN(dummy32) << 2);
> +		READMEM(buf, dummy32);
> +
> +		if (dummy32 > NFS4_MAXLABELLEN)
> +			return nfserr_resource;
> +
> +		*label = kzalloc(sizeof(struct nfs4_label), GFP_KERNEL);

Could we allocate this some toher way (it's small, right?) and avoid the
extra dynamic allocation here, just for simplicity's sake?

> +		if (*label == NULL) {
> +			host_err = -ENOMEM;
> +			goto out_nfserr;
> +		}
> +
> +		(*label)->label = kmalloc(dummy32 + 1, GFP_KERNEL);

Might be nice to arrange NFS4_MAXLABELLEN to ensure this is never a
higher-order allocation.

> +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
> +static inline __be32
> +nfsd4_encode_security_label(struct svc_rqst *rqstp, struct dentry *dentry, __be32 **pp, int *buflen)
> +{
> +	void *context;
> +	int err;
> +	int len;
> +	uint32_t lfs = 0;
> +	__be32 *p = *pp;
> +
> +	err = 0;
> +	(void)security_inode_getsecctx(dentry->d_inode, &context, &len);
> +	if (len < 0)
> +		return nfserrno(len);
> +
> +	if (*buflen < ((XDR_QUADLEN(len) << 2) + 4 +4)) {

We could use better helpers for this; it's kind of lame to have to do
this by hand.

> +		err = nfserr_resource;
> +		goto out;
> +	}
> +
> +	/* XXX: A call to the translation code should be placed here
> +	 * for now send 0  until we have that to indicate the null
> +	 * translation */ 

I guess I should try to understand what that is some day.

> +
> +	if ((*buflen -= 4) < 0)

Redundant?

--b.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
@ 2010-07-07 17:42         ` Chuck Lever
  0 siblings, 0 replies; 95+ messages in thread
From: Chuck Lever @ 2010-07-07 17:42 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, hch, viro, sds, matthew.dodd, trond.myklebust,
	bfields, linux-kernel, linux-fsdevel, linux-security-module,
	selinux, linux-nfs

On 07/ 7/10 12:21 PM, Casey Schaufler wrote:
> Chuck Lever wrote:
>> My comments below apply to the other NFS client patches as well.  This
>> seemed like the right one to use for code examples.
>>
>> On 07/ 7/10 10:31 AM, David P. Quigley wrote:

   [ ... snipped ... ]

>>> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
>>> index a2abd1a..c512a0c 100644
>>> --- a/include/linux/nfs4.h
>>> +++ b/include/linux/nfs4.h
>>> @@ -167,6 +167,13 @@ struct nfs4_acl {
>>>        struct nfs4_ace    aces[0];
>>>    };
>>>
>>> +struct nfs4_label {
>>> +    void        *label;
>>> +    u32        len;
>>> +    uint32_t    lfs;
>>> +};
>>
>> If we have support for NFS labels in NFSv3, would we also use struct
>> nfs4_label?
>>
>> It seems to me you want something more generic, just like nfs_fh or
>> nfs_fattr, to represent these.  Over time, I'm guessing label support
>> won't be tied to a specific NFS version.  And, you are passing these
>> around in the generic NFS functions (for post-op updates and inode
>> revalidation, and what not).
>>
>> Can I recommend "struct nfs_seclabel" instead?  Then have
>> nfs_seclabel_alloc() and nfs_seclabel_free().
>
> Security has been the primary consumer of labels to date, but
> the xattr concept has always been envisioned as useful in many
> ways. That, and people have so many different views on what is
> and isn't security and whether it is good or evil that you are
> asking to limit the value if you tie "security" to the names.
> Plus, it adds unnecessary characters.

My main point is that the "nfs4" prefix is probably not optimal in the 
long run.  It seems to me that these labels are of generic use in the 
NFS client, and not necessarily specific to version 4.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
@ 2010-07-07 17:42         ` Chuck Lever
  0 siblings, 0 replies; 95+ messages in thread
From: Chuck Lever @ 2010-07-07 17:42 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	sds-+05T5uksL2qpZYMLLGbcSA, matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	bfields-uC3wQj2KruNg9hUCZPvPmw,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

On 07/ 7/10 12:21 PM, Casey Schaufler wrote:
> Chuck Lever wrote:
>> My comments below apply to the other NFS client patches as well.  This
>> seemed like the right one to use for code examples.
>>
>> On 07/ 7/10 10:31 AM, David P. Quigley wrote:

   [ ... snipped ... ]

>>> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
>>> index a2abd1a..c512a0c 100644
>>> --- a/include/linux/nfs4.h
>>> +++ b/include/linux/nfs4.h
>>> @@ -167,6 +167,13 @@ struct nfs4_acl {
>>>        struct nfs4_ace    aces[0];
>>>    };
>>>
>>> +struct nfs4_label {
>>> +    void        *label;
>>> +    u32        len;
>>> +    uint32_t    lfs;
>>> +};
>>
>> If we have support for NFS labels in NFSv3, would we also use struct
>> nfs4_label?
>>
>> It seems to me you want something more generic, just like nfs_fh or
>> nfs_fattr, to represent these.  Over time, I'm guessing label support
>> won't be tied to a specific NFS version.  And, you are passing these
>> around in the generic NFS functions (for post-op updates and inode
>> revalidation, and what not).
>>
>> Can I recommend "struct nfs_seclabel" instead?  Then have
>> nfs_seclabel_alloc() and nfs_seclabel_free().
>
> Security has been the primary consumer of labels to date, but
> the xattr concept has always been envisioned as useful in many
> ways. That, and people have so many different views on what is
> and isn't security and whether it is good or evil that you are
> asking to limit the value if you tie "security" to the names.
> Plus, it adds unnecessary characters.

My main point is that the "nfs4" prefix is probably not optimal in the 
long run.  It seems to me that these labels are of generic use in the 
NFS client, and not necessarily specific to version 4.
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
  2010-07-07 16:22       ` David P. Quigley
  (?)
  (?)
@ 2010-07-07 17:49       ` Chuck Lever
  2010-07-07 18:11           ` David P. Quigley
  -1 siblings, 1 reply; 95+ messages in thread
From: Chuck Lever @ 2010-07-07 17:49 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On 07/ 7/10 12:22 PM, David P. Quigley wrote:
> Hello Chuck,
>     Thank you for the comments. I'll go through and address them inline
> (Sorry for the top post).
>
> On Wed, 2010-07-07 at 12:01 -0400, Chuck Lever wrote:
>> My comments below apply to the other NFS client patches as well.  This
>> seemed like the right one to use for code examples.
>>
>> On 07/ 7/10 10:31 AM, David P. Quigley wrote:

   [ ... snipped ... ]

>> It seems to me you want something more generic, just like nfs_fh or
>> nfs_fattr, to represent these.  Over time, I'm guessing label support
>> won't be tied to a specific NFS version.  And, you are passing these
>> around in the generic NFS functions (for post-op updates and inode
>> revalidation, and what not).
>>
>> Can I recommend "struct nfs_seclabel" instead?  Then have
>> nfs_seclabel_alloc() and nfs_seclabel_free().
>
> I can definitely rename them to be more generic. I don't see anything
> else besides NFSv4 using them but its fine with me to rename them. The
> reason we call them nfs4_label is because we modeled it after the NFSv4
> acl support code. I spoke with Christoph a long time ago and he
> suggested that it should be handled the same way that the NFSv4 ACLs are
> handled as opposed to the iattr thing we were trying.
>
>>
>> Does it make sense to deduplicate these in the client's memory?  It
>> seems to me that you could have hundreds or thousands that all contain
>> the same label information.
>
> I don't think it is worth the effort. We are only using these structures
> until the security label is crammed into the inode. Once that happens
> they get freed. You shouldn't have them sitting around for very long.

OK, the lifetime of these things wasn't clear.

> They will be pulled again when the inode attributes expire and need to
> be revalidated. For things like SELinux you could argue that the LSM
> might benefit from this (and it might already do it but I'm not sure)
> but I think that is something to be handled by the LSM itself or the
> credentials code (since it already supports COW credentials it should be
> possible).

I think the lifetime of the label structure then is about the same as 
the lifetime of an nfs_attr, and not at all the same as an ACL.  I'm 
just guessing here.

Would it then make sense to add a field that refers to the security 
label to struct nfs_fattr instead?  That might simplify or eliminate all 
of the internal API changes.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 05/10] KConfig: Add KConfig entries for Labeled NFS
@ 2010-07-07 17:53       ` Chuck Lever
  0 siblings, 0 replies; 95+ messages in thread
From: Chuck Lever @ 2010-07-07 17:53 UTC (permalink / raw)
  To: J. Bruce Fields
  Cc: David P. Quigley, hch, viro, casey, sds, matthew.dodd,
	trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On 07/ 7/10 12:56 PM, J. Bruce Fields wrote:
> On Wed, Jul 07, 2010 at 10:31:21AM -0400, David P. Quigley wrote:
>> 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.
>
> Will there also be some way to turn these on and off at run-time (maybe
> for particular exports or filesystems?)
>
> And if so, will there be any reason not to have this on all the time?  I
> don't think we'll want a config option for every future possible NFSv4.x
> feature.

I would guess that the ability to build without this feature would be 
desirable if it added significant bulk to the object code.  If it 
doesn't, then I agree with you that having it adds unneeded clutter to 
the code, and additional complexity to kernel configuration that most 
people will ignore and/or get wrong.

>>
>> Signed-off-by: Matthew N. Dodd<Matthew.Dodd@sparta.com>
>> Signed-off-by: David P. Quigley<dpquigl@tycho.nsa.gov>
>> ---
>>   fs/nfs/Kconfig  |   16 ++++++++++++++++
>>   fs/nfsd/Kconfig |   13 +++++++++++++
>>   2 files changed, 29 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
>> index a43d07e..67b158c 100644
>> --- a/fs/nfs/Kconfig
>> +++ b/fs/nfs/Kconfig
>> @@ -83,6 +83,22 @@ config NFS_V4_1
>>
>>   	  Unless you're an NFS developer, say N.
>>
>> +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 enable fine-grained 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.
>> +	Without this an NFSv4 mount will have the same label on each file.
>> +
>> +	If you do not wish to enable fine-grained security labels SELinux or
>> +	Smack policies on NFSv4 files, say N.
>> +
>> +
>> +	  If unsure, say N.
>> +
>>   config ROOT_NFS
>>   	bool "Root file system on NFS"
>>   	depends on NFS_FS=y&&  IP_PNP
>> diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
>> index 503b9da..3a282f8 100644
>> --- a/fs/nfsd/Kconfig
>> +++ b/fs/nfsd/Kconfig
>> @@ -79,3 +79,16 @@ config NFSD_V4
>>   	  available from http://linux-nfs.org/.
>>
>>   	  If unsure, say N.
>> +
>> +config NFSD_V4_SECURITY_LABEL
>> +	bool "Provide Security Label support for NFSv4 server"
>> +	depends on NFSD_V4&&  SECURITY
>> +	help
>> +
>> +	Say Y here if you want enable fine-grained 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.
>> +	Without this an NFSv4 mount will have the same label on each file.
>> +
>> +	If you do not wish to enable fine-grained security labels SELinux or
>> +	Smack policies on NFSv4 files, say N.
>> --
>> 1.6.2.5
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 05/10] KConfig: Add KConfig entries for Labeled NFS
@ 2010-07-07 17:53       ` Chuck Lever
  0 siblings, 0 replies; 95+ messages in thread
From: Chuck Lever @ 2010-07-07 17:53 UTC (permalink / raw)
  To: J. Bruce Fields
  Cc: David P. Quigley, hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	casey-iSGtlc1asvQWG2LlvL+J4A, sds-+05T5uksL2qpZYMLLGbcSA,
	matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

On 07/ 7/10 12:56 PM, J. Bruce Fields wrote:
> On Wed, Jul 07, 2010 at 10:31:21AM -0400, David P. Quigley wrote:
>> 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.
>
> Will there also be some way to turn these on and off at run-time (maybe
> for particular exports or filesystems?)
>
> And if so, will there be any reason not to have this on all the time?  I
> don't think we'll want a config option for every future possible NFSv4.x
> feature.

I would guess that the ability to build without this feature would be 
desirable if it added significant bulk to the object code.  If it 
doesn't, then I agree with you that having it adds unneeded clutter to 
the code, and additional complexity to kernel configuration that most 
people will ignore and/or get wrong.

>>
>> Signed-off-by: Matthew N. Dodd<Matthew.Dodd-DABiIiYg7OfQT0dZR+AlfA@public.gmane.org>
>> Signed-off-by: David P. Quigley<dpquigl-+05T5uksL2qpZYMLLGbcSA@public.gmane.org>
>> ---
>>   fs/nfs/Kconfig  |   16 ++++++++++++++++
>>   fs/nfsd/Kconfig |   13 +++++++++++++
>>   2 files changed, 29 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
>> index a43d07e..67b158c 100644
>> --- a/fs/nfs/Kconfig
>> +++ b/fs/nfs/Kconfig
>> @@ -83,6 +83,22 @@ config NFS_V4_1
>>
>>   	  Unless you're an NFS developer, say N.
>>
>> +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 enable fine-grained 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.
>> +	Without this an NFSv4 mount will have the same label on each file.
>> +
>> +	If you do not wish to enable fine-grained security labels SELinux or
>> +	Smack policies on NFSv4 files, say N.
>> +
>> +
>> +	  If unsure, say N.
>> +
>>   config ROOT_NFS
>>   	bool "Root file system on NFS"
>>   	depends on NFS_FS=y&&  IP_PNP
>> diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
>> index 503b9da..3a282f8 100644
>> --- a/fs/nfsd/Kconfig
>> +++ b/fs/nfsd/Kconfig
>> @@ -79,3 +79,16 @@ config NFSD_V4
>>   	  available from http://linux-nfs.org/.
>>
>>   	  If unsure, say N.
>> +
>> +config NFSD_V4_SECURITY_LABEL
>> +	bool "Provide Security Label support for NFSv4 server"
>> +	depends on NFSD_V4&&  SECURITY
>> +	help
>> +
>> +	Say Y here if you want enable fine-grained 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.
>> +	Without this an NFSv4 mount will have the same label on each file.
>> +
>> +	If you do not wish to enable fine-grained security labels SELinux or
>> +	Smack policies on NFSv4 files, say N.
>> --
>> 1.6.2.5
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 10/10] NFSD: Server implementation of MAC Labeling
@ 2010-07-07 18:03       ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 18:03 UTC (permalink / raw)
  To: J. Bruce Fields
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

Comments inline

On Wed, 2010-07-07 at 13:21 -0400, J. Bruce Fields wrote:
> On Wed, Jul 07, 2010 at 10:31:26AM -0400, David P. Quigley wrote:
> > This patch adds the ability to encode and decode file labels on the server for
> >  static __be32
> >  nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
> > -		   struct iattr *iattr, struct nfs4_acl **acl)
> > +		   struct iattr *iattr, struct nfs4_acl **acl,
> > +		   struct nfs4_label **label)
> 
> As we add more arguments, I wonder if at some point it becomes worth
> creating something like
> 
> 	struct nfsd4_attrs {
> 		struct iattr iattr;
> 		struct nfs4_acl *acl;
> 		...
> 	}
> 
> and passing that instead?

I can definitely submit something like that as a stand alone patch and
then add our nfs4_label stuff to that instead.

> 
> > +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
> > +	if (bmval[1] & FATTR4_WORD1_SECURITY_LABEL) {
> > +		uint32_t lfs;
> > +
> > +		READ_BUF(4);
> > +		len += 4;
> > +		READ32(lfs);
> > +		READ_BUF(4);
> > +		len += 4;
> > +		READ32(dummy32);
> > +		READ_BUF(dummy32);
> > +		len += (XDR_QUADLEN(dummy32) << 2);
> > +		READMEM(buf, dummy32);
> > +
> > +		if (dummy32 > NFS4_MAXLABELLEN)
> > +			return nfserr_resource;
> > +
> > +		*label = kzalloc(sizeof(struct nfs4_label), GFP_KERNEL);
> 
> Could we allocate this some toher way (it's small, right?) and avoid the
> extra dynamic allocation here, just for simplicity's sake?

How would you suggest going about doing that?

> 
> > +		if (*label == NULL) {
> > +			host_err = -ENOMEM;
> > +			goto out_nfserr;
> > +		}
> > +
> > +		(*label)->label = kmalloc(dummy32 + 1, GFP_KERNEL);
> 
> Might be nice to arrange NFS4_MAXLABELLEN to ensure this is never a
> higher-order allocation.

This should never be more than 4096. Under what circumstances would this
become a higher-order allocation?
> 
> > +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
> > +static inline __be32
> > +nfsd4_encode_security_label(struct svc_rqst *rqstp, struct dentry *dentry, __be32 **pp, int *buflen)
> > +{
> > +	void *context;
> > +	int err;
> > +	int len;
> > +	uint32_t lfs = 0;
> > +	__be32 *p = *pp;
> > +
> > +	err = 0;
> > +	(void)security_inode_getsecctx(dentry->d_inode, &context, &len);
> > +	if (len < 0)
> > +		return nfserrno(len);
> > +
> > +	if (*buflen < ((XDR_QUADLEN(len) << 2) + 4 +4)) {
> 
> We could use better helpers for this; it's kind of lame to have to do
> this by hand.

Give me an idea of what you'd like it to look like and I can try to code
it up.

> 
> > +		err = nfserr_resource;
> > +		goto out;
> > +	}
> > +
> > +	/* XXX: A call to the translation code should be placed here
> > +	 * for now send 0  until we have that to indicate the null
> > +	 * translation */ 
> 
> I guess I should try to understand what that is some day.

Ahh. Sorry that was a place holder for me. The idea is that in order to
allow for multiple models and policies we will have a deamon similar to
idmapd except to handle label translations. An example of this would be
if we have an SELinux box with an MLS policy and a FreeBSD box with
their MLS MAC module. If we want to ensure that they can both talk to
each other we have them agree ahead of time to a label format which is
just MLS label information. The translation daemon on the SELinux side
would take the label strip out the SELinux specific stuff and encode it
into the MLS label (probably a CALIPSO label) to send across the wire.
Then when the BSD box receives it they have their translation daemon
take the label convert it into something that makes sense to them
locally filling in whatever information they need outside of the MLS
label.


> 
> > +
> > +	if ((*buflen -= 4) < 0)
> 
> Redundant?

I don't think so. I'll go back and double check just to be safe.

> 
> --b.


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 10/10] NFSD: Server implementation of MAC Labeling
@ 2010-07-07 18:03       ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 18:03 UTC (permalink / raw)
  To: J. Bruce Fields
  Cc: hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	casey-iSGtlc1asvQWG2LlvL+J4A, sds-+05T5uksL2qpZYMLLGbcSA,
	matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

Comments inline

On Wed, 2010-07-07 at 13:21 -0400, J. Bruce Fields wrote:
> On Wed, Jul 07, 2010 at 10:31:26AM -0400, David P. Quigley wrote:
> > This patch adds the ability to encode and decode file labels on the server for
> >  static __be32
> >  nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
> > -		   struct iattr *iattr, struct nfs4_acl **acl)
> > +		   struct iattr *iattr, struct nfs4_acl **acl,
> > +		   struct nfs4_label **label)
> 
> As we add more arguments, I wonder if at some point it becomes worth
> creating something like
> 
> 	struct nfsd4_attrs {
> 		struct iattr iattr;
> 		struct nfs4_acl *acl;
> 		...
> 	}
> 
> and passing that instead?

I can definitely submit something like that as a stand alone patch and
then add our nfs4_label stuff to that instead.

> 
> > +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
> > +	if (bmval[1] & FATTR4_WORD1_SECURITY_LABEL) {
> > +		uint32_t lfs;
> > +
> > +		READ_BUF(4);
> > +		len += 4;
> > +		READ32(lfs);
> > +		READ_BUF(4);
> > +		len += 4;
> > +		READ32(dummy32);
> > +		READ_BUF(dummy32);
> > +		len += (XDR_QUADLEN(dummy32) << 2);
> > +		READMEM(buf, dummy32);
> > +
> > +		if (dummy32 > NFS4_MAXLABELLEN)
> > +			return nfserr_resource;
> > +
> > +		*label = kzalloc(sizeof(struct nfs4_label), GFP_KERNEL);
> 
> Could we allocate this some toher way (it's small, right?) and avoid the
> extra dynamic allocation here, just for simplicity's sake?

How would you suggest going about doing that?

> 
> > +		if (*label == NULL) {
> > +			host_err = -ENOMEM;
> > +			goto out_nfserr;
> > +		}
> > +
> > +		(*label)->label = kmalloc(dummy32 + 1, GFP_KERNEL);
> 
> Might be nice to arrange NFS4_MAXLABELLEN to ensure this is never a
> higher-order allocation.

This should never be more than 4096. Under what circumstances would this
become a higher-order allocation?
> 
> > +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
> > +static inline __be32
> > +nfsd4_encode_security_label(struct svc_rqst *rqstp, struct dentry *dentry, __be32 **pp, int *buflen)
> > +{
> > +	void *context;
> > +	int err;
> > +	int len;
> > +	uint32_t lfs = 0;
> > +	__be32 *p = *pp;
> > +
> > +	err = 0;
> > +	(void)security_inode_getsecctx(dentry->d_inode, &context, &len);
> > +	if (len < 0)
> > +		return nfserrno(len);
> > +
> > +	if (*buflen < ((XDR_QUADLEN(len) << 2) + 4 +4)) {
> 
> We could use better helpers for this; it's kind of lame to have to do
> this by hand.

Give me an idea of what you'd like it to look like and I can try to code
it up.

> 
> > +		err = nfserr_resource;
> > +		goto out;
> > +	}
> > +
> > +	/* XXX: A call to the translation code should be placed here
> > +	 * for now send 0  until we have that to indicate the null
> > +	 * translation */ 
> 
> I guess I should try to understand what that is some day.

Ahh. Sorry that was a place holder for me. The idea is that in order to
allow for multiple models and policies we will have a deamon similar to
idmapd except to handle label translations. An example of this would be
if we have an SELinux box with an MLS policy and a FreeBSD box with
their MLS MAC module. If we want to ensure that they can both talk to
each other we have them agree ahead of time to a label format which is
just MLS label information. The translation daemon on the SELinux side
would take the label strip out the SELinux specific stuff and encode it
into the MLS label (probably a CALIPSO label) to send across the wire.
Then when the BSD box receives it they have their translation daemon
take the label convert it into something that makes sense to them
locally filling in whatever information they need outside of the MLS
label.


> 
> > +
> > +	if ((*buflen -= 4) < 0)
> 
> Redundant?

I don't think so. I'll go back and double check just to be safe.

> 
> --b.

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 10/10] NFSD: Server implementation of MAC Labeling
@ 2010-07-07 18:03       ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 18:03 UTC (permalink / raw)
  To: J. Bruce Fields
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

Comments inline

On Wed, 2010-07-07 at 13:21 -0400, J. Bruce Fields wrote:
> On Wed, Jul 07, 2010 at 10:31:26AM -0400, David P. Quigley wrote:
> > This patch adds the ability to encode and decode file labels on the server for
> >  static __be32
> >  nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
> > -		   struct iattr *iattr, struct nfs4_acl **acl)
> > +		   struct iattr *iattr, struct nfs4_acl **acl,
> > +		   struct nfs4_label **label)
> 
> As we add more arguments, I wonder if at some point it becomes worth
> creating something like
> 
> 	struct nfsd4_attrs {
> 		struct iattr iattr;
> 		struct nfs4_acl *acl;
> 		...
> 	}
> 
> and passing that instead?

I can definitely submit something like that as a stand alone patch and
then add our nfs4_label stuff to that instead.

> 
> > +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
> > +	if (bmval[1] & FATTR4_WORD1_SECURITY_LABEL) {
> > +		uint32_t lfs;
> > +
> > +		READ_BUF(4);
> > +		len += 4;
> > +		READ32(lfs);
> > +		READ_BUF(4);
> > +		len += 4;
> > +		READ32(dummy32);
> > +		READ_BUF(dummy32);
> > +		len += (XDR_QUADLEN(dummy32) << 2);
> > +		READMEM(buf, dummy32);
> > +
> > +		if (dummy32 > NFS4_MAXLABELLEN)
> > +			return nfserr_resource;
> > +
> > +		*label = kzalloc(sizeof(struct nfs4_label), GFP_KERNEL);
> 
> Could we allocate this some toher way (it's small, right?) and avoid the
> extra dynamic allocation here, just for simplicity's sake?

How would you suggest going about doing that?

> 
> > +		if (*label == NULL) {
> > +			host_err = -ENOMEM;
> > +			goto out_nfserr;
> > +		}
> > +
> > +		(*label)->label = kmalloc(dummy32 + 1, GFP_KERNEL);
> 
> Might be nice to arrange NFS4_MAXLABELLEN to ensure this is never a
> higher-order allocation.

This should never be more than 4096. Under what circumstances would this
become a higher-order allocation?
> 
> > +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
> > +static inline __be32
> > +nfsd4_encode_security_label(struct svc_rqst *rqstp, struct dentry *dentry, __be32 **pp, int *buflen)
> > +{
> > +	void *context;
> > +	int err;
> > +	int len;
> > +	uint32_t lfs = 0;
> > +	__be32 *p = *pp;
> > +
> > +	err = 0;
> > +	(void)security_inode_getsecctx(dentry->d_inode, &context, &len);
> > +	if (len < 0)
> > +		return nfserrno(len);
> > +
> > +	if (*buflen < ((XDR_QUADLEN(len) << 2) + 4 +4)) {
> 
> We could use better helpers for this; it's kind of lame to have to do
> this by hand.

Give me an idea of what you'd like it to look like and I can try to code
it up.

> 
> > +		err = nfserr_resource;
> > +		goto out;
> > +	}
> > +
> > +	/* XXX: A call to the translation code should be placed here
> > +	 * for now send 0  until we have that to indicate the null
> > +	 * translation */ 
> 
> I guess I should try to understand what that is some day.

Ahh. Sorry that was a place holder for me. The idea is that in order to
allow for multiple models and policies we will have a deamon similar to
idmapd except to handle label translations. An example of this would be
if we have an SELinux box with an MLS policy and a FreeBSD box with
their MLS MAC module. If we want to ensure that they can both talk to
each other we have them agree ahead of time to a label format which is
just MLS label information. The translation daemon on the SELinux side
would take the label strip out the SELinux specific stuff and encode it
into the MLS label (probably a CALIPSO label) to send across the wire.
Then when the BSD box receives it they have their translation daemon
take the label convert it into something that makes sense to them
locally filling in whatever information they need outside of the MLS
label.


> 
> > +
> > +	if ((*buflen -= 4) < 0)
> 
> Redundant?

I don't think so. I'll go back and double check just to be safe.

> 
> --b.


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
  2010-07-07 17:49       ` Chuck Lever
@ 2010-07-07 18:11           ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 18:11 UTC (permalink / raw)
  To: Chuck Lever
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, 2010-07-07 at 13:49 -0400, Chuck Lever wrote:
> On 07/ 7/10 12:22 PM, David P. Quigley wrote:
> > Hello Chuck,
> >     Thank you for the comments. I'll go through and address them inline
> > (Sorry for the top post).
> >
> > On Wed, 2010-07-07 at 12:01 -0400, Chuck Lever wrote:
> >> My comments below apply to the other NFS client patches as well.  This
> >> seemed like the right one to use for code examples.
> >>
> >> On 07/ 7/10 10:31 AM, David P. Quigley wrote:
> 
>    [ ... snipped ... ]
> 
> >> It seems to me you want something more generic, just like nfs_fh or
> >> nfs_fattr, to represent these.  Over time, I'm guessing label support
> >> won't be tied to a specific NFS version.  And, you are passing these
> >> around in the generic NFS functions (for post-op updates and inode
> >> revalidation, and what not).
> >>
> >> Can I recommend "struct nfs_seclabel" instead?  Then have
> >> nfs_seclabel_alloc() and nfs_seclabel_free().
> >
> > I can definitely rename them to be more generic. I don't see anything
> > else besides NFSv4 using them but its fine with me to rename them. The
> > reason we call them nfs4_label is because we modeled it after the NFSv4
> > acl support code. I spoke with Christoph a long time ago and he
> > suggested that it should be handled the same way that the NFSv4 ACLs are
> > handled as opposed to the iattr thing we were trying.
> >
> >>
> >> Does it make sense to deduplicate these in the client's memory?  It
> >> seems to me that you could have hundreds or thousands that all contain
> >> the same label information.
> >
> > I don't think it is worth the effort. We are only using these structures
> > until the security label is crammed into the inode. Once that happens
> > they get freed. You shouldn't have them sitting around for very long.
> 
> OK, the lifetime of these things wasn't clear.
> 
> > They will be pulled again when the inode attributes expire and need to
> > be revalidated. For things like SELinux you could argue that the LSM
> > might benefit from this (and it might already do it but I'm not sure)
> > but I think that is something to be handled by the LSM itself or the
> > credentials code (since it already supports COW credentials it should be
> > possible).
> 
> I think the lifetime of the label structure then is about the same as 
> the lifetime of an nfs_attr, and not at all the same as an ACL.  I'm 
> just guessing here.

Intersting I figured that the ACL structure was just to get it to a
point where you could convert the NFS ACL into a posixacl and set it in
the inode. I didn't realize they were hanging around for a while.

> 
> Would it then make sense to add a field that refers to the security 
> label to struct nfs_fattr instead?  That might simplify or eliminate all 
> of the internal API changes.

I want to say that we had it in there at one point and then we endedup
running into a problem and having to change it. I'll ask Matt about what
problems we had sticking it in the nfs_fattr initially.

Dave


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/10] NFSv4: Introduce new label structure
@ 2010-07-07 18:11           ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-07 18:11 UTC (permalink / raw)
  To: Chuck Lever
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, 2010-07-07 at 13:49 -0400, Chuck Lever wrote:
> On 07/ 7/10 12:22 PM, David P. Quigley wrote:
> > Hello Chuck,
> >     Thank you for the comments. I'll go through and address them inline
> > (Sorry for the top post).
> >
> > On Wed, 2010-07-07 at 12:01 -0400, Chuck Lever wrote:
> >> My comments below apply to the other NFS client patches as well.  This
> >> seemed like the right one to use for code examples.
> >>
> >> On 07/ 7/10 10:31 AM, David P. Quigley wrote:
> 
>    [ ... snipped ... ]
> 
> >> It seems to me you want something more generic, just like nfs_fh or
> >> nfs_fattr, to represent these.  Over time, I'm guessing label support
> >> won't be tied to a specific NFS version.  And, you are passing these
> >> around in the generic NFS functions (for post-op updates and inode
> >> revalidation, and what not).
> >>
> >> Can I recommend "struct nfs_seclabel" instead?  Then have
> >> nfs_seclabel_alloc() and nfs_seclabel_free().
> >
> > I can definitely rename them to be more generic. I don't see anything
> > else besides NFSv4 using them but its fine with me to rename them. The
> > reason we call them nfs4_label is because we modeled it after the NFSv4
> > acl support code. I spoke with Christoph a long time ago and he
> > suggested that it should be handled the same way that the NFSv4 ACLs are
> > handled as opposed to the iattr thing we were trying.
> >
> >>
> >> Does it make sense to deduplicate these in the client's memory?  It
> >> seems to me that you could have hundreds or thousands that all contain
> >> the same label information.
> >
> > I don't think it is worth the effort. We are only using these structures
> > until the security label is crammed into the inode. Once that happens
> > they get freed. You shouldn't have them sitting around for very long.
> 
> OK, the lifetime of these things wasn't clear.
> 
> > They will be pulled again when the inode attributes expire and need to
> > be revalidated. For things like SELinux you could argue that the LSM
> > might benefit from this (and it might already do it but I'm not sure)
> > but I think that is something to be handled by the LSM itself or the
> > credentials code (since it already supports COW credentials it should be
> > possible).
> 
> I think the lifetime of the label structure then is about the same as 
> the lifetime of an nfs_attr, and not at all the same as an ACL.  I'm 
> just guessing here.

Intersting I figured that the ACL structure was just to get it to a
point where you could convert the NFS ACL into a posixacl and set it in
the inode. I didn't realize they were hanging around for a while.

> 
> Would it then make sense to add a field that refers to the security 
> label to struct nfs_fattr instead?  That might simplify or eliminate all 
> of the internal API changes.

I want to say that we had it in there at one point and then we endedup
running into a problem and having to change it. I'll ask Matt about what
problems we had sticking it in the nfs_fattr initially.

Dave


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 10/10] NFSD: Server implementation of MAC Labeling
  2010-07-07 18:03       ` David P. Quigley
  (?)
  (?)
@ 2010-07-07 19:24       ` J. Bruce Fields
  2010-07-08 13:27           ` David P. Quigley
  -1 siblings, 1 reply; 95+ messages in thread
From: J. Bruce Fields @ 2010-07-07 19:24 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, Jul 07, 2010 at 02:03:21PM -0400, David P. Quigley wrote:
> Comments inline
> 
> On Wed, 2010-07-07 at 13:21 -0400, J. Bruce Fields wrote:
> > On Wed, Jul 07, 2010 at 10:31:26AM -0400, David P. Quigley wrote:
> > > This patch adds the ability to encode and decode file labels on the server for
> > >  static __be32
> > >  nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
> > > -		   struct iattr *iattr, struct nfs4_acl **acl)
> > > +		   struct iattr *iattr, struct nfs4_acl **acl,
> > > +		   struct nfs4_label **label)
> > 
> > As we add more arguments, I wonder if at some point it becomes worth
> > creating something like
> > 
> > 	struct nfsd4_attrs {
> > 		struct iattr iattr;
> > 		struct nfs4_acl *acl;
> > 		...
> > 	}
> > 
> > and passing that instead?
> 
> I can definitely submit something like that as a stand alone patch and
> then add our nfs4_label stuff to that instead.

Not a big deal, but welcome if such a thing looks more generally useful
(say, if the same arguments are passed elsewhere).

> > > +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
> > > +	if (bmval[1] & FATTR4_WORD1_SECURITY_LABEL) {
> > > +		uint32_t lfs;
> > > +
> > > +		READ_BUF(4);
> > > +		len += 4;
> > > +		READ32(lfs);
> > > +		READ_BUF(4);
> > > +		len += 4;
> > > +		READ32(dummy32);
> > > +		READ_BUF(dummy32);
> > > +		len += (XDR_QUADLEN(dummy32) << 2);
> > > +		READMEM(buf, dummy32);
> > > +
> > > +		if (dummy32 > NFS4_MAXLABELLEN)
> > > +			return nfserr_resource;
> > > +
> > > +		*label = kzalloc(sizeof(struct nfs4_label), GFP_KERNEL);
> > 
> > Could we allocate this some toher way (it's small, right?) and avoid the
> > extra dynamic allocation here, just for simplicity's sake?
> 
> How would you suggest going about doing that?

Maybe make op_label, cr_label, etc., a struct nfs4_label instead of a
struct nfs4_label *?

> 
> > 
> > > +		if (*label == NULL) {
> > > +			host_err = -ENOMEM;
> > > +			goto out_nfserr;
> > > +		}
> > > +
> > > +		(*label)->label = kmalloc(dummy32 + 1, GFP_KERNEL);
> > 
> > Might be nice to arrange NFS4_MAXLABELLEN to ensure this is never a
> > higher-order allocation.
> 
> This should never be more than 4096. Under what circumstances would this
> become a higher-order allocation?

Can't dummy32+1 be 4097?

--b.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 04/10] SELinux: Add new labeling type native labels
  2010-07-07 14:31   ` David P. Quigley
@ 2010-07-07 23:23     ` James Morris
  -1 siblings, 0 replies; 95+ messages in thread
From: James Morris @ 2010-07-07 23:23 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, sds, Matthew N. Dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, 7 Jul 2010, David P. Quigley wrote:

> 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.

It would be useful to have the ability to specify labeling behavior on a 
per-mount basis, with the default remaining as genfs.

Otherwise, this is a global policy decision which affects all NFSv4 
mounts, right?


-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 04/10] SELinux: Add new labeling type native labels
@ 2010-07-07 23:23     ` James Morris
  0 siblings, 0 replies; 95+ messages in thread
From: James Morris @ 2010-07-07 23:23 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, sds, Matthew N. Dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, 7 Jul 2010, David P. Quigley wrote:

> 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.

It would be useful to have the ability to specify labeling behavior on a 
per-mount basis, with the default remaining as genfs.

Otherwise, this is a global policy decision which affects all NFSv4 
mounts, right?


-- 
James Morris
<jmorris@namei.org>

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
  2010-07-07 17:00   ` J. Bruce Fields
@ 2010-07-07 23:30       ` James Morris
  0 siblings, 0 replies; 95+ messages in thread
From: James Morris @ 2010-07-07 23:30 UTC (permalink / raw)
  To: J. Bruce Fields
  Cc: David P. Quigley, hch, viro, casey, sds, matthew.dodd,
	trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Wed, 7 Jul 2010, J. Bruce Fields wrote:

> On Wed, Jul 07, 2010 at 10:31:22AM -0400, David P. Quigley wrote:
> 
> > +#define NFS4_MAXLABELLEN	4096
> 
> Idle curiosity--why 4096?  (Why couldn't it be 16?  And how do we know
> people will never want 8192?)

I think I raised this a while back, too.

The maximum security label size on Linux is:

#define XATTR_SIZE_MAX 65536

Why arbitrarily limit this over the network?

Someone could have a valid local security label which can't be conveyed 
via NFS.



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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-07 23:30       ` James Morris
  0 siblings, 0 replies; 95+ messages in thread
From: James Morris @ 2010-07-07 23:30 UTC (permalink / raw)
  To: J. Bruce Fields
  Cc: David P. Quigley, hch, viro, casey, sds, matthew.dodd,
	trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Wed, 7 Jul 2010, J. Bruce Fields wrote:

> On Wed, Jul 07, 2010 at 10:31:22AM -0400, David P. Quigley wrote:
> 
> > +#define NFS4_MAXLABELLEN	4096
> 
> Idle curiosity--why 4096?  (Why couldn't it be 16?  And how do we know
> people will never want 8192?)

I think I raised this a while back, too.

The maximum security label size on Linux is:

#define XATTR_SIZE_MAX 65536

Why arbitrarily limit this over the network?

Someone could have a valid local security label which can't be conveyed 
via NFS.



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

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/10] Security: Add hook to calculate context based on a negative dentry.
  2010-07-07 14:31   ` David P. Quigley
@ 2010-07-08 12:51     ` Stephen Smalley
  -1 siblings, 0 replies; 95+ messages in thread
From: Stephen Smalley @ 2010-07-08 12:51 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, matthew.dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, 2010-07-07 at 10:31 -0400, David P. Quigley wrote:
> There is a time where we need to calculate a context without the
> inode having been created yet. To do this we take the negative dentry and
> calculate a context based on the process and the parent directory contexts.
> 
> Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
> Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
> ---
>  include/linux/security.h |   22 ++++++++++++++++++++++
>  security/capability.c    |    6 ++++++
>  security/security.c      |    7 +++++++
>  security/selinux/hooks.c |   32 ++++++++++++++++++++++++++++++++
>  4 files changed, 67 insertions(+), 0 deletions(-)
> 

> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 5feecb4..435c51f 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -2577,6 +2577,37 @@ static void selinux_inode_free_security(struct inode *inode)
>  	inode_free_security(inode);
>  }
>  
> +static int selinux_dentry_init_security(struct dentry *dentry, int mode, void **ctx, u32 *ctxlen)
> +{
> +	struct cred *cred = current_cred();
> +	struct task_security_struct *tsec;
> +	struct inode_security_struct *dsec;
> +	struct superblock_security_struct *sbsec;
> +	struct inode *dir = dentry->d_parent->d_inode;

Locking?

> +	u32 newsid;
> +	int rc;
> +
> +	tsec = cred->security;
> +	dsec = dir->i_security;
> +	sbsec = dir->i_sb->s_security;
> +
> +	if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {

The logic in selinux_inode_init_security() has changed to use
(sbsec->flags & SE_SBLABELSUPP) instead.  Possibly you should factor the
common code into a helper.

> +		newsid = tsec->create_sid;
> +	} else {
> +		rc = security_transition_sid(tsec->sid, dsec->sid,
> +					     inode_mode_to_security_class(mode),
> +					     &newsid);
> +		if (rc) {
> +			printk(KERN_WARNING "%s:  "
> +			       "security_transition_sid failed, rc=%d\n",
> +			       __FUNCTION__, -rc);
> +			return rc;
> +		}
> +	}
> +
> +	return security_sid_to_context(newsid, (char **)ctx, ctxlen);
> +}
> +
>  static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
>  				       char **name, void **value,
>  				       size_t *len)
> @@ -5484,6 +5515,7 @@ static struct security_operations selinux_ops = {
>  	.sb_clone_mnt_opts =		selinux_sb_clone_mnt_opts,
>  	.sb_parse_opts_str = 		selinux_parse_opts_str,
>  
> +	.dentry_init_security =		selinux_dentry_init_security,
>  
>  	.inode_alloc_security =		selinux_inode_alloc_security,
>  	.inode_free_security =		selinux_inode_free_security,

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/10] Security: Add hook to calculate context based on a negative dentry.
@ 2010-07-08 12:51     ` Stephen Smalley
  0 siblings, 0 replies; 95+ messages in thread
From: Stephen Smalley @ 2010-07-08 12:51 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, matthew.dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, 2010-07-07 at 10:31 -0400, David P. Quigley wrote:
> There is a time where we need to calculate a context without the
> inode having been created yet. To do this we take the negative dentry and
> calculate a context based on the process and the parent directory contexts.
> 
> Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com>
> Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
> ---
>  include/linux/security.h |   22 ++++++++++++++++++++++
>  security/capability.c    |    6 ++++++
>  security/security.c      |    7 +++++++
>  security/selinux/hooks.c |   32 ++++++++++++++++++++++++++++++++
>  4 files changed, 67 insertions(+), 0 deletions(-)
> 

> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 5feecb4..435c51f 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -2577,6 +2577,37 @@ static void selinux_inode_free_security(struct inode *inode)
>  	inode_free_security(inode);
>  }
>  
> +static int selinux_dentry_init_security(struct dentry *dentry, int mode, void **ctx, u32 *ctxlen)
> +{
> +	struct cred *cred = current_cred();
> +	struct task_security_struct *tsec;
> +	struct inode_security_struct *dsec;
> +	struct superblock_security_struct *sbsec;
> +	struct inode *dir = dentry->d_parent->d_inode;

Locking?

> +	u32 newsid;
> +	int rc;
> +
> +	tsec = cred->security;
> +	dsec = dir->i_security;
> +	sbsec = dir->i_sb->s_security;
> +
> +	if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {

The logic in selinux_inode_init_security() has changed to use
(sbsec->flags & SE_SBLABELSUPP) instead.  Possibly you should factor the
common code into a helper.

> +		newsid = tsec->create_sid;
> +	} else {
> +		rc = security_transition_sid(tsec->sid, dsec->sid,
> +					     inode_mode_to_security_class(mode),
> +					     &newsid);
> +		if (rc) {
> +			printk(KERN_WARNING "%s:  "
> +			       "security_transition_sid failed, rc=%d\n",
> +			       __FUNCTION__, -rc);
> +			return rc;
> +		}
> +	}
> +
> +	return security_sid_to_context(newsid, (char **)ctx, ctxlen);
> +}
> +
>  static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
>  				       char **name, void **value,
>  				       size_t *len)
> @@ -5484,6 +5515,7 @@ static struct security_operations selinux_ops = {
>  	.sb_clone_mnt_opts =		selinux_sb_clone_mnt_opts,
>  	.sb_parse_opts_str = 		selinux_parse_opts_str,
>  
> +	.dentry_init_security =		selinux_dentry_init_security,
>  
>  	.inode_alloc_security =		selinux_inode_alloc_security,
>  	.inode_free_security =		selinux_inode_free_security,

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 10/10] NFSD: Server implementation of MAC Labeling
  2010-07-07 19:24       ` J. Bruce Fields
@ 2010-07-08 13:27           ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-08 13:27 UTC (permalink / raw)
  To: J. Bruce Fields
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, 2010-07-07 at 15:24 -0400, J. Bruce Fields wrote:
> On Wed, Jul 07, 2010 at 02:03:21PM -0400, David P. Quigley wrote:
> > Comments inline
> > 
> > On Wed, 2010-07-07 at 13:21 -0400, J. Bruce Fields wrote:
> > > On Wed, Jul 07, 2010 at 10:31:26AM -0400, David P. Quigley wrote:
> > > > This patch adds the ability to encode and decode file labels on the server for
> > > >  static __be32
> > > >  nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
> > > > -		   struct iattr *iattr, struct nfs4_acl **acl)
> > > > +		   struct iattr *iattr, struct nfs4_acl **acl,
> > > > +		   struct nfs4_label **label)
> > > 
> > > As we add more arguments, I wonder if at some point it becomes worth
> > > creating something like
> > > 
> > > 	struct nfsd4_attrs {
> > > 		struct iattr iattr;
> > > 		struct nfs4_acl *acl;
> > > 		...
> > > 	}
> > > 
> > > and passing that instead?
> > 
> > I can definitely submit something like that as a stand alone patch and
> > then add our nfs4_label stuff to that instead.
> 
> Not a big deal, but welcome if such a thing looks more generally useful
> (say, if the same arguments are passed elsewhere).
> 
> > > > +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
> > > > +	if (bmval[1] & FATTR4_WORD1_SECURITY_LABEL) {
> > > > +		uint32_t lfs;
> > > > +
> > > > +		READ_BUF(4);
> > > > +		len += 4;
> > > > +		READ32(lfs);
> > > > +		READ_BUF(4);
> > > > +		len += 4;
> > > > +		READ32(dummy32);
> > > > +		READ_BUF(dummy32);
> > > > +		len += (XDR_QUADLEN(dummy32) << 2);
> > > > +		READMEM(buf, dummy32);
> > > > +
> > > > +		if (dummy32 > NFS4_MAXLABELLEN)
> > > > +			return nfserr_resource;
> > > > +
> > > > +		*label = kzalloc(sizeof(struct nfs4_label), GFP_KERNEL);
> > > 
> > > Could we allocate this some toher way (it's small, right?) and avoid the
> > > extra dynamic allocation here, just for simplicity's sake?
> > 
> > How would you suggest going about doing that?
> 
> Maybe make op_label, cr_label, etc., a struct nfs4_label instead of a
> struct nfs4_label *?

I'll look into this. Since the structure contains a void * for the label
data it might not be necessary to have to allocate the label structure
itself just make sure its zeroed out so we can check to see if its
initialized with anything.

> 
> > 
> > > 
> > > > +		if (*label == NULL) {
> > > > +			host_err = -ENOMEM;
> > > > +			goto out_nfserr;
> > > > +		}
> > > > +
> > > > +		(*label)->label = kmalloc(dummy32 + 1, GFP_KERNEL);
> > > 
> > > Might be nice to arrange NFS4_MAXLABELLEN to ensure this is never a
> > > higher-order allocation.
> > 
> > This should never be more than 4096. Under what circumstances would this
> > become a higher-order allocation?
> 
> Can't dummy32+1 be 4097?

You're right. My mistake. NFS4_MAXLABELLEN is supposed to include the
null termination. I'll fix this. I wonder if its better to just redefine
NFS4_MAXLABELLEN to be 4095 so when we use the extra null terminator it
will be a page size max.
> 
> --b.


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 10/10] NFSD: Server implementation of MAC Labeling
@ 2010-07-08 13:27           ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-08 13:27 UTC (permalink / raw)
  To: J. Bruce Fields
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Wed, 2010-07-07 at 15:24 -0400, J. Bruce Fields wrote:
> On Wed, Jul 07, 2010 at 02:03:21PM -0400, David P. Quigley wrote:
> > Comments inline
> > 
> > On Wed, 2010-07-07 at 13:21 -0400, J. Bruce Fields wrote:
> > > On Wed, Jul 07, 2010 at 10:31:26AM -0400, David P. Quigley wrote:
> > > > This patch adds the ability to encode and decode file labels on the server for
> > > >  static __be32
> > > >  nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
> > > > -		   struct iattr *iattr, struct nfs4_acl **acl)
> > > > +		   struct iattr *iattr, struct nfs4_acl **acl,
> > > > +		   struct nfs4_label **label)
> > > 
> > > As we add more arguments, I wonder if at some point it becomes worth
> > > creating something like
> > > 
> > > 	struct nfsd4_attrs {
> > > 		struct iattr iattr;
> > > 		struct nfs4_acl *acl;
> > > 		...
> > > 	}
> > > 
> > > and passing that instead?
> > 
> > I can definitely submit something like that as a stand alone patch and
> > then add our nfs4_label stuff to that instead.
> 
> Not a big deal, but welcome if such a thing looks more generally useful
> (say, if the same arguments are passed elsewhere).
> 
> > > > +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
> > > > +	if (bmval[1] & FATTR4_WORD1_SECURITY_LABEL) {
> > > > +		uint32_t lfs;
> > > > +
> > > > +		READ_BUF(4);
> > > > +		len += 4;
> > > > +		READ32(lfs);
> > > > +		READ_BUF(4);
> > > > +		len += 4;
> > > > +		READ32(dummy32);
> > > > +		READ_BUF(dummy32);
> > > > +		len += (XDR_QUADLEN(dummy32) << 2);
> > > > +		READMEM(buf, dummy32);
> > > > +
> > > > +		if (dummy32 > NFS4_MAXLABELLEN)
> > > > +			return nfserr_resource;
> > > > +
> > > > +		*label = kzalloc(sizeof(struct nfs4_label), GFP_KERNEL);
> > > 
> > > Could we allocate this some toher way (it's small, right?) and avoid the
> > > extra dynamic allocation here, just for simplicity's sake?
> > 
> > How would you suggest going about doing that?
> 
> Maybe make op_label, cr_label, etc., a struct nfs4_label instead of a
> struct nfs4_label *?

I'll look into this. Since the structure contains a void * for the label
data it might not be necessary to have to allocate the label structure
itself just make sure its zeroed out so we can check to see if its
initialized with anything.

> 
> > 
> > > 
> > > > +		if (*label == NULL) {
> > > > +			host_err = -ENOMEM;
> > > > +			goto out_nfserr;
> > > > +		}
> > > > +
> > > > +		(*label)->label = kmalloc(dummy32 + 1, GFP_KERNEL);
> > > 
> > > Might be nice to arrange NFS4_MAXLABELLEN to ensure this is never a
> > > higher-order allocation.
> > 
> > This should never be more than 4096. Under what circumstances would this
> > become a higher-order allocation?
> 
> Can't dummy32+1 be 4097?

You're right. My mistake. NFS4_MAXLABELLEN is supposed to include the
null termination. I'll fix this. I wonder if its better to just redefine
NFS4_MAXLABELLEN to be 4095 so when we use the extra null terminator it
will be a page size max.
> 
> --b.


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 04/10] SELinux: Add new labeling type native labels
  2010-07-07 23:23     ` James Morris
@ 2010-07-08 13:31       ` David P. Quigley
  -1 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-08 13:31 UTC (permalink / raw)
  To: James Morris
  Cc: hch, viro, casey, sds, Matthew N. Dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Thu, 2010-07-08 at 09:23 +1000, James Morris wrote:
> On Wed, 7 Jul 2010, David P. Quigley wrote:
> 
> > 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.
> 
> It would be useful to have the ability to specify labeling behavior on a 
> per-mount basis, with the default remaining as genfs.
> 
> Otherwise, this is a global policy decision which affects all NFSv4 
> mounts, right?
> 
> 

I don't believe we have that ability in any other file system. If you
want to decide that you want to use genfs style labels on NFSv4 just use
a context mount. That way you can have the default behavior be use
security label support unless you don't want to and then you can have a
context mount.



^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 04/10] SELinux: Add new labeling type native labels
@ 2010-07-08 13:31       ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-08 13:31 UTC (permalink / raw)
  To: James Morris
  Cc: hch, viro, casey, sds, Matthew N. Dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Thu, 2010-07-08 at 09:23 +1000, James Morris wrote:
> On Wed, 7 Jul 2010, David P. Quigley wrote:
> 
> > 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.
> 
> It would be useful to have the ability to specify labeling behavior on a 
> per-mount basis, with the default remaining as genfs.
> 
> Otherwise, this is a global policy decision which affects all NFSv4 
> mounts, right?
> 
> 

I don't believe we have that ability in any other file system. If you
want to decide that you want to use genfs style labels on NFSv4 just use
a context mount. That way you can have the default behavior be use
security label support unless you don't want to and then you can have a
context mount.



--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-08 13:39         ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-08 13:39 UTC (permalink / raw)
  To: James Morris
  Cc: J. Bruce Fields, hch, viro, casey, sds, matthew.dodd,
	trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Thu, 2010-07-08 at 09:30 +1000, James Morris wrote:
> On Wed, 7 Jul 2010, J. Bruce Fields wrote:
> 
> > On Wed, Jul 07, 2010 at 10:31:22AM -0400, David P. Quigley wrote:
> > 
> > > +#define NFS4_MAXLABELLEN	4096
> > 
> > Idle curiosity--why 4096?  (Why couldn't it be 16?  And how do we know
> > people will never want 8192?)
> 
> I think I raised this a while back, too.
> 
> The maximum security label size on Linux is:
> 
> #define XATTR_SIZE_MAX 65536
> 
> Why arbitrarily limit this over the network?

Because there is no easy way not to. The specification doesn't specify a
limit to label size in the IETF draft. However there is no way to do
allocation of the memory needed to store the label where we first get
access to its size. We tried this before and it failed. When I asked
trond about it he said doing memory allocation in the rpc context isn't
allowed. For the most part what would make this label size inadequate
would be the MLS component. There are some cases where people want every
other compartment or something crazy like that. In terms of a normal
label though 4096 should be more than enough. Just to put this in
perspective the string below is 4096 a's.

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
 aaaaaaaaaa

> 
> Someone could have a valid local security label which can't be conveyed 
> via NFS.
> 
> 
> 
> - James


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-08 13:39         ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-08 13:39 UTC (permalink / raw)
  To: James Morris
  Cc: J. Bruce Fields, hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	casey-iSGtlc1asvQWG2LlvL+J4A, sds-+05T5uksL2qpZYMLLGbcSA,
	matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

On Thu, 2010-07-08 at 09:30 +1000, James Morris wrote:
> On Wed, 7 Jul 2010, J. Bruce Fields wrote:
> 
> > On Wed, Jul 07, 2010 at 10:31:22AM -0400, David P. Quigley wrote:
> > 
> > > +#define NFS4_MAXLABELLEN	4096
> > 
> > Idle curiosity--why 4096?  (Why couldn't it be 16?  And how do we know
> > people will never want 8192?)
> 
> I think I raised this a while back, too.
> 
> The maximum security label size on Linux is:
> 
> #define XATTR_SIZE_MAX 65536
> 
> Why arbitrarily limit this over the network?

Because there is no easy way not to. The specification doesn't specify a
limit to label size in the IETF draft. However there is no way to do
allocation of the memory needed to store the label where we first get
access to its size. We tried this before and it failed. When I asked
trond about it he said doing memory allocation in the rpc context isn't
allowed. For the most part what would make this label size inadequate
would be the MLS component. There are some cases where people want every
other compartment or something crazy like that. In terms of a normal
label though 4096 should be more than enough. Just to put this in
perspective the string below is 4096 a's.

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

> 
> Someone could have a valid local security label which can't be conveyed 
> via NFS.
> 
> 
> 
> - James

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-08 13:39         ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-08 13:39 UTC (permalink / raw)
  To: James Morris
  Cc: J. Bruce Fields, hch, viro, casey, sds, matthew.dodd,
	trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Thu, 2010-07-08 at 09:30 +1000, James Morris wrote:
> On Wed, 7 Jul 2010, J. Bruce Fields wrote:
> 
> > On Wed, Jul 07, 2010 at 10:31:22AM -0400, David P. Quigley wrote:
> > 
> > > +#define NFS4_MAXLABELLEN	4096
> > 
> > Idle curiosity--why 4096?  (Why couldn't it be 16?  And how do we know
> > people will never want 8192?)
> 
> I think I raised this a while back, too.
> 
> The maximum security label size on Linux is:
> 
> #define XATTR_SIZE_MAX 65536
> 
> Why arbitrarily limit this over the network?

Because there is no easy way not to. The specification doesn't specify a
limit to label size in the IETF draft. However there is no way to do
allocation of the memory needed to store the label where we first get
access to its size. We tried this before and it failed. When I asked
trond about it he said doing memory allocation in the rpc context isn't
allowed. For the most part what would make this label size inadequate
would be the MLS component. There are some cases where people want every
other compartment or something crazy like that. In terms of a normal
label though 4096 should be more than enough. Just to put this in
perspective the string below is 4096 a's.

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
 aaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
 aaaaaaaa
aa

> 
> Someone could have a valid local security label which can't be conveyed 
> via NFS.
> 
> 
> 
> - James



--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-08 13:39         ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-08 13:39 UTC (permalink / raw)
  To: James Morris
  Cc: J. Bruce Fields, hch, viro, casey, sds, matthew.dodd,
	trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Thu, 2010-07-08 at 09:30 +1000, James Morris wrote:
> On Wed, 7 Jul 2010, J. Bruce Fields wrote:
> 
> > On Wed, Jul 07, 2010 at 10:31:22AM -0400, David P. Quigley wrote:
> > 
> > > +#define NFS4_MAXLABELLEN	4096
> > 
> > Idle curiosity--why 4096?  (Why couldn't it be 16?  And how do we know
> > people will never want 8192?)
> 
> I think I raised this a while back, too.
> 
> The maximum security label size on Linux is:
> 
> #define XATTR_SIZE_MAX 65536
> 
> Why arbitrarily limit this over the network?

Because there is no easy way not to. The specification doesn't specify a
limit to label size in the IETF draft. However there is no way to do
allocation of the memory needed to store the label where we first get
access to its size. We tried this before and it failed. When I asked
trond about it he said doing memory allocation in the rpc context isn't
allowed. For the most part what would make this label size inadequate
would be the MLS component. There are some cases where people want every
other compartment or something crazy like that. In terms of a normal
label though 4096 should be more than enough. Just to put this in
perspective the string below is 4096 a's.

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aa

> 
> Someone could have a valid local security label which can't be conveyed 
> via NFS.
> 
> 
> 
> - James


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 04/10] SELinux: Add new labeling type native labels
  2010-07-08 13:31       ` David P. Quigley
@ 2010-07-08 22:33         ` James Morris
  -1 siblings, 0 replies; 95+ messages in thread
From: James Morris @ 2010-07-08 22:33 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, sds, Matthew N. Dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Thu, 8 Jul 2010, David P. Quigley wrote:

> > Otherwise, this is a global policy decision which affects all NFSv4 
> > mounts, right?
> > 
> > 
> 
> I don't believe we have that ability in any other file system.

NFS is quite different to other filesystems.  Your files are on other 
systems, for example, which may or may not support security labeling.

> If you want to decide that you want to use genfs style labels on NFSv4 
> just use a context mount.

So, we enable this feature, and virtually all existing mounts break 
because the servers do not support labeling.

> That way you can have the default behavior be 
> use security label support unless you don't want to and then you can 
> have a context mount.

It needs to be the other way around.  This is a new feature, so the 
default needs to be the existing behavior, with security labeling as an 
option to enable at mount time.



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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 04/10] SELinux: Add new labeling type native labels
@ 2010-07-08 22:33         ` James Morris
  0 siblings, 0 replies; 95+ messages in thread
From: James Morris @ 2010-07-08 22:33 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, sds, Matthew N. Dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Thu, 8 Jul 2010, David P. Quigley wrote:

> > Otherwise, this is a global policy decision which affects all NFSv4 
> > mounts, right?
> > 
> > 
> 
> I don't believe we have that ability in any other file system.

NFS is quite different to other filesystems.  Your files are on other 
systems, for example, which may or may not support security labeling.

> If you want to decide that you want to use genfs style labels on NFSv4 
> just use a context mount.

So, we enable this feature, and virtually all existing mounts break 
because the servers do not support labeling.

> That way you can have the default behavior be 
> use security label support unless you don't want to and then you can 
> have a context mount.

It needs to be the other way around.  This is a new feature, so the 
default needs to be the existing behavior, with security labeling as an 
option to enable at mount time.



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

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
  2010-07-08 13:39         ` David P. Quigley
@ 2010-07-08 22:48           ` James Morris
  -1 siblings, 0 replies; 95+ messages in thread
From: James Morris @ 2010-07-08 22:48 UTC (permalink / raw)
  To: David P. Quigley
  Cc: J. Bruce Fields, hch, viro, casey, sds, matthew.dodd,
	trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Thu, 8 Jul 2010, David P. Quigley wrote:

> > The maximum security label size on Linux is:
> > 
> > #define XATTR_SIZE_MAX 65536
> > 
> > Why arbitrarily limit this over the network?
> 
> Because there is no easy way not to. The specification doesn't specify a
> limit to label size in the IETF draft. However there is no way to do
> allocation of the memory needed to store the label where we first get
> access to its size. We tried this before and it failed. When I asked
> trond about it he said doing memory allocation in the rpc context isn't
> allowed.

In the NFSv3 code, the workaround I've been using is to always allocate 
64k, but the correct way of doing this apparently is to use the page 
cache, as is used for ACLs and symlinks.

> For the most part what would make this label size inadequate would be 
> the MLS component. There are some cases where people want every other 
> compartment or something crazy like that. In terms of a normal label 
> though 4096 should be more than enough.

Yes, but we should not unnecessarily limit the network protocol when 
something is valid and possible in the local implementation (which is ~64k 
under Linux).

> Just to put this in perspective the string below is 4096 a's.

A security label include just about anything, e.g. an x509 certificate, or 
a base64 encoded image.

In the Linux implementation, if we can store a local label up to 64k, then 
we should try and ensure that it can be conveyed via NFS.



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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-08 22:48           ` James Morris
  0 siblings, 0 replies; 95+ messages in thread
From: James Morris @ 2010-07-08 22:48 UTC (permalink / raw)
  To: David P. Quigley
  Cc: J. Bruce Fields, hch, viro, casey, sds, matthew.dodd,
	trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Thu, 8 Jul 2010, David P. Quigley wrote:

> > The maximum security label size on Linux is:
> > 
> > #define XATTR_SIZE_MAX 65536
> > 
> > Why arbitrarily limit this over the network?
> 
> Because there is no easy way not to. The specification doesn't specify a
> limit to label size in the IETF draft. However there is no way to do
> allocation of the memory needed to store the label where we first get
> access to its size. We tried this before and it failed. When I asked
> trond about it he said doing memory allocation in the rpc context isn't
> allowed.

In the NFSv3 code, the workaround I've been using is to always allocate 
64k, but the correct way of doing this apparently is to use the page 
cache, as is used for ACLs and symlinks.

> For the most part what would make this label size inadequate would be 
> the MLS component. There are some cases where people want every other 
> compartment or something crazy like that. In terms of a normal label 
> though 4096 should be more than enough.

Yes, but we should not unnecessarily limit the network protocol when 
something is valid and possible in the local implementation (which is ~64k 
under Linux).

> Just to put this in perspective the string below is 4096 a's.

A security label include just about anything, e.g. an x509 certificate, or 
a base64 encoded image.

In the Linux implementation, if we can store a local label up to 64k, then 
we should try and ensure that it can be conveyed via NFS.



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

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-09 13:47             ` Stephen Smalley
  0 siblings, 0 replies; 95+ messages in thread
From: Stephen Smalley @ 2010-07-09 13:47 UTC (permalink / raw)
  To: James Morris
  Cc: David P. Quigley, J. Bruce Fields, hch, viro, casey,
	matthew.dodd, trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Fri, 2010-07-09 at 08:48 +1000, James Morris wrote:
> On Thu, 8 Jul 2010, David P. Quigley wrote:
> 
> > > The maximum security label size on Linux is:
> > > 
> > > #define XATTR_SIZE_MAX 65536
> > > 
> > > Why arbitrarily limit this over the network?
> > 
> > Because there is no easy way not to. The specification doesn't specify a
> > limit to label size in the IETF draft. However there is no way to do
> > allocation of the memory needed to store the label where we first get
> > access to its size. We tried this before and it failed. When I asked
> > trond about it he said doing memory allocation in the rpc context isn't
> > allowed.
> 
> In the NFSv3 code, the workaround I've been using is to always allocate 
> 64k, but the correct way of doing this apparently is to use the page 
> cache, as is used for ACLs and symlinks.
> 
> > For the most part what would make this label size inadequate would be 
> > the MLS component. There are some cases where people want every other 
> > compartment or something crazy like that. In terms of a normal label 
> > though 4096 should be more than enough.
> 
> Yes, but we should not unnecessarily limit the network protocol when 
> something is valid and possible in the local implementation (which is ~64k 
> under Linux).
> 
> > Just to put this in perspective the string below is 4096 a's.
> 
> A security label include just about anything, e.g. an x509 certificate, or 
> a base64 encoded image.
> 
> In the Linux implementation, if we can store a local label up to 64k, then 
> we should try and ensure that it can be conveyed via NFS.

You can't store a local label up to 64k on Linux; that is just what the
xattr API permits, not the underlying filesystem implementations (at
least ext[234]).

# touch foobar
# setfattr -n user.foo -v `perl -e 'print "a" x 4096'` foobar
setfattr: foobar: No space left on device

Also the /proc/self/attr and selinuxfs APIs are presently limited to
page size.

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-09 13:47             ` Stephen Smalley
  0 siblings, 0 replies; 95+ messages in thread
From: Stephen Smalley @ 2010-07-09 13:47 UTC (permalink / raw)
  To: James Morris
  Cc: David P. Quigley, J. Bruce Fields, hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	casey-iSGtlc1asvQWG2LlvL+J4A,
	matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

On Fri, 2010-07-09 at 08:48 +1000, James Morris wrote:
> On Thu, 8 Jul 2010, David P. Quigley wrote:
> 
> > > The maximum security label size on Linux is:
> > > 
> > > #define XATTR_SIZE_MAX 65536
> > > 
> > > Why arbitrarily limit this over the network?
> > 
> > Because there is no easy way not to. The specification doesn't specify a
> > limit to label size in the IETF draft. However there is no way to do
> > allocation of the memory needed to store the label where we first get
> > access to its size. We tried this before and it failed. When I asked
> > trond about it he said doing memory allocation in the rpc context isn't
> > allowed.
> 
> In the NFSv3 code, the workaround I've been using is to always allocate 
> 64k, but the correct way of doing this apparently is to use the page 
> cache, as is used for ACLs and symlinks.
> 
> > For the most part what would make this label size inadequate would be 
> > the MLS component. There are some cases where people want every other 
> > compartment or something crazy like that. In terms of a normal label 
> > though 4096 should be more than enough.
> 
> Yes, but we should not unnecessarily limit the network protocol when 
> something is valid and possible in the local implementation (which is ~64k 
> under Linux).
> 
> > Just to put this in perspective the string below is 4096 a's.
> 
> A security label include just about anything, e.g. an x509 certificate, or 
> a base64 encoded image.
> 
> In the Linux implementation, if we can store a local label up to 64k, then 
> we should try and ensure that it can be conveyed via NFS.

You can't store a local label up to 64k on Linux; that is just what the
xattr API permits, not the underlying filesystem implementations (at
least ext[234]).

# touch foobar
# setfattr -n user.foo -v `perl -e 'print "a" x 4096'` foobar
setfattr: foobar: No space left on device

Also the /proc/self/attr and selinuxfs APIs are presently limited to
page size.

-- 
Stephen Smalley
National Security Agency

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-09 13:47             ` Stephen Smalley
  0 siblings, 0 replies; 95+ messages in thread
From: Stephen Smalley @ 2010-07-09 13:47 UTC (permalink / raw)
  To: James Morris
  Cc: David P. Quigley, J. Bruce Fields, hch, viro, casey,
	matthew.dodd, trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Fri, 2010-07-09 at 08:48 +1000, James Morris wrote:
> On Thu, 8 Jul 2010, David P. Quigley wrote:
> 
> > > The maximum security label size on Linux is:
> > > 
> > > #define XATTR_SIZE_MAX 65536
> > > 
> > > Why arbitrarily limit this over the network?
> > 
> > Because there is no easy way not to. The specification doesn't specify a
> > limit to label size in the IETF draft. However there is no way to do
> > allocation of the memory needed to store the label where we first get
> > access to its size. We tried this before and it failed. When I asked
> > trond about it he said doing memory allocation in the rpc context isn't
> > allowed.
> 
> In the NFSv3 code, the workaround I've been using is to always allocate 
> 64k, but the correct way of doing this apparently is to use the page 
> cache, as is used for ACLs and symlinks.
> 
> > For the most part what would make this label size inadequate would be 
> > the MLS component. There are some cases where people want every other 
> > compartment or something crazy like that. In terms of a normal label 
> > though 4096 should be more than enough.
> 
> Yes, but we should not unnecessarily limit the network protocol when 
> something is valid and possible in the local implementation (which is ~64k 
> under Linux).
> 
> > Just to put this in perspective the string below is 4096 a's.
> 
> A security label include just about anything, e.g. an x509 certificate, or 
> a base64 encoded image.
> 
> In the Linux implementation, if we can store a local label up to 64k, then 
> we should try and ensure that it can be conveyed via NFS.

You can't store a local label up to 64k on Linux; that is just what the
xattr API permits, not the underlying filesystem implementations (at
least ext[234]).

# touch foobar
# setfattr -n user.foo -v `perl -e 'print "a" x 4096'` foobar
setfattr: foobar: No space left on device

Also the /proc/self/attr and selinuxfs APIs are presently limited to
page size.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-09 14:05             ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-09 14:05 UTC (permalink / raw)
  To: James Morris
  Cc: J. Bruce Fields, hch, viro, casey, sds, matthew.dodd,
	trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Fri, 2010-07-09 at 08:48 +1000, James Morris wrote:
> On Thu, 8 Jul 2010, David P. Quigley wrote:
> 
> > > The maximum security label size on Linux is:
> > > 
> > > #define XATTR_SIZE_MAX 65536
> > > 
> > > Why arbitrarily limit this over the network?
> > 
> > Because there is no easy way not to. The specification doesn't specify a
> > limit to label size in the IETF draft. However there is no way to do
> > allocation of the memory needed to store the label where we first get
> > access to its size. We tried this before and it failed. When I asked
> > trond about it he said doing memory allocation in the rpc context isn't
> > allowed.
> 
> In the NFSv3 code, the workaround I've been using is to always allocate 
> 64k, but the correct way of doing this apparently is to use the page 
> cache, as is used for ACLs and symlinks.
> 
> > For the most part what would make this label size inadequate would be 
> > the MLS component. There are some cases where people want every other 
> > compartment or something crazy like that. In terms of a normal label 
> > though 4096 should be more than enough.
> 
> Yes, but we should not unnecessarily limit the network protocol when 
> something is valid and possible in the local implementation (which is ~64k 
> under Linux).
> 
> > Just to put this in perspective the string below is 4096 a's.
> 
> A security label include just about anything, e.g. an x509 certificate, or 
> a base64 encoded image.
> 
> In the Linux implementation, if we can store a local label up to 64k, then 
> we should try and ensure that it can be conveyed via NFS.
> 
> 
> 
> - James


If you want that to be the case you need to make your case to Trond
about that. I've already had this conversation before and he seems to
think that a page is sufficient. Bruce also has concerns about not
wanting these labels to require a high order allocation. Under memory
pressure finding 16 contiguous pages for each label might be a problem.

Dave


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-09 14:05             ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-09 14:05 UTC (permalink / raw)
  To: James Morris
  Cc: J. Bruce Fields, hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	casey-iSGtlc1asvQWG2LlvL+J4A, sds-+05T5uksL2qpZYMLLGbcSA,
	matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

On Fri, 2010-07-09 at 08:48 +1000, James Morris wrote:
> On Thu, 8 Jul 2010, David P. Quigley wrote:
> 
> > > The maximum security label size on Linux is:
> > > 
> > > #define XATTR_SIZE_MAX 65536
> > > 
> > > Why arbitrarily limit this over the network?
> > 
> > Because there is no easy way not to. The specification doesn't specify a
> > limit to label size in the IETF draft. However there is no way to do
> > allocation of the memory needed to store the label where we first get
> > access to its size. We tried this before and it failed. When I asked
> > trond about it he said doing memory allocation in the rpc context isn't
> > allowed.
> 
> In the NFSv3 code, the workaround I've been using is to always allocate 
> 64k, but the correct way of doing this apparently is to use the page 
> cache, as is used for ACLs and symlinks.
> 
> > For the most part what would make this label size inadequate would be 
> > the MLS component. There are some cases where people want every other 
> > compartment or something crazy like that. In terms of a normal label 
> > though 4096 should be more than enough.
> 
> Yes, but we should not unnecessarily limit the network protocol when 
> something is valid and possible in the local implementation (which is ~64k 
> under Linux).
> 
> > Just to put this in perspective the string below is 4096 a's.
> 
> A security label include just about anything, e.g. an x509 certificate, or 
> a base64 encoded image.
> 
> In the Linux implementation, if we can store a local label up to 64k, then 
> we should try and ensure that it can be conveyed via NFS.
> 
> 
> 
> - James


If you want that to be the case you need to make your case to Trond
about that. I've already had this conversation before and he seems to
think that a page is sufficient. Bruce also has concerns about not
wanting these labels to require a high order allocation. Under memory
pressure finding 16 contiguous pages for each label might be a problem.

Dave

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-09 14:05             ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-09 14:05 UTC (permalink / raw)
  To: James Morris
  Cc: J. Bruce Fields, hch, viro, casey, sds, matthew.dodd,
	trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Fri, 2010-07-09 at 08:48 +1000, James Morris wrote:
> On Thu, 8 Jul 2010, David P. Quigley wrote:
> 
> > > The maximum security label size on Linux is:
> > > 
> > > #define XATTR_SIZE_MAX 65536
> > > 
> > > Why arbitrarily limit this over the network?
> > 
> > Because there is no easy way not to. The specification doesn't specify a
> > limit to label size in the IETF draft. However there is no way to do
> > allocation of the memory needed to store the label where we first get
> > access to its size. We tried this before and it failed. When I asked
> > trond about it he said doing memory allocation in the rpc context isn't
> > allowed.
> 
> In the NFSv3 code, the workaround I've been using is to always allocate 
> 64k, but the correct way of doing this apparently is to use the page 
> cache, as is used for ACLs and symlinks.
> 
> > For the most part what would make this label size inadequate would be 
> > the MLS component. There are some cases where people want every other 
> > compartment or something crazy like that. In terms of a normal label 
> > though 4096 should be more than enough.
> 
> Yes, but we should not unnecessarily limit the network protocol when 
> something is valid and possible in the local implementation (which is ~64k 
> under Linux).
> 
> > Just to put this in perspective the string below is 4096 a's.
> 
> A security label include just about anything, e.g. an x509 certificate, or 
> a base64 encoded image.
> 
> In the Linux implementation, if we can store a local label up to 64k, then 
> we should try and ensure that it can be conveyed via NFS.
> 
> 
> 
> - James


If you want that to be the case you need to make your case to Trond
about that. I've already had this conversation before and he seems to
think that a page is sufficient. Bruce also has concerns about not
wanting these labels to require a high order allocation. Under memory
pressure finding 16 contiguous pages for each label might be a problem.

Dave


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 04/10] SELinux: Add new labeling type native labels
  2010-07-08 22:33         ` James Morris
@ 2010-07-09 14:09           ` David P. Quigley
  -1 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-09 14:09 UTC (permalink / raw)
  To: James Morris
  Cc: hch, viro, casey, sds, Matthew N. Dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Fri, 2010-07-09 at 08:33 +1000, James Morris wrote:
> On Thu, 8 Jul 2010, David P. Quigley wrote:
> 
> > > Otherwise, this is a global policy decision which affects all NFSv4 
> > > mounts, right?
> > > 
> > > 
> > 
> > I don't believe we have that ability in any other file system.
> 
> NFS is quite different to other filesystems.  Your files are on other 
> systems, for example, which may or may not support security labeling.

And if that is the case then the capability flag does not get set in the
NFSv4 server caps and we don't use security label support on that mount.

> 
> > If you want to decide that you want to use genfs style labels on NFSv4 
> > just use a context mount.
> 
> So, we enable this feature, and virtually all existing mounts break 
> because the servers do not support labeling.

No it should default back to being nfs_t which is what happens when I
use my client on an export that doesn't have security_label set.

> 
> > That way you can have the default behavior be 
> > use security label support unless you don't want to and then you can 
> > have a context mount.
> 
> It needs to be the other way around.  This is a new feature, so the 
> default needs to be the existing behavior, with security labeling as an 
> option to enable at mount time.

We made sure it falls back properly. It was decided a long time ago with
discussion by several people that having it default to use it if its
there otherwise fall back to the old behavior makes much more sense to
an administrator.

> 
> 
> 
> - James


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 04/10] SELinux: Add new labeling type native labels
@ 2010-07-09 14:09           ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-07-09 14:09 UTC (permalink / raw)
  To: James Morris
  Cc: hch, viro, casey, sds, Matthew N. Dodd, trond.myklebust, bfields,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	linux-nfs

On Fri, 2010-07-09 at 08:33 +1000, James Morris wrote:
> On Thu, 8 Jul 2010, David P. Quigley wrote:
> 
> > > Otherwise, this is a global policy decision which affects all NFSv4 
> > > mounts, right?
> > > 
> > > 
> > 
> > I don't believe we have that ability in any other file system.
> 
> NFS is quite different to other filesystems.  Your files are on other 
> systems, for example, which may or may not support security labeling.

And if that is the case then the capability flag does not get set in the
NFSv4 server caps and we don't use security label support on that mount.

> 
> > If you want to decide that you want to use genfs style labels on NFSv4 
> > just use a context mount.
> 
> So, we enable this feature, and virtually all existing mounts break 
> because the servers do not support labeling.

No it should default back to being nfs_t which is what happens when I
use my client on an export that doesn't have security_label set.

> 
> > That way you can have the default behavior be 
> > use security label support unless you don't want to and then you can 
> > have a context mount.
> 
> It needs to be the other way around.  This is a new feature, so the 
> default needs to be the existing behavior, with security labeling as an 
> option to enable at mount time.

We made sure it falls back properly. It was decided a long time ago with
discussion by several people that having it default to use it if its
there otherwise fall back to the old behavior makes much more sense to
an administrator.

> 
> 
> 
> - James


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4  flags
@ 2010-07-11  5:02               ` Kyle Moffett
  0 siblings, 0 replies; 95+ messages in thread
From: Kyle Moffett @ 2010-07-11  5:02 UTC (permalink / raw)
  To: David P. Quigley
  Cc: James Morris, J. Bruce Fields, hch, viro, casey, sds,
	matthew.dodd, trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Fri, Jul 9, 2010 at 10:05, David P. Quigley <dpquigl@tycho.nsa.gov> wrote:
> On Fri, 2010-07-09 at 08:48 +1000, James Morris wrote:
>> Yes, but we should not unnecessarily limit the network protocol when
>> something is valid and possible in the local implementation (which is ~64k
>> under Linux).
>>
>> A security label include just about anything, e.g. an x509 certificate, or
>> a base64 encoded image.
>>
>> In the Linux implementation, if we can store a local label up to 64k, then
>> we should try and ensure that it can be conveyed via NFS.
>
> If you want that to be the case you need to make your case to Trond
> about that. I've already had this conversation before and he seems to
> think that a page is sufficient. Bruce also has concerns about not
> wanting these labels to require a high order allocation. Under memory
> pressure finding 16 contiguous pages for each label might be a problem.

I would argue that if somebody wants to stick a base64-encoded image
or an x509 certificate in their security labels then shipping the
whole thing across the wire every time somebody does an extended
"stat" is just stupid.  Think about how much overhead there would be
if you did an "ls -Z" of a directory with 100 files (64k * 100 ==
6.4MB!!!), where that data would previously have fit in no more than
10-20k TOTAL.

A better solution would be something along the lines of putting at
most a SHA512 sum in the label field and have a separate caching
communication protocol (either in-band or out-of-band) to pass the
fully-descriptive payload.

Even in local filesystems like ext3 we prefer to turn labels into
numbers, store the number with each inode, and then keep the labels
indexed in a separate datastructure.

Cheers,
Kyle Moffett

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-11  5:02               ` Kyle Moffett
  0 siblings, 0 replies; 95+ messages in thread
From: Kyle Moffett @ 2010-07-11  5:02 UTC (permalink / raw)
  To: David P. Quigley
  Cc: James Morris, J. Bruce Fields, hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	casey-iSGtlc1asvQWG2LlvL+J4A, sds-+05T5uksL2qpZYMLLGbcSA,
	matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

On Fri, Jul 9, 2010 at 10:05, David P. Quigley <dpquigl-+05T5uksL2qpZYMLLGbcSA@public.gmane.org> wrote:
> On Fri, 2010-07-09 at 08:48 +1000, James Morris wrote:
>> Yes, but we should not unnecessarily limit the network protocol when
>> something is valid and possible in the local implementation (which is ~64k
>> under Linux).
>>
>> A security label include just about anything, e.g. an x509 certificate, or
>> a base64 encoded image.
>>
>> In the Linux implementation, if we can store a local label up to 64k, then
>> we should try and ensure that it can be conveyed via NFS.
>
> If you want that to be the case you need to make your case to Trond
> about that. I've already had this conversation before and he seems to
> think that a page is sufficient. Bruce also has concerns about not
> wanting these labels to require a high order allocation. Under memory
> pressure finding 16 contiguous pages for each label might be a problem.

I would argue that if somebody wants to stick a base64-encoded image
or an x509 certificate in their security labels then shipping the
whole thing across the wire every time somebody does an extended
"stat" is just stupid.  Think about how much overhead there would be
if you did an "ls -Z" of a directory with 100 files (64k * 100 ==
6.4MB!!!), where that data would previously have fit in no more than
10-20k TOTAL.

A better solution would be something along the lines of putting at
most a SHA512 sum in the label field and have a separate caching
communication protocol (either in-band or out-of-band) to pass the
fully-descriptive payload.

Even in local filesystems like ext3 we prefer to turn labels into
numbers, store the number with each inode, and then keep the labels
indexed in a separate datastructure.

Cheers,
Kyle Moffett
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-11  5:02               ` Kyle Moffett
  0 siblings, 0 replies; 95+ messages in thread
From: Kyle Moffett @ 2010-07-11  5:02 UTC (permalink / raw)
  To: David P. Quigley
  Cc: James Morris, J. Bruce Fields, hch, viro, casey, sds,
	matthew.dodd, trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Fri, Jul 9, 2010 at 10:05, David P. Quigley <dpquigl@tycho.nsa.gov> wrote:
> On Fri, 2010-07-09 at 08:48 +1000, James Morris wrote:
>> Yes, but we should not unnecessarily limit the network protocol when
>> something is valid and possible in the local implementation (which is ~64k
>> under Linux).
>>
>> A security label include just about anything, e.g. an x509 certificate, or
>> a base64 encoded image.
>>
>> In the Linux implementation, if we can store a local label up to 64k, then
>> we should try and ensure that it can be conveyed via NFS.
>
> If you want that to be the case you need to make your case to Trond
> about that. I've already had this conversation before and he seems to
> think that a page is sufficient. Bruce also has concerns about not
> wanting these labels to require a high order allocation. Under memory
> pressure finding 16 contiguous pages for each label might be a problem.

I would argue that if somebody wants to stick a base64-encoded image
or an x509 certificate in their security labels then shipping the
whole thing across the wire every time somebody does an extended
"stat" is just stupid.  Think about how much overhead there would be
if you did an "ls -Z" of a directory with 100 files (64k * 100 ==
6.4MB!!!), where that data would previously have fit in no more than
10-20k TOTAL.

A better solution would be something along the lines of putting at
most a SHA512 sum in the label field and have a separate caching
communication protocol (either in-band or out-of-band) to pass the
fully-descriptive payload.

Even in local filesystems like ext3 we prefer to turn labels into
numbers, store the number with each inode, and then keep the labels
indexed in a separate datastructure.

Cheers,
Kyle Moffett

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-11  5:02               ` Kyle Moffett
  0 siblings, 0 replies; 95+ messages in thread
From: Kyle Moffett @ 2010-07-11  5:02 UTC (permalink / raw)
  To: David P. Quigley
  Cc: James Morris, J. Bruce Fields, hch, viro, casey, sds,
	matthew.dodd, trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

On Fri, Jul 9, 2010 at 10:05, David P. Quigley <dpquigl@tycho.nsa.gov> wrote:
> On Fri, 2010-07-09 at 08:48 +1000, James Morris wrote:
>> Yes, but we should not unnecessarily limit the network protocol when
>> something is valid and possible in the local implementation (which is ~64k
>> under Linux).
>>
>> A security label include just about anything, e.g. an x509 certificate, or
>> a base64 encoded image.
>>
>> In the Linux implementation, if we can store a local label up to 64k, then
>> we should try and ensure that it can be conveyed via NFS.
>
> If you want that to be the case you need to make your case to Trond
> about that. I've already had this conversation before and he seems to
> think that a page is sufficient. Bruce also has concerns about not
> wanting these labels to require a high order allocation. Under memory
> pressure finding 16 contiguous pages for each label might be a problem.

I would argue that if somebody wants to stick a base64-encoded image
or an x509 certificate in their security labels then shipping the
whole thing across the wire every time somebody does an extended
"stat" is just stupid.  Think about how much overhead there would be
if you did an "ls -Z" of a directory with 100 files (64k * 100 ==
6.4MB!!!), where that data would previously have fit in no more than
10-20k TOTAL.

A better solution would be something along the lines of putting at
most a SHA512 sum in the label field and have a separate caching
communication protocol (either in-band or out-of-band) to pass the
fully-descriptive payload.

Even in local filesystems like ext3 we prefer to turn labels into
numbers, store the number with each inode, and then keep the labels
indexed in a separate datastructure.

Cheers,
Kyle Moffett

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-11  5:12                 ` Casey Schaufler
  0 siblings, 0 replies; 95+ messages in thread
From: Casey Schaufler @ 2010-07-11  5:12 UTC (permalink / raw)
  To: Kyle Moffett
  Cc: David P. Quigley, James Morris, J. Bruce Fields, hch, viro, sds,
	matthew.dodd, trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

Kyle Moffett wrote:
> ...
> Even in local filesystems like ext3 we prefer to turn labels into
> numbers, store the number with each inode, and then keep the labels
> indexed in a separate datastructure.
>   

I don't know what system you're talking about, but that notion
was pretty well dispelled in the late 1980's, after the SystemV/MLS
and SecureWare examples.

> Cheers,
> Kyle Moffett
>
>
>   


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-11  5:12                 ` Casey Schaufler
  0 siblings, 0 replies; 95+ messages in thread
From: Casey Schaufler @ 2010-07-11  5:12 UTC (permalink / raw)
  To: Kyle Moffett
  Cc: David P. Quigley, James Morris, J. Bruce Fields,
	hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	sds-+05T5uksL2qpZYMLLGbcSA, matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

Kyle Moffett wrote:
> ...
> Even in local filesystems like ext3 we prefer to turn labels into
> numbers, store the number with each inode, and then keep the labels
> indexed in a separate datastructure.
>   

I don't know what system you're talking about, but that notion
was pretty well dispelled in the late 1980's, after the SystemV/MLS
and SecureWare examples.

> Cheers,
> Kyle Moffett
>
>
>   

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-11  5:12                 ` Casey Schaufler
  0 siblings, 0 replies; 95+ messages in thread
From: Casey Schaufler @ 2010-07-11  5:12 UTC (permalink / raw)
  To: Kyle Moffett
  Cc: David P. Quigley, James Morris, J. Bruce Fields, hch, viro, sds,
	matthew.dodd, trond.myklebust, linux-kernel, linux-fsdevel,
	linux-security-module, selinux, linux-nfs

Kyle Moffett wrote:
> ...
> Even in local filesystems like ext3 we prefer to turn labels into
> numbers, store the number with each inode, and then keep the labels
> indexed in a separate datastructure.
>   

I don't know what system you're talking about, but that notion
was pretty well dispelled in the late 1980's, after the SystemV/MLS
and SecureWare examples.

> Cheers,
> Kyle Moffett
>
>
>   


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
  2010-07-11  5:12                 ` Casey Schaufler
@ 2010-07-12 14:36                   ` Stephen Smalley
  -1 siblings, 0 replies; 95+ messages in thread
From: Stephen Smalley @ 2010-07-12 14:36 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Kyle Moffett, David P. Quigley, James Morris, J. Bruce Fields,
	hch, viro, matthew.dodd, trond.myklebust, linux-kernel,
	linux-fsdevel, linux-security-module, selinux, linux-nfs

On Sat, 2010-07-10 at 22:12 -0700, Casey Schaufler wrote:
> Kyle Moffett wrote:
> > ...
> > Even in local filesystems like ext3 we prefer to turn labels into
> > numbers, store the number with each inode, and then keep the labels
> > indexed in a separate datastructure.
> >   
> 
> I don't know what system you're talking about, but that notion
> was pretty well dispelled in the late 1980's, after the SystemV/MLS
> and SecureWare examples.

SELinux did that too before switching to using xattrs for label storage.
Persistent security identifier (PSID) associated with each inode (either
stored directly in the inode in the original kernel patches or
associated through a separate mapping in the LSM-based implementation),
with a mapping from PSID to context stored in a mapping within each
filesystem.  Allowed you to keep the labels with the volume but avoided
storing the same label multiple times.

The xattr based implementation can sometimes share storage but only when
the xattr is stored in the additional block (not when they are stored
inline) and only if all of the xattrs on the file are identical.

> > Cheers,
> > Kyle Moffett
> >
> >
> >   

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-12 14:36                   ` Stephen Smalley
  0 siblings, 0 replies; 95+ messages in thread
From: Stephen Smalley @ 2010-07-12 14:36 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Kyle Moffett, David P. Quigley, James Morris, J. Bruce Fields,
	hch, viro, matthew.dodd, trond.myklebust, linux-kernel,
	linux-fsdevel, linux-security-module, selinux, linux-nfs

On Sat, 2010-07-10 at 22:12 -0700, Casey Schaufler wrote:
> Kyle Moffett wrote:
> > ...
> > Even in local filesystems like ext3 we prefer to turn labels into
> > numbers, store the number with each inode, and then keep the labels
> > indexed in a separate datastructure.
> >   
> 
> I don't know what system you're talking about, but that notion
> was pretty well dispelled in the late 1980's, after the SystemV/MLS
> and SecureWare examples.

SELinux did that too before switching to using xattrs for label storage.
Persistent security identifier (PSID) associated with each inode (either
stored directly in the inode in the original kernel patches or
associated through a separate mapping in the LSM-based implementation),
with a mapping from PSID to context stored in a mapping within each
filesystem.  Allowed you to keep the labels with the volume but avoided
storing the same label multiple times.

The xattr based implementation can sometimes share storage but only when
the xattr is stored in the additional block (not when they are stored
inline) and only if all of the xattrs on the file are identical.

> > Cheers,
> > Kyle Moffett
> >
> >
> >   

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4  flags
@ 2010-07-17  0:09                     ` Kyle Moffett
  0 siblings, 0 replies; 95+ messages in thread
From: Kyle Moffett @ 2010-07-17  0:09 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Casey Schaufler, David P. Quigley, James Morris, J. Bruce Fields,
	hch, viro, matthew.dodd, trond.myklebust, linux-kernel,
	linux-fsdevel, linux-security-module, selinux, linux-nfs

On Mon, Jul 12, 2010 at 10:36, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On Sat, 2010-07-10 at 22:12 -0700, Casey Schaufler wrote:
>> Kyle Moffett wrote:
>> > ...
>> > Even in local filesystems like ext3 we prefer to turn labels into
>> > numbers, store the number with each inode, and then keep the labels
>> > indexed in a separate datastructure.
>> >
>>
>> I don't know what system you're talking about, but that notion
>> was pretty well dispelled in the late 1980's, after the SystemV/MLS
>> and SecureWare examples.
>
> SELinux did that too before switching to using xattrs for label storage.
> Persistent security identifier (PSID) associated with each inode (either
> stored directly in the inode in the original kernel patches or
> associated through a separate mapping in the LSM-based implementation),
> with a mapping from PSID to context stored in a mapping within each
> filesystem.  Allowed you to keep the labels with the volume but avoided
> storing the same label multiple times.
>
> The xattr based implementation can sometimes share storage but only when
> the xattr is stored in the additional block (not when they are stored
> inline) and only if all of the xattrs on the file are identical.

Hmm, for some reason I was still thinking that we stored an encoded
form of the label even in xattrs.  Whoops!

On the other hand, I guess it should be noted that the "common" case
of an SELinux label is the inline storage case, labels are on average
no more than ~40 bytes:
  system_u:object_r:sysadm_homedir_t:s0

In filesystems that are space optimized (like squashfs), we still
prefer to pack xattrs, symlinks, and even file permissions as tightly
as possible through table lookups of various forms.  Heck, the
read-only squashfs only stores a single empty-directory inode and
references it wherever needed.

On the other hand, if you're doing something completely silly with 64k
labels then any hope of inline storage went out the window along with
any space savings from nifty FS optimizations like de-duplication or
tail-packing.

Cheers,
Kyle Moffett

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-17  0:09                     ` Kyle Moffett
  0 siblings, 0 replies; 95+ messages in thread
From: Kyle Moffett @ 2010-07-17  0:09 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Casey Schaufler, David P. Quigley, James Morris, J. Bruce Fields,
	hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA, linux-nfs-u79uwXL29TY76Z2rM5mHXA

On Mon, Jul 12, 2010 at 10:36, Stephen Smalley <sds-+05T5uksL2qpZYMLLGbcSA@public.gmane.org> wrote:
> On Sat, 2010-07-10 at 22:12 -0700, Casey Schaufler wrote:
>> Kyle Moffett wrote:
>> > ...
>> > Even in local filesystems like ext3 we prefer to turn labels into
>> > numbers, store the number with each inode, and then keep the labels
>> > indexed in a separate datastructure.
>> >
>>
>> I don't know what system you're talking about, but that notion
>> was pretty well dispelled in the late 1980's, after the SystemV/MLS
>> and SecureWare examples.
>
> SELinux did that too before switching to using xattrs for label storage.
> Persistent security identifier (PSID) associated with each inode (either
> stored directly in the inode in the original kernel patches or
> associated through a separate mapping in the LSM-based implementation),
> with a mapping from PSID to context stored in a mapping within each
> filesystem.  Allowed you to keep the labels with the volume but avoided
> storing the same label multiple times.
>
> The xattr based implementation can sometimes share storage but only when
> the xattr is stored in the additional block (not when they are stored
> inline) and only if all of the xattrs on the file are identical.

Hmm, for some reason I was still thinking that we stored an encoded
form of the label even in xattrs.  Whoops!

On the other hand, I guess it should be noted that the "common" case
of an SELinux label is the inline storage case, labels are on average
no more than ~40 bytes:
  system_u:object_r:sysadm_homedir_t:s0

In filesystems that are space optimized (like squashfs), we still
prefer to pack xattrs, symlinks, and even file permissions as tightly
as possible through table lookups of various forms.  Heck, the
read-only squashfs only stores a single empty-directory inode and
references it wherever needed.

On the other hand, if you're doing something completely silly with 64k
labels then any hope of inline storage went out the window along with
any space savings from nifty FS optimizations like de-duplication or
tail-packing.

Cheers,
Kyle Moffett
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-17  0:09                     ` Kyle Moffett
  0 siblings, 0 replies; 95+ messages in thread
From: Kyle Moffett @ 2010-07-17  0:09 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Casey Schaufler, David P. Quigley, James Morris, J. Bruce Fields,
	hch, viro, matthew.dodd, trond.myklebust, linux-kernel,
	linux-fsdevel, linux-security-module, selinux, linux-nfs

On Mon, Jul 12, 2010 at 10:36, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On Sat, 2010-07-10 at 22:12 -0700, Casey Schaufler wrote:
>> Kyle Moffett wrote:
>> > ...
>> > Even in local filesystems like ext3 we prefer to turn labels into
>> > numbers, store the number with each inode, and then keep the labels
>> > indexed in a separate datastructure.
>> >
>>
>> I don't know what system you're talking about, but that notion
>> was pretty well dispelled in the late 1980's, after the SystemV/MLS
>> and SecureWare examples.
>
> SELinux did that too before switching to using xattrs for label storage.
> Persistent security identifier (PSID) associated with each inode (either
> stored directly in the inode in the original kernel patches or
> associated through a separate mapping in the LSM-based implementation),
> with a mapping from PSID to context stored in a mapping within each
> filesystem.  Allowed you to keep the labels with the volume but avoided
> storing the same label multiple times.
>
> The xattr based implementation can sometimes share storage but only when
> the xattr is stored in the additional block (not when they are stored
> inline) and only if all of the xattrs on the file are identical.

Hmm, for some reason I was still thinking that we stored an encoded
form of the label even in xattrs.  Whoops!

On the other hand, I guess it should be noted that the "common" case
of an SELinux label is the inline storage case, labels are on average
no more than ~40 bytes:
  system_u:object_r:sysadm_homedir_t:s0

In filesystems that are space optimized (like squashfs), we still
prefer to pack xattrs, symlinks, and even file permissions as tightly
as possible through table lookups of various forms.  Heck, the
read-only squashfs only stores a single empty-directory inode and
references it wherever needed.

On the other hand, if you're doing something completely silly with 64k
labels then any hope of inline storage went out the window along with
any space savings from nifty FS optimizations like de-duplication or
tail-packing.

Cheers,
Kyle Moffett


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags
@ 2010-07-17  0:09                     ` Kyle Moffett
  0 siblings, 0 replies; 95+ messages in thread
From: Kyle Moffett @ 2010-07-17  0:09 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Casey Schaufler, David P. Quigley, James Morris, J. Bruce Fields,
	hch, viro, matthew.dodd, trond.myklebust, linux-kernel,
	linux-fsdevel, linux-security-module, selinux, linux-nfs

On Mon, Jul 12, 2010 at 10:36, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On Sat, 2010-07-10 at 22:12 -0700, Casey Schaufler wrote:
>> Kyle Moffett wrote:
>> > ...
>> > Even in local filesystems like ext3 we prefer to turn labels into
>> > numbers, store the number with each inode, and then keep the labels
>> > indexed in a separate datastructure.
>> >
>>
>> I don't know what system you're talking about, but that notion
>> was pretty well dispelled in the late 1980's, after the SystemV/MLS
>> and SecureWare examples.
>
> SELinux did that too before switching to using xattrs for label storage.
> Persistent security identifier (PSID) associated with each inode (either
> stored directly in the inode in the original kernel patches or
> associated through a separate mapping in the LSM-based implementation),
> with a mapping from PSID to context stored in a mapping within each
> filesystem.  Allowed you to keep the labels with the volume but avoided
> storing the same label multiple times.
>
> The xattr based implementation can sometimes share storage but only when
> the xattr is stored in the additional block (not when they are stored
> inline) and only if all of the xattrs on the file are identical.

Hmm, for some reason I was still thinking that we stored an encoded
form of the label even in xattrs.  Whoops!

On the other hand, I guess it should be noted that the "common" case
of an SELinux label is the inline storage case, labels are on average
no more than ~40 bytes:
  system_u:object_r:sysadm_homedir_t:s0

In filesystems that are space optimized (like squashfs), we still
prefer to pack xattrs, symlinks, and even file permissions as tightly
as possible through table lookups of various forms.  Heck, the
read-only squashfs only stores a single empty-directory inode and
references it wherever needed.

On the other hand, if you're doing something completely silly with 64k
labels then any hope of inline storage went out the window along with
any space savings from nifty FS optimizations like de-duplication or
tail-packing.

Cheers,
Kyle Moffett

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: Labeled-NFS: Security Label support in NFSv4
  2010-06-08 16:22 ` David P. Quigley
  (?)
  (?)
@ 2010-06-08 23:10 ` J. Bruce Fields
  -1 siblings, 0 replies; 95+ messages in thread
From: J. Bruce Fields @ 2010-06-08 23:10 UTC (permalink / raw)
  To: David P. Quigley
  Cc: hch, viro, casey, sds, matthew.dodd, trond.myklebust,
	linux-kernel, linux-fsdevel, linux-security-module, selinux,
	labeled-nfs

On Tue, Jun 08, 2010 at 12:22:46PM -0400, David P. Quigley wrote:
> It has been quite a while since the last time we submitted a patch set to the
> mailing list for review. I met with Trond at the last IETF meeting and he
> suggested that we resubmit the patches for review since the IETF process has
> moved along since the last posting. When reviewing the code please be critical
> of it. 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
> 
> 

Note the bakeathon's next week.  I'm hosting (and going a little crazy
trying to do the setup), and I think Trond's travelling on vacation this
week.  Hopefully others will have comments, but if you want anything
from either of us you may want to try again in a couple weeks.

--b.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Labeled-NFS: Security Label support in NFSv4
@ 2010-06-08 16:22 ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-06-08 16:22 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux, labeled-nfs

It has been quite a while since the last time we submitted a patch set to the
mailing list for review. I met with Trond at the last IETF meeting and he
suggested that we resubmit the patches for review since the IETF process has
moved along since the last posting. When reviewing the code please be critical
of it. 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



^ permalink raw reply	[flat|nested] 95+ messages in thread

* Labeled-NFS: Security Label support in NFSv4
@ 2010-06-08 16:22 ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-06-08 16:22 UTC (permalink / raw)
  To: hch-wEGCiKHe2LqWVfeAwA7xHQ,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	casey-iSGtlc1asvQWG2LlvL+J4A, sds-+05T5uksL2qpZYMLLGbcSA,
	matthew.dodd-DABiIiYg7OfQT0dZR+AlfA,
	trond.myklebust-41N18TsMXrtuMpJDpNschA,
	bfields-uC3wQj2KruNg9hUCZPvPmw
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	selinux-+05T5uksL2qpZYMLLGbcSA,
	labeled-nfs-6DNke4IJHB0gsBAKwltoeQ

It has been quite a while since the last time we submitted a patch set to the
mailing list for review. I met with Trond at the last IETF meeting and he
suggested that we resubmit the patches for review since the IETF process has
moved along since the last posting. When reviewing the code please be critical
of it. 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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Labeled-NFS: Security Label support in NFSv4
@ 2010-06-08 16:22 ` David P. Quigley
  0 siblings, 0 replies; 95+ messages in thread
From: David P. Quigley @ 2010-06-08 16:22 UTC (permalink / raw)
  To: hch, viro, casey, sds, matthew.dodd, trond.myklebust, bfields
  Cc: linux-kernel, linux-fsdevel, linux-security-module, selinux, labeled-nfs

It has been quite a while since the last time we submitted a patch set to the
mailing list for review. I met with Trond at the last IETF meeting and he
suggested that we resubmit the patches for review since the IETF process has
moved along since the last posting. When reviewing the code please be critical
of it. 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



--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 95+ messages in thread

end of thread, other threads:[~2010-07-17  0:09 UTC | newest]

Thread overview: 95+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-07-07 14:31 Labeled-NFS: Security Label support in NFSv4 David P. Quigley
2010-07-07 14:31 ` David P. Quigley
2010-07-07 14:31 ` [PATCH 01/10] Security: Add hook to calculate context based on a negative dentry David P. Quigley
2010-07-07 14:31   ` David P. Quigley
2010-07-08 12:51   ` Stephen Smalley
2010-07-08 12:51     ` Stephen Smalley
2010-07-07 14:31 ` [PATCH 02/10] Security: Add Hook to test if the particular xattr is part of a MAC model David P. Quigley
2010-07-07 14:31   ` David P. Quigley
2010-07-07 16:49   ` J. Bruce Fields
2010-07-07 16:49     ` J. Bruce Fields
2010-07-07 14:31 ` [PATCH 03/10] LSM: Add flags field to security_sb_set_mnt_opts for in kernel mount data David P. Quigley
2010-07-07 14:31   ` David P. Quigley
2010-07-07 14:31 ` [PATCH 04/10] SELinux: Add new labeling type native labels David P. Quigley
2010-07-07 14:31   ` David P. Quigley
2010-07-07 23:23   ` James Morris
2010-07-07 23:23     ` James Morris
2010-07-08 13:31     ` David P. Quigley
2010-07-08 13:31       ` David P. Quigley
2010-07-08 22:33       ` James Morris
2010-07-08 22:33         ` James Morris
2010-07-09 14:09         ` David P. Quigley
2010-07-09 14:09           ` David P. Quigley
2010-07-07 14:31 ` [PATCH 05/10] KConfig: Add KConfig entries for Labeled NFS David P. Quigley
2010-07-07 14:31   ` David P. Quigley
2010-07-07 16:56   ` J. Bruce Fields
2010-07-07 16:56     ` J. Bruce Fields
2010-07-07 17:05     ` David P. Quigley
2010-07-07 17:05       ` David P. Quigley
2010-07-07 17:05       ` David P. Quigley
2010-07-07 17:53     ` Chuck Lever
2010-07-07 17:53       ` Chuck Lever
2010-07-07 14:31 ` [PATCH 06/10] NFSv4: Add label recommended attribute and NFSv4 flags David P. Quigley
2010-07-07 14:31   ` David P. Quigley
2010-07-07 17:00   ` J. Bruce Fields
2010-07-07 23:30     ` James Morris
2010-07-07 23:30       ` James Morris
2010-07-08 13:39       ` David P. Quigley
2010-07-08 13:39         ` David P. Quigley
2010-07-08 13:39         ` David P. Quigley
2010-07-08 13:39         ` David P. Quigley
2010-07-08 22:48         ` James Morris
2010-07-08 22:48           ` James Morris
2010-07-09 13:47           ` Stephen Smalley
2010-07-09 13:47             ` Stephen Smalley
2010-07-09 13:47             ` Stephen Smalley
2010-07-09 14:05           ` David P. Quigley
2010-07-09 14:05             ` David P. Quigley
2010-07-09 14:05             ` David P. Quigley
2010-07-11  5:02             ` Kyle Moffett
2010-07-11  5:02               ` Kyle Moffett
2010-07-11  5:02               ` Kyle Moffett
2010-07-11  5:02               ` Kyle Moffett
2010-07-11  5:12               ` Casey Schaufler
2010-07-11  5:12                 ` Casey Schaufler
2010-07-11  5:12                 ` Casey Schaufler
2010-07-12 14:36                 ` Stephen Smalley
2010-07-12 14:36                   ` Stephen Smalley
2010-07-17  0:09                   ` Kyle Moffett
2010-07-17  0:09                     ` Kyle Moffett
2010-07-17  0:09                     ` Kyle Moffett
2010-07-17  0:09                     ` Kyle Moffett
2010-07-07 14:31 ` [PATCH 07/10] NFSv4: Introduce new label structure David P. Quigley
2010-07-07 14:31   ` David P. Quigley
2010-07-07 16:01   ` Chuck Lever
2010-07-07 16:21     ` Casey Schaufler
2010-07-07 16:21       ` Casey Schaufler
2010-07-07 16:21       ` Casey Schaufler
2010-07-07 16:24       ` David P. Quigley
2010-07-07 16:24         ` David P. Quigley
2010-07-07 16:24         ` David P. Quigley
2010-07-07 17:42       ` Chuck Lever
2010-07-07 17:42         ` Chuck Lever
2010-07-07 16:22     ` David P. Quigley
2010-07-07 16:22       ` David P. Quigley
2010-07-07 16:22       ` David P. Quigley
2010-07-07 17:49       ` Chuck Lever
2010-07-07 18:11         ` David P. Quigley
2010-07-07 18:11           ` David P. Quigley
2010-07-07 14:31 ` [PATCH 08/10] NFS: Client implementation of Labeled-NFS David P. Quigley
2010-07-07 14:31   ` David P. Quigley
2010-07-07 14:31 ` [PATCH 09/10] NFS: Extend NFS xattr handlers to accept the security namespace David P. Quigley
2010-07-07 14:31   ` David P. Quigley
2010-07-07 14:31 ` [PATCH 10/10] NFSD: Server implementation of MAC Labeling David P. Quigley
2010-07-07 14:31   ` David P. Quigley
2010-07-07 17:21   ` J. Bruce Fields
2010-07-07 18:03     ` David P. Quigley
2010-07-07 18:03       ` David P. Quigley
2010-07-07 18:03       ` David P. Quigley
2010-07-07 19:24       ` J. Bruce Fields
2010-07-08 13:27         ` David P. Quigley
2010-07-08 13:27           ` David P. Quigley
  -- strict thread matches above, loose matches on Subject: below --
2010-06-08 16:22 Labeled-NFS: Security Label support in NFSv4 David P. Quigley
2010-06-08 16:22 ` David P. Quigley
2010-06-08 16:22 ` David P. Quigley
2010-06-08 23:10 ` J. Bruce Fields

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.