Skip to content

Commit c0cbe70

Browse files
neilbrownchucklever
authored andcommitted
NFSD: add posix ACLs to struct nfsd_attrs
pacl and dpacl pointers are added to struct nfsd_attrs, which requires that we have an nfsd_attrs_free() function to free them. Those nfsv4 functions that can set ACLs now set up these pointers based on the passed in NFSv4 ACL. nfsd_setattr() sets the acls as appropriate. Errors are handled as with security labels. Signed-off-by: NeilBrown <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent d6a97d3 commit c0cbe70

File tree

5 files changed

+47
-71
lines changed

5 files changed

+47
-71
lines changed

fs/nfsd/acl.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,16 @@
3838
struct nfs4_acl;
3939
struct svc_fh;
4040
struct svc_rqst;
41+
struct nfsd_attrs;
42+
enum nfs_ftype4;
4143

4244
int nfs4_acl_bytes(int entries);
4345
int nfs4_acl_get_whotype(char *, u32);
4446
__be32 nfs4_acl_write_who(struct xdr_stream *xdr, int who);
4547

4648
int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
4749
struct nfs4_acl **acl);
48-
__be32 nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
49-
struct nfs4_acl *acl);
50+
__be32 nfsd4_acl_to_attr(enum nfs_ftype4 type, struct nfs4_acl *acl,
51+
struct nfsd_attrs *attr);
5052

5153
#endif /* LINUX_NFS4_ACL_H */

fs/nfsd/nfs4acl.c

Lines changed: 7 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -751,58 +751,26 @@ static int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl,
751751
return ret;
752752
}
753753

754-
__be32
755-
nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
756-
struct nfs4_acl *acl)
754+
__be32 nfsd4_acl_to_attr(enum nfs_ftype4 type, struct nfs4_acl *acl,
755+
struct nfsd_attrs *attr)
757756
{
758-
__be32 error;
759757
int host_error;
760-
struct dentry *dentry;
761-
struct inode *inode;
762-
struct posix_acl *pacl = NULL, *dpacl = NULL;
763758
unsigned int flags = 0;
764759

765-
/* Get inode */
766-
error = fh_verify(rqstp, fhp, 0, NFSD_MAY_SATTR);
767-
if (error)
768-
return error;
769-
770-
dentry = fhp->fh_dentry;
771-
inode = d_inode(dentry);
760+
if (!acl)
761+
return nfs_ok;
772762

773-
if (S_ISDIR(inode->i_mode))
763+
if (type == NF4DIR)
774764
flags = NFS4_ACL_DIR;
775765

776-
host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
766+
host_error = nfs4_acl_nfsv4_to_posix(acl, &attr->na_pacl,
767+
&attr->na_dpacl, flags);
777768
if (host_error == -EINVAL)
778769
return nfserr_attrnotsupp;
779-
if (host_error < 0)
780-
goto out_nfserr;
781-
782-
fh_lock(fhp);
783-
784-
host_error = set_posix_acl(&init_user_ns, inode, ACL_TYPE_ACCESS, pacl);
785-
if (host_error < 0)
786-
goto out_drop_lock;
787-
788-
if (S_ISDIR(inode->i_mode)) {
789-
host_error = set_posix_acl(&init_user_ns, inode,
790-
ACL_TYPE_DEFAULT, dpacl);
791-
}
792-
793-
out_drop_lock:
794-
fh_unlock(fhp);
795-
796-
posix_acl_release(pacl);
797-
posix_acl_release(dpacl);
798-
out_nfserr:
799-
if (host_error == -EOPNOTSUPP)
800-
return nfserr_attrnotsupp;
801770
else
802771
return nfserrno(host_error);
803772
}
804773

805-
806774
static short
807775
ace2type(struct nfs4_ace *ace)
808776
{

fs/nfsd/nfs4proc.c

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -128,26 +128,6 @@ is_create_with_attrs(struct nfsd4_open *open)
128128
|| open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1);
129129
}
130130

