Skip to content

Commit d6a97d3

Browse files
neilbrownchucklever
authored andcommitted
NFSD: add security label to struct nfsd_attrs
nfsd_setattr() now sets a security label if provided, and nfsv4 provides it in the 'open' and 'create' paths and the 'setattr' path. If setting the label failed (including because the kernel doesn't support labels), an error field in 'struct nfsd_attrs' is set, and the caller can respond. The open/create callers clear FATTR4_WORD2_SECURITY_LABEL in the returned attr set in this case. The setattr caller returns the error. Signed-off-by: NeilBrown <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 93adc1e commit d6a97d3

File tree

3 files changed

+15
-68
lines changed

3 files changed

+15
-68
lines changed

fs/nfsd/nfs4proc.c

Lines changed: 9 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -64,36 +64,6 @@ MODULE_PARM_DESC(nfsd4_ssc_umount_timeout,
6464
"idle msecs before unmount export from source server");
6565
#endif
6666

67-
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
68-
#include <linux/security.h>
69-
70-
static inline void
71-
nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
72-
{
73-
struct inode *inode = d_inode(resfh->fh_dentry);
74-
int status;
75-
76-
inode_lock(inode);
77-
status = security_inode_setsecctx(resfh->fh_dentry,
78-
label->data, label->len);
79-
inode_unlock(inode);
80-
81-
if (status)
82-
/*
83-
* XXX: We should really fail the whole open, but we may
84-
* already have created a new file, so it may be too
85-
* late. For now this seems the least of evils:
86-
*/
87-
bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
88-
89-
return;
90-
}
91-
#else
92-
static inline void
93-
nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
94-
{ }
95-
#endif
96-
9767
#define NFSDDBG_FACILITY NFSDDBG_PROC
9868

9969
static u32 nfsd_attrmask[] = {
@@ -288,6 +258,7 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
288258
struct iattr *iap = &open->op_iattr;
289259
struct nfsd_attrs attrs = {
290260
.na_iattr = iap,
261+
.na_seclabel = &open->op_label,
291262
};
292263
struct dentry *parent, *child;
293264
__u32 v_mtime, v_atime;
@@ -409,6 +380,8 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
409380
set_attr:
410381
status = nfsd_create_setattr(rqstp, fhp, resfhp, &attrs);
411382

383+
if (attrs.na_labelerr)
384+
open->op_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
412385
out:
413386
fh_unlock(fhp);
414387
if (child && !IS_ERR(child))
@@ -450,9 +423,6 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
450423
status = nfsd4_create_file(rqstp, current_fh, *resfh, open);
451424
current->fs->umask = 0;
452425

453-
if (!status && open->op_label.len)
454-
nfsd4_security_inode_setsecctx(*resfh, &open->op_label, open->op_bmval);
455-
456426
/*
457427
* Following rfc 3530 14.2.16, and rfc 5661 18.16.4
458428
* use the returned bitmask to indicate which attributes
@@ -792,6 +762,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
792762
struct nfsd4_create *create = &u->create;
793763
struct nfsd_attrs attrs = {
794764
.na_iattr = &create->cr_iattr,
765+
.na_seclabel = &create->cr_label,
795766
};
796767
struct svc_fh resfh;
797768
__be32 status;
@@ -864,8 +835,8 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
864835
if (status)
865836
goto out;
866837

867-
if (create->cr_label.len)
868-
nfsd4_security_inode_setsecctx(&resfh, &create->cr_label, create->cr_bmval);
838+
if (attrs.na_labelerr)
839+
create->cr_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
869840

870841
if (create->cr_acl != NULL)
871842
do_set_nfs4_acl(rqstp, &resfh, create->cr_acl,
@@ -1150,6 +1121,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
11501121
struct nfsd4_setattr *setattr = &u->setattr;
11511122
struct nfsd_attrs attrs = {
11521123
.na_iattr = &setattr->sa_iattr,
1124+
.na_seclabel = &setattr->sa_label,
11531125
};
11541126
__be32 status = nfs_ok;
11551127
int err;
@@ -1178,13 +1150,10 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
11781150
setattr->sa_acl);
11791151
if (status)
11801152
goto out;
1181-
if (setattr->sa_label.len)
1182-
status = nfsd4_set_nfs4_label(rqstp, &cstate->current_fh,
1183-
&setattr->sa_label);
1184-
if (status)
1185-
goto out;
11861153
status = nfsd_setattr(rqstp, &cstate->current_fh, &attrs,
11871154
0, (time64_t)0);
1155+
if (!status)
1156+
status = nfserrno(attrs.na_labelerr);
11881157
out:
11891158
fh_drop_write(&cstate->current_fh);
11901159
return status;

fs/nfsd/vfs.c

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,9 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
458458
host_err = notify_change(&init_user_ns, dentry, iap, NULL);
459459

460460
out_unlock:
461+
if (attr->na_seclabel && attr->na_seclabel->len)
462+
attr->na_labelerr = security_inode_setsecctx(dentry,
463+
attr->na_seclabel->data, attr->na_seclabel->len);
461464
fh_unlock(fhp);
462465
if (size_change)
463466
put_write_access(inode);
@@ -496,32 +499,6 @@ int nfsd4_is_junction(struct dentry *dentry)
496499
return 0;
497500
return 1;
498501
}
499-
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
500-
__be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
501-
struct xdr_netobj *label)
502-
{
503-
__be32 error;
504-
int host_error;
505-
struct dentry *dentry;
506-
507-
error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, NFSD_MAY_SATTR);
508-
if (error)
509-
return error;
510-
511-
dentry = fhp->fh_dentry;
512-
513-
inode_lock(d_inode(dentry));
514-
host_error = security_inode_setsecctx(dentry, label->data, label->len);
515-
inode_unlock(d_inode(dentry));
516-
return nfserrno(host_error);
517-
}
518-
#else
519-
__be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
520-
struct xdr_netobj *label)
521-
{
522-
return nfserr_notsupp;
523-
}
524-
#endif
525502

526503
static struct nfsd4_compound_state *nfsd4_get_cstate(struct svc_rqst *rqstp)
527504
{

fs/nfsd/vfs.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ typedef int (*nfsd_filldir_t)(void *, const char *, int, loff_t, u64, unsigned);
4444
/* nfsd/vfs.c */
4545
struct nfsd_attrs {
4646
struct iattr *na_iattr; /* input */
47+
struct xdr_netobj *na_seclabel; /* input */
48+
49+
int na_labelerr; /* output */
4750
};
4851

4952
int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
@@ -57,8 +60,6 @@ __be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *,
5760
struct nfsd_attrs *, int, time64_t);
5861
int nfsd_mountpoint(struct dentry *, struct svc_export *);
5962
#ifdef CONFIG_NFSD_V4
60-
__be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
61-
struct xdr_netobj *);
6263
__be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *,
6364
struct file *, loff_t, loff_t, int);
6465
__be32 nfsd4_clone_file_range(struct svc_rqst *rqstp,

0 commit comments

Comments
 (0)