History

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

Linus Torvalds committed 6 years ago

Commit f82e7b52 parents 4f9b3a3 a7a519a19 files · +571 −57Browse files

Unified · Split

19 files
  1. fs/cifs/cache.c +2 −7
  2. fs/cifs/cifs_debug.c +1 −3
  3. fs/cifs/cifsacl.c +64 −15
  4. fs/cifs/cifsacl.h +15 −0
  5. fs/cifs/cifsfs.c +1 −1
  6. fs/cifs/cifsglob.h +18 −0
  7. fs/cifs/cifsproto.h +3 −0
  8. fs/cifs/dir.c +4 −1
  9. fs/cifs/file.c +4 −1
  10. fs/cifs/fscache.c +15 −2
  11. fs/cifs/fscache.h +9 −0
  12. fs/cifs/inode.c +182 −3
  13. fs/cifs/link.c +3 −1
  14. fs/cifs/smb2glob.h +1 −0
  15. fs/cifs/smb2inode.c +105 −0
  16. fs/cifs/smb2pdu.c +109 −22
  17. fs/cifs/smb2pdu.h +26 −1
  18. fs/cifs/smb2proto.h +6 −0
  19. fs/cifs/trace.h +3 −0
fs/cifs/cache.c+2−7
@@ -53,13 +53,6 @@ const struct fscache_cookie_def cifs_fscache_server_index_def = { · 52 unmodified lines
53 .type = FSCACHE_COOKIE_TYPE_INDEX,53 .type = FSCACHE_COOKIE_TYPE_INDEX,
54};54};
55 55
56/*
57 * Auxiliary data attached to CIFS superblock within the cache
58 */
59struct cifs_fscache_super_auxdata {
60 u64 resource_id; /* unique server resource id */
61};
62
63char *extract_sharename(const char *treename)56char *extract_sharename(const char *treename)
64{57{
65 const char *src;58 const char *src;
@@ -98,6 +91,8 @@ fscache_checkaux cifs_fscache_super_check_aux(void *cookie_netfs_data, · 32 unmodified lines
98 91
99 memset(&auxdata, 0, sizeof(auxdata));92 memset(&auxdata, 0, sizeof(auxdata));
100 auxdata.resource_id = tcon->resource_id;93 auxdata.resource_id = tcon->resource_id;
94 auxdata.vol_create_time = tcon->vol_create_time;
95 auxdata.vol_serial_number = tcon->vol_serial_number;
101 96
102 if (memcmp(data, &auxdata, datalen) != 0)97 if (memcmp(data, &auxdata, datalen) != 0)
103 return FSCACHE_CHECKAUX_OBSOLETE;98 return FSCACHE_CHECKAUX_OBSOLETE;
fs/cifs/cifs_debug.c+1−3
@@ -221,8 +221,6 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) · 220 unmodified lines
221 struct cifs_ses *ses;221 struct cifs_ses *ses;
222 struct cifs_tcon *tcon;222 struct cifs_tcon *tcon;
223 int i, j;223 int i, j;
224 const char *security_types[] = {"Unspecified", "LANMAN", "NTLM",
225 "NTLMv2", "RawNTLMSSP", "Kerberos"};
226 224
227 seq_puts(m,225 seq_puts(m,
228 "Display Internal CIFS Data Structures for Debugging\n"226 "Display Internal CIFS Data Structures for Debugging\n"
@@ -379,7 +377,7 @@ skip_rdma: · 150 unmodified lines
379 }377 }
380 378
381 seq_printf(m,"Security type: %s\n",379 seq_printf(m,"Security type: %s\n",
382 security_types[server->ops->select_sectype(server, ses->sectype)]);380 get_security_type_str(server->ops->select_sectype(server, ses->sectype)));
383 381
384 if (server->rdma)382 if (server->rdma)
385 seq_printf(m, "RDMA\n\t");383 seq_printf(m, "RDMA\n\t");
fs/cifs/cifsacl.c+64−15
@@ -849,6 +849,28 @@ unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode) · 848 unmodified lines
849 return ace_size;849 return ace_size;
850}850}
851 851
852unsigned 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
852static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,874static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
853 struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid)875 struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid)
854{876{
@@ -978,7 +1000,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb, · 123 unmodified lines
978/* Convert permission bits from mode to equivalent CIFS ACL */1000/* Convert permission bits from mode to equivalent CIFS ACL */
979static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,1001static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
980 __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid,1002 __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid,
981 bool mode_from_sid, int *aclflag)1003 bool mode_from_sid, bool id_from_sid, int *aclflag)
982{1004{
983 int rc = 0;1005 int rc = 0;
984 __u32 dacloffset;1006 __u32 dacloffset;
@@ -1019,12 +1041,23 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, · 34 unmodified lines
1019 if (!nowner_sid_ptr)1041 if (!nowner_sid_ptr)
1020 return -ENOMEM;1042 return -ENOMEM;
1021 id = from_kuid(&init_user_ns, uid);1043 id = from_kuid(&init_user_ns, uid);
1022 rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);1044 if (id_from_sid) {
1023 if (rc) {1045 struct owner_sid *osid = (struct owner_sid *)nowner_sid_ptr;
1024 cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",1046 /* Populate the user ownership fields S-1-5-88-1 */
1025 __func__, rc, id);1047 osid->Revision = 1;
1026 kfree(nowner_sid_ptr);1048 osid->NumAuth = 3;
1027 return rc;1049 osid->Authority[5] = 5;
1050 osid->SubAuthorities[0] = cpu_to_le32(88);
1051 osid->SubAuthorities[1] = cpu_to_le32(1);
1052 osid->SubAuthorities[2] = cpu_to_le32(id);
1053 } else { /* lookup sid with upcall */
1054 rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
1055 if (rc) {
1056 cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
1057 __func__, rc, id);
1058 kfree(nowner_sid_ptr);
1059 return rc;
1060 }
1028 }1061 }
1029 cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);1062 cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
1030 kfree(nowner_sid_ptr);1063 kfree(nowner_sid_ptr);
@@ -1039,12 +1072,23 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, · 8 unmodified lines
1039 if (!ngroup_sid_ptr)1072 if (!ngroup_sid_ptr)
1040 return -ENOMEM;1073 return -ENOMEM;
1041 id = from_kgid(&init_user_ns, gid);1074 id = from_kgid(&init_user_ns, gid);
1042 rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);1075 if (id_from_sid) {
1043 if (rc) {1076 struct owner_sid *gsid = (struct owner_sid *)ngroup_sid_ptr;
1044 cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",1077 /* Populate the group ownership fields S-1-5-88-2 */
1045 __func__, rc, id);1078 gsid->Revision = 1;
1046 kfree(ngroup_sid_ptr);1079 gsid->NumAuth = 3;
1047 return rc;1080 gsid->Authority[5] = 5;
1081 gsid->SubAuthorities[0] = cpu_to_le32(88);
1082 gsid->SubAuthorities[1] = cpu_to_le32(2);
1083 gsid->SubAuthorities[2] = cpu_to_le32(id);
1084 } else { /* lookup sid with upcall */
1085 rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
1086 if (rc) {
1087 cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
1088 __func__, rc, id);
1089 kfree(ngroup_sid_ptr);
1090 return rc;
1091 }
1048 }1092 }
1049 cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);1093 cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
1050 kfree(ngroup_sid_ptr);1094 kfree(ngroup_sid_ptr);
@@ -1247,7 +1291,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, · 196 unmodified lines
1247 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);1291 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1248 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);1292 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1249 struct smb_version_operations *ops;1293 struct smb_version_operations *ops;
1250 bool mode_from_sid;1294 bool mode_from_sid, id_from_sid;
1251 1295
1252 if (IS_ERR(tlink))1296 if (IS_ERR(tlink))
1253 return PTR_ERR(tlink);1297 return PTR_ERR(tlink);
@@ -1290,8 +1334,13 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, · 36 unmodified lines
1290 else1334 else
1291 mode_from_sid = false;1335 mode_from_sid = false;
1292 1336
1337 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
1338 id_from_sid = true;
1339 else
1340 id_from_sid = false;
1341
1293 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,1342 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1294 mode_from_sid, &aclflag);1343 mode_from_sid, id_from_sid, &aclflag);
1295 1344
1296 cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);1345 cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
1297 1346
fs/cifs/cifsacl.h+15−0
@@ -176,6 +176,21 @@ struct smb3_acl { · 175 unmodified lines
176 __le16 Sbz2; /* MBZ */176 __le16 Sbz2; /* MBZ */
177} __packed;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 */
183struct owner_sid {
184 u8 Revision;
185 u8 NumAuth;
186 u8 Authority[6];
187 __le32 SubAuthorities[3];
188} __packed;
189
190struct owner_group_sids {
191 struct owner_sid owner;
192 struct owner_sid group;
193} __packed;
179 194
180/*195/*
181 * Minimum security identifier can be one for system defined Users196 * Minimum security identifier can be one for system defined Users
fs/cifs/cifsfs.c+1−1
@@ -623,7 +623,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root) · 622 unmodified lines
623 seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);623 seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
624 624
625 if (tcon->ses->chan_max > 1)625 if (tcon->ses->chan_max > 1)
626 seq_printf(s, ",multichannel,max_channel=%zu",626 seq_printf(s, ",multichannel,max_channels=%zu",
627 tcon->ses->chan_max);627 tcon->ses->chan_max);
628 628
629 return 0;629 return 0;
fs/cifs/cifsglob.h+18−0
@@ -2008,6 +2008,24 @@ extern struct smb_version_values smb302_values; · 2007 unmodified lines
2008extern struct smb_version_operations smb311_operations;2008extern struct smb_version_operations smb311_operations;
2009extern struct smb_version_values smb311_values;2009extern struct smb_version_values smb311_values;
2010 2010
2011static 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
2011static inline bool is_smb1_server(struct TCP_Server_Info *server)2029static inline bool is_smb1_server(struct TCP_Server_Info *server)
2012{2030{
2013 return strcmp(server->vals->version_string, SMB1_VERSION_STRING) == 0;2031 return strcmp(server->vals->version_string, SMB1_VERSION_STRING) == 0;
fs/cifs/cifsproto.h+3−0
@@ -198,6 +198,8 @@ extern struct inode *cifs_iget(struct super_block *sb, · 197 unmodified lines
198extern int cifs_get_inode_info(struct inode **inode, const char *full_path,198extern int cifs_get_inode_info(struct inode **inode, const char *full_path,
199 FILE_ALL_INFO *data, struct super_block *sb,199 FILE_ALL_INFO *data, struct super_block *sb,
200 int xid, const struct cifs_fid *fid);200 int xid, const struct cifs_fid *fid);
201extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path,
202 struct super_block *sb, unsigned int xid);
201extern int cifs_get_inode_info_unix(struct inode **pinode,203extern int cifs_get_inode_info_unix(struct inode **pinode,
202 const unsigned char *search_path,204 const unsigned char *search_path,
203 struct super_block *sb, unsigned int xid);205 struct super_block *sb, unsigned int xid);
@@ -220,6 +222,7 @@ extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, · 16 unmodified lines
220 const char *, int);222 const char *, int);
221extern unsigned int setup_authusers_ACE(struct cifs_ace *pace);223extern unsigned int setup_authusers_ACE(struct cifs_ace *pace);
222extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode);224extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode);
225extern unsigned int setup_special_user_owner_ACE(struct cifs_ace *pace);
223 226
224extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);227extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
225extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,228extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
fs/cifs/dir.c+4−1
@@ -411,6 +411,7 @@ cifs_create_get_file_info: · 410 unmodified lines
411 rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,411 rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,
412 xid);412 xid);
413 else {413 else {
414 /* TODO: Add support for calling POSIX query info here, but passing in fid */
414 rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,415 rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,
415 xid, fid);416 xid, fid);
416 if (newinode) {417 if (newinode) {
@@ -700,7 +701,9 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, · 283 unmodified lines
700 cifs_dbg(FYI, "Full path: %s inode = 0x%p\n",701 cifs_dbg(FYI, "Full path: %s inode = 0x%p\n",
701 full_path, d_inode(direntry));702 full_path, d_inode(direntry));
702 703
703 if (pTcon->unix_ext) {704 if (pTcon->posix_extensions)
705 rc = smb311_posix_get_inode_info(&newInode, full_path, parent_dir_inode->i_sb, xid);
706 else if (pTcon->unix_ext) {
704 rc = cifs_get_inode_info_unix(&newInode, full_path,707 rc = cifs_get_inode_info_unix(&newInode, full_path,
705 parent_dir_inode->i_sb, xid);708 parent_dir_inode->i_sb, xid);
706 } else {709 } else {
fs/cifs/file.c+4−1
@@ -243,6 +243,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, · 242 unmodified lines
243 if (rc)243 if (rc)
244 goto out;244 goto out;
245 245
246 /* TODO: Add support for calling posix query info but with passing in fid */
246 if (tcon->unix_ext)247 if (tcon->unix_ext)
247 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,248 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
248 xid);249 xid);
@@ -800,7 +801,9 @@ reopen_success: · 551 unmodified lines
800 if (!is_interrupt_error(rc))801 if (!is_interrupt_error(rc))
801 mapping_set_error(inode->i_mapping, rc);802 mapping_set_error(inode->i_mapping, rc);
802 803
803 if (tcon->unix_ext)804 if (tcon->posix_extensions)
805 rc = smb311_posix_get_inode_info(&inode, full_path, inode->i_sb, xid);
806 else if (tcon->unix_ext)
804 rc = cifs_get_inode_info_unix(&inode, full_path,807 rc = cifs_get_inode_info_unix(&inode, full_path,
805 inode->i_sb, xid);808 inode->i_sb, xid);
806 else809 else
fs/cifs/fscache.c+15−2
@@ -96,6 +96,7 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) · 95 unmodified lines
96{96{
97 struct TCP_Server_Info *server = tcon->ses->server;97 struct TCP_Server_Info *server = tcon->ses->server;
98 char *sharename;98 char *sharename;
99 struct cifs_fscache_super_auxdata auxdata;
99 100
100 sharename = extract_sharename(tcon->treeName);101 sharename = extract_sharename(tcon->treeName);
101 if (IS_ERR(sharename)) {102 if (IS_ERR(sharename)) {
@@ -104,11 +105,16 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) · 2 unmodified lines
104 return;105 return;
105 }106 }
106 107
108 memset(&auxdata, 0, sizeof(auxdata));
109 auxdata.resource_id = tcon->resource_id;
110 auxdata.vol_create_time = tcon->vol_create_time;
111 auxdata.vol_serial_number = tcon->vol_serial_number;
112
107 tcon->fscache =113 tcon->fscache =
108 fscache_acquire_cookie(server->fscache,114 fscache_acquire_cookie(server->fscache,
109 &cifs_fscache_super_index_def,115 &cifs_fscache_super_index_def,
110 sharename, strlen(sharename),116 sharename, strlen(sharename),
111 &tcon->resource_id, sizeof(tcon->resource_id),117 &auxdata, sizeof(auxdata),
112 tcon, 0, true);118 tcon, 0, true);
113 kfree(sharename);119 kfree(sharename);
114 cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",120 cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
@@ -117,8 +123,15 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) · 2 unmodified lines
117 123
118void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)124void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
119{125{
126 struct cifs_fscache_super_auxdata auxdata;
127
128 memset(&auxdata, 0, sizeof(auxdata));
129 auxdata.resource_id = tcon->resource_id;
130 auxdata.vol_create_time = tcon->vol_create_time;
131 auxdata.vol_serial_number = tcon->vol_serial_number;
132
120 cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache);133 cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache);
121 fscache_relinquish_cookie(tcon->fscache, &tcon->resource_id, false);134 fscache_relinquish_cookie(tcon->fscache, &auxdata, false);
122 tcon->fscache = NULL;135 tcon->fscache = NULL;
123}136}
124 137
fs/cifs/fscache.h+9−0
@@ -27,6 +27,15 @@ · 26 unmodified lines
27 27
28#ifdef CONFIG_CIFS_FSCACHE28#ifdef CONFIG_CIFS_FSCACHE
29 29
30/*
31 * Auxiliary data attached to CIFS superblock within the cache
32 */
33struct 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
30/*39/*
31 * Auxiliary data attached to CIFS inode within the cache40 * Auxiliary data attached to CIFS inode within the cache
32 */41 */
fs/cifs/inode.c+182−3
@@ -32,6 +32,7 @@ · 31 unmodified lines
32#include "cifspdu.h"32#include "cifspdu.h"
33#include "cifsglob.h"33#include "cifsglob.h"
34#include "cifsproto.h"34#include "cifsproto.h"
35#include "smb2proto.h"
35#include "cifs_debug.h"36#include "cifs_debug.h"
36#include "cifs_fs_sb.h"37#include "cifs_fs_sb.h"
37#include "cifs_unicode.h"38#include "cifs_unicode.h"
@@ -595,6 +596,62 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, · 557 unmodified lines
595#endif596#endif
596}597}
597 598
599/* Fill a cifs_fattr struct with info from POSIX info struct */
600static void
601smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct smb311_posix_qinfo *info,
602 struct super_block *sb, bool adjust_tz, bool symlink)
603{
604 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
605 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
606
607 memset(fattr, 0, sizeof(*fattr));
608
609 /* no fattr->flags to set */
610 fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes);
611 fattr->cf_uniqueid = le64_to_cpu(info->Inode);
612
613 if (info->LastAccessTime)
614 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
615 else
616 ktime_get_coarse_real_ts64(&fattr->cf_atime);
617
618 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
619 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
620
621 if (adjust_tz) {
622 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
623 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
624 }
625
626 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
627 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
628 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
629
630 fattr->cf_nlink = le32_to_cpu(info->HardLinks);
631 fattr->cf_mode = (umode_t) le32_to_cpu(info->Mode);
632 /* The srv fs device id is overridden on network mount so setting rdev isn't needed here */
633 /* fattr->cf_rdev = le32_to_cpu(info->DeviceId); */
634
635 if (symlink) {
636 fattr->cf_mode |= S_IFLNK;
637 fattr->cf_dtype = DT_LNK;
638 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
639 fattr->cf_mode |= S_IFDIR;
640 fattr->cf_dtype = DT_DIR;
641 } else { /* file */
642 fattr->cf_mode |= S_IFREG;
643 fattr->cf_dtype = DT_REG;
644 }
645 /* else if reparse point ... TODO: add support for FIFO and blk dev; special file types */
646
647 fattr->cf_uid = cifs_sb->mnt_uid; /* TODO: map uid and gid from SID */
648 fattr->cf_gid = cifs_sb->mnt_gid;
649
650 cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n",
651 fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
652}
653
654
598/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */655/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
599static void656static void
600cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,657cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
@@ -1023,6 +1080,121 @@ out: · 422 unmodified lines
1023 return rc;1080 return rc;
1024}1081}
1025 1082
1083int
1084smb311_posix_get_inode_info(struct inode **inode,
1085 const char *full_path,
1086 struct super_block *sb, unsigned int xid)
1087{
1088 struct cifs_tcon *tcon;
1089 struct TCP_Server_Info *server;
1090 struct tcon_link *tlink;
1091 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1092 bool adjust_tz = false;
1093 struct cifs_fattr fattr = {0};
1094 bool symlink = false;
1095 struct smb311_posix_qinfo *data = NULL;
1096 int rc = 0;
1097 int tmprc = 0;
1098
1099 tlink = cifs_sb_tlink(cifs_sb);
1100 if (IS_ERR(tlink))
1101 return PTR_ERR(tlink);
1102 tcon = tlink_tcon(tlink);
1103 server = tcon->ses->server;
1104
1105 /*
1106 * 1. Fetch file metadata
1107 */
1108
1109 if (is_inode_cache_good(*inode)) {
1110 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
1111 goto out;
1112 }
1113 data = kmalloc(sizeof(struct smb311_posix_qinfo), GFP_KERNEL);
1114 if (!data) {
1115 rc = -ENOMEM;
1116 goto out;
1117 }
1118
1119 rc = smb311_posix_query_path_info(xid, tcon, cifs_sb,
1120 full_path, data,
1121 &adjust_tz, &symlink);
1122
1123 /*
1124 * 2. Convert it to internal cifs metadata (fattr)
1125 */
1126
1127 switch (rc) {
1128 case 0:
1129 smb311_posix_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
1130 break;
1131 case -EREMOTE:
1132 /* DFS link, no metadata available on this server */
1133 cifs_create_dfs_fattr(&fattr, sb);
1134 rc = 0;
1135 break;
1136 case -EACCES:
1137 /*
1138 * For SMB2 and later the backup intent flag
1139 * is already sent if needed on open and there
1140 * is no path based FindFirst operation to use
1141 * to retry with so nothing we can do, bail out
1142 */
1143 goto out;
1144 default:
1145 cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
1146 goto out;
1147 }
1148
1149
1150 /*
1151 * 3. Tweak fattr based on mount options
1152 */
1153
1154 /* check for Minshall+French symlinks */
1155 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
1156 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
1157 full_path);
1158 if (tmprc)
1159 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
1160 }
1161
1162 /*
1163 * 4. Update inode with final fattr data
1164 */
1165
1166 if (!*inode) {
1167 *inode = cifs_iget(sb, &fattr);
1168 if (!*inode)
1169 rc = -ENOMEM;
1170 } else {
1171 /* we already have inode, update it */
1172
1173 /* if uniqueid is different, return error */
1174 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
1175 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
1176 CIFS_I(*inode)->time = 0; /* force reval */
1177 rc = -ESTALE;
1178 goto out;
1179 }
1180
1181 /* if filetype is different, return error */
1182 if (unlikely(((*inode)->i_mode & S_IFMT) !=
1183 (fattr.cf_mode & S_IFMT))) {
1184 CIFS_I(*inode)->time = 0; /* force reval */
1185 rc = -ESTALE;
1186 goto out;
1187 }
1188
1189 cifs_fattr_to_inode(*inode, &fattr);
1190 }
1191out:
1192 cifs_put_tlink(tlink);
1193 kfree(data);
1194 return rc;
1195}
1196
1197
1026static const struct inode_operations cifs_ipc_inode_ops = {1198static const struct inode_operations cifs_ipc_inode_ops = {
1027 .lookup = cifs_lookup,1199 .lookup = cifs_lookup,
1028};1200};
@@ -1161,7 +1333,10 @@ struct inode *cifs_root_iget(struct super_block *sb) · 132 unmodified lines
1161 }1333 }
1162 1334
1163 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));1335 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
1164 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);1336 if (tcon->posix_extensions)
1337 rc = smb311_posix_get_inode_info(&inode, path, sb, xid);
1338 else
1339 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
1165 1340
1166iget_no_retry:1341iget_no_retry:
1167 if (!inode) {1342 if (!inode) {
@@ -1517,7 +1692,9 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, · 349 unmodified lines
1517 int rc = 0;1692 int rc = 0;
1518 struct inode *inode = NULL;1693 struct inode *inode = NULL;
1519 1694
1520 if (tcon->unix_ext)1695 if (tcon->posix_extensions)
1696 rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid);
1697 else if (tcon->unix_ext)
1521 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,1698 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
1522 xid);1699 xid);
1523 else1700 else
@@ -2114,7 +2291,9 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry) · 590 unmodified lines
2114 dentry, cifs_get_time(dentry), jiffies);2291 dentry, cifs_get_time(dentry), jiffies);
2115 2292
2116again:2293again:
2117 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)2294 if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions)
2295 rc = smb311_posix_get_inode_info(&inode, full_path, sb, xid);
2296 else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
2118 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);2297 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
2119 else2298 else
2120 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,2299 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
fs/cifs/link.c+3−1
@@ -701,7 +701,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) · 700 unmodified lines
701 cifs_sb_target->local_nls); */701 cifs_sb_target->local_nls); */
702 702
703 if (rc == 0) {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 rc = cifs_get_inode_info_unix(&newinode, full_path,707 rc = cifs_get_inode_info_unix(&newinode, full_path,
706 inode->i_sb, xid);708 inode->i_sb, xid);
707 else709 else
fs/cifs/smb2glob.h+1−0
@@ -45,6 +45,7 @@ · 44 unmodified lines
45#define SMB2_OP_HARDLINK 845#define SMB2_OP_HARDLINK 8
46#define SMB2_OP_SET_EOF 946#define SMB2_OP_SET_EOF 9
47#define SMB2_OP_RMDIR 1047#define SMB2_OP_RMDIR 10
48#define SMB2_OP_POSIX_QUERY_INFO 11
48 49
49/* Used when constructing chained read requests. */50/* Used when constructing chained read requests. */
50#define CHAINED_REQUEST 151#define CHAINED_REQUEST 1
fs/cifs/smb2inode.c+105−0
@@ -166,6 +166,40 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, · 165 unmodified lines
166 trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid,166 trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid,
167 full_path);167 full_path);
168 break;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 case SMB2_OP_DELETE:203 case SMB2_OP_DELETE:
170 trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path);204 trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path);
171 break;205 break;
@@ -379,6 +413,24 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, · 207 unmodified lines
379 trace_smb3_query_info_compound_done(xid, ses->Suid,413 trace_smb3_query_info_compound_done(xid, ses->Suid,
380 tcon->tid);414 tcon->tid);
381 break;415 break;
416 case SMB2_OP_POSIX_QUERY_INFO:
417 if (rc == 0) {
418 qi_rsp = (struct smb2_query_info_rsp *)
419 rsp_iov[1].iov_base;
420 rc = smb2_validate_and_copy_iov(
421 le16_to_cpu(qi_rsp->OutputBufferOffset),
422 le32_to_cpu(qi_rsp->OutputBufferLength),
423 &rsp_iov[1], sizeof(struct smb311_posix_qinfo) /* add SIDs */, ptr);
424 }
425 if (rqst[1].rq_iov)
426 SMB2_query_info_free(&rqst[1]);
427 if (rqst[2].rq_iov)
428 SMB2_close_free(&rqst[2]);
429 if (rc)
430 trace_smb3_posix_query_info_compound_err(xid, ses->Suid, tcon->tid, rc);
431 else
432 trace_smb3_posix_query_info_compound_done(xid, ses->Suid, tcon->tid);
433 break;
382 case SMB2_OP_DELETE:434 case SMB2_OP_DELETE:
383 if (rc)435 if (rc)
384 trace_smb3_delete_err(xid, ses->Suid, tcon->tid, rc);436 trace_smb3_delete_err(xid, ses->Suid, tcon->tid, rc);
@@ -512,6 +564,59 @@ out: · 127 unmodified lines
512 return rc;564 return rc;
513}565}
514 566
567
568int
569smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
570 struct cifs_sb_info *cifs_sb, const char *full_path,
571 struct smb311_posix_qinfo *data, bool *adjust_tz, bool *symlink)
572{
573 int rc;
574 __u32 create_options = 0;
575 struct cifsFileInfo *cfile;
576 struct smb311_posix_qinfo *smb2_data;
577
578 *adjust_tz = false;
579 *symlink = false;
580
581 /* BB TODO: Make struct larger when add support for parsing owner SIDs */
582 smb2_data = kzalloc(sizeof(struct smb311_posix_qinfo),
583 GFP_KERNEL);
584 if (smb2_data == NULL)
585 return -ENOMEM;
586
587 /*
588 * BB TODO: Add support for using the cached root handle.
589 * Create SMB2_query_posix_info worker function to do non-compounded query
590 * when we already have an open file handle for this. For now this is fast enough
591 * (always using the compounded version).
592 */
593
594 cifs_get_readable_path(tcon, full_path, &cfile);
595 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
596 FILE_READ_ATTRIBUTES, FILE_OPEN, create_options,
597 ACL_NO_MODE, smb2_data, SMB2_OP_POSIX_QUERY_INFO, cfile);
598 if (rc == -EOPNOTSUPP) {
599 /* BB TODO: When support for special files added to Samba re-verify this path */
600 *symlink = true;
601 create_options |= OPEN_REPARSE_POINT;
602
603 /* Failed on a symbolic link - query a reparse point info */
604 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
605 FILE_READ_ATTRIBUTES, FILE_OPEN,
606 create_options, ACL_NO_MODE,
607 smb2_data, SMB2_OP_POSIX_QUERY_INFO, NULL);
608 }
609 if (rc)
610 goto out;
611
612 /* TODO: will need to allow for the 2 SIDs when add support for getting owner UID/GID */
613 memcpy(data, smb2_data, sizeof(struct smb311_posix_qinfo));
614
615out:
616 kfree(smb2_data);
617 return rc;
618}
619
515int620int
516smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,621smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
517 struct cifs_tcon *tcon, const char *name,622 struct cifs_tcon *tcon, const char *name,
fs/cifs/smb2pdu.c+109−22
@@ -2317,28 +2317,75 @@ add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp) · 2316 unmodified lines
2317 return 0;2317 return 0;
2318}2318}
2319 2319
2320/* See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */
2321static 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/* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */2344/* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */
2321static struct crt_sd_ctxt *2345static struct crt_sd_ctxt *
2322create_sd_buf(umode_t mode, unsigned int *len)2346create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
2323{2347{
2324 struct crt_sd_ctxt *buf;2348 struct crt_sd_ctxt *buf;
2325 struct cifs_ace *pace;2349 struct cifs_ace *pace;
2326 unsigned int sdlen, acelen;2350 unsigned int sdlen, acelen;
2351 unsigned int owner_offset = 0;
2352 unsigned int group_offset = 0;
2353
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 }
2327 2363
2328 *len = roundup(sizeof(struct crt_sd_ctxt) + sizeof(struct cifs_ace) * 2,
2329 8);
2330 buf = kzalloc(*len, GFP_KERNEL);2364 buf = kzalloc(*len, GFP_KERNEL);
2331 if (buf == NULL)2365 if (buf == NULL)
2332 return buf;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 sdlen = sizeof(struct smb3_sd) + sizeof(struct smb3_acl) +2377 sdlen = sizeof(struct smb3_sd) + sizeof(struct smb3_acl) +
2335 2 * sizeof(struct cifs_ace);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 buf->ccontext.DataOffset = cpu_to_le16(offsetof2385 buf->ccontext.DataOffset = cpu_to_le16(offsetof
2338 (struct crt_sd_ctxt, sd));2386 (struct crt_sd_ctxt, sd));
2339 buf->ccontext.DataLength = cpu_to_le32(sdlen);2387 buf->ccontext.DataLength = cpu_to_le32(sdlen);
2340 buf->ccontext.NameOffset = cpu_to_le16(offsetof2388 buf->ccontext.NameOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, Name));
2341 (struct crt_sd_ctxt, Name));
2342 buf->ccontext.NameLength = cpu_to_le16(4);2389 buf->ccontext.NameLength = cpu_to_le16(4);
2343 /* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */2390 /* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */
2344 buf->Name[0] = 'S';2391 buf->Name[0] = 'S';
@@ -2359,23 +2406,34 @@ create_sd_buf(umode_t mode, unsigned int *len) · 14 unmodified lines
2359 /* create one ACE to hold the mode embedded in reserved special SID */2406 /* create one ACE to hold the mode embedded in reserved special SID */
2360 pace = (struct cifs_ace *)(sizeof(struct crt_sd_ctxt) + (char *)buf);2407 pace = (struct cifs_ace *)(sizeof(struct crt_sd_ctxt) + (char *)buf);
2361 acelen = setup_special_mode_ACE(pace, (__u64)mode);2408 acelen = setup_special_mode_ACE(pace, (__u64)mode);
2409
2410 if (set_owner) {
2411 /* we do not need to reallocate buffer to add the two more ACEs. plenty of space */
2412 pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) + (char *)buf));
2413 acelen += setup_special_user_owner_ACE(pace);
2414 /* it does not appear necessary to add an ACE for the NFS group SID */
2415 buf->acl.AceCount = cpu_to_le16(3);
2416 } else
2417 buf->acl.AceCount = cpu_to_le16(2);
2418
2362 /* and one more ACE to allow access for authenticated users */2419 /* and one more ACE to allow access for authenticated users */
2363 pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) +2420 pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) +
2364 (char *)buf));2421 (char *)buf));
2365 acelen += setup_authusers_ACE(pace);2422 acelen += setup_authusers_ACE(pace);
2423
2366 buf->acl.AclSize = cpu_to_le16(sizeof(struct cifs_acl) + acelen);2424 buf->acl.AclSize = cpu_to_le16(sizeof(struct cifs_acl) + acelen);
2367 buf->acl.AceCount = cpu_to_le16(2);2425
2368 return buf;2426 return buf;
2369}2427}
2370 2428
2371static int2429static int
2372add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)2430add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode, bool set_owner)
2373{2431{
2374 struct smb2_create_req *req = iov[0].iov_base;2432 struct smb2_create_req *req = iov[0].iov_base;
2375 unsigned int num = *num_iovec;2433 unsigned int num = *num_iovec;
2376 unsigned int len = 0;2434 unsigned int len = 0;
2377 2435
2378 iov[num].iov_base = create_sd_buf(mode, &len);2436 iov[num].iov_base = create_sd_buf(mode, set_owner, &len);
2379 if (iov[num].iov_base == NULL)2437 if (iov[num].iov_base == NULL)
2380 return -ENOMEM;2438 return -ENOMEM;
2381 iov[num].iov_len = len;2439 iov[num].iov_len = len;
@@ -2764,21 +2822,35 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, · 382 unmodified lines
2764 return rc;2822 return rc;
2765 }2823 }
2766 2824
2767 if ((oparms->disposition != FILE_OPEN) &&2825 if ((oparms->disposition != FILE_OPEN) && (oparms->cifs_sb)) {
2768 (oparms->cifs_sb) &&2826 bool set_mode;
2769 (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) &&2827 bool set_owner;
2770 (oparms->mode != ACL_NO_MODE)) {2828
2771 if (n_iov > 2) {2829 if ((oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) &&
2772 struct create_context *ccontext =2830 (oparms->mode != ACL_NO_MODE))
2773 (struct create_context *)iov[n_iov-1].iov_base;2831 set_mode = true;
2774 ccontext->Next =2832 else {
2775 cpu_to_le32(iov[n_iov-1].iov_len);2833 set_mode = false;
2834 oparms->mode = ACL_NO_MODE;
2776 }2835 }
2777 2836
2778 cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode);2837 if (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
2779 rc = add_sd_context(iov, &n_iov, oparms->mode);2838 set_owner = true;
2780 if (rc)2839 else
2781 return rc;2840 set_owner = false;
2841
2842 if (set_owner | set_mode) {
2843 if (n_iov > 2) {
2844 struct create_context *ccontext =
2845 (struct create_context *)iov[n_iov-1].iov_base;
2846 ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len);
2847 }
2848
2849 cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode);
2850 rc = add_sd_context(iov, &n_iov, oparms->mode, set_owner);
2851 if (rc)
2852 return rc;
2853 }
2782 }2854 }
2783 2855
2784 if (n_iov > 2) {2856 if (n_iov > 2) {
@@ -2973,7 +3045,9 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, · 188 unmodified lines
2973 * response size smaller.3045 * response size smaller.
2974 */3046 */
2975 req->MaxOutputResponse = cpu_to_le32(max_response_size);3047 req->MaxOutputResponse = cpu_to_le32(max_response_size);
2976 req->sync_hdr.CreditCharge = cpu_to_le16(DIV_ROUND_UP(max_response_size, SMB2_MAX_BUFFER_SIZE));3048 req->sync_hdr.CreditCharge =
3049 cpu_to_le16(DIV_ROUND_UP(max(indatalen, max_response_size),
3050 SMB2_MAX_BUFFER_SIZE));
2977 if (is_fsctl)3051 if (is_fsctl)
2978 req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL);3052 req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL);
2979 else3053 else
@@ -3456,6 +3530,19 @@ int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, · 476 unmodified lines
3456 NULL);3530 NULL);
3457}3531}
3458 3532
3533int
3534SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon,
3535 u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen)
3536{
3537 size_t output_len = sizeof(struct smb311_posix_qinfo *) +
3538 (sizeof(struct cifs_sid) * 2) + (PATH_MAX * 2);
3539 *plen = 0;
3540
3541 return query_info(xid, tcon, persistent_fid, volatile_fid,
3542 SMB_FIND_FILE_POSIX_INFO, SMB2_O_INFO_FILE, 0,
3543 output_len, sizeof(struct smb311_posix_qinfo), (void **)&data, plen);
3544}
3545
3459int3546int
3460SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,3547SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
3461 u64 persistent_fid, u64 volatile_fid,3548 u64 persistent_fid, u64 volatile_fid,
fs/cifs/smb2pdu.h+26−1
@@ -1653,7 +1653,7 @@ struct create_posix_rsp { · 1652 unmodified lines
1653} __packed;1653} __packed;
1654 1654
1655/*1655/*
1656 * SMB2-only POSIX info level1656 * SMB2-only POSIX info level for query dir
1657 *1657 *
1658 * See posix_info_sid_size(), posix_info_extra_size() and1658 * See posix_info_sid_size(), posix_info_extra_size() and
1659 * posix_info_parse() to help with the handling of this struct.1659 * posix_info_parse() to help with the handling of this struct.
@@ -1683,6 +1683,31 @@ struct smb2_posix_info { · 23 unmodified lines
1683 */1683 */
1684} __packed;1684} __packed;
1685 1685
1686/* Level 100 query info */
1687struct 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[];
1703 /*
1704 * var sized owner SID
1705 * var sized group SID
1706 * le32 filenamelength
1707 * u8 filename[]
1708 */
1709} __packed;
1710
1686/*1711/*
1687 * Parsed version of the above struct. Allows direct access to the1712 * Parsed version of the above struct. Allows direct access to the
1688 * variable length fields1713 * variable length fields
fs/cifs/smb2proto.h+6−0
@@ -182,6 +182,8 @@ extern int SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst, · 181 unmodified lines
182 struct TCP_Server_Info *server,182 struct TCP_Server_Info *server,
183 u64 persistent_file_id, u64 volatile_file_id);183 u64 persistent_file_id, u64 volatile_file_id);
184extern void SMB2_flush_free(struct smb_rqst *rqst);184extern void SMB2_flush_free(struct smb_rqst *rqst);
185extern 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);
185extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,187extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
186 u64 persistent_file_id, u64 volatile_file_id,188 u64 persistent_file_id, u64 volatile_file_id,
187 struct smb2_file_all_info *data);189 struct smb2_file_all_info *data);
@@ -289,6 +291,10 @@ extern int smb2_query_info_compound(const unsigned int xid, · 101 unmodified lines
289 u32 class, u32 type, u32 output_len,291 u32 class, u32 type, u32 output_len,
290 struct kvec *rsp, int *buftype,292 struct kvec *rsp, int *buftype,
291 struct cifs_sb_info *cifs_sb);293 struct cifs_sb_info *cifs_sb);
294/* query path info from the server using SMB311 POSIX extensions*/
295extern int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
296 struct cifs_sb_info *sb, const char *path, struct smb311_posix_qinfo *qinf,
297 bool *adjust_tx, bool *symlink);
292int posix_info_parse(const void *beg, const void *end,298int posix_info_parse(const void *beg, const void *end,
293 struct smb2_posix_info_parsed *out);299 struct smb2_posix_info_parsed *out);
294int posix_info_sid_size(const void *beg, const void *end);300int posix_info_sid_size(const void *beg, const void *end);
fs/cifs/trace.h+3−0
@@ -318,6 +318,7 @@ DEFINE_EVENT(smb3_inf_compound_enter_class, smb3_##name, \ · 317 unmodified lines
318 TP_ARGS(xid, tid, sesid, full_path))318 TP_ARGS(xid, tid, sesid, full_path))
319 319
320DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(query_info_compound_enter);320DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(query_info_compound_enter);
321DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(posix_query_info_compound_enter);
321DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(hardlink_enter);322DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(hardlink_enter);
322DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rename_enter);323DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rename_enter);
323DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rmdir_enter);324DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rmdir_enter);
@@ -354,6 +355,7 @@ DEFINE_EVENT(smb3_inf_compound_done_class, smb3_##name, \ · 30 unmodified lines
354 TP_ARGS(xid, tid, sesid))355 TP_ARGS(xid, tid, sesid))
355 356
356DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(query_info_compound_done);357DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(query_info_compound_done);
358DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(posix_query_info_compound_done);
357DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(hardlink_done);359DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(hardlink_done);
358DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rename_done);360DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rename_done);
359DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rmdir_done);361DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rmdir_done);
@@ -395,6 +397,7 @@ DEFINE_EVENT(smb3_inf_compound_err_class, smb3_##name, \ · 35 unmodified lines
395 TP_ARGS(xid, tid, sesid, rc))397 TP_ARGS(xid, tid, sesid, rc))
396 398
397DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query_info_compound_err);399DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query_info_compound_err);
400DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(posix_query_info_compound_err);
398DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(hardlink_err);401DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(hardlink_err);
399DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rename_err);402DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rename_err);
400DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rmdir_err);403DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rmdir_err);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t