131-
/*
132-
* if error occurs when setting the acl, just clear the acl bit
133-
* in the returned attr bitmap.
134-
*/
135-
static void
136-
do_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
137-
struct nfs4_acl *acl, u32 *bmval)
138-
{
139-
__be32 status;
140-
141-
status = nfsd4_set_nfs4_acl(rqstp, fhp, acl);
142-
if (status)
143-
/*
144-
* We should probably fail the whole open at this point,
145-
* but we've already created the file, so it's too late;
146-
* So this seems the least of evils:
147-
*/
148-
bmval[0] &= ~FATTR4_WORD0_ACL;
149-
}
150-
151131
static inline void
152132
fh_dup2(struct svc_fh *dst, struct svc_fh *src)
153133
{
@@ -281,6 +261,9 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
281261
if (host_err)
282262
return nfserrno(host_err);
283263

264+
if (is_create_with_attrs(open))
265+
nfsd4_acl_to_attr(NF4REG, open->op_acl, &attrs);
266+
284267
fh_lock_nested(fhp, I_MUTEX_PARENT);
285268

286269
child = lookup_one_len(open->op_fname, parent, open->op_fnamelen);
@@ -382,8 +365,11 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
382365

383366
if (attrs.na_labelerr)
384367
open->op_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
368+
if (attrs.na_aclerr)
369+
open->op_bmval[0] &= ~FATTR4_WORD0_ACL;
385370
out:
386371
fh_unlock(fhp);
372+
nfsd_attrs_free(&attrs);
387373
if (child && !IS_ERR(child))
388374
dput(child);
389375
fh_drop_write(fhp);
@@ -446,9 +432,6 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
446432
if (status)
447433
goto out;
448434

449-
if (is_create_with_attrs(open) && open->op_acl != NULL)
450-
do_set_nfs4_acl(rqstp, *resfh, open->op_acl, open->op_bmval);
451-
452435
nfsd4_set_open_owner_reply_cache(cstate, open, *resfh);
453436
accmode = NFSD_MAY_NOP;
454437
if (open->op_created ||
@@ -779,6 +762,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
779762
if (status)
780763
return status;
781764

765+
status = nfsd4_acl_to_attr(create->cr_type, create->cr_acl, &attrs);
782766
current->fs->umask = create->cr_umask;
783767
switch (create->cr_type) {
784768
case NF4LNK:
@@ -837,10 +821,8 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
837821

838822
if (attrs.na_labelerr)
839823
create->cr_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
840-
841-
if (create->cr_acl != NULL)
842-
do_set_nfs4_acl(rqstp, &resfh, create->cr_acl,
843-
create->cr_bmval);
824+
if (attrs.na_aclerr)
825+
create->cr_bmval[0] &= ~FATTR4_WORD0_ACL;
844826

845827
fh_unlock(&cstate->current_fh);
846828
set_change_info(&create->cr_cinfo, &cstate->current_fh);
@@ -849,6 +831,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
849831
fh_put(&resfh);
850832
out_umask:
851833
current->fs->umask = 0;
834+
nfsd_attrs_free(&attrs);
852835
return status;
853836
}
854837

@@ -1123,6 +1106,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
11231106
.na_iattr = &setattr->sa_iattr,
11241107
.na_seclabel = &setattr->sa_label,
11251108
};
1109+
struct inode *inode;
11261110
__be32 status = nfs_ok;
11271111
int err;
11281112

@@ -1145,16 +1129,18 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
11451129
if (status)
11461130
goto out;
11471131

1148-
if (setattr->sa_acl != NULL)
1149-
status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
1150-
setattr->sa_acl);
1132+
inode = cstate->current_fh.fh_dentry->d_inode;
1133+
status = nfsd4_acl_to_attr(S_ISDIR(inode->i_mode) ? NF4DIR : NF4REG,
1134+
setattr->sa_acl, &attrs);
1135+
11511136
if (status)
11521137
goto out;
11531138
status = nfsd_setattr(rqstp, &cstate->current_fh, &attrs,
11541139
0, (time64_t)0);
11551140
if (!status)
11561141
status = nfserrno(attrs.na_labelerr);
11571142
out:
1143+
nfsd_attrs_free(&attrs);
11581144
fh_drop_write(&cstate->current_fh);
11591145
return status;
11601146
}

fs/nfsd/vfs.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,15 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
461461
if (attr->na_seclabel && attr->na_seclabel->len)
462462
attr->na_labelerr = security_inode_setsecctx(dentry,
463463
attr->na_seclabel->data, attr->na_seclabel->len);
464+
if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && attr->na_pacl)
465+
attr->na_aclerr = set_posix_acl(&init_user_ns,
466+
inode, ACL_TYPE_ACCESS,
467+
attr->na_pacl);
468+
if (IS_ENABLED(CONFIG_FS_POSIX_ACL) &&
469+
!attr->na_aclerr && attr->na_dpacl && S_ISDIR(inode->i_mode))
470+
attr->na_aclerr = set_posix_acl(&init_user_ns,
471+
inode, ACL_TYPE_DEFAULT,
472+
attr->na_dpacl);
464473
fh_unlock(fhp);
465474
if (size_change)
466475
put_write_access(inode);

fs/nfsd/vfs.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#ifndef LINUX_NFSD_VFS_H
77
#define LINUX_NFSD_VFS_H
88

9+
#include <linux/fs.h>
10+
#include <linux/posix_acl.h>
911
#include "nfsfh.h"
1012
#include "nfsd.h"
1113

@@ -45,10 +47,19 @@ typedef int (*nfsd_filldir_t)(void *, const char *, int, loff_t, u64, unsigned);
4547
struct nfsd_attrs {
4648
struct iattr *na_iattr; /* input */
4749
struct xdr_netobj *na_seclabel; /* input */
50+
struct posix_acl *na_pacl; /* input */
51+
struct posix_acl *na_dpacl; /* input */
4852

4953
int na_labelerr; /* output */
54+
int na_aclerr; /* output */
5055
};
5156

57+
static inline void nfsd_attrs_free(struct nfsd_attrs *attrs)
58+
{
59+
posix_acl_release(attrs->na_pacl);
60+
posix_acl_release(attrs->na_dpacl);
61+
}
62+
5263
int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
5364
struct svc_export **expp);
5465
__be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *,

0 commit comments

Comments
 (0)