]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/nfsd/nfs4proc.c
Merge branch 'for-3.11' of git://linux-nfs.org/~bfields/linux
[karo-tx-linux.git] / fs / nfsd / nfs4proc.c
index 27d74a2945151cfbdf76e41cd381b90a0efe4d09..a7cee864e7b245e5ead7c8f04b509a5cfe9c59a8 100644 (file)
 #include "current_stateid.h"
 #include "netns.h"
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+#include <linux/security.h>
+
+static inline void
+nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
+{
+       struct inode *inode = resfh->fh_dentry->d_inode;
+       int status;
+
+       mutex_lock(&inode->i_mutex);
+       status = security_inode_setsecctx(resfh->fh_dentry,
+               label->data, label->len);
+       mutex_unlock(&inode->i_mutex);
+
+       if (status)
+               /*
+                * XXX: We should really fail the whole open, but we may
+                * already have created a new file, so it may be too
+                * late.  For now this seems the least of evils:
+                */
+               bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
+
+       return;
+}
+#else
+static inline void
+nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
+{ }
+#endif
+
 #define NFSDDBG_FACILITY               NFSDDBG_PROC
 
 static u32 nfsd_attrmask[] = {
@@ -239,6 +269,9 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
                                        (u32 *)open->op_verf.data,
                                        &open->op_truncate, &open->op_created);
 
+               if (!status && open->op_label.len)
+                       nfsd4_security_inode_setsecctx(resfh, &open->op_label, open->op_bmval);
+
                /*
                 * Following rfc 3530 14.2.16, use the returned bitmask
                 * to indicate which attributes we used to store the
@@ -263,7 +296,8 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
 
        nfsd4_set_open_owner_reply_cache(cstate, open, resfh);
        accmode = NFSD_MAY_NOP;
-       if (open->op_created)
+       if (open->op_created ||
+                       open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
                accmode |= NFSD_MAY_OWNER_OVERRIDE;
        status = do_open_permission(rqstp, resfh, open, accmode);
        set_change_info(&open->op_cinfo, current_fh);
@@ -637,6 +671,9 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        if (status)
                goto out;
 
+       if (create->cr_label.len)
+               nfsd4_security_inode_setsecctx(&resfh, &create->cr_label, create->cr_bmval);
+
        if (create->cr_acl != NULL)
                do_set_nfs4_acl(rqstp, &resfh, create->cr_acl,
                                create->cr_bmval);
@@ -916,6 +953,11 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                                            setattr->sa_acl);
        if (status)
                goto out;
+       if (setattr->sa_label.len)
+               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: