aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4xdr.c
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/nfs4xdr.c
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/nfs4xdr.c')
-rw-r--r--fs/nfsd/nfs4xdr.c108
1 files changed, 100 insertions, 8 deletions
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;