aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4acl.c133
1 files changed, 38 insertions, 95 deletions
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 785418b0b799..6c52658e9a26 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -129,9 +129,7 @@ struct ace_container {
129 129
130static short ace2type(struct nfs4_ace *); 130static short ace2type(struct nfs4_ace *);
131static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int); 131static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
132static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int);
133int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); 132int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
134static int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
135 133
136struct nfs4_acl * 134struct nfs4_acl *
137nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, 135nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
@@ -344,46 +342,6 @@ sort_pacl(struct posix_acl *pacl)
344 return; 342 return;
345} 343}
346 344
347int
348nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
349 struct posix_acl **dpacl, unsigned int flags)
350{
351 struct nfs4_acl *dacl;
352 int error = -ENOMEM;
353
354 *pacl = NULL;
355 *dpacl = NULL;
356
357 dacl = nfs4_acl_new();
358 if (dacl == NULL)
359 goto out;
360
361 error = nfs4_acl_split(acl, dacl);
362 if (error)
363 goto out_acl;
364
365 *pacl = _nfsv4_to_posix_one(acl, flags);
366 if (IS_ERR(*pacl)) {
367 error = PTR_ERR(*pacl);
368 *pacl = NULL;
369 goto out_acl;
370 }
371
372 *dpacl = _nfsv4_to_posix_one(dacl, flags);
373 if (IS_ERR(*dpacl)) {
374 error = PTR_ERR(*dpacl);
375 *dpacl = NULL;
376 }
377out_acl:
378 if (error) {
379 posix_acl_release(*pacl);
380 *pacl = NULL;
381 }
382 nfs4_acl_free(dacl);
383out:
384 return error;
385}
386
387/* 345/*
388 * While processing the NFSv4 ACE, this maintains bitmasks representing 346 * While processing the NFSv4 ACE, this maintains bitmasks representing
389 * which permission bits have been allowed and which denied to a given 347 * which permission bits have been allowed and which denied to a given
@@ -668,76 +626,61 @@ static void process_one_v4_ace(struct posix_acl_state *state,
668 } 626 }
669} 627}
670 628
671static struct posix_acl * 629int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
672_nfsv4_to_posix_one(struct nfs4_acl *n4acl, unsigned int flags) 630 struct posix_acl **dpacl, unsigned int flags)
673{ 631{
674 struct posix_acl_state state; 632 struct posix_acl_state effective_acl_state, default_acl_state;
675 struct posix_acl *pacl;
676 struct nfs4_ace *ace; 633 struct nfs4_ace *ace;
677 int ret; 634 int ret;
678 635
679 ret = init_state(&state, n4acl->naces); 636 ret = init_state(&effective_acl_state, acl->naces);
680 if (ret) 637 if (ret)
681 return ERR_PTR(ret); 638 return ret;
682 639 ret = init_state(&default_acl_state, acl->naces);
683 list_for_each_entry(ace, &n4acl->ace_head, l_ace) 640 if (ret)
684 process_one_v4_ace(&state, ace); 641 goto out_estate;
685 642 ret = -EINVAL;
686 pacl = posix_state_to_acl(&state, flags); 643 list_for_each_entry(ace, &acl->ace_head, l_ace) {
687
688 free_state(&state);
689
690 if (!IS_ERR(pacl))
691 sort_pacl(pacl);
692 return pacl;
693}
694
695static int
696nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
697{
698 struct list_head *h, *n;
699 struct nfs4_ace *ace;
700 int error = 0;
701
702 list_for_each_safe(h, n, &acl->ace_head) {
703 ace = list_entry(h, struct nfs4_ace, l_ace);
704
705 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE && 644 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
706 ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE) 645 ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
707 return -EINVAL; 646 goto out_dstate;
708
709 if (ace->flag & ~NFS4_SUPPORTED_FLAGS) 647 if (ace->flag & ~NFS4_SUPPORTED_FLAGS)
710 return -EINVAL; 648 goto out_dstate;
711
712 if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) { 649 if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) {
713 /* Leave this ace in the effective acl: */ 650 process_one_v4_ace(&effective_acl_state, ace);
714 continue; 651 continue;
715 } 652 }
653 if (!(flags & NFS4_ACL_DIR))
654 goto out_dstate;
716 /* 655 /*
717 * Note that when only one of FILE_INHERIT or DIRECTORY_INHERIT 656 * Note that when only one of FILE_INHERIT or DIRECTORY_INHERIT
718 * is set, we're effectively turning on the other. That's OK, 657 * is set, we're effectively turning on the other. That's OK,
719 * according to rfc 3530. 658 * according to rfc 3530.
720 */ 659 */
721 if (ace->flag & NFS4_ACE_INHERIT_ONLY_ACE) { 660 process_one_v4_ace(&default_acl_state, ace);
722 /* Add this ace to the default acl and remove it 661
723 * from the effective acl: */ 662 if (!(ace->flag & NFS4_ACE_INHERIT_ONLY_ACE))
724 error = nfs4_acl_add_ace(dacl, ace->type, ace->flag, 663 process_one_v4_ace(&effective_acl_state, ace);
725 ace->access_mask, ace->whotype, ace->who);
726 if (error)
727 return error;
728 list_del(h);
729 kfree(ace);
730 acl->naces--;
731 } else {
732 /* Add this ace to the default, but leave it in
733 * the effective acl as well: */
734 error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
735 ace->access_mask, ace->whotype, ace->who);
736 if (error)
737 return error;
738 }
739 } 664 }
740 return 0; 665 *pacl = posix_state_to_acl(&effective_acl_state, flags);
666 if (IS_ERR(*pacl)) {
667 ret = PTR_ERR(*pacl);
668 goto out_dstate;
669 }
670 *dpacl = posix_state_to_acl(&default_acl_state, flags);
671 if (IS_ERR(*dpacl)) {
672 ret = PTR_ERR(*dpacl);
673 posix_acl_release(*pacl);
674 goto out_dstate;
675 }
676 sort_pacl(*pacl);
677 sort_pacl(*dpacl);
678 ret = 0;
679out_dstate:
680 free_state(&default_acl_state);
681out_estate:
682 free_state(&effective_acl_state);
683 return ret;
741} 684}
742 685
743static short 686static short