aboutsummaryrefslogtreecommitdiffstats
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
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>
-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)