summaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifsacl.c
diff options
context:
space:
mode:
authorSteve French <stfrench@microsoft.com>2019-07-19 02:30:07 -0400
committerSteve French <stfrench@microsoft.com>2019-09-16 12:43:37 -0400
commite2f8fbfb8d09c06decde162090fac3ee220aa280 (patch)
tree34c4ff53129c327ade33e86e2967f53baa5e66ab /fs/cifs/cifsacl.c
parent1afdea4f19a97ed98f65c41fd11c77e5264838ae (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.c37
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
705static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, 704static 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 */
853static int parse_sec_desc(struct cifs_sb_info *cifs_sb, 864static 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 */
1129int 1141int
1130cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, 1142cifs_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);