20
20
*/
21
21
/*
22
22
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24
23
* Copyright (c) 2013 by Delphix. All rights reserved.
24
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25
25
*/
26
26
27
27
@@ -2681,47 +2681,30 @@ zfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr)
2681
2681
return (zfs_zaccess (zp , v4_mode , 0 , B_FALSE , cr ));
2682
2682
}
2683
2683
2684
- static int
2685
- zfs_delete_final_check (znode_t * zp , znode_t * dzp ,
2686
- mode_t available_perms , cred_t * cr )
2687
- {
2688
- int error ;
2689
- uid_t downer ;
2690
-
2691
- downer = zfs_fuid_map_id (ZTOZSB (dzp ), KUID_TO_SUID (ZTOI (dzp )-> i_uid ),
2692
- cr , ZFS_OWNER );
2693
-
2694
- error = secpolicy_vnode_access2 (cr , ZTOI (dzp ),
2695
- downer , available_perms , S_IWUSR |S_IXUSR );
2696
-
2697
- if (error == 0 )
2698
- error = zfs_sticky_remove_access (dzp , zp , cr );
2699
-
2700
- return (error );
2701
- }
2684
+ /* See zfs_zaccess_delete() */
2685
+ int zfs_write_implies_delete_child = 1 ;
2702
2686
2703
2687
/*
2704
- * Determine whether Access should be granted/deny, without
2705
- * consulting least priv subsystem.
2688
+ * Determine whether delete access should be granted.
2706
2689
*
2707
2690
* The following chart is the recommended NFSv4 enforcement for
2708
2691
* ability to delete an object.
2709
2692
*
2710
2693
* -------------------------------------------------------
2711
- * | Parent Dir | Target Object Permissions |
2694
+ * | Parent Dir | Target Object Permissions |
2712
2695
* | permissions | |
2713
2696
* -------------------------------------------------------
2714
2697
* | | ACL Allows | ACL Denies| Delete |
2715
2698
* | | Delete | Delete | unspecified|
2716
2699
* -------------------------------------------------------
2717
- * | ACL Allows | Permit | Permit | Permit |
2718
- * | DELETE_CHILD | |
2700
+ * | ACL Allows | Permit | Permit * | Permit |
2701
+ * | DELETE_CHILD | | | |
2719
2702
* -------------------------------------------------------
2720
- * | ACL Denies | Permit | Deny | Deny |
2703
+ * | ACL Denies | Permit * | Deny | Deny |
2721
2704
* | DELETE_CHILD | | | |
2722
2705
* -------------------------------------------------------
2723
2706
* | ACL specifies | | | |
2724
- * | only allow | Permit | Permit | Permit |
2707
+ * | only allow | Permit | Permit * | Permit |
2725
2708
* | write and | | | |
2726
2709
* | execute | | | |
2727
2710
* -------------------------------------------------------
@@ -2731,91 +2714,175 @@ zfs_delete_final_check(znode_t *zp, znode_t *dzp,
2731
2714
* -------------------------------------------------------
2732
2715
* ^
2733
2716
* |
2734
- * No search privilege, can't even look up file?
2717
+ * Re. execute permission on the directory: if that's missing,
2718
+ * the vnode lookup of the target will fail before we get here.
2719
+ *
2720
+ * Re [*] in the table above: We are intentionally disregarding the
2721
+ * NFSv4 committee recommendation for these three cells of the matrix
2722
+ * because that recommendation conflicts with the behavior expected
2723
+ * by Windows clients for ACL evaluation. See acl.h for notes on
2724
+ * which ACE_... flags should be checked for which operations.
2725
+ * Specifically, the NFSv4 committee recommendation is in conflict
2726
+ * with the Windows interpretation of DENY ACEs, where DENY ACEs
2727
+ * should take precedence ahead of ALLOW ACEs.
2728
+ *
2729
+ * This implementation takes a conservative approach by checking for
2730
+ * DENY ACEs on both the target object and it's container; checking
2731
+ * the ACE_DELETE on the target object, and ACE_DELETE_CHILD on the
2732
+ * container. If a DENY ACE is found for either of those, delete
2733
+ * access is denied. (Note that DENY ACEs are very rare.)
2735
2734
*
2735
+ * Note that after these changes, entire the second row and the
2736
+ * entire middle column of the table above change to Deny.
2737
+ * Accordingly, the logic here is somewhat simplified.
2738
+ *
2739
+ * First check for DENY ACEs that apply.
2740
+ * If either target or container has a deny, EACCES.
2741
+ *
2742
+ * Delete access can then be summarized as follows:
2743
+ * 1: The object to be deleted grants ACE_DELETE, or
2744
+ * 2: The containing directory grants ACE_DELETE_CHILD.
2745
+ * In a Windows system, that would be the end of the story.
2746
+ * In this system, (2) has some complications...
2747
+ * 2a: "sticky" bit on a directory adds restrictions, and
2748
+ * 2b: existing ACEs from previous versions of ZFS may
2749
+ * not carry ACE_DELETE_CHILD where they should, so we
2750
+ * also allow delete when ACE_WRITE_DATA is granted.
2751
+ *
2752
+ * Note: 2b is technically a work-around for a prior bug,
2753
+ * which hopefully can go away some day. For those who
2754
+ * no longer need the work around, and for testing, this
2755
+ * work-around is made conditional via the tunable:
2756
+ * zfs_write_implies_delete_child
2736
2757
*/
2737
2758
int
2738
2759
zfs_zaccess_delete (znode_t * dzp , znode_t * zp , cred_t * cr )
2739
2760
{
2761
+ uint32_t wanted_dirperms ;
2740
2762
uint32_t dzp_working_mode = 0 ;
2741
2763
uint32_t zp_working_mode = 0 ;
2742
2764
int dzp_error , zp_error ;
2743
- mode_t available_perms ;
2744
- boolean_t dzpcheck_privs = B_TRUE ;
2745
- boolean_t zpcheck_privs = B_TRUE ;
2746
-
2747
- /*
2748
- * We want specific DELETE permissions to
2749
- * take precedence over WRITE/EXECUTE. We don't
2750
- * want an ACL such as this to mess us up.
2751
- * user:joe:write_data:deny,user:joe:delete:allow
2752
- *
2753
- * However, deny permissions may ultimately be overridden
2754
- * by secpolicy_vnode_access().
2755
- *
2756
- * We will ask for all of the necessary permissions and then
2757
- * look at the working modes from the directory and target object
2758
- * to determine what was found.
2759
- */
2765
+ boolean_t dzpcheck_privs ;
2766
+ boolean_t zpcheck_privs ;
2760
2767
2761
2768
if (zp -> z_pflags & (ZFS_IMMUTABLE | ZFS_NOUNLINK ))
2762
2769
return (SET_ERROR (EPERM ));
2763
2770
2764
2771
/*
2765
- * First row
2766
- * If the directory permissions allow the delete, we are done.
2772
+ * Case 1:
2773
+ * If target object grants ACE_DELETE then we are done. This is
2774
+ * indicated by a return value of 0. For this case we don't worry
2775
+ * about the sticky bit because sticky only applies to the parent
2776
+ * directory and this is the child access result.
2777
+ *
2778
+ * If we encounter a DENY ACE here, we're also done (EACCES).
2779
+ * Note that if we hit a DENY ACE here (on the target) it should
2780
+ * take precedence over a DENY ACE on the container, so that when
2781
+ * we have more complete auditing support we will be able to
2782
+ * report an access failure against the specific target.
2783
+ * (This is part of why we're checking the target first.)
2767
2784
*/
2768
- if ((dzp_error = zfs_zaccess_common (dzp , ACE_DELETE_CHILD ,
2769
- & dzp_working_mode , & dzpcheck_privs , B_FALSE , cr )) == 0 )
2785
+ zp_error = zfs_zaccess_common (zp , ACE_DELETE , & zp_working_mode ,
2786
+ & zpcheck_privs , B_FALSE , cr );
2787
+ if (zp_error == EACCES ) {
2788
+ /* We hit a DENY ACE. */
2789
+ if (!zpcheck_privs )
2790
+ return (SET_ERROR (zp_error ));
2791
+ return (secpolicy_vnode_remove (cr ));
2792
+
2793
+ }
2794
+ if (zp_error == 0 )
2770
2795
return (0 );
2771
2796
2772
2797
/*
2773
- * If target object has delete permission then we are done
2798
+ * Case 2:
2799
+ * If the containing directory grants ACE_DELETE_CHILD,
2800
+ * or we're in backward compatibility mode and the
2801
+ * containing directory has ACE_WRITE_DATA, allow.
2802
+ * Case 2b is handled with wanted_dirperms.
2774
2803
*/
2775
- if ((zp_error = zfs_zaccess_common (zp , ACE_DELETE , & zp_working_mode ,
2776
- & zpcheck_privs , B_FALSE , cr )) == 0 )
2777
- return (0 );
2778
-
2779
- ASSERT (dzp_error && zp_error );
2780
-
2781
- if (!dzpcheck_privs )
2782
- return (dzp_error );
2783
- if (!zpcheck_privs )
2784
- return (zp_error );
2804
+ wanted_dirperms = ACE_DELETE_CHILD ;
2805
+ if (zfs_write_implies_delete_child )
2806
+ wanted_dirperms |= ACE_WRITE_DATA ;
2807
+ dzp_error = zfs_zaccess_common (dzp , wanted_dirperms ,
2808
+ & dzp_working_mode , & dzpcheck_privs , B_FALSE , cr );
2809
+ if (dzp_error == EACCES ) {
2810
+ /* We hit a DENY ACE. */
2811
+ if (!dzpcheck_privs )
2812
+ return (SET_ERROR (dzp_error ));
2813
+ return (secpolicy_vnode_remove (cr ));
2814
+ }
2785
2815
2786
2816
/*
2787
- * Second row
2817
+ * Cases 2a, 2b (continued)
2788
2818
*
2789
- * If directory returns EACCES then delete_child was denied
2790
- * due to deny delete_child. In this case send the request through
2791
- * secpolicy_vnode_remove(). We don't use zfs_delete_final_check()
2792
- * since that *could* allow the delete based on write/execute permission
2793
- * and we want delete permissions to override write/execute.
2819
+ * Note: dzp_working_mode now contains any permissions
2820
+ * that were NOT granted. Therefore, if any of the
2821
+ * wanted_dirperms WERE granted, we will have:
2822
+ * dzp_working_mode != wanted_dirperms
2823
+ * We're really asking if ANY of those permissions
2824
+ * were granted, and if so, grant delete access.
2794
2825
*/
2795
-
2796
- if (dzp_error == EACCES )
2797
- return (secpolicy_vnode_remove (cr ));
2826
+ if (dzp_working_mode != wanted_dirperms )
2827
+ dzp_error = 0 ;
2798
2828
2799
2829
/*
2800
- * Third Row
2801
- * only need to see if we have write/execute on directory.
2830
+ * dzp_error is 0 if the container granted us permissions to "modify".
2831
+ * If we do not have permission via one or more ACEs, our current
2832
+ * privileges may still permit us to modify the container.
2833
+ *
2834
+ * dzpcheck_privs is false when i.e. the FS is read-only.
2835
+ * Otherwise, do privilege checks for the container.
2802
2836
*/
2837
+ if (dzp_error != 0 && dzpcheck_privs ) {
2838
+ uid_t owner ;
2803
2839
2804
- dzp_error = zfs_zaccess_common (dzp , ACE_EXECUTE |ACE_WRITE_DATA ,
2805
- & dzp_working_mode , & dzpcheck_privs , B_FALSE , cr );
2840
+ /*
2841
+ * The secpolicy call needs the requested access and
2842
+ * the current access mode of the container, but it
2843
+ * only knows about Unix-style modes (VEXEC, VWRITE),
2844
+ * so this must condense the fine-grained ACE bits into
2845
+ * Unix modes.
2846
+ *
2847
+ * The VEXEC flag is easy, because we know that has
2848
+ * always been checked before we get here (during the
2849
+ * lookup of the target vnode). The container has not
2850
+ * granted us permissions to "modify", so we do not set
2851
+ * the VWRITE flag in the current access mode.
2852
+ */
2853
+ owner = zfs_fuid_map_id (ZTOZSB (dzp ),
2854
+ KUID_TO_SUID (ZTOI (dzp )-> i_uid ), cr , ZFS_OWNER );
2855
+ dzp_error = secpolicy_vnode_access2 (cr , ZTOI (dzp ),
2856
+ owner , S_IXUSR , S_IWUSR |S_IXUSR );
2857
+ }
2858
+ if (dzp_error != 0 ) {
2859
+ /*
2860
+ * Note: We may have dzp_error = -1 here (from
2861
+ * zfs_zacess_common). Don't return that.
2862
+ */
2863
+ return (SET_ERROR (EACCES ));
2864
+ }
2806
2865
2807
- if (dzp_error != 0 && !dzpcheck_privs )
2808
- return (dzp_error );
2809
2866
2810
2867
/*
2811
- * Fourth row
2868
+ * At this point, we know that the directory permissions allow
2869
+ * us to modify, but we still need to check for the additional
2870
+ * restrictions that apply when the "sticky bit" is set.
2871
+ *
2872
+ * Yes, zfs_sticky_remove_access() also checks this bit, but
2873
+ * checking it here and skipping the call below is nice when
2874
+ * you're watching all of this with dtrace.
2812
2875
*/
2876
+ if ((dzp -> z_mode & S_ISVTX ) == 0 )
2877
+ return (0 );
2813
2878
2814
- available_perms = (dzp_working_mode & ACE_WRITE_DATA ) ? 0 : S_IWUSR ;
2815
- available_perms |= (dzp_working_mode & ACE_EXECUTE ) ? 0 : S_IXUSR ;
2816
-
2817
- return (zfs_delete_final_check (zp , dzp , available_perms , cr ));
2818
-
2879
+ /*
2880
+ * zfs_sticky_remove_access will succeed if:
2881
+ * 1. The sticky bit is absent.
2882
+ * 2. We pass the sticky bit restrictions.
2883
+ * 3. We have privileges that always allow file removal.
2884
+ */
2885
+ return (zfs_sticky_remove_access (dzp , zp , cr ));
2819
2886
}
2820
2887
2821
2888
int
0 commit comments