diff options
author | Steve French <stfrench@microsoft.com> | 2019-07-19 02:30:07 -0400 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2019-09-16 12:43:37 -0400 |
commit | e2f8fbfb8d09c06decde162090fac3ee220aa280 (patch) | |
tree | 34c4ff53129c327ade33e86e2967f53baa5e66ab /fs/cifs/cifsacl.c | |
parent | 1afdea4f19a97ed98f65c41fd11c77e5264838ae (diff) |
cifs: get mode bits from special sid on stat
When mounting with "modefromsid" retrieve mode bits from
special SID (S-1-5-88-3) on stat. Subsequent patch will fix
setattr (chmod) to save mode bits in S-1-5-88-3-<mode>
Note that when an ACE matching S-1-5-88-3 is not found, we
default the mode to an approximation based on the owner, group
and everyone permissions (as with the "cifsacl" mount option).
See See e.g.
https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/hh509017(v=ws.10)
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs/cifsacl.c')
-rw-r--r-- | fs/cifs/cifsacl.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 1d377b7f2860..7fe4509e6c03 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -701,10 +701,9 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl) | |||
701 | } | 701 | } |
702 | #endif | 702 | #endif |
703 | 703 | ||
704 | |||
705 | static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | 704 | static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, |
706 | struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, | 705 | struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, |
707 | struct cifs_fattr *fattr) | 706 | struct cifs_fattr *fattr, bool mode_from_special_sid) |
708 | { | 707 | { |
709 | int i; | 708 | int i; |
710 | int num_aces = 0; | 709 | int num_aces = 0; |
@@ -757,22 +756,34 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
757 | #ifdef CONFIG_CIFS_DEBUG2 | 756 | #ifdef CONFIG_CIFS_DEBUG2 |
758 | dump_ace(ppace[i], end_of_acl); | 757 | dump_ace(ppace[i], end_of_acl); |
759 | #endif | 758 | #endif |
760 | if (compare_sids(&(ppace[i]->sid), pownersid) == 0) | 759 | if (mode_from_special_sid && |
760 | (compare_sids(&(ppace[i]->sid), | ||
761 | &sid_unix_NFS_mode) == 0)) { | ||
762 | /* | ||
763 | * Full permissions are: | ||
764 | * 07777 = S_ISUID | S_ISGID | S_ISVTX | | ||
765 | * S_IRWXU | S_IRWXG | S_IRWXO | ||
766 | */ | ||
767 | fattr->cf_mode &= ~07777; | ||
768 | fattr->cf_mode |= | ||
769 | le32_to_cpu(ppace[i]->sid.sub_auth[2]); | ||
770 | break; | ||
771 | } else if (compare_sids(&(ppace[i]->sid), pownersid) == 0) | ||
761 | access_flags_to_mode(ppace[i]->access_req, | 772 | access_flags_to_mode(ppace[i]->access_req, |
762 | ppace[i]->type, | 773 | ppace[i]->type, |
763 | &fattr->cf_mode, | 774 | &fattr->cf_mode, |
764 | &user_mask); | 775 | &user_mask); |
765 | if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) | 776 | else if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) |
766 | access_flags_to_mode(ppace[i]->access_req, | 777 | access_flags_to_mode(ppace[i]->access_req, |
767 | ppace[i]->type, | 778 | ppace[i]->type, |
768 | &fattr->cf_mode, | 779 | &fattr->cf_mode, |
769 | &group_mask); | 780 | &group_mask); |
770 | if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) | 781 | else if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) |
771 | access_flags_to_mode(ppace[i]->access_req, | 782 | access_flags_to_mode(ppace[i]->access_req, |
772 | ppace[i]->type, | 783 | ppace[i]->type, |
773 | &fattr->cf_mode, | 784 | &fattr->cf_mode, |
774 | &other_mask); | 785 | &other_mask); |
775 | if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0) | 786 | else if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0) |
776 | access_flags_to_mode(ppace[i]->access_req, | 787 | access_flags_to_mode(ppace[i]->access_req, |
777 | ppace[i]->type, | 788 | ppace[i]->type, |
778 | &fattr->cf_mode, | 789 | &fattr->cf_mode, |
@@ -851,7 +862,8 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | |||
851 | 862 | ||
852 | /* Convert CIFS ACL to POSIX form */ | 863 | /* Convert CIFS ACL to POSIX form */ |
853 | static int parse_sec_desc(struct cifs_sb_info *cifs_sb, | 864 | static int parse_sec_desc(struct cifs_sb_info *cifs_sb, |
854 | struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr) | 865 | struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr, |
866 | bool get_mode_from_special_sid) | ||
855 | { | 867 | { |
856 | int rc = 0; | 868 | int rc = 0; |
857 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; | 869 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; |
@@ -900,7 +912,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb, | |||
900 | 912 | ||
901 | if (dacloffset) | 913 | if (dacloffset) |
902 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, | 914 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, |
903 | group_sid_ptr, fattr); | 915 | group_sid_ptr, fattr, get_mode_from_special_sid); |
904 | else | 916 | else |
905 | cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */ | 917 | cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */ |
906 | 918 | ||
@@ -1128,8 +1140,8 @@ out: | |||
1128 | /* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */ | 1140 | /* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */ |
1129 | int | 1141 | int |
1130 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | 1142 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, |
1131 | struct inode *inode, const char *path, | 1143 | struct inode *inode, bool mode_from_special_sid, |
1132 | const struct cifs_fid *pfid) | 1144 | const char *path, const struct cifs_fid *pfid) |
1133 | { | 1145 | { |
1134 | struct cifs_ntsd *pntsd = NULL; | 1146 | struct cifs_ntsd *pntsd = NULL; |
1135 | u32 acllen = 0; | 1147 | u32 acllen = 0; |
@@ -1156,8 +1168,11 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | |||
1156 | if (IS_ERR(pntsd)) { | 1168 | if (IS_ERR(pntsd)) { |
1157 | rc = PTR_ERR(pntsd); | 1169 | rc = PTR_ERR(pntsd); |
1158 | cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); | 1170 | cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); |
1171 | } else if (mode_from_special_sid) { | ||
1172 | rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true); | ||
1159 | } else { | 1173 | } else { |
1160 | rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr); | 1174 | /* get approximated mode from ACL */ |
1175 | rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false); | ||
1161 | kfree(pntsd); | 1176 | kfree(pntsd); |
1162 | if (rc) | 1177 | if (rc) |
1163 | cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc); | 1178 | cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc); |