Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag '5.8-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6

Pull more cifs updates from Steve French:
"12 cifs/smb3 fixes, 2 for stable.

- add support for idsfromsid on create and chgrp/chown allowing
ability to save owner information more naturally for some workloads

- improve query info (getattr) when SMB3.1.1 posix extensions are
negotiated by using new query info level"

* tag '5.8-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6:
smb3: Add debug message for new file creation with idsfromsid mount option
cifs: fix chown and chgrp when idsfromsid mount option enabled
smb3: allow uid and gid owners to be set on create with idsfromsid mount option
smb311: Add tracepoints for new compound posix query info
smb311: add support for using info level for posix extensions query
smb311: Add support for lookup with posix extensions query info
smb311: Add support for SMB311 query info (non-compounded)
SMB311: Add support for query info using posix extensions (level 100)
smb3: add indatalen that can be a non-zero value to calculation of credit charge in smb2 ioctl
smb3: fix typo in mount options displayed in /proc/mounts
cifs: Add get_security_type_str function to return sec type.
smb3: extend fscache mount volume coherency check

+571 -57
+2 -7
fs/cifs/cache.c
··· 53 53 .type = FSCACHE_COOKIE_TYPE_INDEX, 54 54 }; 55 55 56 - /* 57 - * Auxiliary data attached to CIFS superblock within the cache 58 - */ 59 - struct cifs_fscache_super_auxdata { 60 - u64 resource_id; /* unique server resource id */ 61 - }; 62 - 63 56 char *extract_sharename(const char *treename) 64 57 { 65 58 const char *src; ··· 91 98 92 99 memset(&auxdata, 0, sizeof(auxdata)); 93 100 auxdata.resource_id = tcon->resource_id; 101 + auxdata.vol_create_time = tcon->vol_create_time; 102 + auxdata.vol_serial_number = tcon->vol_serial_number; 94 103 95 104 if (memcmp(data, &auxdata, datalen) != 0) 96 105 return FSCACHE_CHECKAUX_OBSOLETE;
+1 -3
fs/cifs/cifs_debug.c
··· 221 221 struct cifs_ses *ses; 222 222 struct cifs_tcon *tcon; 223 223 int i, j; 224 - const char *security_types[] = {"Unspecified", "LANMAN", "NTLM", 225 - "NTLMv2", "RawNTLMSSP", "Kerberos"}; 226 224 227 225 seq_puts(m, 228 226 "Display Internal CIFS Data Structures for Debugging\n" ··· 377 379 } 378 380 379 381 seq_printf(m,"Security type: %s\n", 380 - security_types[server->ops->select_sectype(server, ses->sectype)]); 382 + get_security_type_str(server->ops->select_sectype(server, ses->sectype))); 381 383 382 384 if (server->rdma) 383 385 seq_printf(m, "RDMA\n\t");
+64 -15
fs/cifs/cifsacl.c
··· 849 849 return ace_size; 850 850 } 851 851 852 + unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace) 853 + { 854 + int i; 855 + unsigned int ace_size = 28; 856 + 857 + pntace->type = ACCESS_ALLOWED_ACE_TYPE; 858 + pntace->flags = 0x0; 859 + pntace->access_req = cpu_to_le32(GENERIC_ALL); 860 + pntace->sid.num_subauth = 3; 861 + pntace->sid.revision = 1; 862 + for (i = 0; i < NUM_AUTHS; i++) 863 + pntace->sid.authority[i] = sid_unix_NFS_users.authority[i]; 864 + 865 + pntace->sid.sub_auth[0] = sid_unix_NFS_users.sub_auth[0]; 866 + pntace->sid.sub_auth[1] = sid_unix_NFS_users.sub_auth[1]; 867 + pntace->sid.sub_auth[2] = cpu_to_le32(current_fsgid().val); 868 + 869 + /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */ 870 + pntace->size = cpu_to_le16(ace_size); 871 + return ace_size; 872 + } 873 + 852 874 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, 853 875 struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid) 854 876 { ··· 1000 978 /* Convert permission bits from mode to equivalent CIFS ACL */ 1001 979 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, 1002 980 __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, 1003 - bool mode_from_sid, int *aclflag) 981 + bool mode_from_sid, bool id_from_sid, int *aclflag) 1004 982 { 1005 983 int rc = 0; 1006 984 __u32 dacloffset; ··· 1041 1019 if (!nowner_sid_ptr) 1042 1020 return -ENOMEM; 1043 1021 id = from_kuid(&init_user_ns, uid); 1044 - rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr); 1045 - if (rc) { 1046 - cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n", 1047 - __func__, rc, id); 1048 - kfree(nowner_sid_ptr); 1049 - return rc; 1022 + if (id_from_sid) { 1023 + struct owner_sid *osid = (struct owner_sid *)nowner_sid_ptr; 1024 + /* Populate the user ownership fields S-1-5-88-1 */ 1025 + osid->Revision = 1; 1026 + osid->NumAuth = 3; 1027 + osid->Authority[5] = 5; 1028 + osid->SubAuthorities[0] = cpu_to_le32(88); 1029 + osid->SubAuthorities[1] = cpu_to_le32(1); 1030 + osid->SubAuthorities[2] = cpu_to_le32(id); 1031 + } else { /* lookup sid with upcall */ 1032 + rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr); 1033 + if (rc) { 1034 + cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n", 1035 + __func__, rc, id); 1036 + kfree(nowner_sid_ptr); 1037 + return rc; 1038 + } 1050 1039 } 1051 1040 cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr); 1052 1041 kfree(nowner_sid_ptr); ··· 1072 1039 if (!ngroup_sid_ptr) 1073 1040 return -ENOMEM; 1074 1041 id = from_kgid(&init_user_ns, gid); 1075 - rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr); 1076 - if (rc) { 1077 - cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n", 1078 - __func__, rc, id); 1079 - kfree(ngroup_sid_ptr); 1080 - return rc; 1042 + if (id_from_sid) { 1043 + struct owner_sid *gsid = (struct owner_sid *)ngroup_sid_ptr; 1044 + /* Populate the group ownership fields S-1-5-88-2 */ 1045 + gsid->Revision = 1; 1046 + gsid->NumAuth = 3; 1047 + gsid->Authority[5] = 5; 1048 + gsid->SubAuthorities[0] = cpu_to_le32(88); 1049 + gsid->SubAuthorities[1] = cpu_to_le32(2); 1050 + gsid->SubAuthorities[2] = cpu_to_le32(id); 1051 + } else { /* lookup sid with upcall */ 1052 + rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr); 1053 + if (rc) { 1054 + cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n", 1055 + __func__, rc, id); 1056 + kfree(ngroup_sid_ptr); 1057 + return rc; 1058 + } 1081 1059 } 1082 1060 cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr); 1083 1061 kfree(ngroup_sid_ptr); ··· 1291 1247 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 1292 1248 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); 1293 1249 struct smb_version_operations *ops; 1294 - bool mode_from_sid; 1250 + bool mode_from_sid, id_from_sid; 1295 1251 1296 1252 if (IS_ERR(tlink)) 1297 1253 return PTR_ERR(tlink); ··· 1334 1290 else 1335 1291 mode_from_sid = false; 1336 1292 1293 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) 1294 + id_from_sid = true; 1295 + else 1296 + id_from_sid = false; 1297 + 1337 1298 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid, 1338 - mode_from_sid, &aclflag); 1299 + mode_from_sid, id_from_sid, &aclflag); 1339 1300 1340 1301 cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc); 1341 1302
+15
fs/cifs/cifsacl.h
··· 176 176 __le16 Sbz2; /* MBZ */ 177 177 } __packed; 178 178 179 + /* 180 + * Used to store the special 'NFS SIDs' used to persist the POSIX uid and gid 181 + * See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx 182 + */ 183 + struct owner_sid { 184 + u8 Revision; 185 + u8 NumAuth; 186 + u8 Authority[6]; 187 + __le32 SubAuthorities[3]; 188 + } __packed; 189 + 190 + struct owner_group_sids { 191 + struct owner_sid owner; 192 + struct owner_sid group; 193 + } __packed; 179 194 180 195 /* 181 196 * Minimum security identifier can be one for system defined Users
+1 -1
fs/cifs/cifsfs.c
··· 623 623 seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); 624 624 625 625 if (tcon->ses->chan_max > 1) 626 - seq_printf(s, ",multichannel,max_channel=%zu", 626 + seq_printf(s, ",multichannel,max_channels=%zu", 627 627 tcon->ses->chan_max); 628 628 629 629 return 0;
+18
fs/cifs/cifsglob.h
··· 2008 2008 extern struct smb_version_operations smb311_operations; 2009 2009 extern struct smb_version_values smb311_values; 2010 2010 2011 + static inline char *get_security_type_str(enum securityEnum sectype) 2012 + { 2013 + switch (sectype) { 2014 + case RawNTLMSSP: 2015 + return "RawNTLMSSP"; 2016 + case Kerberos: 2017 + return "Kerberos"; 2018 + case NTLMv2: 2019 + return "NTLMv2"; 2020 + case NTLM: 2021 + return "NTLM"; 2022 + case LANMAN: 2023 + return "LANMAN"; 2024 + default: 2025 + return "Unknown"; 2026 + } 2027 + } 2028 + 2011 2029 static inline bool is_smb1_server(struct TCP_Server_Info *server) 2012 2030 { 2013 2031 return strcmp(server->vals->version_string, SMB1_VERSION_STRING) == 0;
+3
fs/cifs/cifsproto.h
··· 198 198 extern int cifs_get_inode_info(struct inode **inode, const char *full_path, 199 199 FILE_ALL_INFO *data, struct super_block *sb, 200 200 int xid, const struct cifs_fid *fid); 201 + extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path, 202 + struct super_block *sb, unsigned int xid); 201 203 extern int cifs_get_inode_info_unix(struct inode **pinode, 202 204 const unsigned char *search_path, 203 205 struct super_block *sb, unsigned int xid); ··· 222 220 const char *, int); 223 221 extern unsigned int setup_authusers_ACE(struct cifs_ace *pace); 224 222 extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode); 223 + extern unsigned int setup_special_user_owner_ACE(struct cifs_ace *pace); 225 224 226 225 extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); 227 226 extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
+4 -1
fs/cifs/dir.c
··· 411 411 rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb, 412 412 xid); 413 413 else { 414 + /* TODO: Add support for calling POSIX query info here, but passing in fid */ 414 415 rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb, 415 416 xid, fid); 416 417 if (newinode) { ··· 701 700 cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", 702 701 full_path, d_inode(direntry)); 703 702 704 - if (pTcon->unix_ext) { 703 + if (pTcon->posix_extensions) 704 + rc = smb311_posix_get_inode_info(&newInode, full_path, parent_dir_inode->i_sb, xid); 705 + else if (pTcon->unix_ext) { 705 706 rc = cifs_get_inode_info_unix(&newInode, full_path, 706 707 parent_dir_inode->i_sb, xid); 707 708 } else {
+4 -1
fs/cifs/file.c
··· 243 243 if (rc) 244 244 goto out; 245 245 246 + /* TODO: Add support for calling posix query info but with passing in fid */ 246 247 if (tcon->unix_ext) 247 248 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, 248 249 xid); ··· 801 800 if (!is_interrupt_error(rc)) 802 801 mapping_set_error(inode->i_mapping, rc); 803 802 804 - if (tcon->unix_ext) 803 + if (tcon->posix_extensions) 804 + rc = smb311_posix_get_inode_info(&inode, full_path, inode->i_sb, xid); 805 + else if (tcon->unix_ext) 805 806 rc = cifs_get_inode_info_unix(&inode, full_path, 806 807 inode->i_sb, xid); 807 808 else
+15 -2
fs/cifs/fscache.c
··· 96 96 { 97 97 struct TCP_Server_Info *server = tcon->ses->server; 98 98 char *sharename; 99 + struct cifs_fscache_super_auxdata auxdata; 99 100 100 101 sharename = extract_sharename(tcon->treeName); 101 102 if (IS_ERR(sharename)) { ··· 105 104 return; 106 105 } 107 106 107 + memset(&auxdata, 0, sizeof(auxdata)); 108 + auxdata.resource_id = tcon->resource_id; 109 + auxdata.vol_create_time = tcon->vol_create_time; 110 + auxdata.vol_serial_number = tcon->vol_serial_number; 111 + 108 112 tcon->fscache = 109 113 fscache_acquire_cookie(server->fscache, 110 114 &cifs_fscache_super_index_def, 111 115 sharename, strlen(sharename), 112 - &tcon->resource_id, sizeof(tcon->resource_id), 116 + &auxdata, sizeof(auxdata), 113 117 tcon, 0, true); 114 118 kfree(sharename); 115 119 cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", ··· 123 117 124 118 void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) 125 119 { 120 + struct cifs_fscache_super_auxdata auxdata; 121 + 122 + memset(&auxdata, 0, sizeof(auxdata)); 123 + auxdata.resource_id = tcon->resource_id; 124 + auxdata.vol_create_time = tcon->vol_create_time; 125 + auxdata.vol_serial_number = tcon->vol_serial_number; 126 + 126 127 cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache); 127 - fscache_relinquish_cookie(tcon->fscache, &tcon->resource_id, false); 128 + fscache_relinquish_cookie(tcon->fscache, &auxdata, false); 128 129 tcon->fscache = NULL; 129 130 } 130 131
+9
fs/cifs/fscache.h
··· 28 28 #ifdef CONFIG_CIFS_FSCACHE 29 29 30 30 /* 31 + * Auxiliary data attached to CIFS superblock within the cache 32 + */ 33 + struct cifs_fscache_super_auxdata { 34 + u64 resource_id; /* unique server resource id */ 35 + __le64 vol_create_time; 36 + u32 vol_serial_number; 37 + } __packed; 38 + 39 + /* 31 40 * Auxiliary data attached to CIFS inode within the cache 32 41 */ 33 42 struct cifs_fscache_inode_auxdata {
+182 -3
fs/cifs/inode.c
··· 32 32 #include "cifspdu.h" 33 33 #include "cifsglob.h" 34 34 #include "cifsproto.h" 35 + #include "smb2proto.h" 35 36 #include "cifs_debug.h" 36 37 #include "cifs_fs_sb.h" 37 38 #include "cifs_unicode.h" ··· 596 595 #endif 597 596 } 598 597 598 + /* Fill a cifs_fattr struct with info from POSIX info struct */ 599 + static void 600 + smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct smb311_posix_qinfo *info, 601 + struct super_block *sb, bool adjust_tz, bool symlink) 602 + { 603 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 604 + struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 605 + 606 + memset(fattr, 0, sizeof(*fattr)); 607 + 608 + /* no fattr->flags to set */ 609 + fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes); 610 + fattr->cf_uniqueid = le64_to_cpu(info->Inode); 611 + 612 + if (info->LastAccessTime) 613 + fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); 614 + else 615 + ktime_get_coarse_real_ts64(&fattr->cf_atime); 616 + 617 + fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); 618 + fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); 619 + 620 + if (adjust_tz) { 621 + fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj; 622 + fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj; 623 + } 624 + 625 + fattr->cf_eof = le64_to_cpu(info->EndOfFile); 626 + fattr->cf_bytes = le64_to_cpu(info->AllocationSize); 627 + fattr->cf_createtime = le64_to_cpu(info->CreationTime); 628 + 629 + fattr->cf_nlink = le32_to_cpu(info->HardLinks); 630 + fattr->cf_mode = (umode_t) le32_to_cpu(info->Mode); 631 + /* The srv fs device id is overridden on network mount so setting rdev isn't needed here */ 632 + /* fattr->cf_rdev = le32_to_cpu(info->DeviceId); */ 633 + 634 + if (symlink) { 635 + fattr->cf_mode |= S_IFLNK; 636 + fattr->cf_dtype = DT_LNK; 637 + } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { 638 + fattr->cf_mode |= S_IFDIR; 639 + fattr->cf_dtype = DT_DIR; 640 + } else { /* file */ 641 + fattr->cf_mode |= S_IFREG; 642 + fattr->cf_dtype = DT_REG; 643 + } 644 + /* else if reparse point ... TODO: add support for FIFO and blk dev; special file types */ 645 + 646 + fattr->cf_uid = cifs_sb->mnt_uid; /* TODO: map uid and gid from SID */ 647 + fattr->cf_gid = cifs_sb->mnt_gid; 648 + 649 + cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n", 650 + fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink); 651 + } 652 + 653 + 599 654 /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ 600 655 static void 601 656 cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, ··· 1080 1023 return rc; 1081 1024 } 1082 1025 1026 + int 1027 + smb311_posix_get_inode_info(struct inode **inode, 1028 + const char *full_path, 1029 + struct super_block *sb, unsigned int xid) 1030 + { 1031 + struct cifs_tcon *tcon; 1032 + struct TCP_Server_Info *server; 1033 + struct tcon_link *tlink; 1034 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 1035 + bool adjust_tz = false; 1036 + struct cifs_fattr fattr = {0}; 1037 + bool symlink = false; 1038 + struct smb311_posix_qinfo *data = NULL; 1039 + int rc = 0; 1040 + int tmprc = 0; 1041 + 1042 + tlink = cifs_sb_tlink(cifs_sb); 1043 + if (IS_ERR(tlink)) 1044 + return PTR_ERR(tlink); 1045 + tcon = tlink_tcon(tlink); 1046 + server = tcon->ses->server; 1047 + 1048 + /* 1049 + * 1. Fetch file metadata 1050 + */ 1051 + 1052 + if (is_inode_cache_good(*inode)) { 1053 + cifs_dbg(FYI, "No need to revalidate cached inode sizes\n"); 1054 + goto out; 1055 + } 1056 + data = kmalloc(sizeof(struct smb311_posix_qinfo), GFP_KERNEL); 1057 + if (!data) { 1058 + rc = -ENOMEM; 1059 + goto out; 1060 + } 1061 + 1062 + rc = smb311_posix_query_path_info(xid, tcon, cifs_sb, 1063 + full_path, data, 1064 + &adjust_tz, &symlink); 1065 + 1066 + /* 1067 + * 2. Convert it to internal cifs metadata (fattr) 1068 + */ 1069 + 1070 + switch (rc) { 1071 + case 0: 1072 + smb311_posix_info_to_fattr(&fattr, data, sb, adjust_tz, symlink); 1073 + break; 1074 + case -EREMOTE: 1075 + /* DFS link, no metadata available on this server */ 1076 + cifs_create_dfs_fattr(&fattr, sb); 1077 + rc = 0; 1078 + break; 1079 + case -EACCES: 1080 + /* 1081 + * For SMB2 and later the backup intent flag 1082 + * is already sent if needed on open and there 1083 + * is no path based FindFirst operation to use 1084 + * to retry with so nothing we can do, bail out 1085 + */ 1086 + goto out; 1087 + default: 1088 + cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc); 1089 + goto out; 1090 + } 1091 + 1092 + 1093 + /* 1094 + * 3. Tweak fattr based on mount options 1095 + */ 1096 + 1097 + /* check for Minshall+French symlinks */ 1098 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { 1099 + tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr, 1100 + full_path); 1101 + if (tmprc) 1102 + cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc); 1103 + } 1104 + 1105 + /* 1106 + * 4. Update inode with final fattr data 1107 + */ 1108 + 1109 + if (!*inode) { 1110 + *inode = cifs_iget(sb, &fattr); 1111 + if (!*inode) 1112 + rc = -ENOMEM; 1113 + } else { 1114 + /* we already have inode, update it */ 1115 + 1116 + /* if uniqueid is different, return error */ 1117 + if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM && 1118 + CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) { 1119 + CIFS_I(*inode)->time = 0; /* force reval */ 1120 + rc = -ESTALE; 1121 + goto out; 1122 + } 1123 + 1124 + /* if filetype is different, return error */ 1125 + if (unlikely(((*inode)->i_mode & S_IFMT) != 1126 + (fattr.cf_mode & S_IFMT))) { 1127 + CIFS_I(*inode)->time = 0; /* force reval */ 1128 + rc = -ESTALE; 1129 + goto out; 1130 + } 1131 + 1132 + cifs_fattr_to_inode(*inode, &fattr); 1133 + } 1134 + out: 1135 + cifs_put_tlink(tlink); 1136 + kfree(data); 1137 + return rc; 1138 + } 1139 + 1140 + 1083 1141 static const struct inode_operations cifs_ipc_inode_ops = { 1084 1142 .lookup = cifs_lookup, 1085 1143 }; ··· 1333 1161 } 1334 1162 1335 1163 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb)); 1336 - rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL); 1164 + if (tcon->posix_extensions) 1165 + rc = smb311_posix_get_inode_info(&inode, path, sb, xid); 1166 + else 1167 + rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL); 1337 1168 1338 1169 iget_no_retry: 1339 1170 if (!inode) { ··· 1692 1517 int rc = 0; 1693 1518 struct inode *inode = NULL; 1694 1519 1695 - if (tcon->unix_ext) 1520 + if (tcon->posix_extensions) 1521 + rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid); 1522 + else if (tcon->unix_ext) 1696 1523 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb, 1697 1524 xid); 1698 1525 else ··· 2291 2114 dentry, cifs_get_time(dentry), jiffies); 2292 2115 2293 2116 again: 2294 - if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) 2117 + if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions) 2118 + rc = smb311_posix_get_inode_info(&inode, full_path, sb, xid); 2119 + else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) 2295 2120 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); 2296 2121 else 2297 2122 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
+3 -1
fs/cifs/link.c
··· 701 701 cifs_sb_target->local_nls); */ 702 702 703 703 if (rc == 0) { 704 - if (pTcon->unix_ext) 704 + if (pTcon->posix_extensions) 705 + rc = smb311_posix_get_inode_info(&newinode, full_path, inode->i_sb, xid); 706 + else if (pTcon->unix_ext) 705 707 rc = cifs_get_inode_info_unix(&newinode, full_path, 706 708 inode->i_sb, xid); 707 709 else
+1
fs/cifs/smb2glob.h
··· 45 45 #define SMB2_OP_HARDLINK 8 46 46 #define SMB2_OP_SET_EOF 9 47 47 #define SMB2_OP_RMDIR 10 48 + #define SMB2_OP_POSIX_QUERY_INFO 11 48 49 49 50 /* Used when constructing chained read requests. */ 50 51 #define CHAINED_REQUEST 1
+105
fs/cifs/smb2inode.c
··· 166 166 trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid, 167 167 full_path); 168 168 break; 169 + case SMB2_OP_POSIX_QUERY_INFO: 170 + rqst[num_rqst].rq_iov = &vars->qi_iov[0]; 171 + rqst[num_rqst].rq_nvec = 1; 172 + 173 + if (cfile) 174 + rc = SMB2_query_info_init(tcon, server, 175 + &rqst[num_rqst], 176 + cfile->fid.persistent_fid, 177 + cfile->fid.volatile_fid, 178 + SMB_FIND_FILE_POSIX_INFO, 179 + SMB2_O_INFO_FILE, 0, 180 + /* TBD: fix following to allow for longer SIDs */ 181 + sizeof(struct smb311_posix_qinfo *) + (PATH_MAX * 2) + 182 + (sizeof(struct cifs_sid) * 2), 0, NULL); 183 + else { 184 + rc = SMB2_query_info_init(tcon, server, 185 + &rqst[num_rqst], 186 + COMPOUND_FID, 187 + COMPOUND_FID, 188 + SMB_FIND_FILE_POSIX_INFO, 189 + SMB2_O_INFO_FILE, 0, 190 + sizeof(struct smb311_posix_qinfo *) + (PATH_MAX * 2) + 191 + (sizeof(struct cifs_sid) * 2), 0, NULL); 192 + if (!rc) { 193 + smb2_set_next_command(tcon, &rqst[num_rqst]); 194 + smb2_set_related(&rqst[num_rqst]); 195 + } 196 + } 197 + 198 + if (rc) 199 + goto finished; 200 + num_rqst++; 201 + trace_smb3_posix_query_info_compound_enter(xid, ses->Suid, tcon->tid, full_path); 202 + break; 169 203 case SMB2_OP_DELETE: 170 204 trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path); 171 205 break; ··· 413 379 trace_smb3_query_info_compound_done(xid, ses->Suid, 414 380 tcon->tid); 415 381 break; 382 + case SMB2_OP_POSIX_QUERY_INFO: 383 + if (rc == 0) { 384 + qi_rsp = (struct smb2_query_info_rsp *) 385 + rsp_iov[1].iov_base; 386 + rc = smb2_validate_and_copy_iov( 387 + le16_to_cpu(qi_rsp->OutputBufferOffset), 388 + le32_to_cpu(qi_rsp->OutputBufferLength), 389 + &rsp_iov[1], sizeof(struct smb311_posix_qinfo) /* add SIDs */, ptr); 390 + } 391 + if (rqst[1].rq_iov) 392 + SMB2_query_info_free(&rqst[1]); 393 + if (rqst[2].rq_iov) 394 + SMB2_close_free(&rqst[2]); 395 + if (rc) 396 + trace_smb3_posix_query_info_compound_err(xid, ses->Suid, tcon->tid, rc); 397 + else 398 + trace_smb3_posix_query_info_compound_done(xid, ses->Suid, tcon->tid); 399 + break; 416 400 case SMB2_OP_DELETE: 417 401 if (rc) 418 402 trace_smb3_delete_err(xid, ses->Suid, tcon->tid, rc); ··· 559 507 goto out; 560 508 561 509 move_smb2_info_to_cifs(data, smb2_data); 510 + out: 511 + kfree(smb2_data); 512 + return rc; 513 + } 514 + 515 + 516 + int 517 + smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 518 + struct cifs_sb_info *cifs_sb, const char *full_path, 519 + struct smb311_posix_qinfo *data, bool *adjust_tz, bool *symlink) 520 + { 521 + int rc; 522 + __u32 create_options = 0; 523 + struct cifsFileInfo *cfile; 524 + struct smb311_posix_qinfo *smb2_data; 525 + 526 + *adjust_tz = false; 527 + *symlink = false; 528 + 529 + /* BB TODO: Make struct larger when add support for parsing owner SIDs */ 530 + smb2_data = kzalloc(sizeof(struct smb311_posix_qinfo), 531 + GFP_KERNEL); 532 + if (smb2_data == NULL) 533 + return -ENOMEM; 534 + 535 + /* 536 + * BB TODO: Add support for using the cached root handle. 537 + * Create SMB2_query_posix_info worker function to do non-compounded query 538 + * when we already have an open file handle for this. For now this is fast enough 539 + * (always using the compounded version). 540 + */ 541 + 542 + cifs_get_readable_path(tcon, full_path, &cfile); 543 + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 544 + FILE_READ_ATTRIBUTES, FILE_OPEN, create_options, 545 + ACL_NO_MODE, smb2_data, SMB2_OP_POSIX_QUERY_INFO, cfile); 546 + if (rc == -EOPNOTSUPP) { 547 + /* BB TODO: When support for special files added to Samba re-verify this path */ 548 + *symlink = true; 549 + create_options |= OPEN_REPARSE_POINT; 550 + 551 + /* Failed on a symbolic link - query a reparse point info */ 552 + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 553 + FILE_READ_ATTRIBUTES, FILE_OPEN, 554 + create_options, ACL_NO_MODE, 555 + smb2_data, SMB2_OP_POSIX_QUERY_INFO, NULL); 556 + } 557 + if (rc) 558 + goto out; 559 + 560 + /* TODO: will need to allow for the 2 SIDs when add support for getting owner UID/GID */ 561 + memcpy(data, smb2_data, sizeof(struct smb311_posix_qinfo)); 562 + 562 563 out: 563 564 kfree(smb2_data); 564 565 return rc;
+109 -22
fs/cifs/smb2pdu.c
··· 2317 2317 return 0; 2318 2318 } 2319 2319 2320 + /* See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */ 2321 + static void setup_owner_group_sids(char *buf) 2322 + { 2323 + struct owner_group_sids *sids = (struct owner_group_sids *)buf; 2324 + 2325 + /* Populate the user ownership fields S-1-5-88-1 */ 2326 + sids->owner.Revision = 1; 2327 + sids->owner.NumAuth = 3; 2328 + sids->owner.Authority[5] = 5; 2329 + sids->owner.SubAuthorities[0] = cpu_to_le32(88); 2330 + sids->owner.SubAuthorities[1] = cpu_to_le32(1); 2331 + sids->owner.SubAuthorities[2] = cpu_to_le32(current_fsuid().val); 2332 + 2333 + /* Populate the group ownership fields S-1-5-88-2 */ 2334 + sids->group.Revision = 1; 2335 + sids->group.NumAuth = 3; 2336 + sids->group.Authority[5] = 5; 2337 + sids->group.SubAuthorities[0] = cpu_to_le32(88); 2338 + sids->group.SubAuthorities[1] = cpu_to_le32(2); 2339 + sids->group.SubAuthorities[2] = cpu_to_le32(current_fsgid().val); 2340 + 2341 + cifs_dbg(FYI, "owner S-1-5-88-1-%d, group S-1-5-88-2-%d\n", current_fsuid().val, current_fsgid().val); 2342 + } 2343 + 2320 2344 /* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */ 2321 2345 static struct crt_sd_ctxt * 2322 - create_sd_buf(umode_t mode, unsigned int *len) 2346 + create_sd_buf(umode_t mode, bool set_owner, unsigned int *len) 2323 2347 { 2324 2348 struct crt_sd_ctxt *buf; 2325 2349 struct cifs_ace *pace; 2326 2350 unsigned int sdlen, acelen; 2351 + unsigned int owner_offset = 0; 2352 + unsigned int group_offset = 0; 2327 2353 2328 - *len = roundup(sizeof(struct crt_sd_ctxt) + sizeof(struct cifs_ace) * 2, 2329 - 8); 2354 + *len = roundup(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 2), 8); 2355 + 2356 + if (set_owner) { 2357 + /* offset fields are from beginning of security descriptor not of create context */ 2358 + owner_offset = sizeof(struct smb3_acl) + (sizeof(struct cifs_ace) * 2); 2359 + 2360 + /* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */ 2361 + *len += sizeof(struct owner_group_sids); 2362 + } 2363 + 2330 2364 buf = kzalloc(*len, GFP_KERNEL); 2331 2365 if (buf == NULL) 2332 2366 return buf; 2333 2367 2368 + if (set_owner) { 2369 + buf->sd.OffsetOwner = cpu_to_le32(owner_offset); 2370 + group_offset = owner_offset + sizeof(struct owner_sid); 2371 + buf->sd.OffsetGroup = cpu_to_le32(group_offset); 2372 + } else { 2373 + buf->sd.OffsetOwner = 0; 2374 + buf->sd.OffsetGroup = 0; 2375 + } 2376 + 2334 2377 sdlen = sizeof(struct smb3_sd) + sizeof(struct smb3_acl) + 2335 2378 2 * sizeof(struct cifs_ace); 2379 + if (set_owner) { 2380 + sdlen += sizeof(struct owner_group_sids); 2381 + setup_owner_group_sids(owner_offset + sizeof(struct create_context) + 8 /* name */ 2382 + + (char *)buf); 2383 + } 2336 2384 2337 2385 buf->ccontext.DataOffset = cpu_to_le16(offsetof 2338 2386 (struct crt_sd_ctxt, sd)); 2339 2387 buf->ccontext.DataLength = cpu_to_le32(sdlen); 2340 - buf->ccontext.NameOffset = cpu_to_le16(offsetof 2341 - (struct crt_sd_ctxt, Name)); 2388 + buf->ccontext.NameOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, Name)); 2342 2389 buf->ccontext.NameLength = cpu_to_le16(4); 2343 2390 /* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */ 2344 2391 buf->Name[0] = 'S'; ··· 2406 2359 /* create one ACE to hold the mode embedded in reserved special SID */ 2407 2360 pace = (struct cifs_ace *)(sizeof(struct crt_sd_ctxt) + (char *)buf); 2408 2361 acelen = setup_special_mode_ACE(pace, (__u64)mode); 2362 + 2363 + if (set_owner) { 2364 + /* we do not need to reallocate buffer to add the two more ACEs. plenty of space */ 2365 + pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) + (char *)buf)); 2366 + acelen += setup_special_user_owner_ACE(pace); 2367 + /* it does not appear necessary to add an ACE for the NFS group SID */ 2368 + buf->acl.AceCount = cpu_to_le16(3); 2369 + } else 2370 + buf->acl.AceCount = cpu_to_le16(2); 2371 + 2409 2372 /* and one more ACE to allow access for authenticated users */ 2410 2373 pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) + 2411 2374 (char *)buf)); 2412 2375 acelen += setup_authusers_ACE(pace); 2376 + 2413 2377 buf->acl.AclSize = cpu_to_le16(sizeof(struct cifs_acl) + acelen); 2414 - buf->acl.AceCount = cpu_to_le16(2); 2378 + 2415 2379 return buf; 2416 2380 } 2417 2381 2418 2382 static int 2419 - add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) 2383 + add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode, bool set_owner) 2420 2384 { 2421 2385 struct smb2_create_req *req = iov[0].iov_base; 2422 2386 unsigned int num = *num_iovec; 2423 2387 unsigned int len = 0; 2424 2388 2425 - iov[num].iov_base = create_sd_buf(mode, &len); 2389 + iov[num].iov_base = create_sd_buf(mode, set_owner, &len); 2426 2390 if (iov[num].iov_base == NULL) 2427 2391 return -ENOMEM; 2428 2392 iov[num].iov_len = len; ··· 2822 2764 return rc; 2823 2765 } 2824 2766 2825 - if ((oparms->disposition != FILE_OPEN) && 2826 - (oparms->cifs_sb) && 2827 - (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) && 2828 - (oparms->mode != ACL_NO_MODE)) { 2829 - if (n_iov > 2) { 2830 - struct create_context *ccontext = 2831 - (struct create_context *)iov[n_iov-1].iov_base; 2832 - ccontext->Next = 2833 - cpu_to_le32(iov[n_iov-1].iov_len); 2767 + if ((oparms->disposition != FILE_OPEN) && (oparms->cifs_sb)) { 2768 + bool set_mode; 2769 + bool set_owner; 2770 + 2771 + if ((oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) && 2772 + (oparms->mode != ACL_NO_MODE)) 2773 + set_mode = true; 2774 + else { 2775 + set_mode = false; 2776 + oparms->mode = ACL_NO_MODE; 2834 2777 } 2835 2778 2836 - cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode); 2837 - rc = add_sd_context(iov, &n_iov, oparms->mode); 2838 - if (rc) 2839 - return rc; 2779 + if (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) 2780 + set_owner = true; 2781 + else 2782 + set_owner = false; 2783 + 2784 + if (set_owner | set_mode) { 2785 + if (n_iov > 2) { 2786 + struct create_context *ccontext = 2787 + (struct create_context *)iov[n_iov-1].iov_base; 2788 + ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len); 2789 + } 2790 + 2791 + cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode); 2792 + rc = add_sd_context(iov, &n_iov, oparms->mode, set_owner); 2793 + if (rc) 2794 + return rc; 2795 + } 2840 2796 } 2841 2797 2842 2798 if (n_iov > 2) { ··· 3045 2973 * response size smaller. 3046 2974 */ 3047 2975 req->MaxOutputResponse = cpu_to_le32(max_response_size); 3048 - req->sync_hdr.CreditCharge = cpu_to_le16(DIV_ROUND_UP(max_response_size, SMB2_MAX_BUFFER_SIZE)); 2976 + req->sync_hdr.CreditCharge = 2977 + cpu_to_le16(DIV_ROUND_UP(max(indatalen, max_response_size), 2978 + SMB2_MAX_BUFFER_SIZE)); 3049 2979 if (is_fsctl) 3050 2980 req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL); 3051 2981 else ··· 3528 3454 sizeof(struct smb2_file_all_info) + PATH_MAX * 2, 3529 3455 sizeof(struct smb2_file_all_info), (void **)&data, 3530 3456 NULL); 3457 + } 3458 + 3459 + int 3460 + SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon, 3461 + u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen) 3462 + { 3463 + size_t output_len = sizeof(struct smb311_posix_qinfo *) + 3464 + (sizeof(struct cifs_sid) * 2) + (PATH_MAX * 2); 3465 + *plen = 0; 3466 + 3467 + return query_info(xid, tcon, persistent_fid, volatile_fid, 3468 + SMB_FIND_FILE_POSIX_INFO, SMB2_O_INFO_FILE, 0, 3469 + output_len, sizeof(struct smb311_posix_qinfo), (void **)&data, plen); 3531 3470 } 3532 3471 3533 3472 int
+26 -1
fs/cifs/smb2pdu.h
··· 1653 1653 } __packed; 1654 1654 1655 1655 /* 1656 - * SMB2-only POSIX info level 1656 + * SMB2-only POSIX info level for query dir 1657 1657 * 1658 1658 * See posix_info_sid_size(), posix_info_extra_size() and 1659 1659 * posix_info_parse() to help with the handling of this struct. ··· 1675 1675 __le32 HardLinks; 1676 1676 __le32 ReparseTag; 1677 1677 __le32 Mode; 1678 + /* 1679 + * var sized owner SID 1680 + * var sized group SID 1681 + * le32 filenamelength 1682 + * u8 filename[] 1683 + */ 1684 + } __packed; 1685 + 1686 + /* Level 100 query info */ 1687 + struct smb311_posix_qinfo { 1688 + __le64 CreationTime; 1689 + __le64 LastAccessTime; 1690 + __le64 LastWriteTime; 1691 + __le64 ChangeTime; 1692 + __le64 EndOfFile; 1693 + __le64 AllocationSize; 1694 + __le32 DosAttributes; 1695 + __le64 Inode; 1696 + __le32 DeviceId; 1697 + __le32 Zero; 1698 + /* beginning of POSIX Create Context Response */ 1699 + __le32 HardLinks; 1700 + __le32 ReparseTag; 1701 + __le32 Mode; 1702 + u8 Sids[]; 1678 1703 /* 1679 1704 * var sized owner SID 1680 1705 * var sized group SID
+6
fs/cifs/smb2proto.h
··· 182 182 struct TCP_Server_Info *server, 183 183 u64 persistent_file_id, u64 volatile_file_id); 184 184 extern void SMB2_flush_free(struct smb_rqst *rqst); 185 + extern int SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon, 186 + u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen); 185 187 extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, 186 188 u64 persistent_file_id, u64 volatile_file_id, 187 189 struct smb2_file_all_info *data); ··· 291 289 u32 class, u32 type, u32 output_len, 292 290 struct kvec *rsp, int *buftype, 293 291 struct cifs_sb_info *cifs_sb); 292 + /* query path info from the server using SMB311 POSIX extensions*/ 293 + extern int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 294 + struct cifs_sb_info *sb, const char *path, struct smb311_posix_qinfo *qinf, 295 + bool *adjust_tx, bool *symlink); 294 296 int posix_info_parse(const void *beg, const void *end, 295 297 struct smb2_posix_info_parsed *out); 296 298 int posix_info_sid_size(const void *beg, const void *end);
+3
fs/cifs/trace.h
··· 318 318 TP_ARGS(xid, tid, sesid, full_path)) 319 319 320 320 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(query_info_compound_enter); 321 + DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(posix_query_info_compound_enter); 321 322 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(hardlink_enter); 322 323 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rename_enter); 323 324 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rmdir_enter); ··· 355 354 TP_ARGS(xid, tid, sesid)) 356 355 357 356 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(query_info_compound_done); 357 + DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(posix_query_info_compound_done); 358 358 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(hardlink_done); 359 359 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rename_done); 360 360 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rmdir_done); ··· 397 395 TP_ARGS(xid, tid, sesid, rc)) 398 396 399 397 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query_info_compound_err); 398 + DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(posix_query_info_compound_err); 400 399 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(hardlink_err); 401 400 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rename_err); 402 401 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rmdir_err);