aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorDavid Quigley <dpquigl@davequigley.com>2013-05-02 13:19:10 -0400
committerJ. Bruce Fields <bfields@redhat.com>2013-05-15 09:27:02 -0400
commit18032ca062e621e15683cb61c066ef3dc5414a7b (patch)
tree18b061105452a5d47a85c0f693a151227ff3c02c /fs/nfsd
parent4bdc33ed5bd9fbaa243bda6fdccb22674aed6305 (diff)
NFSD: Server implementation of MAC Labeling
Implement labeled NFS on the server: encoding and decoding, and writing and reading, of file labels. Enabled with CONFIG_NFSD_V4_SECURITY_LABEL. Signed-off-by: Matthew N. Dodd <Matthew.Dodd@sparta.com> Signed-off-by: Miguel Rodel Felipe <Rodel_FM@dsi.a-star.edu.sg> Signed-off-by: Phua Eu Gene <PHUA_Eu_Gene@dsi.a-star.edu.sg> Signed-off-by: Khin Mi Mi Aung <Mi_Mi_AUNG@dsi.a-star.edu.sg> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/Kconfig16
-rw-r--r--fs/nfsd/nfs4proc.c41
-rw-r--r--fs/nfsd/nfs4xdr.c108
-rw-r--r--fs/nfsd/nfsd.h18
-rw-r--r--fs/nfsd/vfs.c28
-rw-r--r--fs/nfsd/vfs.h2
-rw-r--r--fs/nfsd/xdr4.h4
7 files changed, 207 insertions, 10 deletions
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index 430b6872806f..dc8f1ef665ce 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -81,6 +81,22 @@ config NFSD_V4
81 81
82 If unsure, say N. 82 If unsure, say N.
83 83
84config NFSD_V4_SECURITY_LABEL
85 bool "Provide Security Label support for NFSv4 server"
86 depends on NFSD_V4 && SECURITY
87 help
88
89 Say Y here if you want enable fine-grained security label attribute
90 support for NFS version 4. Security labels allow security modules like
91 SELinux and Smack to label files to facilitate enforcement of their policies.
92 Without this an NFSv4 mount will have the same label on each file.
93
94 If you do not wish to enable fine-grained security labels SELinux or
95 Smack policies on NFSv4 files, say N.
96
97 WARNING: there is still a chance of backwards-incompatible protocol changes.
98 For now we recommend "Y" only for developers and testers."
99
84config NFSD_FAULT_INJECTION 100config NFSD_FAULT_INJECTION
85 bool "NFS server manual fault injection" 101 bool "NFS server manual fault injection"
86 depends on NFSD_V4 && DEBUG_KERNEL 102 depends on NFSD_V4 && DEBUG_KERNEL
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 27d74a294515..1a1ff247bc59 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -42,6 +42,36 @@
42#include "current_stateid.h" 42#include "current_stateid.h"
43#include "netns.h" 43#include "netns.h"
44 44
45#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
46#include <linux/security.h>
47
48static inline void
49nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
50{
51 struct inode *inode = resfh->fh_dentry->d_inode;
52 int status;
53
54 mutex_lock(&inode->i_mutex);
55 status = security_inode_setsecctx(resfh->fh_dentry,
56 label->data, label->len);
57 mutex_unlock(&inode->i_mutex);
58
59 if (status)
60 /*
61 * XXX: We should really fail the whole open, but we may
62 * already have created a new file, so it may be too
63 * late. For now this seems the least of evils:
64 */
65 bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
66
67 return;
68}
69#else
70static inline void
71nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
72{ }
73#endif
74
45#define NFSDDBG_FACILITY NFSDDBG_PROC 75#define NFSDDBG_FACILITY NFSDDBG_PROC
46 76
47static u32 nfsd_attrmask[] = { 77static u32 nfsd_attrmask[] = {
@@ -239,6 +269,9 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
239 (u32 *)open->op_verf.data, 269 (u32 *)open->op_verf.data,
240 &open->op_truncate, &open->op_created); 270 &open->op_truncate, &open->op_created);
241 271
272 if (!status && open->op_label.len)
273 nfsd4_security_inode_setsecctx(resfh, &open->op_label, open->op_bmval);
274
242 /* 275 /*
243 * Following rfc 3530 14.2.16, use the returned bitmask 276 * Following rfc 3530 14.2.16, use the returned bitmask
244 * to indicate which attributes we used to store the 277 * to indicate which attributes we used to store the
@@ -637,6 +670,9 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
637 if (status) 670 if (status)
638 goto out; 671 goto out;
639 672
673 if (create->cr_label.len)
674 nfsd4_security_inode_setsecctx(&resfh, &create->cr_label, create->cr_bmval);
675
640 if (create->cr_acl != NULL) 676 if (create->cr_acl != NULL)
641 do_set_nfs4_acl(rqstp, &resfh, create->cr_acl, 677 do_set_nfs4_acl(rqstp, &resfh, create->cr_acl,
642 create->cr_bmval); 678 create->cr_bmval);
@@ -916,6 +952,11 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
916 setattr->sa_acl); 952 setattr->sa_acl);
917 if (status) 953 if (status)
918 goto out; 954 goto out;
955 if (setattr->sa_label.len)
956 status = nfsd4_set_nfs4_label(rqstp, &cstate->current_fh,
957 &setattr->sa_label);
958 if (status)
959 goto out;
919 status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr, 960 status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
920 0, (time_t)0); 961 0, (time_t)0);
921out: 962out:
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 9aeacddafa3f..dfca5121de53 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -55,6 +55,11 @@
55#include "cache.h" 55#include "cache.h"
56#include "netns.h" 56#include "netns.h"
57 57
58#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
59#include <linux/security.h>
60#endif
61
62
58#define NFSDDBG_FACILITY NFSDDBG_XDR 63#define NFSDDBG_FACILITY NFSDDBG_XDR
59 64
60/* 65/*
@@ -242,7 +247,8 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
242 247
243static __be32 248static __be32
244nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, 249nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
245 struct iattr *iattr, struct nfs4_acl **acl) 250 struct iattr *iattr, struct nfs4_acl **acl,
251 struct xdr_netobj *label)
246{ 252{
247 int expected_len, len = 0; 253 int expected_len, len = 0;
248 u32 dummy32; 254 u32 dummy32;
@@ -380,6 +386,32 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
380 goto xdr_error; 386 goto xdr_error;
381 } 387 }
382 } 388 }
389
390 label->len = 0;
391#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
392 if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
393 READ_BUF(4);
394 len += 4;
395 READ32(dummy32); /* lfs: we don't use it */
396 READ_BUF(4);
397 len += 4;
398 READ32(dummy32); /* pi: we don't use it either */
399 READ_BUF(4);
400 len += 4;
401 READ32(dummy32);
402 READ_BUF(dummy32);
403 if (dummy32 > NFSD4_MAX_SEC_LABEL_LEN)
404 return nfserr_badlabel;
405 len += (XDR_QUADLEN(dummy32) << 2);
406 READMEM(buf, dummy32);
407 label->data = kzalloc(dummy32 + 1, GFP_KERNEL);
408 if (!label->data)
409 return nfserr_jukebox;
410 defer_free(argp, kfree, label->data);
411 memcpy(label->data, buf, dummy32);
412 }
413#endif
414
383 if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0 415 if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
384 || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1 416 || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
385 || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2) 417 || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2)
@@ -576,7 +608,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
576 return status; 608 return status;
577 609
578 status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr, 610 status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
579 &create->cr_acl); 611 &create->cr_acl, &create->cr_label);
580 if (status) 612 if (status)
581 goto out; 613 goto out;
582 614
@@ -827,7 +859,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
827 case NFS4_CREATE_UNCHECKED: 859 case NFS4_CREATE_UNCHECKED:
828 case NFS4_CREATE_GUARDED: 860 case NFS4_CREATE_GUARDED:
829 status = nfsd4_decode_fattr(argp, open->op_bmval, 861 status = nfsd4_decode_fattr(argp, open->op_bmval,
830 &open->op_iattr, &open->op_acl); 862 &open->op_iattr, &open->op_acl, &open->op_label);
831 if (status) 863 if (status)
832 goto out; 864 goto out;
833 break; 865 break;
@@ -841,7 +873,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
841 READ_BUF(NFS4_VERIFIER_SIZE); 873 READ_BUF(NFS4_VERIFIER_SIZE);
842 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE); 874 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
843 status = nfsd4_decode_fattr(argp, open->op_bmval, 875 status = nfsd4_decode_fattr(argp, open->op_bmval,
844 &open->op_iattr, &open->op_acl); 876 &open->op_iattr, &open->op_acl, &open->op_label);
845 if (status) 877 if (status)
846 goto out; 878 goto out;
847 break; 879 break;
@@ -1063,7 +1095,7 @@ nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *seta
1063 if (status) 1095 if (status)
1064 return status; 1096 return status;
1065 return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr, 1097 return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
1066 &setattr->sa_acl); 1098 &setattr->sa_acl, &setattr->sa_label);
1067} 1099}
1068 1100
1069static __be32 1101static __be32
@@ -1954,6 +1986,36 @@ nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace,
1954 FATTR4_WORD0_RDATTR_ERROR) 1986 FATTR4_WORD0_RDATTR_ERROR)
1955#define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID 1987#define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
1956 1988
1989#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
1990static inline __be32
1991nfsd4_encode_security_label(struct svc_rqst *rqstp, void *context, int len, __be32 **pp, int *buflen)
1992{
1993 __be32 *p = *pp;
1994
1995 if (*buflen < ((XDR_QUADLEN(len) << 2) + 4 + 4 + 4))
1996 return nfserr_resource;
1997
1998 /*
1999 * For now we use a 0 here to indicate the null translation; in
2000 * the future we may place a call to translation code here.
2001 */
2002 if ((*buflen -= 8) < 0)
2003 return nfserr_resource;
2004
2005 WRITE32(0); /* lfs */
2006 WRITE32(0); /* pi */
2007 p = xdr_encode_opaque(p, context, len);
2008 *buflen -= (XDR_QUADLEN(len) << 2) + 4;
2009
2010 *pp = p;
2011 return 0;
2012}
2013#else
2014static inline __be32
2015nfsd4_encode_security_label(struct svc_rqst *rqstp, struct dentry *dentry, __be32 **pp, int *buflen)
2016{ return 0; }
2017#endif
2018
1957static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err) 2019static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
1958{ 2020{
1959 /* As per referral draft: */ 2021 /* As per referral draft: */
@@ -2013,6 +2075,9 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
2013 int err; 2075 int err;
2014 int aclsupport = 0; 2076 int aclsupport = 0;
2015 struct nfs4_acl *acl = NULL; 2077 struct nfs4_acl *acl = NULL;
2078 void *context = NULL;
2079 int contextlen;
2080 bool contextsupport = false;
2016 struct nfsd4_compoundres *resp = rqstp->rq_resp; 2081 struct nfsd4_compoundres *resp = rqstp->rq_resp;
2017 u32 minorversion = resp->cstate.minorversion; 2082 u32 minorversion = resp->cstate.minorversion;
2018 struct path path = { 2083 struct path path = {
@@ -2066,6 +2131,21 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
2066 } 2131 }
2067 } 2132 }
2068 2133
2134#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
2135 if ((bmval[2] & FATTR4_WORD2_SECURITY_LABEL) ||
2136 bmval[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
2137 err = security_inode_getsecctx(dentry->d_inode,
2138 &context, &contextlen);
2139 contextsupport = (err == 0);
2140 if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
2141 if (err == -EOPNOTSUPP)
2142 bmval2 &= ~FATTR4_WORD2_SECURITY_LABEL;
2143 else if (err)
2144 goto out_nfserr;
2145 }
2146 }
2147#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
2148
2069 if (bmval2) { 2149 if (bmval2) {
2070 if ((buflen -= 16) < 0) 2150 if ((buflen -= 16) < 0)
2071 goto out_resource; 2151 goto out_resource;
@@ -2094,6 +2174,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
2094 2174
2095 if (!aclsupport) 2175 if (!aclsupport)
2096 word0 &= ~FATTR4_WORD0_ACL; 2176 word0 &= ~FATTR4_WORD0_ACL;
2177 if (!contextsupport)
2178 word2 &= ~FATTR4_WORD2_SECURITY_LABEL;
2097 if (!word2) { 2179 if (!word2) {
2098 if ((buflen -= 12) < 0) 2180 if ((buflen -= 12) < 0)
2099 goto out_resource; 2181 goto out_resource;
@@ -2401,6 +2483,12 @@ out_acl:
2401 get_parent_attributes(exp, &stat); 2483 get_parent_attributes(exp, &stat);
2402 WRITE64(stat.ino); 2484 WRITE64(stat.ino);
2403 } 2485 }
2486 if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
2487 status = nfsd4_encode_security_label(rqstp, context,
2488 contextlen, &p, &buflen);
2489 if (status)
2490 goto out;
2491 }
2404 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { 2492 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
2405 WRITE32(3); 2493 WRITE32(3);
2406 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0); 2494 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0);
@@ -2413,6 +2501,8 @@ out_acl:
2413 status = nfs_ok; 2501 status = nfs_ok;
2414 2502
2415out: 2503out:
2504 if (context)
2505 security_release_secctx(context, contextlen);
2416 kfree(acl); 2506 kfree(acl);
2417 if (fhp == &tempfh) 2507 if (fhp == &tempfh)
2418 fh_put(&tempfh); 2508 fh_put(&tempfh);
@@ -3177,16 +3267,18 @@ nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
3177{ 3267{
3178 __be32 *p; 3268 __be32 *p;
3179 3269
3180 RESERVE_SPACE(12); 3270 RESERVE_SPACE(16);
3181 if (nfserr) { 3271 if (nfserr) {
3182 WRITE32(2); 3272 WRITE32(3);
3273 WRITE32(0);
3183 WRITE32(0); 3274 WRITE32(0);
3184 WRITE32(0); 3275 WRITE32(0);
3185 } 3276 }
3186 else { 3277 else {
3187 WRITE32(2); 3278 WRITE32(3);
3188 WRITE32(setattr->sa_bmval[0]); 3279 WRITE32(setattr->sa_bmval[0]);
3189 WRITE32(setattr->sa_bmval[1]); 3280 WRITE32(setattr->sa_bmval[1]);
3281 WRITE32(setattr->sa_bmval[2]);
3190 } 3282 }
3191 ADJUST_ARGS(); 3283 ADJUST_ARGS();
3192 return nfserr; 3284 return nfserr;
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 15e7e1d531f0..2bbd94e51efc 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -328,6 +328,13 @@ void nfsd_lockd_shutdown(void);
328#define NFSD4_1_SUPPORTED_ATTRS_WORD2 \ 328#define NFSD4_1_SUPPORTED_ATTRS_WORD2 \
329 (NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT) 329 (NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT)
330 330
331#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
332#define NFSD4_2_SUPPORTED_ATTRS_WORD2 \
333 (NFSD4_1_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SECURITY_LABEL)
334#else
335#define NFSD4_2_SUPPORTED_ATTRS_WORD2 0
336#endif
337
331static inline u32 nfsd_suppattrs0(u32 minorversion) 338static inline u32 nfsd_suppattrs0(u32 minorversion)
332{ 339{
333 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0 340 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0
@@ -342,8 +349,11 @@ static inline u32 nfsd_suppattrs1(u32 minorversion)
342 349
343static inline u32 nfsd_suppattrs2(u32 minorversion) 350static inline u32 nfsd_suppattrs2(u32 minorversion)
344{ 351{
345 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD2 352 switch (minorversion) {
346 : NFSD4_SUPPORTED_ATTRS_WORD2; 353 default: return NFSD4_2_SUPPORTED_ATTRS_WORD2;
354 case 1: return NFSD4_1_SUPPORTED_ATTRS_WORD2;
355 case 0: return NFSD4_SUPPORTED_ATTRS_WORD2;
356 }
347} 357}
348 358
349/* These will return ERR_INVAL if specified in GETATTR or READDIR. */ 359/* These will return ERR_INVAL if specified in GETATTR or READDIR. */
@@ -356,7 +366,11 @@ static inline u32 nfsd_suppattrs2(u32 minorversion)
356#define NFSD_WRITEABLE_ATTRS_WORD1 \ 366#define NFSD_WRITEABLE_ATTRS_WORD1 \
357 (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \ 367 (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \
358 | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) 368 | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
369#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
370#define NFSD_WRITEABLE_ATTRS_WORD2 FATTR4_WORD2_SECURITY_LABEL
371#else
359#define NFSD_WRITEABLE_ATTRS_WORD2 0 372#define NFSD_WRITEABLE_ATTRS_WORD2 0
373#endif
360 374
361#define NFSD_SUPPATTR_EXCLCREAT_WORD0 \ 375#define NFSD_SUPPATTR_EXCLCREAT_WORD0 \
362 NFSD_WRITEABLE_ATTRS_WORD0 376 NFSD_WRITEABLE_ATTRS_WORD0
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 84ce601d8063..1e757fa45c40 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -28,6 +28,7 @@
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <linux/exportfs.h> 29#include <linux/exportfs.h>
30#include <linux/writeback.h> 30#include <linux/writeback.h>
31#include <linux/security.h>
31 32
32#ifdef CONFIG_NFSD_V3 33#ifdef CONFIG_NFSD_V3
33#include "xdr3.h" 34#include "xdr3.h"
@@ -621,6 +622,33 @@ int nfsd4_is_junction(struct dentry *dentry)
621 return 0; 622 return 0;
622 return 1; 623 return 1;
623} 624}
625#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
626__be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
627 struct xdr_netobj *label)
628{
629 __be32 error;
630 int host_error;
631 struct dentry *dentry;
632
633 error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, NFSD_MAY_SATTR);
634 if (error)
635 return error;
636
637 dentry = fhp->fh_dentry;
638
639 mutex_lock(&dentry->d_inode->i_mutex);
640 host_error = security_inode_setsecctx(dentry, label->data, label->len);
641 mutex_unlock(&dentry->d_inode->i_mutex);
642 return nfserrno(host_error);
643}
644#else
645__be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
646 struct xdr_netobj *label)
647{
648 return nfserr_notsupp;
649}
650#endif
651
624#endif /* defined(CONFIG_NFSD_V4) */ 652#endif /* defined(CONFIG_NFSD_V4) */
625 653
626#ifdef CONFIG_NFSD_V3 654#ifdef CONFIG_NFSD_V3
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index 8d2b40d71669..a4be2e389670 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -55,6 +55,8 @@ int nfsd_mountpoint(struct dentry *, struct svc_export *);
55__be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *, 55__be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
56 struct nfs4_acl *); 56 struct nfs4_acl *);
57int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **); 57int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
58__be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
59 struct xdr_netobj *);
58#endif /* CONFIG_NFSD_V4 */ 60#endif /* CONFIG_NFSD_V4 */
59__be32 nfsd_create(struct svc_rqst *, struct svc_fh *, 61__be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
60 char *name, int len, struct iattr *attrs, 62 char *name, int len, struct iattr *attrs,
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 3b271d2092b6..b3ed6446ed8e 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -40,6 +40,7 @@
40#include "state.h" 40#include "state.h"
41#include "nfsd.h" 41#include "nfsd.h"
42 42
43#define NFSD4_MAX_SEC_LABEL_LEN 2048
43#define NFSD4_MAX_TAGLEN 128 44#define NFSD4_MAX_TAGLEN 128
44#define XDR_LEN(n) (((n) + 3) & ~3) 45#define XDR_LEN(n) (((n) + 3) & ~3)
45 46
@@ -118,6 +119,7 @@ struct nfsd4_create {
118 struct iattr cr_iattr; /* request */ 119 struct iattr cr_iattr; /* request */
119 struct nfsd4_change_info cr_cinfo; /* response */ 120 struct nfsd4_change_info cr_cinfo; /* response */
120 struct nfs4_acl *cr_acl; 121 struct nfs4_acl *cr_acl;
122 struct xdr_netobj cr_label;
121}; 123};
122#define cr_linklen u.link.namelen 124#define cr_linklen u.link.namelen
123#define cr_linkname u.link.name 125#define cr_linkname u.link.name
@@ -246,6 +248,7 @@ struct nfsd4_open {
246 struct nfs4_file *op_file; /* used during processing */ 248 struct nfs4_file *op_file; /* used during processing */
247 struct nfs4_ol_stateid *op_stp; /* used during processing */ 249 struct nfs4_ol_stateid *op_stp; /* used during processing */
248 struct nfs4_acl *op_acl; 250 struct nfs4_acl *op_acl;
251 struct xdr_netobj op_label;
249}; 252};
250#define op_iattr iattr 253#define op_iattr iattr
251 254
@@ -330,6 +333,7 @@ struct nfsd4_setattr {
330 u32 sa_bmval[3]; /* request */ 333 u32 sa_bmval[3]; /* request */
331 struct iattr sa_iattr; /* request */ 334 struct iattr sa_iattr; /* request */
332 struct nfs4_acl *sa_acl; 335 struct nfs4_acl *sa_acl;
336 struct xdr_netobj sa_label;
333}; 337};
334 338
335struct nfsd4_setclientid { 339struct nfsd4_setclientid {