[kernel/Label_NFS] Label NFS port to Fedora 3.7.0-0.rc7.git1.2.fc19
Steve Dickson
steved at fedoraproject.org
Tue Dec 4 15:50:03 UTC 2012
commit 838e4208cccf722716a5a02f03871bf07413a32c
Author: Steve Dickson <steved at redhat.com>
Date: Tue Dec 4 10:39:29 2012 -0500
Label NFS port to Fedora 3.7.0-0.rc7.git1.2.fc19
Signed-off-by: Steve Dickson <steved at redhat.com>
config-generic | 1 +
config-x86_64-generic | 2 +-
kernel.spec | 6 +-
lnfs-3.7.0-0.rc7.git1.2.fc19.patch | 3923 ++++++++++++++++++++++++++++++
lnfs-unset-3.7.0-0.rc7.git1.2.fc19.patch | 124 +
5 files changed, 4054 insertions(+), 2 deletions(-)
---
diff --git a/config-generic b/config-generic
index a27aedd..8def083 100644
--- a/config-generic
+++ b/config-generic
@@ -3652,6 +3652,7 @@ CONFIG_NFS_V4=y
# CONFIG_NFS_SWAP is not set
CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
+NFS_V4_SECURITY_LABEL=y
CONFIG_NFSD=m
CONFIG_NFSD_V3=y
CONFIG_NFSD_V3_ACL=y
diff --git a/config-x86_64-generic b/config-x86_64-generic
index 6003f11..4e2ba56 100644
--- a/config-x86_64-generic
+++ b/config-x86_64-generic
@@ -123,4 +123,4 @@ CONFIG_BPF_JIT=y
# Should be 32bit only, but lacks KConfig depends
# CONFIG_XO15_EBOOK is not set
-
+CONFIG_NFS_V4_SECURITY_LABEL=y
diff --git a/kernel.spec b/kernel.spec
index 0ba866e..65cfdef 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -31,7 +31,7 @@ Summary: The Linux kernel
#
# (Uncomment the '#' and both spaces below to set the buildid.)
#
-# % define buildid .local
+%define buildid .lnfs37rc2
###################################################################
# The buildid can also be specified on the rpmbuild command line
@@ -719,6 +719,8 @@ Patch2901: linux-2.6-v4l-dvb-experimental.patch
# fs fixes
# NFSv4
+Patch3000: lnfs-3.7.0-0.rc7.git1.2.fc19.patch
+Patch3001: lnfs-unset-3.7.0-0.rc7.git1.2.fc19.patch
# patches headed upstream
Patch10000: fs-proc-devtree-remove_proc_entry.patch
@@ -1370,6 +1372,8 @@ ApplyPatch arm-tegra-sdhci-module-fix.patch
# eCryptfs
# NFSv4
+ApplyPatch lnfs-3.7.0-0.rc7.git1.2.fc19.patch
+ApplyPatch lnfs-unset-3.7.0-0.rc7.git1.2.fc19.patch
# USB
diff --git a/lnfs-3.7.0-0.rc7.git1.2.fc19.patch b/lnfs-3.7.0-0.rc7.git1.2.fc19.patch
new file mode 100644
index 0000000..e57c32a
--- /dev/null
+++ b/lnfs-3.7.0-0.rc7.git1.2.fc19.patch
@@ -0,0 +1,3923 @@
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/client.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/client.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/client.c.orig 2012-11-29 16:37:13.672901481 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/client.c 2012-12-03 10:53:55.645785378 -0500
+@@ -1080,7 +1080,7 @@ struct nfs_server *nfs_create_server(str
+ }
+
+ if (!(fattr->valid & NFS_ATTR_FATTR)) {
+- error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh, fattr);
++ error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh, fattr, NULL);
+ if (error < 0) {
+ dprintk("nfs_create_server: getattr error = %d\n", -error);
+ goto error;
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/export.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/export.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/export.c.orig 2012-09-30 19:47:46.000000000 -0400
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/export.c 2012-12-03 10:53:55.670785398 -0500
+@@ -1112,6 +1112,9 @@ static struct flags {
+ { NFSEXP_ASYNC, {"async", "sync"}},
+ { NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}},
+ { NFSEXP_NOHIDE, {"nohide", ""}},
++#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
++ { NFSEXP_SECURITY_LABEL, {"security_label", ""}},
++#endif
+ { NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
+ { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
+ { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/dir.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/dir.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/dir.c.orig 2012-11-29 16:37:13.680901489 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/dir.c 2012-12-03 10:53:55.653785381 -0500
+@@ -447,7 +447,7 @@ void nfs_prime_dcache(struct dentry *par
+ dentry = d_lookup(parent, &filename);
+ if (dentry != NULL) {
+ if (nfs_same_file(dentry, entry)) {
+- nfs_refresh_inode(dentry->d_inode, entry->fattr);
++ nfs_refresh_inode(dentry->d_inode, entry->fattr, entry->label);
+ goto out;
+ } else {
+ d_drop(dentry);
+@@ -459,7 +459,7 @@ void nfs_prime_dcache(struct dentry *par
+ if (dentry == NULL)
+ return;
+
+- inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr);
++ inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr, entry->label);
+ if (IS_ERR(inode))
+ goto out;
+
+@@ -581,7 +581,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir
+ entry.fh = nfs_alloc_fhandle();
+ entry.fattr = nfs_alloc_fattr();
+ entry.server = NFS_SERVER(inode);
+- if (entry.fh == NULL || entry.fattr == NULL)
++ entry.label = nfs4_label_alloc(GFP_NOWAIT);
++ if (entry.fh == NULL || entry.fattr == NULL || entry.label == NULL)
+ goto out;
+
+ array = nfs_readdir_get_array(page);
+@@ -616,6 +617,7 @@ out_release_array:
+ out:
+ nfs_free_fattr(entry.fattr);
+ nfs_free_fhandle(entry.fh);
++ nfs4_label_free(entry.label);
+ return status;
+ }
+
+@@ -1034,6 +1036,7 @@ static int nfs_lookup_revalidate(struct
+ struct dentry *parent;
+ struct nfs_fh *fhandle = NULL;
+ struct nfs_fattr *fattr = NULL;
++ struct nfs4_label *label = NULL;
+ int error;
+
+ if (flags & LOOKUP_RCU)
+@@ -1076,16 +1079,30 @@ static int nfs_lookup_revalidate(struct
+ if (fhandle == NULL || fattr == NULL)
+ goto out_error;
+
+- 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_error;
++ }
++#endif
++
++ error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
+ if (error)
+ goto out_bad;
+ if (nfs_compare_fh(NFS_FH(inode), fhandle))
+ goto out_bad;
+- if ((error = nfs_refresh_inode(inode, fattr)) != 0)
++ if ((error = nfs_refresh_inode(inode, fattr, label)) != 0)
+ goto out_bad;
+
+ nfs_free_fattr(fattr);
+ nfs_free_fhandle(fhandle);
++
++#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));
+ out_valid:
+@@ -1122,6 +1139,7 @@ out_zap_parent:
+ out_error:
+ nfs_free_fattr(fattr);
+ nfs_free_fhandle(fhandle);
++ nfs4_label_free(label);
+ dput(parent);
+ dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n",
+ __func__, dentry->d_parent->d_name.name,
+@@ -1207,6 +1225,7 @@ struct dentry *nfs_lookup(struct inode *
+ struct inode *inode = NULL;
+ struct nfs_fh *fhandle = NULL;
+ struct nfs_fattr *fattr = NULL;
++ struct nfs4_label *label = NULL;
+ int error;
+
+ dfprintk(VFS, "NFS: lookup(%s/%s)\n",
+@@ -1233,17 +1252,24 @@ struct dentry *nfs_lookup(struct inode *
+ if (fhandle == NULL || fattr == NULL)
+ 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;
++ }
++#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 = ERR_CAST(inode);
+ if (IS_ERR(res))
+ goto out_unblock_sillyrename;
+@@ -1262,6 +1288,10 @@ no_entry:
+ out_unblock_sillyrename:
+ nfs_unblock_sillyrename(parent);
+ out:
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL))
++ nfs4_label_free(label);
++#endif
+ nfs_free_fattr(fattr);
+ nfs_free_fhandle(fhandle);
+ return res;
+@@ -1477,7 +1507,8 @@ no_open:
+ * 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;
+@@ -1490,18 +1521,18 @@ int nfs_instantiate(struct dentry *dentr
+ 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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/Kconfig.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/Kconfig
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/Kconfig.orig 2012-09-30 19:47:46.000000000 -0400
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/Kconfig 2012-12-03 10:53:55.669785397 -0500
+@@ -81,6 +81,19 @@ config NFSD_V4
+
+ If unsure, say N.
+
++config NFSD_V4_SECURITY_LABEL
++ bool "Provide Security Label support for NFSv4 server"
++ depends on NFSD_V4 && SECURITY
++ help
++
++ 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.
++
+ config NFSD_FAULT_INJECTION
+ bool "NFS server manual fault injection"
+ depends on NFSD_V4 && DEBUG_KERNEL
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/nfs4proc.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/nfs4proc.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/nfs4proc.c.orig 2012-11-29 16:37:14.048901772 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/nfs4proc.c 2012-12-03 10:53:55.671785399 -0500
+@@ -41,6 +41,10 @@
+ #include "vfs.h"
+ #include "current_stateid.h"
+
++#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
++#include <linux/security.h>
++#endif
++
+ #define NFSDDBG_FACILITY NFSDDBG_PROC
+
+ static u32 nfsd_attrmask[] = {
+@@ -228,6 +232,18 @@ do_open_lookup(struct svc_rqst *rqstp, s
+ (u32 *)open->op_verf.data,
+ &open->op_truncate, &open->op_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
+@@ -588,6 +604,18 @@ nfsd4_create(struct svc_rqst *rqstp, str
+ 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;
+
+@@ -869,6 +897,11 @@ nfsd4_setattr(struct svc_rqst *rqstp, st
+ 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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/nfs4xdr.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/nfs4xdr.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/nfs4xdr.c.orig 2012-11-29 16:37:14.066901788 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/nfs4xdr.c 2012-12-03 10:53:55.672785400 -0500
+@@ -54,6 +54,11 @@
+ #include "state.h"
+ #include "cache.h"
+
++#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
++#include <linux/security.h>
++#endif
++
++
+ #define NFSDDBG_FACILITY NFSDDBG_XDR
+
+ /*
+@@ -241,7 +246,8 @@ nfsd4_decode_bitmap(struct nfsd4_compoun
+
+ 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;
+@@ -385,6 +391,50 @@ nfsd4_decode_fattr(struct nfsd4_compound
+ goto xdr_error;
+ }
+ }
++#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
++ if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
++ uint32_t pi;
++ uint32_t lfs;
++
++ READ_BUF(4);
++ len += 4;
++ READ32(lfs);
++ READ_BUF(4);
++ len += 4;
++ READ32(pi);
++ 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)->pi = pi;
++ (*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)
+@@ -494,7 +544,7 @@ nfsd4_decode_create(struct nfsd4_compoun
+ 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;
+
+@@ -744,7 +794,7 @@ nfsd4_decode_open(struct nfsd4_compounda
+ 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;
+@@ -758,7 +808,7 @@ nfsd4_decode_open(struct nfsd4_compounda
+ READ_BUF(NFS4_VERIFIER_SIZE);
+ COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
+ 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;
+@@ -981,7 +1031,7 @@ nfsd4_decode_setattr(struct nfsd4_compou
+ 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
+@@ -1045,7 +1095,7 @@ nfsd4_decode_verify(struct nfsd4_compoun
+ * 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;
+@@ -1998,6 +2048,47 @@ nfsd4_encode_aclname(struct svc_rqst *rq
+ FATTR4_WORD0_RDATTR_ERROR)
+ #define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
+
++#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 pi = 0;
++ 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 + 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);
++ WRITE32(pi);
++ 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
++
+ static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
+ {
+ /* As per referral draft: */
+@@ -2122,6 +2213,14 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
+
+ if (!aclsupport)
+ word0 &= ~FATTR4_WORD0_ACL;
++#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
++ if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
++ word2 |= FATTR4_WORD2_SECURITY_LABEL;
++ else
++ word2 &= ~FATTR4_WORD2_SECURITY_LABEL;
++#else
++ word2 &= ~FATTR4_WORD2_SECURITY_LABEL;
++#endif
+ if (!word2) {
+ if ((buflen -= 12) < 0)
+ goto out_resource;
+@@ -2444,6 +2543,16 @@ out_acl:
+ }
+ WRITE64(stat.ino);
+ }
++#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
++ if (bmval2 & FATTR4_WORD2_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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/nfsd.h.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/nfsd.h
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/nfsd.h.orig 2012-11-29 16:37:14.081901803 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/nfsd.h 2012-12-03 10:53:55.673785401 -0500
+@@ -322,10 +322,10 @@ extern time_t nfsd4_grace;
+ | 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)
+
+-#define NFSD4_SUPPORTED_ATTRS_WORD2 0
++#define NFSD4_SUPPORTED_ATTRS_WORD2 FATTR4_WORD2_SECURITY_LABEL
+
+ #define NFSD4_1_SUPPORTED_ATTRS_WORD0 \
+ NFSD4_SUPPORTED_ATTRS_WORD0
+@@ -364,7 +364,7 @@ static inline u32 nfsd_suppattrs2(u32 mi
+ #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)
+-#define NFSD_WRITEABLE_ATTRS_WORD2 0
++#define NFSD_WRITEABLE_ATTRS_WORD2 FATTR4_WORD2_SECURITY_LABEL
+
+ #define NFSD_SUPPATTR_EXCLCREAT_WORD0 \
+ NFSD_WRITEABLE_ATTRS_WORD0
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/vfs.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/vfs.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/vfs.c.orig 2012-11-29 16:37:14.133901832 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/vfs.c 2012-12-03 10:53:55.674785401 -0500
+@@ -28,6 +28,7 @@
+ #include <asm/uaccess.h>
+ #include <linux/exportfs.h>
+ #include <linux/writeback.h>
++#include <linux/security.h>
+
+ #ifdef CONFIG_NFSD_V3
+ #include "xdr3.h"
+@@ -621,6 +622,36 @@ int nfsd4_is_junction(struct dentry *den
+ return 0;
+ return 1;
+ }
++
++#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_NFSD_V4) */
+
+ #ifdef CONFIG_NFSD_V3
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/vfs.h.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/vfs.h
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/vfs.h.orig 2012-09-30 19:47:46.000000000 -0400
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/vfs.h 2012-12-03 10:53:55.674785401 -0500
+@@ -55,6 +55,8 @@ int nfsd_mountpoint(struct dentry *, str
+ __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,
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/xdr4.h.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/xdr4.h
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/xdr4.h.orig 2012-09-30 19:47:46.000000000 -0400
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfsd/xdr4.h 2012-12-03 10:53:55.675785402 -0500
+@@ -118,6 +118,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
+@@ -246,6 +247,7 @@ struct nfsd4_open {
+ struct nfs4_file *op_file; /* used during processing */
+ struct nfs4_ol_stateid *op_stp; /* used during processing */
+ struct nfs4_acl *op_acl;
++ struct nfs4_label *op_label;
+ };
+ #define op_iattr iattr
+
+@@ -330,6 +332,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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/getroot.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/getroot.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/getroot.c.orig 2012-11-29 16:37:13.711901517 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/getroot.c 2012-12-03 10:53:55.653785381 -0500
+@@ -95,7 +95,7 @@ struct dentry *nfs_get_root(struct super
+ goto out;
+ }
+
+- 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");
+ ret = ERR_CAST(inode);
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/inode.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/inode.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/inode.c.orig 2012-11-29 16:37:13.728901534 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/inode.c 2012-12-03 10:53:55.655785383 -0500
+@@ -61,7 +61,7 @@
+ static bool 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;
+
+@@ -156,9 +156,18 @@ static void nfs_zap_caches_locked(struct
+
+ memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf));
+ 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;
++ nfsi->cache_validity |= NFS_INO_INVALID_ATTR
++ | NFS_INO_INVALID_LABEL
++ | 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_ATTR
++ | NFS_INO_INVALID_LABEL
++ | NFS_INO_INVALID_ACCESS
++ | NFS_INO_INVALID_ACL
++ | NFS_INO_REVAL_PAGECACHE;
+ }
+
+ void nfs_zap_caches(struct inode *inode)
+@@ -246,12 +255,77 @@ nfs_init_locked(struct inode *inode, voi
+ return 0;
+ }
+
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
++ struct nfs4_label *label)
++{
++ int error;
++
++ 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);
++ }
++}
++
++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;
++ label->pi = 0;
++ return label;
++}
++EXPORT_SYMBOL_GPL(nfs4_label_alloc);
++
++void nfs4_label_init(struct nfs4_label *label)
++{
++ if (label && label->label) {
++ *(unsigned char *)label->label = 0;
++ label->len = NFS4_MAXLABELLEN;
++ /* 0 is the null format meaning that the data is not
++ to be translated */
++ label->lfs = 0;
++ label->pi = 0;
++ }
++ return;
++}
++EXPORT_SYMBOL_GPL(nfs4_label_init);
++
++void nfs4_label_free(struct nfs4_label *label)
++{
++ kfree(label);
++ return;
++}
++EXPORT_SYMBOL_GPL(nfs4_label_free);
++
++#else
++void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
++ struct nfs4_label *label)
++{
++}
++#endif
++EXPORT_SYMBOL_GPL(nfs_setsecurity);
++
+ /*
+ * 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,
+@@ -373,6 +447,9 @@ nfs_fhget(struct super_block *sb, struct
+ */
+ 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;
+@@ -381,7 +458,7 @@ nfs_fhget(struct super_block *sb, struct
+
+ unlock_new_inode(inode);
+ } else
+- nfs_refresh_inode(inode, fattr);
++ nfs_refresh_inode(inode, fattr, label);
+ dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n",
+ inode->i_sb->s_id,
+ (long long)NFS_FILEID(inode),
+@@ -438,7 +515,7 @@ nfs_setattr(struct dentry *dentry, struc
+ NFS_PROTO(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);
+ nfs_free_fattr(fattr);
+ out:
+ return error;
+@@ -735,6 +812,7 @@ struct nfs_open_context *nfs_find_open_c
+ spin_unlock(&inode->i_lock);
+ return ctx;
+ }
++EXPORT_SYMBOL_GPL(nfs_find_open_context);
+
+ static void nfs_file_clear_open_context(struct file *filp)
+ {
+@@ -780,6 +858,7 @@ int
+ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+ {
+ int status = -ESTALE;
++ struct nfs4_label *label = NULL;
+ struct nfs_fattr *fattr = NULL;
+ struct nfs_inode *nfsi = NFS_I(inode);
+
+@@ -797,7 +876,16 @@ __nfs_revalidate_inode(struct nfs_server
+ 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,
+@@ -810,7 +898,7 @@ __nfs_revalidate_inode(struct nfs_server
+ 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,
+@@ -826,6 +914,10 @@ __nfs_revalidate_inode(struct nfs_server
+ (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
+ nfs_free_fattr(fattr);
+ return status;
+ }
+@@ -853,7 +945,8 @@ static int nfs_attribute_cache_expired(s
+ */
+ 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_cache_expired(inode))
+ return NFS_STALE(inode) ? -ESTALE : 0;
+ return __nfs_revalidate_inode(server, inode);
+@@ -1163,10 +1256,10 @@ static int nfs_inode_attrs_need_update(c
+ ((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);
+ }
+
+@@ -1180,21 +1273,21 @@ static int nfs_refresh_inode_locked(stru
+ * 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;
+ }
+ EXPORT_SYMBOL_GPL(nfs_refresh_inode);
+
+-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);
+
+@@ -1203,7 +1296,7 @@ static int nfs_post_op_update_inode_lock
+ 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);
+ }
+
+ /**
+@@ -1220,12 +1313,12 @@ static int nfs_post_op_update_inode_lock
+ * 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;
+ }
+@@ -1277,7 +1370,7 @@ int nfs_post_op_update_inode_force_wcc(s
+ 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;
+ }
+@@ -1295,7 +1388,7 @@ EXPORT_SYMBOL_GPL(nfs_post_op_update_ino
+ *
+ * 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);
+@@ -1446,6 +1539,10 @@ static int nfs_update_inode(struct inode
+ | 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;
+@@ -1467,7 +1564,7 @@ static int nfs_update_inode(struct inode
+ 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;
+@@ -1480,6 +1577,7 @@ static int nfs_update_inode(struct inode
+ }
+ }
+ 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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/Kconfig.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/Kconfig
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/Kconfig.orig 2012-11-29 16:37:13.607901430 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/Kconfig 2012-12-03 10:53:55.645785378 -0500
+@@ -131,6 +131,22 @@ config NFS_V4_1_IMPLEMENTATION_ID_DOMAIN
+ If the NFS client is unchanged from the upstream kernel, this
+ option should be set to the default "kernel.org".
+
++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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/namespace.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/namespace.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/namespace.c.orig 2012-11-29 16:37:13.751901554 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/namespace.c 2012-12-03 10:53:55.656785384 -0500
+@@ -260,7 +260,7 @@ struct vfsmount *nfs_submount(struct nfs
+ struct dentry *parent = dget_parent(dentry);
+
+ /* Look it up again to get its attributes */
+- err = server->nfs_client->rpc_ops->lookup(parent->d_inode, &dentry->d_name, fh, fattr);
++ err = server->nfs_client->rpc_ops->lookup(parent->d_inode, &dentry->d_name, fh, fattr, NULL);
+ dput(parent);
+ if (err != 0)
+ return ERR_PTR(err);
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs3acl.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs3acl.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs3acl.c.orig 2012-11-29 16:37:13.794901580 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs3acl.c 2012-12-03 10:53:55.656785384 -0500
+@@ -240,7 +240,7 @@ struct posix_acl *nfs3_proc_getacl(struc
+
+ switch (status) {
+ case 0:
+- status = nfs_refresh_inode(inode, res.fattr);
++ status = nfs_refresh_inode(inode, res.fattr, NULL);
+ break;
+ case -EPFNOSUPPORT:
+ case -EPROTONOSUPPORT:
+@@ -352,7 +352,7 @@ static int nfs3_proc_setacls(struct inod
+
+ 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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs3proc.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs3proc.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs3proc.c.orig 2012-09-30 19:47:46.000000000 -0400
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs3proc.c 2012-12-03 10:53:55.657785385 -0500
+@@ -98,7 +98,7 @@ nfs3_proc_get_root(struct nfs_server *se
+ */
+ 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],
+@@ -143,7 +143,8 @@ nfs3_proc_setattr(struct dentry *dentry,
+
+ 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 nfs3_diropargs arg = {
+ .fh = NFS_FH(dir),
+@@ -168,7 +169,7 @@ nfs3_proc_lookup(struct inode *dir, stru
+
+ nfs_fattr_init(fattr);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+- nfs_refresh_inode(dir, res.dir_attr);
++ nfs_refresh_inode(dir, res.dir_attr, NULL);
+ if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) {
+ msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
+ msg.rpc_argp = fhandle;
+@@ -216,7 +217,7 @@ static int nfs3_proc_access(struct inode
+ goto out;
+
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+- nfs_refresh_inode(inode, res.fattr);
++ nfs_refresh_inode(inode, res.fattr, NULL);
+ if (status == 0) {
+ entry->mask = 0;
+ if (res.access & NFS3_ACCESS_READ)
+@@ -255,7 +256,7 @@ static int nfs3_proc_readlink(struct ino
+ msg.rpc_resp = fattr;
+
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+- nfs_refresh_inode(inode, fattr);
++ nfs_refresh_inode(inode, fattr, NULL);
+ nfs_free_fattr(fattr);
+ out:
+ dprintk("NFS reply readlink: %d\n", status);
+@@ -298,9 +299,9 @@ static int nfs3_do_create(struct inode *
+ 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;
+ }
+
+@@ -381,7 +382,7 @@ nfs3_proc_create(struct inode *dir, stru
+ * 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;
+@@ -414,7 +415,7 @@ nfs3_proc_remove(struct inode *dir, stru
+ goto out;
+
+ 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);
+ nfs_free_fattr(res.dir_attr);
+ out:
+ dprintk("NFS reply remove: %d\n", status);
+@@ -439,7 +440,7 @@ nfs3_proc_unlink_done(struct rpc_task *t
+ 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;
+ }
+
+@@ -464,8 +465,8 @@ nfs3_proc_rename_done(struct rpc_task *t
+ return 0;
+ res = task->tk_msg.rpc_resp;
+
+- nfs_post_op_update_inode(old_dir, res->old_fattr);
+- nfs_post_op_update_inode(new_dir, res->new_fattr);
++ nfs_post_op_update_inode(old_dir, res->old_fattr, NULL);
++ nfs_post_op_update_inode(new_dir, res->new_fattr, NULL);
+ return 1;
+ }
+
+@@ -495,8 +496,8 @@ nfs3_proc_rename(struct inode *old_dir,
+ goto out;
+
+ status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
+- nfs_post_op_update_inode(old_dir, res.old_fattr);
+- nfs_post_op_update_inode(new_dir, res.new_fattr);
++ nfs_post_op_update_inode(old_dir, res.old_fattr, NULL);
++ nfs_post_op_update_inode(new_dir, res.new_fattr, NULL);
+ out:
+ nfs_free_fattr(res.old_fattr);
+ nfs_free_fattr(res.new_fattr);
+@@ -528,8 +529,8 @@ nfs3_proc_link(struct inode *inode, stru
+ goto out;
+
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+- 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, NULL);
++ nfs_post_op_update_inode(inode, res.fattr, NULL);
+ out:
+ nfs_free_fattr(res.dir_attr);
+ nfs_free_fattr(res.fattr);
+@@ -622,7 +623,7 @@ nfs3_proc_rmdir(struct inode *dir, struc
+
+ msg.rpc_resp = 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);
+ nfs_free_fattr(dir_attr);
+ out:
+ dprintk("NFS reply rmdir: %d\n", status);
+@@ -677,7 +678,7 @@ nfs3_proc_readdir(struct dentry *dentry,
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+
+ nfs_invalidate_atime(dir);
+- nfs_refresh_inode(dir, res.dir_attr);
++ nfs_refresh_inode(dir, res.dir_attr, NULL);
+
+ nfs_free_fattr(res.dir_attr);
+ out:
+@@ -816,7 +817,7 @@ static int nfs3_read_done(struct rpc_tas
+ return -EAGAIN;
+
+ nfs_invalidate_atime(inode);
+- nfs_refresh_inode(inode, &data->fattr);
++ nfs_refresh_inode(inode, &data->fattr, NULL);
+ return 0;
+ }
+
+@@ -860,7 +861,7 @@ static int nfs3_commit_done(struct rpc_t
+ {
+ 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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4_fs.h.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4_fs.h
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4_fs.h.orig 2012-11-29 16:37:13.802901578 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4_fs.h 2012-12-03 10:53:55.658785386 -0500
+@@ -230,7 +230,7 @@ extern int nfs4_server_capabilities(stru
+ extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struct qstr *,
+ struct nfs4_fs_locations *, struct page *);
+ extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, struct qstr *,
+- struct nfs_fh *, struct nfs_fattr *);
++ struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *);
+ extern int nfs4_proc_secinfo(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *);
+ extern int nfs4_release_lockowner(struct nfs4_lock_state *);
+ extern const struct xattr_handler *nfs4_xattr_handlers[];
+@@ -304,10 +304,10 @@ is_ds_client(struct nfs_client *clp)
+ extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[];
+
+ extern const u32 nfs4_fattr_bitmap[3];
+-extern const u32 nfs4_statfs_bitmap[2];
+-extern const u32 nfs4_pathconf_bitmap[2];
++extern const u32 nfs4_statfs_bitmap[3];
++extern const u32 nfs4_pathconf_bitmap[3];
+ extern const u32 nfs4_fsinfo_bitmap[3];
+-extern const u32 nfs4_fs_locations_bitmap[2];
++extern const u32 nfs4_fs_locations_bitmap[3];
+
+ void nfs4_free_client(struct nfs_client *);
+
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4namespace.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4namespace.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4namespace.c.orig 2012-11-29 16:37:13.858901623 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4namespace.c 2012-12-03 10:53:55.658785386 -0500
+@@ -368,7 +368,7 @@ struct vfsmount *nfs4_submount(struct nf
+ struct vfsmount *mnt;
+
+ /* Look it up again to get its attributes and sec flavor */
+- client = nfs4_proc_lookup_mountpoint(parent->d_inode, &dentry->d_name, fh, fattr);
++ client = nfs4_proc_lookup_mountpoint(parent->d_inode, &dentry->d_name, fh, fattr, NULL);
+ dput(parent);
+ if (IS_ERR(client))
+ return ERR_CAST(client);
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4proc.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4proc.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4proc.c.orig 2012-11-29 16:37:13.869901632 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4proc.c 2012-12-03 10:53:55.664785392 -0500
+@@ -78,11 +78,12 @@ static int _nfs4_recover_proc_open(struc
+ 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 void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
+-static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *);
+-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 *, struct nfs_fh *, struct nfs_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);
+ 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);
+ #ifdef CONFIG_NFS_V4_1
+ static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *);
+ static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *);
+@@ -131,7 +132,12 @@ const u32 nfs4_fattr_bitmap[3] = {
+ | FATTR4_WORD1_SPACE_USED
+ | FATTR4_WORD1_TIME_ACCESS
+ | FATTR4_WORD1_TIME_METADATA
+- | FATTR4_WORD1_TIME_MODIFY
++ | FATTR4_WORD1_TIME_MODIFY,
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ FATTR4_WORD2_SECURITY_LABEL
++#else
++ 0
++#endif
+ };
+
+ static const u32 nfs4_pnfs_open_bitmap[3] = {
+@@ -158,18 +164,20 @@ static const u32 nfs4_open_noattr_bitmap
+ | FATTR4_WORD0_FILEID,
+ };
+
+-const u32 nfs4_statfs_bitmap[2] = {
++const u32 nfs4_statfs_bitmap[3] = {
+ FATTR4_WORD0_FILES_AVAIL
+ | FATTR4_WORD0_FILES_FREE
+ | FATTR4_WORD0_FILES_TOTAL,
+ FATTR4_WORD1_SPACE_AVAIL
+ | FATTR4_WORD1_SPACE_FREE
+- | FATTR4_WORD1_SPACE_TOTAL
++ | FATTR4_WORD1_SPACE_TOTAL,
++ 0
+ };
+
+-const u32 nfs4_pathconf_bitmap[2] = {
++const u32 nfs4_pathconf_bitmap[3] = {
+ FATTR4_WORD0_MAXLINK
+ | FATTR4_WORD0_MAXNAME,
++ 0,
+ 0
+ };
+
+@@ -182,7 +190,7 @@ const u32 nfs4_fsinfo_bitmap[3] = { FATT
+ FATTR4_WORD2_LAYOUT_BLKSIZE
+ };
+
+-const u32 nfs4_fs_locations_bitmap[2] = {
++const u32 nfs4_fs_locations_bitmap[3] = {
+ FATTR4_WORD0_TYPE
+ | FATTR4_WORD0_CHANGE
+ | FATTR4_WORD0_SIZE
+@@ -198,7 +206,8 @@ const u32 nfs4_fs_locations_bitmap[2] =
+ | FATTR4_WORD1_TIME_ACCESS
+ | FATTR4_WORD1_TIME_METADATA
+ | FATTR4_WORD1_TIME_MODIFY
+- | FATTR4_WORD1_MOUNTED_ON_FILEID
++ | FATTR4_WORD1_MOUNTED_ON_FILEID,
++ 0
+ };
+
+ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
+@@ -821,6 +830,7 @@ struct nfs4_opendata {
+ struct nfs4_string owner_name;
+ struct nfs4_string group_name;
+ struct nfs_fattr f_attr;
++ struct nfs4_label *f_label;
+ struct dentry *dir;
+ struct dentry *dentry;
+ struct nfs4_state_owner *owner;
+@@ -836,6 +846,7 @@ struct nfs4_opendata {
+ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
+ {
+ p->o_res.f_attr = &p->f_attr;
++ p->o_res.f_label = p->f_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;
+@@ -846,7 +857,7 @@ static void nfs4_init_opendata_res(struc
+
+ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
+ struct nfs4_state_owner *sp, fmode_t fmode, int flags,
+- const struct iattr *attrs,
++ const struct iattr *attrs, struct nfs4_label *label,
+ gfp_t gfp_mask)
+ {
+ struct dentry *parent = dget_parent(dentry);
+@@ -857,9 +868,16 @@ static struct nfs4_opendata *nfs4_openda
+ p = kzalloc(sizeof(*p), gfp_mask);
+ 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_mask);
++ if (p->f_label == NULL)
++ goto err_free_p;
++ }
++#endif
+ p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid, gfp_mask);
+ if (p->o_arg.seqid == NULL)
+- goto err_free;
++ goto err_free_label;
+ nfs_sb_active(dentry->d_sb);
+ p->dentry = dget(dentry);
+ p->dir = parent;
+@@ -884,6 +902,7 @@ static struct nfs4_opendata *nfs4_openda
+ p->o_arg.bitmask = server->attr_bitmask;
+ p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0];
+ p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
++ p->o_arg.label = label;
+ if (attrs != NULL && attrs->ia_valid != 0) {
+ __be32 verf[2];
+
+@@ -901,7 +920,13 @@ static struct nfs4_opendata *nfs4_openda
+ 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);
++#endif
++err_free_p:
+ kfree(p);
+ err:
+ dput(parent);
+@@ -918,6 +943,10 @@ static void nfs4_opendata_free(struct kr
+ 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);
++#endif
+ dput(p->dir);
+ dput(p->dentry);
+ nfs_sb_deactive(sb);
+@@ -1185,7 +1214,7 @@ _nfs4_opendata_reclaim_to_nfs4_state(str
+ if (state == NULL)
+ goto err;
+
+- ret = nfs_refresh_inode(inode, &data->f_attr);
++ ret = nfs_refresh_inode(inode, &data->f_attr, data->f_label);
+ if (ret)
+ goto err;
+
+@@ -1215,7 +1244,7 @@ _nfs4_opendata_to_nfs4_state(struct nfs4
+ 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;
+@@ -1265,7 +1294,7 @@ static struct nfs4_opendata *nfs4_open_r
+ {
+ struct nfs4_opendata *opendata;
+
+- opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0, NULL, GFP_NOFS);
++ opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0, NULL, NULL, GFP_NOFS);
+ if (opendata == NULL)
+ return ERR_PTR(-ENOMEM);
+ opendata->state = state;
+@@ -1785,7 +1814,7 @@ static int _nfs4_proc_open(struct nfs4_o
+ 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;
+ }
+
+@@ -1962,6 +1991,7 @@ static int _nfs4_do_open(struct inode *d
+ fmode_t fmode,
+ int flags,
+ struct iattr *sattr,
++ struct nfs4_label *label,
+ struct rpc_cred *cred,
+ struct nfs4_state **res,
+ struct nfs4_threshold **ctx_th)
+@@ -1970,6 +2000,7 @@ static int _nfs4_do_open(struct inode *d
+ struct nfs4_state *state = NULL;
+ struct nfs_server *server = NFS_SERVER(dir);
+ struct nfs4_opendata *opendata;
++ struct nfs4_label *olabel = NULL;
+ int status;
+
+ /* Protect against reboot recovery conflicts */
+@@ -1985,10 +2016,20 @@ static int _nfs4_do_open(struct inode *d
+ if (dentry->d_inode != NULL)
+ nfs4_return_incompatible_delegation(dentry->d_inode, fmode);
+ status = -ENOMEM;
+- opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr, GFP_KERNEL);
++ opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr, label, GFP_KERNEL);
+ if (opendata == NULL)
+ goto err_put_state_owner;
+
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (label && nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
++ olabel = nfs4_label_alloc(GFP_KERNEL);
++ if (olabel == NULL) {
++ status = -ENOMEM;
++ goto err_opendata_put;
++ }
++ }
++#endif
++
+ if (ctx_th && server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) {
+ opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc();
+ if (!opendata->f_attr.mdsthreshold)
+@@ -2019,10 +2060,12 @@ static int _nfs4_do_open(struct inode *d
+ nfs_fattr_init(opendata->o_res.f_attr);
+ status = nfs4_do_setattr(state->inode, cred,
+ opendata->o_res.f_attr, sattr,
+- state);
+- if (status == 0)
++ state, label, olabel);
++ if (status == 0) {
+ nfs_setattr_update_inode(state->inode, sattr);
+- nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr);
++ nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr, olabel);
++ nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel);
++ }
+ }
+
+ if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server))
+@@ -2031,6 +2074,10 @@ static int _nfs4_do_open(struct inode *d
+ kfree(opendata->f_attr.mdsthreshold);
+ opendata->f_attr.mdsthreshold = NULL;
+
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL))
++ nfs4_label_free(olabel);
++#endif
+ nfs4_opendata_put(opendata);
+ nfs4_put_state_owner(sp);
+ *res = state;
+@@ -2051,6 +2098,7 @@ static struct nfs4_state *nfs4_do_open(s
+ fmode_t fmode,
+ int flags,
+ struct iattr *sattr,
++ struct nfs4_label *label,
+ struct rpc_cred *cred,
+ struct nfs4_threshold **ctx_th)
+ {
+@@ -2060,7 +2108,7 @@ static struct nfs4_state *nfs4_do_open(s
+
+ fmode &= FMODE_READ|FMODE_WRITE|FMODE_EXEC;
+ do {
+- status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred,
++ status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, label, cred,
+ &res, ctx_th);
+ if (status == 0)
+ break;
+@@ -2105,7 +2153,8 @@ static struct nfs4_state *nfs4_do_open(s
+
+ 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 = {
+@@ -2113,9 +2162,11 @@ static int _nfs4_do_setattr(struct inode
+ .iap = sattr,
+ .server = server,
+ .bitmask = server->attr_bitmask,
++ .label = ilabel,
+ };
+ struct nfs_setattrres res = {
+ .fattr = fattr,
++ .label = olabel,
+ .server = server,
+ };
+ struct rpc_message msg = {
+@@ -2127,6 +2178,10 @@ static int _nfs4_do_setattr(struct inode
+ 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 (state != NULL) {
+@@ -2150,7 +2205,8 @@ static int _nfs4_do_setattr(struct inode
+
+ 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 nfs4_exception exception = {
+@@ -2159,7 +2215,7 @@ static int nfs4_do_setattr(struct inode
+ };
+ int err;
+ do {
+- err = _nfs4_do_setattr(inode, cred, fattr, sattr, state);
++ err = _nfs4_do_setattr(inode, cred, fattr, sattr, state, ilabel, olabel);
+ switch (err) {
+ case -NFS4ERR_OPENMODE:
+ if (state && !(state->state & FMODE_WRITE)) {
+@@ -2246,7 +2302,7 @@ static void nfs4_close_done(struct rpc_t
+ 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);
+ dprintk("%s: done, ret = %d!\n", __func__, task->tk_status);
+ }
+
+@@ -2354,7 +2410,7 @@ int nfs4_do_close(struct nfs4_state *sta
+ if (calldata->arg.seqid == NULL)
+ goto out_free_calldata;
+ 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;
+@@ -2384,10 +2440,26 @@ static struct inode *
+ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
+ {
+ struct nfs4_state *state;
++ struct nfs4_label l, *label = NULL;
++
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
++ struct dentry *dentry = ctx->dentry;
++ int error;
++ error = security_dentry_init_security(dentry, attr->ia_mode,
++ &dentry->d_name, &l.label, &l.len);
++ if (error == 0)
++ label = &l;
++ }
++#endif
+
+ /* Protect against concurrent sillydeletes */
+- state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr,
++ state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr, label,
+ ctx->cred, &ctx->mdsthreshold);
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (label)
++ security_release_secctx(l.label, l.len);
++#endif
+ if (IS_ERR(state))
+ return ERR_CAST(state);
+ ctx->state = state;
+@@ -2447,10 +2519,26 @@ static int _nfs4_server_capabilities(str
+ server->caps |= NFS_CAP_CTIME;
+ if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY)
+ server->caps |= NFS_CAP_MTIME;
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL) {
++ server->caps |= NFS_CAP_SECURITY_LABEL;
++ } else
++#endif
++ server->attr_bitmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
++
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ memcpy(server->attr_bitmask_nl, res.attr_bitmask, sizeof(server->attr_bitmask));
++ server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
++#endif
+
+ 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;
++ server->cache_consistency_bitmask[2] &= FATTR4_WORD2_SECURITY_LABEL;
++ memcpy(server->cache_consistency_bitmask_nl, server->cache_consistency_bitmask,
++ sizeof(server->cache_consistency_bitmask_nl));
++ server->cache_consistency_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
+ server->acl_bitmask = res.acl_bitmask;
+ server->fh_expire_type = res.fh_expire_type;
+ }
+@@ -2473,8 +2561,9 @@ int nfs4_server_capabilities(struct nfs_
+ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
+ struct nfs_fsinfo *info)
+ {
++ u32 bitmask[3];
+ struct nfs4_lookup_root_arg args = {
+- .bitmask = nfs4_fattr_bitmap,
++ .bitmask = bitmask,
+ };
+ struct nfs4_lookup_res res = {
+ .server = server,
+@@ -2487,6 +2576,10 @@ static int _nfs4_lookup_root(struct nfs_
+ .rpc_resp = &res,
+ };
+
++ bitmask[0] = nfs4_fattr_bitmap[0];
++ bitmask[1] = nfs4_fattr_bitmap[1];
++ bitmask[2] = nfs4_fattr_bitmap[2] & ~FATTR4_WORD2_SECURITY_LABEL;
++
+ nfs_fattr_init(info->fattr);
+ return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
+ }
+@@ -2584,6 +2677,7 @@ static int nfs4_proc_get_root(struct nfs
+ {
+ int error;
+ struct nfs_fattr *fattr = info->fattr;
++ struct nfs4_label *label = NULL;
+
+ error = nfs4_server_capabilities(server, mntfh);
+ if (error < 0) {
+@@ -2591,7 +2685,13 @@ static int nfs4_proc_get_root(struct nfs
+ return error;
+ }
+
+- error = nfs4_proc_getattr(server, mntfh, fattr);
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ label = nfs4_label_alloc(GFP_KERNEL);
++ if (label == NULL)
++ return -ENOMEM;
++#endif
++
++ error = nfs4_proc_getattr(server, mntfh, fattr, label);
+ if (error < 0) {
+ dprintk("nfs4_get_root: getattr error = %d\n", -error);
+ return error;
+@@ -2601,6 +2701,11 @@ static int nfs4_proc_get_root(struct nfs
+ !nfs_fsid_equal(&server->fsid, &fattr->fsid))
+ memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid));
+
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (server->caps & NFS_CAP_SECURITY_LABEL)
++ nfs4_label_free(label);
++#endif
++
+ return error;
+ }
+
+@@ -2647,7 +2752,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,
+@@ -2655,6 +2761,7 @@ static int _nfs4_proc_getattr(struct nfs
+ };
+ struct nfs4_getattr_res res = {
+ .fattr = fattr,
++ .label = label,
+ .server = server,
+ };
+ struct rpc_message msg = {
+@@ -2662,18 +2769,24 @@ static int _nfs4_proc_getattr(struct nfs
+ .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->client, server, &msg, &args.seq_args, &res.seq_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;
+@@ -2703,11 +2816,16 @@ nfs4_proc_setattr(struct dentry *dentry,
+ struct inode *inode = dentry->d_inode;
+ struct rpc_cred *cred = NULL;
+ struct nfs4_state *state = NULL;
++ struct nfs4_label *olabel = NULL;
+ int status;
+
+ if (pnfs_ld_layoutret_on_setattr(inode))
+ pnfs_return_layout(inode);
+
++ olabel = nfs4_label_alloc(GFP_KERNEL);
++ if (olabel == NULL)
++ return -ENOMEM;
++
+ nfs_fattr_init(fattr);
+
+ /* Deal with open(O_TRUNC) */
+@@ -2729,7 +2847,7 @@ nfs4_proc_setattr(struct dentry *dentry,
+ }
+ }
+
+- status = nfs4_do_setattr(inode, cred, fattr, sattr, state);
++ status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, NULL);
+ if (status == 0)
+ nfs_setattr_update_inode(inode, sattr);
+ return status;
+@@ -2737,7 +2855,7 @@ nfs4_proc_setattr(struct dentry *dentry,
+
+ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir,
+ const struct qstr *name, struct nfs_fh *fhandle,
+- struct nfs_fattr *fattr)
++ struct nfs_fattr *fattr, struct nfs4_label *label)
+ {
+ struct nfs_server *server = NFS_SERVER(dir);
+ int status;
+@@ -2749,6 +2867,7 @@ static int _nfs4_proc_lookup(struct rpc_
+ struct nfs4_lookup_res res = {
+ .server = server,
+ .fattr = fattr,
++ .label = label,
+ .fh = fhandle,
+ };
+ struct rpc_message msg = {
+@@ -2757,6 +2876,11 @@ static int _nfs4_proc_lookup(struct rpc_
+ .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 lookup %s\n", name->name);
+@@ -2775,13 +2899,13 @@ static void nfs_fixup_secinfo_attributes
+
+ static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir,
+ struct qstr *name, struct nfs_fh *fhandle,
+- struct nfs_fattr *fattr)
++ struct nfs_fattr *fattr, struct nfs4_label *label)
+ {
+ struct nfs4_exception exception = { };
+ struct rpc_clnt *client = *clnt;
+ int err;
+ do {
+- err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr);
++ err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr, label);
+ switch (err) {
+ case -NFS4ERR_BADNAME:
+ err = -ENOENT;
+@@ -2815,12 +2939,13 @@ out:
+ }
+
+ static int nfs4_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)
+ {
+ int status;
+ struct rpc_clnt *client = NFS_CLIENT(dir);
+
+- status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr);
++ status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, label);
+ if (client != NFS_CLIENT(dir)) {
+ rpc_shutdown_client(client);
+ nfs_fixup_secinfo_attributes(fattr);
+@@ -2830,12 +2955,13 @@ static int nfs4_proc_lookup(struct inode
+
+ struct rpc_clnt *
+ nfs4_proc_lookup_mountpoint(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)
+ {
+ int status;
+ struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir));
+
+- status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr);
++ status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, label);
+ if (status < 0) {
+ rpc_shutdown_client(client);
+ return ERR_PTR(status);
+@@ -2852,6 +2978,7 @@ static int _nfs4_proc_access(struct inod
+ };
+ struct nfs4_accessres res = {
+ .server = server,
++ .label = NULL,
+ };
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
+@@ -2860,7 +2987,7 @@ static int _nfs4_proc_access(struct inod
+ .rpc_cred = entry->cred,
+ };
+ int mode = entry->mask;
+- int status;
++ int status = 0;
+
+ /*
+ * Determine which access bits we want to ask for...
+@@ -2882,12 +3009,27 @@ static int _nfs4_proc_access(struct inod
+ res.fattr = nfs_alloc_fattr();
+ if (res.fattr == NULL)
+ return -ENOMEM;
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (server->caps & NFS_CAP_SECURITY_LABEL) {
++ res.label = nfs4_label_alloc(GFP_KERNEL);
++ if (res.label == NULL) {
++ status = -ENOMEM;
++ goto out;
++ }
++ }
++#endif
+
+ status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
+ if (!status) {
+ nfs_access_set_mask(entry, res.access);
+- nfs_refresh_inode(inode, res.fattr);
++ nfs_refresh_inode(inode, res.fattr, res.label);
+ }
++
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (server->caps & NFS_CAP_SECURITY_LABEL)
++ nfs4_label_free(res.label);
++#endif
++out:
+ nfs_free_fattr(res.fattr);
+ return status;
+ }
+@@ -2965,6 +3107,7 @@ static int
+ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+ int flags)
+ {
++ struct nfs4_label l, *ilabel = NULL;
+ struct nfs_open_context *ctx;
+ struct nfs4_state *state;
+ int status = 0;
+@@ -2973,9 +3116,18 @@ nfs4_proc_create(struct inode *dir, stru
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
++ status = security_dentry_init_security(dentry, sattr->ia_mode,
++ &dentry->d_name, &l.label, &l.len);
++ if (status == 0)
++ ilabel = &l;
++ }
++#endif
++
+ sattr->ia_mode &= ~current_umask();
+ state = nfs4_do_open(dir, dentry, ctx->mode,
+- flags, sattr, ctx->cred,
++ flags, sattr, ilabel, ctx->cred,
+ &ctx->mdsthreshold);
+ d_drop(dentry);
+ if (IS_ERR(state)) {
+@@ -2986,6 +3138,10 @@ nfs4_proc_create(struct inode *dir, stru
+ nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+ ctx->state = state;
+ out:
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (ilabel)
++ security_release_secctx(ilabel->label, ilabel->len);
++#endif
+ put_nfs_open_context(ctx);
+ return status;
+ }
+@@ -3010,6 +3166,7 @@ static int _nfs4_proc_remove(struct inod
+ status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1);
+ if (status == 0)
+ update_changeattr(dir, &res.cinfo);
++
+ return status;
+ }
+
+@@ -3034,6 +3191,8 @@ static void nfs4_proc_unlink_setup(struc
+ res->server = server;
+ msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
+ nfs41_init_sequence(&args->seq_args, &res->seq_res, 1);
++
++ nfs_fattr_init(res->dir_attr);
+ }
+
+ static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data)
+@@ -3055,6 +3214,7 @@ static int nfs4_proc_unlink_done(struct
+ if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
+ return 0;
+ update_changeattr(dir, &res->cinfo);
++
+ return 1;
+ }
+
+@@ -3103,6 +3263,8 @@ static int _nfs4_proc_rename(struct inod
+ .new_dir = NFS_FH(new_dir),
+ .old_name = old_name,
+ .new_name = new_name,
++ .old_label = NULL,
++ .new_label = NULL,
+ };
+ struct nfs_renameres res = {
+ .server = server,
+@@ -3113,12 +3275,33 @@ static int _nfs4_proc_rename(struct inod
+ .rpc_resp = &res,
+ };
+ int status = -ENOMEM;
++
++#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)
++ goto out;
++ res.new_label = nfs4_label_alloc(GFP_NOWAIT);
++ if (res.new_label == NULL) {
++ nfs4_label_free(res.old_label);
++ goto out;
++ }
++ }
++#endif
+
+ status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
+ if (!status) {
+ update_changeattr(old_dir, &res.old_cinfo);
+ update_changeattr(new_dir, &res.new_cinfo);
+ }
++
++#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
++out:
+ return status;
+ }
+
+@@ -3147,6 +3330,7 @@ static int _nfs4_proc_link(struct inode
+ };
+ struct nfs4_link_res res = {
+ .server = server,
++ .label = NULL,
+ };
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
+@@ -3159,11 +3343,25 @@ static int _nfs4_proc_link(struct inode
+ if (res.fattr == NULL)
+ goto out;
+
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (server->caps & NFS_CAP_SECURITY_LABEL) {
++ res.label = nfs4_label_alloc(GFP_KERNEL);
++ if (res.label == NULL)
++ goto out;
++ }
++#endif
++
+ status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
+ if (!status) {
+ update_changeattr(dir, &res.cinfo);
+- nfs_post_op_update_inode(inode, res.fattr);
++ 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);
++#endif
++
+ out:
+ nfs_free_fattr(res.fattr);
+ return status;
+@@ -3187,6 +3385,7 @@ struct nfs4_createdata {
+ struct nfs4_create_res res;
+ struct nfs_fh fh;
+ struct nfs_fattr fattr;
++ struct nfs4_label *label;
+ };
+
+ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
+@@ -3198,6 +3397,13 @@ static struct nfs4_createdata *nfs4_allo
+ 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;
++ }
++#endif
+ data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE];
+ data->msg.rpc_argp = &data->arg;
+ data->msg.rpc_resp = &data->res;
+@@ -3210,9 +3416,13 @@ static struct nfs4_createdata *nfs4_allo
+ data->res.server = server;
+ data->res.fh = &data->fh;
+ data->res.fattr = &data->fattr;
++ data->res.label = data->label;
+ nfs_fattr_init(data->res.fattr);
+ }
+ return data;
++out_free:
++ kfree(data);
++ return NULL;
+ }
+
+ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
+@@ -3221,18 +3431,23 @@ static int nfs4_do_create(struct inode *
+ &data->arg.seq_args, &data->res.seq_res, 1);
+ if (status == 0) {
+ update_changeattr(dir, &data->res.dir_cinfo);
+- status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
++ 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);
++#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;
+@@ -3248,6 +3463,7 @@ static int _nfs4_proc_symlink(struct ino
+ 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);
+
+@@ -3260,18 +3476,34 @@ static int nfs4_proc_symlink(struct inod
+ 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,
++ &dentry->d_name, &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;
+@@ -3280,6 +3512,7 @@ static int _nfs4_proc_mkdir(struct inode
+ if (data == NULL)
+ goto out;
+
++ data->arg.label = label;
+ status = nfs4_do_create(dir, dentry, data);
+
+ nfs4_free_createdata(data);
+@@ -3291,15 +3524,29 @@ static int nfs4_proc_mkdir(struct inode
+ 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,
++ &dentry->d_name, &l.label, &l.len);
++ if (err == 0)
++ label = &l;
++ }
++#endif
++
+ sattr->ia_mode &= ~current_umask();
+ 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);
+ return err;
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (label)
++ security_release_secctx(l.label, l.len);
++#endif
+ }
+
+ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
+@@ -3314,7 +3561,9 @@ static int _nfs4_proc_readdir(struct den
+ .bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
+ .plus = plus,
+ };
+- struct nfs4_readdir_res res;
++ struct nfs4_readdir_res res = {
++ .pgbase = 0,
++ };
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READDIR],
+ .rpc_argp = &args,
+@@ -3356,7 +3605,7 @@ static int nfs4_proc_readdir(struct dent
+ }
+
+ 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;
+@@ -3381,7 +3630,8 @@ static int _nfs4_proc_mknod(struct inode
+ 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);
+@@ -3393,14 +3643,28 @@ static int nfs4_proc_mknod(struct inode
+ 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,
++ &dentry->d_name, &l.label, &l.len);
++ if (err == 0)
++ label = &l;
++ }
++#endif
++
+ sattr->ia_mode &= ~current_umask();
+ 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;
+ }
+
+@@ -3618,7 +3882,11 @@ static void nfs4_proc_write_setup(struct
+ data->args.bitmask = NULL;
+ data->res.fattr = NULL;
+ } else
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ data->args.bitmask = server->cache_consistency_bitmask_nl;
++#else
+ data->args.bitmask = server->cache_consistency_bitmask;
++#endif
+
+ if (!data->write_done_cb)
+ data->write_done_cb = nfs4_write_done_cb;
+@@ -4042,6 +4310,182 @@ static int nfs4_proc_set_acl(struct inod
+ return err;
+ }
+
++#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[3] = { 0, 0, FATTR4_WORD2_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[3] = { 0, 0, FATTR4_WORD2_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 (state != NULL) {
++ struct nfs_lockowner lockowner = {
++ .l_owner = current->files,
++ .l_pid = current->tgid,
++ };
++
++ msg.rpc_cred = state->owner->so_cred;
++ nfs4_select_rw_stateid(&args.stateid, state, FMODE_WRITE,
++ &lockowner);
++ } else if (nfs4_copy_delegation_stateid(&args.stateid, inode,
++ FMODE_WRITE)) {
++ /* Use that stateid */
++ } else
++ nfs4_stateid_copy(&args.stateid, &zero_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.pi = 0;
++ ilabel.lfs = 0;
++ 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)
+ {
+@@ -4332,7 +4776,7 @@ static int _nfs4_proc_delegreturn(struct
+ nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
+ data->args.fhandle = &data->fh;
+ data->args.stateid = &data->stateid;
+- data->args.bitmask = server->cache_consistency_bitmask;
++ data->args.bitmask = server->cache_consistency_bitmask_nl;
+ nfs_copy_fh(&data->fh, NFS_FH(inode));
+ nfs4_stateid_copy(&data->stateid, stateid);
+ data->res.fattr = &data->fattr;
+@@ -4356,7 +4800,7 @@ static int _nfs4_proc_delegreturn(struct
+ if (status == 0)
+ nfs_post_op_update_inode_force_wcc(inode, &data->fattr);
+ else
+- nfs_refresh_inode(inode, &data->fattr);
++ nfs_refresh_inode(inode, &data->fattr, NULL);
+ out:
+ rpc_put_task(task);
+ return status;
+@@ -5198,6 +5642,53 @@ static size_t nfs4_xattr_list_nfs4_acl(s
+ return len;
+ }
+
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++static inline int nfs4_server_supports_labels(struct nfs_server *server)
++{
++ return server->caps & NFS_CAP_SECURITY_LABEL;
++}
++
++static int nfs4_xattr_set_nfs4_label(struct dentry *dentry, const char *key,
++ const void *buf, size_t buflen,
++ int flags, int type)
++{
++ if (security_ismaclabel(key))
++ return nfs4_set_security_label(dentry, buf, buflen);
++
++ return -EOPNOTSUPP;
++}
++
++static int nfs4_xattr_get_nfs4_label(struct dentry *dentry, const char *key,
++ void *buf, size_t buflen, int type)
++{
++ if (security_ismaclabel(key))
++ return nfs4_get_security_label(dentry->d_inode, buf, buflen);
++ return -EOPNOTSUPP;
++}
++
++static size_t nfs4_xattr_list_nfs4_label(struct dentry *dentry, char *list,
++ size_t list_len, const char *name,
++ size_t name_len, int type)
++{
++ size_t len = 0;
++
++ if (nfs_server_capable(dentry->d_inode, NFS_CAP_SECURITY_LABEL)) {
++ len = security_inode_listsecurity(dentry->d_inode, NULL, 0);
++ if (list && len <= list_len)
++ security_inode_listsecurity(dentry->d_inode, list, len);
++ }
++ return len;
++}
++
++static const struct xattr_handler nfs4_xattr_nfs4_label_handler = {
++ .prefix = XATTR_SECURITY_PREFIX,
++ .list = nfs4_xattr_list_nfs4_label,
++ .get = nfs4_xattr_get_nfs4_label,
++ .set = nfs4_xattr_set_nfs4_label,
++};
++#endif
++
++
+ /*
+ * nfs_fhget will use either the mounted_on_fileid or the fileid
+ */
+@@ -5221,8 +5712,10 @@ static int _nfs4_proc_fs_locations(struc
+ struct page *page)
+ {
+ struct nfs_server *server = NFS_SERVER(dir);
+- u32 bitmask[2] = {
++ u32 bitmask[3] = {
+ [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
++ [1] = 0,
++ [2] = 0
+ };
+ struct nfs4_fs_locations_arg args = {
+ .dir_fh = NFS_FH(dir),
+@@ -7154,6 +7647,9 @@ static const struct xattr_handler nfs4_x
+
+ const struct xattr_handler *nfs4_xattr_handlers[] = {
+ &nfs4_xattr_nfs4_acl_handler,
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ &nfs4_xattr_nfs4_label_handler,
++#endif
+ NULL
+ };
+
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4xdr.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4xdr.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4xdr.c.orig 2012-11-29 16:37:13.923901662 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/nfs4xdr.c 2012-12-03 10:53:55.667785395 -0500
+@@ -101,12 +101,19 @@ 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
++/* PI(4 bytes) + LFS(4 bytes) + 1(for null terminator?) + MAXLABELLEN */
++#define nfs4_label_maxsz (4 + 4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN))
++#else
++#define nfs4_label_maxsz 0
++#endif
+ /* We support only one layout type per file system */
+ #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8)
+ /* 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 + decode_mdsthreshold_maxsz))
++ nfs4_group_maxsz + nfs4_label_maxsz + \
++ decode_mdsthreshold_maxsz))
+ #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \
+ nfs4_fattr_value_maxsz)
+ #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
+@@ -114,6 +121,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)
+@@ -191,9 +199,11 @@ static int nfs4_stat_to_errno(int);
+ encode_stateid_maxsz + 3)
+ #define decode_read_maxsz (op_decode_hdr_maxsz + 2)
+ #define encode_readdir_maxsz (op_encode_hdr_maxsz + \
+- 2 + encode_verifier_maxsz + 5)
++ 2 + encode_verifier_maxsz + 5 + \
++ nfs4_label_maxsz)
+ #define decode_readdir_maxsz (op_decode_hdr_maxsz + \
+- decode_verifier_maxsz)
++ decode_verifier_maxsz + \
++ nfs4_label_maxsz + nfs4_fattr_maxsz)
+ #define encode_readlink_maxsz (op_encode_hdr_maxsz)
+ #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1)
+ #define encode_write_maxsz (op_encode_hdr_maxsz + \
+@@ -969,7 +979,9 @@ static void encode_nfs4_verifier(struct
+ encode_opaque_fixed(xdr, 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];
+@@ -980,15 +992,16 @@ static void encode_attrs(struct xdr_stre
+ int len;
+ uint32_t bmval0 = 0;
+ uint32_t bmval1 = 0;
++ uint32_t bmval2 = 0;
+
+ /*
+ * We reserve enough space to write the entire attribute buffer at once.
+ * In the worst-case, this would be
+- * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime)
+- * = 36 bytes, plus any contribution from variable-length fields
++ * 16(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime)
++ * = 40 bytes, plus any contribution from variable-length fields
+ * such as owner/group.
+ */
+- len = 16;
++ len = 20;
+
+ /* Sigh */
+ if (iap->ia_valid & ATTR_SIZE)
+@@ -1018,6 +1031,10 @@ static void encode_attrs(struct xdr_stre
+ }
+ len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
+ }
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (label)
++ len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2);
++#endif
+ if (iap->ia_valid & ATTR_ATIME_SET)
+ len += 16;
+ else if (iap->ia_valid & ATTR_ATIME)
+@@ -1032,9 +1049,9 @@ static void encode_attrs(struct xdr_stre
+ * We write the bitmap length now, but leave the bitmap and the attribute
+ * buffer length to be backfilled at the end of this routine.
+ */
+- *p++ = cpu_to_be32(2);
++ *p++ = cpu_to_be32(3);
+ q = p;
+- p += 3;
++ p += 4;
+
+ if (iap->ia_valid & ATTR_SIZE) {
+ bmval0 |= FATTR4_WORD0_SIZE;
+@@ -1074,6 +1091,15 @@ static void encode_attrs(struct xdr_stre
+ bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
+ *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
+ }
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (label) {
++ bmval2 |= FATTR4_WORD2_SECURITY_LABEL;
++ *p++ = cpu_to_be32(label->lfs);
++ *p++ = cpu_to_be32(label->pi);
++ *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.
+@@ -1083,9 +1109,10 @@ static void encode_attrs(struct xdr_stre
+ len, ((char *)p - (char *)q) + 4);
+ BUG();
+ }
+- len = (char *)p - (char *)q - 12;
++ len = (char *)p - (char *)q - 16;
+ *q++ = htonl(bmval0);
+ *q++ = htonl(bmval1);
++ *q++ = htonl(bmval2);
+ *q = htonl(len);
+
+ /* out: */
+@@ -1139,7 +1166,7 @@ static void encode_create(struct xdr_str
+ }
+
+ encode_string(xdr, create->name->len, create->name->name);
+- 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)
+@@ -1191,8 +1218,10 @@ encode_getattr_three(struct xdr_stream *
+
+ static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
+ {
+- encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0],
+- bitmask[1] & nfs4_fattr_bitmap[1], hdr);
++ encode_getattr_three(xdr, bitmask[0] & nfs4_fattr_bitmap[0],
++ bitmask[1] & nfs4_fattr_bitmap[1],
++ bitmask[2] & nfs4_fattr_bitmap[2],
++ hdr);
+ }
+
+ static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask,
+@@ -1370,21 +1399,23 @@ static inline void encode_createmode(str
+ 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_mvops->minor_version > 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);
+@@ -1564,20 +1595,43 @@ static void encode_readdir(struct xdr_st
+ encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr);
+ encode_uint64(xdr, readdir->cookie);
+ encode_nfs4_verifier(xdr, &readdir->verifier);
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ p = reserve_space(xdr, 24);
++#else
+ p = reserve_space(xdr, 20);
++#endif
+ *p++ = cpu_to_be32(dircount);
+ *p++ = cpu_to_be32(readdir->count);
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ *p++ = cpu_to_be32(3);
++#else
+ *p++ = cpu_to_be32(2);
+-
++#endif
+ *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]);
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ *p++ = cpu_to_be32(attrs[1] & readdir->bitmask[1]);
++ *p = cpu_to_be32(readdir->bitmask[2]);
++#else
+ *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]);
++#endif
+ memcpy(verf, readdir->verifier.data, sizeof(verf));
+- dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x\n",
++ __func__,
++ (unsigned long long)readdir->cookie,
++ verf[0], verf[1],
++ attrs[0] & readdir->bitmask[0],
++ attrs[1] & readdir->bitmask[1],
++ readdir->bitmask[2]);
++#else
++ dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
+ __func__,
+ (unsigned long long)readdir->cookie,
+ verf[0], verf[1],
+ attrs[0] & readdir->bitmask[0],
+ attrs[1] & readdir->bitmask[1]);
++#endif
++
+ }
+
+ static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr)
+@@ -1637,7 +1691,7 @@ static void encode_setattr(struct xdr_st
+ {
+ encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr);
+ encode_nfs4_stateid(xdr, &arg->stateid);
+- 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)
+@@ -4056,6 +4110,67 @@ static int decode_attr_time_delta(struct
+ return status;
+ }
+
++static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap,
++ struct nfs4_label *label)
++{
++ uint32_t pi = 0;
++ uint32_t lfs = 0;
++ __u32 len;
++ __be32 *p;
++ int status = 0;
++
++ if (unlikely(bitmap[2] & (FATTR4_WORD2_SECURITY_LABEL - 1U)))
++ return -EIO;
++ if (likely(bitmap[2] & FATTR4_WORD2_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;
++ pi = 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) {
++ nfs4_label_init(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->pi = pi;
++ label->lfs = lfs;
++ status = NFS_ATTR_FATTR_V4_SECURITY_LABEL;
++ }
++ } else {
++ printk("%s(): NULL label.\n", __func__);
++ dump_stack();
++ goto out_overflow;
++ }
++ bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
++ } else
++ printk(KERN_WARNING "%s: label too long (%u)!\n",
++ __func__, len);
++ }
++ if (label && label->label)
++ dprintk("%s: label=%s, len=%d, PI=%d, LFS=%d\n", __func__,
++ label->label, label->len, label->pi, label->lfs);
++ return status;
++
++out_overflow:
++ print_overflow_msg(__func__, xdr);
++ return -EIO;
++}
++
+ static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
+ {
+ int status = 0;
+@@ -4398,7 +4513,7 @@ out_overflow:
+
+ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
+ struct nfs_fattr *fattr, struct nfs_fh *fh,
+- struct nfs4_fs_locations *fs_loc,
++ struct nfs4_fs_locations *fs_loc, struct nfs4_label *label,
+ const struct nfs_server *server)
+ {
+ int status;
+@@ -4506,6 +4621,11 @@ static int decode_getfattr_attrs(struct
+ if (status < 0)
+ goto xdr_error;
+
++ status = decode_attr_security_label(xdr, bitmap, label);
++ if (status < 0)
++ goto xdr_error;
++ fattr->valid |= status;
++
+ xdr_error:
+ dprintk("%s: xdr returned %d\n", __func__, -status);
+ return status;
+@@ -4513,7 +4633,7 @@ xdr_error:
+
+ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr,
+ struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc,
+- const struct nfs_server *server)
++ struct nfs4_label *label, const struct nfs_server *server)
+ {
+ unsigned int savep;
+ uint32_t attrlen,
+@@ -4532,7 +4652,8 @@ static int decode_getfattr_generic(struc
+ if (status < 0)
+ goto xdr_error;
+
+- status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, server);
++ status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc,
++ label, server);
+ if (status < 0)
+ goto xdr_error;
+
+@@ -4543,9 +4664,9 @@ xdr_error:
+ }
+
+ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
+- const struct nfs_server *server)
++ struct nfs4_label *label, const struct nfs_server *server)
+ {
+- return decode_getfattr_generic(xdr, fattr, NULL, NULL, server);
++ return decode_getfattr_generic(xdr, fattr, NULL, NULL, label, server);
+ }
+
+ /*
+@@ -5877,7 +5998,7 @@ static int nfs4_xdr_dec_open_downgrade(s
+ 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);
+ out:
+ return status;
+ }
+@@ -5903,7 +6024,7 @@ static int nfs4_xdr_dec_access(struct rp
+ status = decode_access(xdr, &res->supported, &res->access);
+ if (status != 0)
+ goto out;
+- decode_getfattr(xdr, res->fattr, res->server);
++ decode_getfattr(xdr, res->fattr, res->label, res->server);
+ out:
+ return status;
+ }
+@@ -5932,7 +6053,7 @@ static int nfs4_xdr_dec_lookup(struct rp
+ status = decode_getfh(xdr, res->fh);
+ if (status)
+ goto out;
+- status = decode_getfattr(xdr, res->fattr, res->server);
++ status = decode_getfattr(xdr, res->fattr, res->label, res->server);
+ out:
+ return status;
+ }
+@@ -5958,7 +6079,8 @@ static int nfs4_xdr_dec_lookup_root(stru
+ goto out;
+ status = decode_getfh(xdr, res->fh);
+ if (status == 0)
+- status = decode_getfattr(xdr, res->fattr, res->server);
++ status = decode_getfattr(xdr, res->fattr,
++ res->label, res->server);
+ out:
+ return status;
+ }
+@@ -6049,7 +6171,7 @@ static int nfs4_xdr_dec_link(struct rpc_
+ status = decode_restorefh(xdr);
+ if (status)
+ goto out;
+- decode_getfattr(xdr, res->fattr, res->server);
++ decode_getfattr(xdr, res->fattr, res->label, res->server);
+ out:
+ return status;
+ }
+@@ -6078,7 +6200,7 @@ static int nfs4_xdr_dec_create(struct rp
+ status = decode_getfh(xdr, res->fh);
+ if (status)
+ goto out;
+- decode_getfattr(xdr, res->fattr, res->server);
++ decode_getfattr(xdr, res->fattr, res->label, res->server);
+ out:
+ return status;
+ }
+@@ -6110,7 +6232,7 @@ static int nfs4_xdr_dec_getattr(struct r
+ 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);
+ out:
+ return status;
+ }
+@@ -6212,7 +6334,7 @@ static int nfs4_xdr_dec_close(struct rpc
+ * 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);
+ out:
+ return status;
+ }
+@@ -6243,7 +6365,7 @@ static int nfs4_xdr_dec_open(struct rpc_
+ goto out;
+ if (res->access_request)
+ decode_access(xdr, &res->access_supported, &res->access_result);
+- decode_getfattr(xdr, res->f_attr, res->server);
++ decode_getfattr(xdr, res->f_attr, res->f_label, res->server);
+ out:
+ return status;
+ }
+@@ -6293,7 +6415,7 @@ static int nfs4_xdr_dec_open_noattr(stru
+ goto out;
+ if (res->access_request)
+ decode_access(xdr, &res->access_supported, &res->access_result);
+- decode_getfattr(xdr, res->f_attr, res->server);
++ decode_getfattr(xdr, res->f_attr, NULL, res->server);
+ out:
+ return status;
+ }
+@@ -6320,7 +6442,7 @@ static int nfs4_xdr_dec_setattr(struct r
+ status = decode_setattr(xdr);
+ if (status)
+ goto out;
+- decode_getfattr(xdr, res->fattr, res->server);
++ decode_getfattr(xdr, res->fattr, res->label, res->server);
+ out:
+ return status;
+ }
+@@ -6500,7 +6622,7 @@ static int nfs4_xdr_dec_write(struct rpc
+ if (status)
+ goto out;
+ if (res->fattr)
+- decode_getfattr(xdr, res->fattr, res->server);
++ decode_getfattr(xdr, res->fattr, NULL, res->server);
+ if (!status)
+ status = res->count;
+ out:
+@@ -6681,7 +6803,7 @@ static int nfs4_xdr_dec_delegreturn(stru
+ status = decode_putfh(xdr);
+ if (status != 0)
+ goto out;
+- status = decode_getfattr(xdr, res->fattr, res->server);
++ status = decode_getfattr(xdr, res->fattr, res->label, res->server);
+ if (status != 0)
+ goto out;
+ status = decode_delegreturn(xdr);
+@@ -6714,7 +6836,7 @@ static int nfs4_xdr_dec_fs_locations(str
+ xdr_enter_page(xdr, PAGE_SIZE);
+ status = decode_getfattr_generic(xdr, &res->fs_locations->fattr,
+ NULL, res->fs_locations,
+- res->fs_locations->server);
++ NULL, res->fs_locations->server);
+ out:
+ return status;
+ }
+@@ -6995,7 +7117,7 @@ static int nfs4_xdr_dec_layoutcommit(str
+ status = decode_layoutcommit(xdr, rqstp, res);
+ if (status)
+ goto out;
+- decode_getfattr(xdr, res->fattr, res->server);
++ decode_getfattr(xdr, res->fattr, NULL, res->server);
+ out:
+ return status;
+ }
+@@ -7127,7 +7249,7 @@ int nfs4_decode_dirent(struct xdr_stream
+ goto out_overflow;
+
+ if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh,
+- NULL, entry->server) < 0)
++ NULL, entry->label, entry->server) < 0)
+ goto out_overflow;
+ if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
+ entry->ino = entry->fattr->mounted_on_fileid;
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/proc.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/proc.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/proc.c.orig 2012-09-30 19:47:46.000000000 -0400
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/proc.c 2012-12-03 10:53:55.668785396 -0500
+@@ -131,7 +131,7 @@ nfs_proc_get_root(struct nfs_server *ser
+ */
+ 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],
+@@ -179,7 +179,8 @@ nfs_proc_setattr(struct dentry *dentry,
+
+ 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),
+@@ -276,7 +277,7 @@ nfs_proc_create(struct inode *dir, struc
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ nfs_mark_for_revalidate(dir);
+ if (status == 0)
+- status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
++ status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL);
+ nfs_free_createdata(data);
+ out:
+ dprintk("NFS reply create: %d\n", status);
+@@ -323,7 +324,7 @@ nfs_proc_mknod(struct inode *dir, struct
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ }
+ if (status == 0)
+- status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
++ status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL);
+ nfs_free_createdata(data);
+ out:
+ dprintk("NFS reply mknod: %d\n", status);
+@@ -479,7 +480,7 @@ nfs_proc_symlink(struct inode *dir, stru
+ * should fill in the data with a LOOKUP call on the wire.
+ */
+ if (status == 0)
+- status = nfs_instantiate(dentry, fh, fattr);
++ status = nfs_instantiate(dentry, fh, fattr, NULL);
+
+ out_free:
+ nfs_free_fattr(fattr);
+@@ -508,7 +509,7 @@ nfs_proc_mkdir(struct inode *dir, struct
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ nfs_mark_for_revalidate(dir);
+ if (status == 0)
+- status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
++ status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL);
+ nfs_free_createdata(data);
+ out:
+ dprintk("NFS reply mkdir: %d\n", status);
+@@ -647,7 +648,7 @@ static int nfs_read_done(struct rpc_task
+
+ nfs_invalidate_atime(inode);
+ if (task->tk_status >= 0) {
+- nfs_refresh_inode(inode, data->res.fattr);
++ nfs_refresh_inode(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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/super.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/super.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/super.c.orig 2012-11-29 16:37:13.972901705 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/fs/nfs/super.c 2012-12-03 10:53:55.669785397 -0500
+@@ -875,6 +875,7 @@ int nfs_show_stats(struct seq_file *m, s
+ seq_printf(m, "\n\tnfsv4:\t");
+ seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
+ seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]);
++ seq_printf(m, ",bm2=0x%x", nfss->attr_bitmask[2]);
+ seq_printf(m, ",acl=0x%x", nfss->acl_bitmask);
+ show_sessions(m, nfss);
+ show_pnfs(m, nfss);
+@@ -2405,7 +2406,23 @@ static int nfs_bdi_register(struct nfs_s
+ int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot,
+ struct nfs_mount_info *mount_info)
+ {
+- return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts);
++ int error;
++ unsigned long kflags = 0, kflags_out = 0;
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL)
++ kflags |= SECURITY_LSM_NATIVE_LABELS;
++#endif
++ error = security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts,
++ kflags, &kflags_out);
++ if (error)
++ goto err;
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL &&
++ !(kflags_out & SECURITY_LSM_NATIVE_LABELS))
++ NFS_SB(s)->caps &= ~NFS_CAP_SECURITY_LABEL;
++#endif
++err:
++ return error;
+ }
+ EXPORT_SYMBOL_GPL(nfs_set_sb_security);
+
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs4.h.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs4.h
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs4.h.orig 2012-11-29 16:37:19.038905615 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs4.h 2012-12-03 10:53:55.698785414 -0500
+@@ -28,6 +28,14 @@ struct nfs4_acl {
+ struct nfs4_ace aces[0];
+ };
+
++struct nfs4_label {
++ uint32_t lfs;
++ uint32_t pi;
++ u32 len;
++ void *label;
++};
++
++
+ typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
+
+ struct nfs_stateid4 {
+@@ -373,6 +381,7 @@ enum lock_type4 {
+ #define FATTR4_WORD1_MOUNTED_ON_FILEID (1UL << 23)
+ #define FATTR4_WORD1_FS_LAYOUT_TYPES (1UL << 30)
+ #define FATTR4_WORD2_LAYOUT_BLKSIZE (1UL << 1)
++#define FATTR4_WORD2_SECURITY_LABEL (1UL << 17)
+ #define FATTR4_WORD2_MDSTHRESHOLD (1UL << 4)
+
+ /* MDS threshold bitmap bits */
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs_fs.h.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs_fs.h
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs_fs.h.orig 2012-11-29 16:37:19.047905624 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs_fs.h 2012-12-03 10:53:55.699785414 -0500
+@@ -199,6 +199,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
+@@ -328,9 +329,9 @@ extern void nfs_zap_mapping(struct inode
+ 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 void nfs_access_add_cache(struct inode *, struct nfs_access_entry *);
+@@ -344,6 +345,8 @@ extern int __nfs_revalidate_inode(struct
+ 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);
+@@ -460,7 +463,8 @@ extern const struct file_operations nfs_
+ 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);
+
+@@ -489,6 +493,20 @@ extern int nfs_mountpoint_expiry_timeout
+ extern void nfs_release_automount_timer(void);
+
+ /*
++ * linux/fs/nfs/nfs4proc.c
++ */
++
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++extern struct nfs4_label *nfs4_label_alloc(gfp_t flags);
++extern void nfs4_label_init(struct nfs4_label *);
++extern void nfs4_label_free(struct nfs4_label *);
++#else
++static inline struct nfs4_label *nfs4_label_alloc(gfp_t flags) { return NULL; }
++static inline void nfs4_label_init(struct nfs4_label *) {}
++static inline void nfs4_label_free(struct nfs4_label *label) {}
++#endif
++
++/*
+ * linux/fs/nfs/unlink.c
+ */
+ extern void nfs_complete_unlink(struct dentry *dentry, struct inode *);
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs_fs_sb.h.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs_fs_sb.h
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs_fs_sb.h.orig 2012-11-29 16:37:19.054905631 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs_fs_sb.h 2012-12-03 10:53:55.707785421 -0500
+@@ -145,11 +145,18 @@ struct nfs_server {
+ u32 attr_bitmask[3];/* V4 bitmask representing the set
+ of attributes supported on this
+ filesystem */
+- u32 cache_consistency_bitmask[2];
++ u32 attr_bitmask_nl[3];
++ /* V4 bitmask representing the
++ set of attributes supported
++ on this filesystem excluding
++ the label support bit. */
++ u32 cache_consistency_bitmask[3];
+ /* V4 bitmask representing the subset
+ of change attribute, size, ctime
+ and mtime attributes supported by
+ the server */
++ u32 cache_consistency_bitmask_nl[3];
++ /* As above, excluding label. */
+ u32 acl_bitmask; /* V4 bitmask representing the ACEs
+ that are supported on this
+ filesystem */
+@@ -197,6 +204,7 @@ struct nfs_server {
+ #define NFS_CAP_MTIME (1U << 13)
+ #define NFS_CAP_POSIX_LOCK (1U << 14)
+ #define NFS_CAP_UIDGID_NOMAP (1U << 15)
++#define NFS_CAP_SECURITY_LABEL (1U << 16)
+
+
+ /* maximum number of slots to use */
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs_xdr.h.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs_xdr.h
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs_xdr.h.orig 2012-11-29 16:37:19.071905644 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/nfs_xdr.h 2012-12-03 10:53:55.708785422 -0500
+@@ -104,6 +104,7 @@ struct nfs_fattr {
+ #define NFS_ATTR_FATTR_MOUNTED_ON_FILEID (1U << 22)
+ #define NFS_ATTR_FATTR_OWNER_NAME (1U << 23)
+ #define NFS_ATTR_FATTR_GROUP_NAME (1U << 24)
++#define NFS_ATTR_FATTR_V4_SECURITY_LABEL (1U << 25)
+
+ #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \
+ | NFS_ATTR_FATTR_MODE \
+@@ -123,7 +124,8 @@ struct nfs_fattr {
+ #define NFS_ATTR_FATTR_V3 (NFS_ATTR_FATTR \
+ | NFS_ATTR_FATTR_SPACE_USED)
+ #define NFS_ATTR_FATTR_V4 (NFS_ATTR_FATTR \
+- | NFS_ATTR_FATTR_SPACE_USED)
++ | NFS_ATTR_FATTR_SPACE_USED \
++ | NFS_ATTR_FATTR_V4_SECURITY_LABEL)
+
+ /*
+ * Info on the file system
+@@ -350,6 +352,7 @@ struct nfs_openargs {
+ const u32 * bitmask;
+ const u32 * open_bitmap;
+ __u32 claim;
++ const struct nfs4_label *label;
+ struct nfs4_sequence_args seq_args;
+ };
+
+@@ -359,6 +362,7 @@ struct nfs_openres {
+ struct nfs4_change_info cinfo;
+ __u32 rflags;
+ struct nfs_fattr * f_attr;
++ struct nfs4_label *f_label;
+ struct nfs_seqid * seqid;
+ const struct nfs_server *server;
+ fmode_t delegation_type;
+@@ -403,6 +407,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;
+@@ -476,6 +481,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;
+ };
+@@ -496,6 +502,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;
+@@ -564,6 +571,7 @@ struct nfs_removeargs {
+ struct nfs_removeres {
+ const struct nfs_server *server;
+ struct nfs_fattr *dir_attr;
++ struct nfs4_label *dir_label;
+ struct nfs4_change_info cinfo;
+ struct nfs4_sequence_res seq_res;
+ };
+@@ -576,6 +584,8 @@ struct nfs_renameargs {
+ 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;
+ struct nfs4_sequence_args seq_args;
+ };
+
+@@ -583,8 +593,10 @@ struct nfs_renameres {
+ 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;
+ };
+
+@@ -600,6 +612,7 @@ struct nfs_entry {
+ int eof;
+ struct nfs_fh * fh;
+ struct nfs_fattr * fattr;
++ struct nfs4_label *label;
+ unsigned char d_type;
+ struct nfs_server * server;
+ };
+@@ -631,6 +644,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;
+ };
+
+@@ -666,6 +680,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;
+ };
+@@ -712,6 +727,7 @@ struct nfs3_setaclargs {
+ struct nfs_diropok {
+ struct nfs_fh * fh;
+ struct nfs_fattr * fattr;
++ struct nfs4_label *label;
+ };
+
+ struct nfs_readlinkargs {
+@@ -841,6 +857,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;
+@@ -863,6 +880,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;
+ };
+
+@@ -870,6 +888,7 @@ 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 nfs4_sequence_res seq_res;
+ };
+@@ -895,6 +914,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 {
+@@ -908,8 +928,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;
+ };
+
+@@ -925,6 +947,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;
+ };
+
+@@ -1379,11 +1402,12 @@ struct nfs_rpc_ops {
+ struct dentry *(*try_mount) (int, const char *, struct nfs_mount_info *,
+ struct nfs_subversion *);
+ 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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/security.h.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/security.h
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/security.h.orig 2012-11-29 16:37:19.946906321 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/linux/security.h 2012-12-03 10:53:55.710785424 -0500
+@@ -26,6 +26,7 @@
+ #include <linux/capability.h>
+ #include <linux/slab.h>
+ #include <linux/err.h>
++#include <linux/string.h>
+
+ struct linux_binprm;
+ struct cred;
+@@ -60,6 +61,9 @@ struct mm_struct;
+ #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;
+ struct user_namespace;
+@@ -306,6 +310,15 @@ static inline void security_free_mnt_opt
+ * 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.
++ * @name name of the last path component used to create file
++ * @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.
+ *
+@@ -1291,6 +1304,13 @@ static inline void security_free_mnt_opt
+ * @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. Returns 0 if name is a MAC
++ * attribute otherwise returns non-zero.
++ * @name full extended attribute name to check against
++ * LSM as a MAC label.
++ *
+ * @secid_to_secctx:
+ * Convert secid to security context. If secdata is NULL the length of
+ * the result will be returned in seclen, but no secdata will be returned.
+@@ -1417,10 +1437,16 @@ struct security_operations {
+ int (*sb_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);
++ int (*dentry_init_security) (struct dentry *dentry, int mode,
++ struct qstr *name, void **ctx,
++ u32 *ctxlen);
++
+
+ #ifdef CONFIG_SECURITY_PATH
+ int (*path_unlink) (struct path *dir, struct dentry *dentry);
+@@ -1567,6 +1593,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);
+@@ -1698,10 +1725,16 @@ int security_sb_mount(const char *dev_na
+ const char *type, unsigned long flags, void *data);
+ int security_sb_umount(struct vfsmount *mnt, int flags);
+ int security_sb_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);
++int security_dentry_init_security(struct dentry *dentry, int mode,
++ struct qstr *name, void **ctx,
++ u32 *ctxlen);
+
+ int security_inode_alloc(struct inode *inode);
+ void security_inode_free(struct inode *inode);
+@@ -1812,6 +1845,7 @@ void security_d_instantiate(struct dentr
+ 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_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);
+@@ -1983,7 +2017,9 @@ static inline int security_sb_pivotroot(
+ }
+
+ 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;
+ }
+@@ -2005,6 +2041,16 @@ static inline int security_inode_alloc(s
+ static inline void security_inode_free(struct inode *inode)
+ { }
+
++static inline int security_dentry_init_security(struct dentry *dentry,
++ int mode,
++ struct qstr *name,
++ void **ctx,
++ u32 *ctxlen)
++{
++ return -EOPNOTSUPP;
++}
++
++
+ static inline int security_inode_init_security(struct inode *inode,
+ struct inode *dir,
+ const struct qstr *qstr,
+@@ -2485,6 +2531,11 @@ static inline int security_netlink_send(
+ return cap_netlink_send(sk, skb);
+ }
+
++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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/uapi/linux/nfs4.h.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/uapi/linux/nfs4.h
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/uapi/linux/nfs4.h.orig 2012-11-29 16:37:22.518908252 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/uapi/linux/nfs4.h 2012-12-03 10:53:55.711785425 -0500
+@@ -25,6 +25,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
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/uapi/linux/nfsd/export.h.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/uapi/linux/nfsd/export.h
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/uapi/linux/nfsd/export.h.orig 2012-11-29 16:37:22.520908254 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/include/uapi/linux/nfsd/export.h 2012-12-03 10:53:55.711785425 -0500
+@@ -28,7 +28,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 */
+@@ -47,7 +48,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 \
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/capability.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/capability.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/capability.c.orig 2012-11-29 16:37:29.717913881 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/capability.c 2012-12-03 10:53:55.711785425 -0500
+@@ -91,7 +91,10 @@ static int cap_sb_pivotroot(struct 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;
+@@ -108,6 +111,13 @@ static int cap_sb_parse_opts_str(char *o
+ return 0;
+ }
+
++static int cap_dentry_init_security(struct dentry *dentry, int mode,
++ struct qstr *name, void **ctx,
++ u32 *ctxlen)
++{
++ return 0;
++}
++
+ static int cap_inode_alloc_security(struct inode *inode)
+ {
+ return 0;
+@@ -790,6 +800,11 @@ static int cap_setprocattr(struct task_s
+ 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;
+@@ -905,6 +920,7 @@ void __init security_fixup_ops(struct se
+ 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);
+@@ -1007,6 +1023,7 @@ void __init security_fixup_ops(struct se
+ 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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/security.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/security.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/security.c.orig 2012-11-29 16:37:29.952914090 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/security.c 2012-12-03 10:53:55.712785426 -0500
+@@ -12,6 +12,7 @@
+ */
+
+ #include <linux/capability.h>
++#include <linux/dcache.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+@@ -293,9 +294,12 @@ int security_sb_pivotroot(struct path *o
+ }
+
+ 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);
+
+@@ -324,6 +328,15 @@ void security_inode_free(struct inode *i
+ security_ops->inode_free_security(inode);
+ }
+
++int security_dentry_init_security(struct dentry *dentry, int mode,
++ struct qstr *name, void **ctx,
++ u32 *ctxlen)
++{
++ return security_ops->dentry_init_security(dentry, mode, name,
++ ctx, ctxlen);
++}
++EXPORT_SYMBOL(security_dentry_init_security);
++
+ int security_inode_init_security(struct inode *inode, struct inode *dir,
+ const struct qstr *qstr,
+ const initxattrs initxattrs, void *fs_data)
+@@ -647,6 +660,7 @@ int security_inode_listsecurity(struct i
+ 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)
+ {
+@@ -1037,6 +1051,12 @@ int security_netlink_send(struct sock *s
+ return security_ops->netlink_send(sk, skb);
+ }
+
++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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/selinux/hooks.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/selinux/hooks.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/selinux/hooks.c.orig 2012-11-30 09:16:55.312835507 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/selinux/hooks.c 2012-12-03 10:53:55.714785428 -0500
+@@ -80,6 +80,7 @@
+ #include <linux/syslog.h>
+ #include <linux/user_namespace.h>
+ #include <linux/export.h>
++#include <linux/security.h>
+ #include <linux/msg.h>
+ #include <linux/shm.h>
+
+@@ -283,13 +284,14 @@ static void superblock_free_security(str
+
+ /* The file system's label must be initialized prior to use. */
+
+-static const char *labeling_behaviors[6] = {
++static const 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);
+@@ -551,7 +553,9 @@ static int bad_option(struct superblock_
+ * 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;
+@@ -579,6 +583,12 @@ static int selinux_set_mnt_opts(struct s
+ "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
+@@ -669,14 +679,21 @@ static int selinux_set_mnt_opts(struct s
+ 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);
+@@ -691,6 +708,11 @@ static int selinux_set_mnt_opts(struct s
+ * 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,
+@@ -722,7 +744,8 @@ static int selinux_set_mnt_opts(struct s
+ }
+
+ 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");
+@@ -948,7 +971,7 @@ static int superblock_doinit(struct supe
+ 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);
+@@ -1190,6 +1213,8 @@ static int inode_doinit_with_dentry(stru
+ }
+
+ switch (sbsec->behavior) {
++ case SECURITY_FS_USE_NATIVE:
++ break;
+ case SECURITY_FS_USE_XATTR:
+ if (!inode->i_op->getxattr) {
+ isec->sid = sbsec->def_sid;
+@@ -2521,6 +2546,40 @@ static void selinux_inode_free_security(
+ inode_free_security(inode);
+ }
+
++static int selinux_dentry_init_security(struct dentry *dentry, int mode,
++ struct qstr *name, 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),
++ name,
++ &newsid);
++ if (rc) {
++ printk(KERN_WARNING
++ "%s: security_transition_sid failed, rc=%d\n",
++ __func__, -rc);
++ return rc;
++ }
++ }
++
++ return security_sid_to_context(newsid, (char **)ctx, ctxlen);
++}
++
+ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
+ const struct qstr *qstr, char **name,
+ void **value, size_t *len)
+@@ -2855,7 +2914,10 @@ static void selinux_inode_post_setxattr(
+ return;
+ }
+
++ isec->sclass = inode_mode_to_security_class(inode->i_mode);
+ isec->sid = newsid;
++ isec->initialized = 1;
++
+ return;
+ }
+
+@@ -2943,6 +3005,7 @@ static int selinux_inode_setsecurity(str
+ if (rc)
+ return rc;
+
++ isec->sclass = inode_mode_to_security_class(inode->i_mode);
+ isec->sid = newsid;
+ isec->initialized = 1;
+ return 0;
+@@ -5405,6 +5468,11 @@ abort_change:
+ return error;
+ }
+
++static int selinux_ismaclabel(const char *name)
++{
++ return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
++}
++
+ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+ {
+ return security_sid_to_context(secid, secdata, seclen);
+@@ -5547,6 +5615,7 @@ static struct security_operations selinu
+ .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,
+@@ -5642,6 +5711,7 @@ static struct security_operations selinu
+ .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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/selinux/include/security.h.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/selinux/include/security.h
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/selinux/include/security.h.orig 2012-11-30 09:16:55.312835507 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/selinux/include/security.h 2012-12-03 10:53:55.715785429 -0500
+@@ -171,6 +171,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 -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/selinux/ss/policydb.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/selinux/ss/policydb.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/selinux/ss/policydb.c.orig 2012-09-30 19:47:46.000000000 -0400
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/selinux/ss/policydb.c 2012-12-03 10:53:55.716785430 -0500
+@@ -2168,7 +2168,10 @@ static int ocontext_read(struct policydb
+
+ rc = -EINVAL;
+ 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 out;
++ if (c->v.behavior > SECURITY_FS_USE_MAX)
+ goto out;
+
+ rc = -ENOMEM;
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/smack/smack_lsm.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/smack/smack_lsm.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/smack/smack_lsm.c.orig 2012-11-29 16:37:30.025914150 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc19.x86_64/security/smack/smack_lsm.c 2012-12-03 10:53:55.718785432 -0500
+@@ -3335,6 +3335,16 @@ static void smack_audit_rule_free(void *
+ #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_SMACK_SUFFIX) == 0);
++}
++
++
++/**
+ * smack_secid_to_secctx - return the smack label for a secid
+ * @secid: incoming integer
+ * @secdata: destination
+@@ -3530,6 +3540,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,
diff --git a/lnfs-unset-3.7.0-0.rc7.git1.2.fc19.patch b/lnfs-unset-3.7.0-0.rc7.git1.2.fc19.patch
new file mode 100644
index 0000000..2a1d764
--- /dev/null
+++ b/lnfs-unset-3.7.0-0.rc7.git1.2.fc19.patch
@@ -0,0 +1,124 @@
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc17.x86_64/fs/nfs/nfs4proc.c.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc17.x86_64/fs/nfs/nfs4proc.c
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc17.x86_64/fs/nfs/nfs4proc.c.orig 2012-12-03 10:58:51.086841436 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc17.x86_64/fs/nfs/nfs4proc.c 2012-12-03 11:34:01.065752872 -0500
+@@ -925,8 +925,8 @@ err_free_label:
+ #ifdef CONFIG_NFS_V4_SECURITY_LABEL
+ if (server->caps & NFS_CAP_SECURITY_LABEL)
+ nfs4_label_free(p->f_label);
+-#endif
+ err_free_p:
++#endif
+ kfree(p);
+ err:
+ dput(parent);
+@@ -2440,9 +2440,10 @@ static struct inode *
+ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
+ {
+ struct nfs4_state *state;
+- struct nfs4_label l, *label = NULL;
+-
++ struct nfs4_label *label = NULL;
+ #ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ struct nfs4_label l;
++
+ if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+ struct dentry *dentry = ctx->dentry;
+ int error;
+@@ -3028,8 +3029,8 @@ static int _nfs4_proc_access(struct inod
+ #ifdef CONFIG_NFS_V4_SECURITY_LABEL
+ if (server->caps & NFS_CAP_SECURITY_LABEL)
+ nfs4_label_free(res.label);
+-#endif
+ out:
++#endif
+ nfs_free_fattr(res.fattr);
+ return status;
+ }
+@@ -3107,7 +3108,10 @@ static int
+ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+ int flags)
+ {
+- struct nfs4_label l, *ilabel = NULL;
++ struct nfs4_label *ilabel = NULL;
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ struct nfs4_label l;
++#endif
+ struct nfs_open_context *ctx;
+ struct nfs4_state *state;
+ int status = 0;
+@@ -3300,8 +3304,8 @@ static int _nfs4_proc_rename(struct inod
+ nfs4_label_free(res.old_label);
+ nfs4_label_free(res.new_label);
+ }
+-#endif
+ out:
++#endif
+ return status;
+ }
+
+@@ -3420,7 +3424,9 @@ static struct nfs4_createdata *nfs4_allo
+ nfs_fattr_init(data->res.fattr);
+ }
+ return data;
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+ out_free:
++#endif
+ kfree(data);
+ return NULL;
+ }
+@@ -3476,11 +3482,11 @@ static int nfs4_proc_symlink(struct inod
+ struct page *page, unsigned int len, struct iattr *sattr)
+ {
+ struct nfs4_exception exception = { };
+- struct nfs4_label l, *label = NULL;
+ int err;
+-
+-
++ struct nfs4_label *label = NULL;
+ #ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ struct nfs4_label l;
++
+ if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+ err = security_dentry_init_security(dentry, sattr->ia_mode,
+ &dentry->d_name, &l.label, &l.len);
+@@ -3524,7 +3530,10 @@ static int nfs4_proc_mkdir(struct inode
+ struct iattr *sattr)
+ {
+ struct nfs4_exception exception = { };
+- struct nfs4_label l, *label = NULL;
++ struct nfs4_label *label = NULL;
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ struct nfs4_label l;
++#endif
+ int err;
+
+ #ifdef CONFIG_NFS_V4_SECURITY_LABEL
+@@ -3642,9 +3651,12 @@ out:
+ 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;
++ struct nfs4_exception exception = { };
++ struct nfs4_label *label = NULL;
++#ifdef CONFIG_NFS_V4_SECURITY_LABEL
++ struct nfs4_label l;
++#endif
+
+ #ifdef CONFIG_NFS_V4_SECURITY_LABEL
+ if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL)) {
+diff -up linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc17.x86_64/include/linux/nfs_fs.h.orig linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc17.x86_64/include/linux/nfs_fs.h
+--- linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc17.x86_64/include/linux/nfs_fs.h.orig 2012-12-03 11:08:32.524060597 -0500
++++ linux-3.7.0-0.rc7.git1.2.lnfs37rc2.fc17.x86_64/include/linux/nfs_fs.h 2012-12-03 11:09:38.431071109 -0500
+@@ -502,8 +502,8 @@ extern void nfs4_label_init(struct nfs4_
+ extern void nfs4_label_free(struct nfs4_label *);
+ #else
+ static inline struct nfs4_label *nfs4_label_alloc(gfp_t flags) { return NULL; }
+-static inline void nfs4_label_init(struct nfs4_label *) {}
+-static inline void nfs4_label_free(struct nfs4_label *label) {}
++static inline void nfs4_label_init(void *label) {}
++static inline void nfs4_label_free(void *label) {}
+ #endif
+
+ /*
More information about the scm-commits
mailing list