diff options
Diffstat (limited to 'fs/nfsd/nfs4acl.c')
-rw-r--r-- | fs/nfsd/nfs4acl.c | 133 |
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 | ||
130 | static short ace2type(struct nfs4_ace *); | 130 | static short ace2type(struct nfs4_ace *); |
131 | static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int); | 131 | static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int); |
132 | static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int); | ||
133 | int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); | 132 | int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); |
134 | static int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *); | ||
135 | 133 | ||
136 | struct nfs4_acl * | 134 | struct nfs4_acl * |
137 | nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, | 135 | nfs4_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 | ||
347 | int | ||
348 | nfs4_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 | } | ||
377 | out_acl: | ||
378 | if (error) { | ||
379 | posix_acl_release(*pacl); | ||
380 | *pacl = NULL; | ||
381 | } | ||
382 | nfs4_acl_free(dacl); | ||
383 | out: | ||
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 | ||
671 | static struct posix_acl * | 629 | int 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 | |||
695 | static int | ||
696 | nfs4_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; | ||
679 | out_dstate: | ||
680 | free_state(&default_acl_state); | ||
681 | out_estate: | ||
682 | free_state(&effective_acl_state); | ||
683 | return ret; | ||
741 | } | 684 | } |
742 | 685 | ||
743 | static short | 686 | static short |