Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

NFSD: Add support for POSIX draft ACLs for file creation

NFSv4.2 clients can specify POSIX draft ACLs when creating file
objects via OPEN(CREATE) and CREATE operations. The previous patch
added POSIX ACL support to the NFSv4 SETATTR operation for modifying
existing objects, but file creation follows different code paths
that also require POSIX ACL handling.

This patch integrates POSIX ACL support into nfsd4_create() and
nfsd4_create_file(). Ownership of the decoded ACL pointers
(op_dpacl, op_pacl, cr_dpacl, cr_pacl) transfers to the nfsd_attrs
structure immediately, with the original fields cleared to NULL.
This transfer ensures nfsd_attrs_free() releases the ACLs upon
completion while preventing double-free on error paths.

Mutual exclusion between NFSv4 ACLs and POSIX ACLs is enforced:
setting both op_acl and op_dpacl/op_pacl simultaneously returns
nfserr_inval. Errors during ACL application clear the corresponding
bits in the result bitmask (fattr->bmval), signaling partial
completion to the client.

Signed-off-by: Rick Macklem <rmacklem@uoguelph.ca>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

authored by

Rick Macklem and committed by
Chuck Lever
d2ca5060 5fc51dfc

+53 -9
+53 -9
fs/nfsd/nfs4proc.c
··· 91 91 return nfserr_attrnotsupp; 92 92 if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry))) 93 93 return nfserr_attrnotsupp; 94 + if ((bmval[2] & (FATTR4_WORD2_POSIX_DEFAULT_ACL | 95 + FATTR4_WORD2_POSIX_ACCESS_ACL)) && 96 + !IS_POSIXACL(d_inode(dentry))) 97 + return nfserr_attrnotsupp; 94 98 if ((bmval[2] & FATTR4_WORD2_SECURITY_LABEL) && 95 99 !(exp->ex_flags & NFSEXP_SECURITY_LABEL)) 96 100 return nfserr_attrnotsupp; ··· 269 265 if (host_err) 270 266 return nfserrno(host_err); 271 267 272 - if (is_create_with_attrs(open)) 273 - nfsd4_acl_to_attr(NF4REG, open->op_acl, &attrs); 268 + if (open->op_acl) { 269 + if (open->op_dpacl || open->op_pacl) { 270 + status = nfserr_inval; 271 + goto out_write; 272 + } 273 + if (is_create_with_attrs(open)) 274 + nfsd4_acl_to_attr(NF4REG, open->op_acl, &attrs); 275 + } else if (is_create_with_attrs(open)) { 276 + /* The dpacl and pacl will get released by nfsd_attrs_free(). */ 277 + attrs.na_dpacl = open->op_dpacl; 278 + attrs.na_pacl = open->op_pacl; 279 + open->op_dpacl = NULL; 280 + open->op_pacl = NULL; 281 + } 274 282 275 283 child = start_creating(&nop_mnt_idmap, parent, 276 284 &QSTR_LEN(open->op_fname, open->op_fnamelen)); ··· 395 379 open->op_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL; 396 380 if (attrs.na_paclerr || attrs.na_dpaclerr) 397 381 open->op_bmval[0] &= ~FATTR4_WORD0_ACL; 382 + if (attrs.na_dpaclerr) 383 + open->op_bmval[2] &= ~FATTR4_WORD2_POSIX_DEFAULT_ACL; 384 + if (attrs.na_paclerr) 385 + open->op_bmval[2] &= ~FATTR4_WORD2_POSIX_ACCESS_ACL; 398 386 out: 399 387 end_creating(child); 400 388 nfsd_attrs_free(&attrs); ··· 566 546 open->op_rqstp = rqstp; 567 547 568 548 /* This check required by spec. */ 569 - if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL) 570 - return nfserr_inval; 549 + if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL) { 550 + status = nfserr_inval; 551 + goto out_err; 552 + } 571 553 572 554 open->op_created = false; 573 555 /* ··· 578 556 */ 579 557 if (nfsd4_has_session(cstate) && 580 558 !test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE, &cstate->clp->cl_flags) && 581 - open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) 582 - return nfserr_grace; 559 + open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) { 560 + status = nfserr_grace; 561 + goto out_err; 562 + } 583 563 584 564 if (nfsd4_has_session(cstate)) 585 565 copy_clientid(&open->op_clientid, cstate->session); ··· 668 644 } 669 645 nfsd4_cleanup_open_state(cstate, open); 670 646 nfsd4_bump_seqid(cstate, status); 647 + out_err: 648 + posix_acl_release(open->op_dpacl); 649 + posix_acl_release(open->op_pacl); 671 650 return status; 672 651 } 673 652 ··· 811 784 struct nfsd_attrs attrs = { 812 785 .na_iattr = &create->cr_iattr, 813 786 .na_seclabel = &create->cr_label, 787 + .na_dpacl = create->cr_dpacl, 788 + .na_pacl = create->cr_pacl, 814 789 }; 815 790 struct svc_fh resfh; 816 791 __be32 status; 817 792 dev_t rdev; 818 793 794 + create->cr_dpacl = NULL; 795 + create->cr_pacl = NULL; 796 + 819 797 fh_init(&resfh, NFS4_FHSIZE); 820 798 821 799 status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, NFSD_MAY_NOP); 822 800 if (status) 823 - return status; 801 + goto out_aftermask; 824 802 825 803 status = check_attr_support(cstate, create->cr_bmval, nfsd_attrmask); 826 804 if (status) 827 - return status; 805 + goto out_aftermask; 828 806 829 - status = nfsd4_acl_to_attr(create->cr_type, create->cr_acl, &attrs); 807 + if (create->cr_acl) { 808 + if (create->cr_dpacl || create->cr_pacl) { 809 + status = nfserr_inval; 810 + goto out_aftermask; 811 + } 812 + status = nfsd4_acl_to_attr(create->cr_type, create->cr_acl, 813 + &attrs); 814 + } 830 815 current->fs->umask = create->cr_umask; 831 816 switch (create->cr_type) { 832 817 case NF4LNK: ··· 899 860 create->cr_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL; 900 861 if (attrs.na_paclerr || attrs.na_dpaclerr) 901 862 create->cr_bmval[0] &= ~FATTR4_WORD0_ACL; 863 + if (attrs.na_dpaclerr) 864 + create->cr_bmval[2] &= ~FATTR4_WORD2_POSIX_DEFAULT_ACL; 865 + if (attrs.na_paclerr) 866 + create->cr_bmval[2] &= ~FATTR4_WORD2_POSIX_ACCESS_ACL; 902 867 set_change_info(&create->cr_cinfo, &cstate->current_fh); 903 868 fh_dup2(&cstate->current_fh, &resfh); 904 869 out: 905 870 fh_put(&resfh); 906 871 out_umask: 907 872 current->fs->umask = 0; 873 + out_aftermask: 908 874 nfsd_attrs_free(&attrs); 909 875 return status; 910 876 }