History

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

Pull cifs fixes from Steve French: - one smb3 (ACL related) fix for stable - one SMB3 security enhancement (when mounting -t smb3 forbid less secure dialects) - some RDMA and compounding fixes * tag '4.18-fixes-smb3' of git://git.samba.org/sfrench/cifs-2.6: cifs: fix a buffer leak in smb2_query_symlink smb3: do not allow insecure cifs mounts when using smb3 CIFS: Fix NULL ptr deref CIFS: fix encryption in SMB3.1.1 CIFS: Pass page offset for encrypting CIFS: Pass page offset for calculating signature CIFS: SMBD: Support page offset in memory registration CIFS: SMBD: Support page offset in RDMA recv CIFS: SMBD: Support page offset in RDMA send CIFS: When sending data on socket, pass the correct page offset CIFS: Introduce helper function to get page offset and length in smb_rqst CIFS: Calculate the correct request length based on page offset and tail size cifs: For SMB2 security informaion query, check for minimum sized security descriptor instead of sizeof FileAllInformation class CIFS: Fix signing for SMB2/3

Linus Torvalds committed 8 years ago

Commit 0c14e432 parents bbaa101 9d874c318 files · +261 −138Browse files

Unified · Split

18 files
  1. fs/cifs/cifsacl.h +14 −0
  2. fs/cifs/cifsencrypt.c +8 −9
  3. fs/cifs/cifsfs.c +18 −4
  4. fs/cifs/cifsglob.h +6 −0
  5. fs/cifs/cifsproto.h +5 −2
  6. fs/cifs/connect.c +17 −15
  7. fs/cifs/link.c +4 −2
  8. fs/cifs/misc.c +17 −0
  9. fs/cifs/smb2file.c +2 −1
  10. fs/cifs/smb2inode.c +2 −1
  11. fs/cifs/smb2misc.c +3 −1
  12. fs/cifs/smb2ops.c +42 −31
  13. fs/cifs/smb2pdu.c +15 −9
  14. fs/cifs/smb2proto.h +1 −1
  15. fs/cifs/smb2transport.c +8 −4
  16. fs/cifs/smbdirect.c +75 −46
  17. fs/cifs/smbdirect.h +1 −1
  18. fs/cifs/transport.c +23 −11
fs/cifs/cifsacl.h+14−0
@@ -98,4 +98,18 @@ struct cifs_ace { · 97 unmodified lines
98 struct cifs_sid sid; /* ie UUID of user or group who gets these perms */98 struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
99} __attribute__((packed));99} __attribute__((packed));
100 100
101/*
102 * Minimum security identifier can be one for system defined Users
103 * and Groups such as NULL SID and World or Built-in accounts such
104 * as Administrator and Guest and consists of
105 * Revision + Num (Sub)Auths + Authority + Domain (one Subauthority)
106 */
107#define MIN_SID_LEN (1 + 1 + 6 + 4) /* in bytes */
108
109/*
110 * Minimum security descriptor can be one without any SACL and DACL and can
111 * consist of revision, type, and two sids of minimum size for owner and group
112 */
113#define MIN_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + (2 * MIN_SID_LEN))
114
101#endif /* _CIFSACL_H */115#endif /* _CIFSACL_H */
fs/cifs/cifsencrypt.c+8−9
@@ -37,6 +37,7 @@ · 36 unmodified lines
37#include <crypto/aead.h>37#include <crypto/aead.h>
38 38
39int __cifs_calc_signature(struct smb_rqst *rqst,39int __cifs_calc_signature(struct smb_rqst *rqst,
40 int start,
40 struct TCP_Server_Info *server, char *signature,41 struct TCP_Server_Info *server, char *signature,
41 struct shash_desc *shash)42 struct shash_desc *shash)
42{43{
@@ -45,10 +46,7 @@ int __cifs_calc_signature(struct smb_rqst *rqst, · 2 unmodified lines
45 struct kvec *iov = rqst->rq_iov;46 struct kvec *iov = rqst->rq_iov;
46 int n_vec = rqst->rq_nvec;47 int n_vec = rqst->rq_nvec;
47 48
48 if (n_vec < 2 || iov[0].iov_len != 4)49 for (i = start; i < n_vec; i++) {
49 return -EIO;
50
51 for (i = 1; i < n_vec; i++) {
52 if (iov[i].iov_len == 0)50 if (iov[i].iov_len == 0)
53 continue;51 continue;
54 if (iov[i].iov_base == NULL) {52 if (iov[i].iov_base == NULL) {
@@ -68,11 +66,12 @@ int __cifs_calc_signature(struct smb_rqst *rqst, · 13 unmodified lines
68 66
69 /* now hash over the rq_pages array */67 /* now hash over the rq_pages array */
70 for (i = 0; i < rqst->rq_npages; i++) {68 for (i = 0; i < rqst->rq_npages; i++) {
71 void *kaddr = kmap(rqst->rq_pages[i]);69 void *kaddr;
72 size_t len = rqst->rq_pagesz;70 unsigned int len, offset;
71
72 rqst_page_get_length(rqst, i, &len, &offset);
73 73
74 if (i == rqst->rq_npages - 1)74 kaddr = (char *) kmap(rqst->rq_pages[i]) + offset;
75 len = rqst->rq_tailsz;
76 75
77 crypto_shash_update(shash, kaddr, len);76 crypto_shash_update(shash, kaddr, len);
78 77
@@ -119,7 +118,7 @@ static int cifs_calc_signature(struct smb_rqst *rqst, · 40 unmodified lines
119 return rc;118 return rc;
120 }119 }
121 120
122 return __cifs_calc_signature(rqst, server, signature,121 return __cifs_calc_signature(rqst, 1, server, signature,
123 &server->secmech.sdescmd5->shash);122 &server->secmech.sdescmd5->shash);
124}123}
125 124
fs/cifs/cifsfs.c+18−4
@@ -698,8 +698,8 @@ static int cifs_set_super(struct super_block *sb, void *data) · 697 unmodified lines
698}698}
699 699
700static struct dentry *700static struct dentry *
701cifs_do_mount(struct file_system_type *fs_type,701cifs_smb3_do_mount(struct file_system_type *fs_type,
702 int flags, const char *dev_name, void *data)702 int flags, const char *dev_name, void *data, bool is_smb3)
703{703{
704 int rc;704 int rc;
705 struct super_block *sb;705 struct super_block *sb;
@@ -710,7 +710,7 @@ cifs_do_mount(struct file_system_type *fs_type, · 4 unmodified lines
710 710
711 cifs_dbg(FYI, "Devname: %s flags: %d\n", dev_name, flags);711 cifs_dbg(FYI, "Devname: %s flags: %d\n", dev_name, flags);
712 712
713 volume_info = cifs_get_volume_info((char *)data, dev_name);713 volume_info = cifs_get_volume_info((char *)data, dev_name, is_smb3);
714 if (IS_ERR(volume_info))714 if (IS_ERR(volume_info))
715 return ERR_CAST(volume_info);715 return ERR_CAST(volume_info);
716 716
@@ -790,6 +790,20 @@ out_nls: · 73 unmodified lines
790 goto out;790 goto out;
791}791}
792 792
793static struct dentry *
794smb3_do_mount(struct file_system_type *fs_type,
795 int flags, const char *dev_name, void *data)
796{
797 return cifs_smb3_do_mount(fs_type, flags, dev_name, data, true);
798}
799
800static struct dentry *
801cifs_do_mount(struct file_system_type *fs_type,
802 int flags, const char *dev_name, void *data)
803{
804 return cifs_smb3_do_mount(fs_type, flags, dev_name, data, false);
805}
806
793static ssize_t807static ssize_t
794cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)808cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)
795{809{
@@ -925,7 +939,7 @@ MODULE_ALIAS_FS("cifs"); · 129 unmodified lines
925static struct file_system_type smb3_fs_type = {939static struct file_system_type smb3_fs_type = {
926 .owner = THIS_MODULE,940 .owner = THIS_MODULE,
927 .name = "smb3",941 .name = "smb3",
928 .mount = cifs_do_mount,942 .mount = smb3_do_mount,
929 .kill_sb = cifs_kill_sb,943 .kill_sb = cifs_kill_sb,
930 /* .fs_flags */944 /* .fs_flags */
931};945};
fs/cifs/cifsglob.h+6−0
@@ -1019,6 +1019,12 @@ tlink_tcon(struct tcon_link *tlink) · 1018 unmodified lines
1019 return tlink->tl_tcon;1019 return tlink->tl_tcon;
1020}1020}
1021 1021
1022static inline struct tcon_link *
1023cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
1024{
1025 return cifs_sb->master_tlink;
1026}
1027
1022extern void cifs_put_tlink(struct tcon_link *tlink);1028extern void cifs_put_tlink(struct tcon_link *tlink);
1023 1029
1024static inline struct tcon_link *1030static inline struct tcon_link *
fs/cifs/cifsproto.h+5−2
@@ -211,7 +211,7 @@ extern int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, · 210 unmodified lines
211extern int cifs_match_super(struct super_block *, void *);211extern int cifs_match_super(struct super_block *, void *);
212extern void cifs_cleanup_volume_info(struct smb_vol *pvolume_info);212extern void cifs_cleanup_volume_info(struct smb_vol *pvolume_info);
213extern struct smb_vol *cifs_get_volume_info(char *mount_data,213extern struct smb_vol *cifs_get_volume_info(char *mount_data,
214 const char *devname);214 const char *devname, bool is_smb3);
215extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *);215extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *);
216extern void cifs_umount(struct cifs_sb_info *);216extern void cifs_umount(struct cifs_sb_info *);
217extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon);217extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon);
@@ -544,7 +544,7 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, · 326 unmodified lines
544 struct cifs_sb_info *cifs_sb,544 struct cifs_sb_info *cifs_sb,
545 const unsigned char *path, char *pbuf,545 const unsigned char *path, char *pbuf,
546 unsigned int *pbytes_written);546 unsigned int *pbytes_written);
547int __cifs_calc_signature(struct smb_rqst *rqst,547int __cifs_calc_signature(struct smb_rqst *rqst, int start,
548 struct TCP_Server_Info *server, char *signature,548 struct TCP_Server_Info *server, char *signature,
549 struct shash_desc *shash);549 struct shash_desc *shash);
550enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,550enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
@@ -557,4 +557,7 @@ int cifs_alloc_hash(const char *name, struct crypto_shash **shash, · 6 unmodified lines
557 struct sdesc **sdesc);557 struct sdesc **sdesc);
558void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc);558void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc);
559 559
560extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
561 unsigned int *len, unsigned int *offset);
562
560#endif /* _CIFSPROTO_H */563#endif /* _CIFSPROTO_H */
fs/cifs/connect.c+17−15
@@ -320,7 +320,7 @@ static int generic_ip_connect(struct TCP_Server_Info *server); · 319 unmodified lines
320static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);320static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
321static void cifs_prune_tlinks(struct work_struct *work);321static void cifs_prune_tlinks(struct work_struct *work);
322static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,322static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
323 const char *devname);323 const char *devname, bool is_smb3);
324 324
325/*325/*
326 * cifs tcp session reconnection326 * cifs tcp session reconnection
@@ -1166,7 +1166,7 @@ cifs_parse_cache_flavor(char *value, struct smb_vol *vol) · 839 unmodified lines
1166}1166}
1167 1167
1168static int1168static int
1169cifs_parse_smb_version(char *value, struct smb_vol *vol)1169cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
1170{1170{
1171 substring_t args[MAX_OPT_ARGS];1171 substring_t args[MAX_OPT_ARGS];
1172 1172
@@ -1176,6 +1176,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol) · 3 unmodified lines
1176 cifs_dbg(VFS, "mount with legacy dialect disabled\n");1176 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1177 return 1;1177 return 1;
1178 }1178 }
1179 if (is_smb3) {
1180 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1181 return 1;
1182 }
1179 vol->ops = &smb1_operations;1183 vol->ops = &smb1_operations;
1180 vol->vals = &smb1_values;1184 vol->vals = &smb1_values;
1181 break;1185 break;
@@ -1184,6 +1188,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol) · 2 unmodified lines
1184 cifs_dbg(VFS, "mount with legacy dialect disabled\n");1188 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1185 return 1;1189 return 1;
1186 }1190 }
1191 if (is_smb3) {
1192 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1193 return 1;
1194 }
1187 vol->ops = &smb20_operations;1195 vol->ops = &smb20_operations;
1188 vol->vals = &smb20_values;1196 vol->vals = &smb20_values;
1189 break;1197 break;
@@ -1272,7 +1280,7 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol) · 82 unmodified lines
1272 1280
1273static int1281static int
1274cifs_parse_mount_options(const char *mountdata, const char *devname,1282cifs_parse_mount_options(const char *mountdata, const char *devname,
1275 struct smb_vol *vol)1283 struct smb_vol *vol, bool is_smb3)
1276{1284{
1277 char *data, *end;1285 char *data, *end;
1278 char *mountdata_copy = NULL, *options;1286 char *mountdata_copy = NULL, *options;
@@ -1985,7 +1993,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, · 706 unmodified lines
1985 if (string == NULL)1993 if (string == NULL)
1986 goto out_nomem;1994 goto out_nomem;
1987 1995
1988 if (cifs_parse_smb_version(string, vol) != 0)1996 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
1989 goto cifs_parse_mount_err;1997 goto cifs_parse_mount_err;
1990 got_version = true;1998 got_version = true;
1991 break;1999 break;
@@ -3116,12 +3124,6 @@ cifs_put_tlink(struct tcon_link *tlink) · 1124 unmodified lines
3116 return;3124 return;
3117}3125}
3118 3126
3119static inline struct tcon_link *
3120cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
3121{
3122 return cifs_sb->master_tlink;
3123}
3124
3125static int3127static int
3126compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)3128compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3127{3129{
@@ -3803,7 +3805,7 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses, · 675 unmodified lines
3803 } else {3805 } else {
3804 cleanup_volume_info_contents(volume_info);3806 cleanup_volume_info_contents(volume_info);
3805 rc = cifs_setup_volume_info(volume_info, mdata,3807 rc = cifs_setup_volume_info(volume_info, mdata,
3806 fake_devname);3808 fake_devname, false);
3807 }3809 }
3808 kfree(fake_devname);3810 kfree(fake_devname);
3809 kfree(cifs_sb->mountdata);3811 kfree(cifs_sb->mountdata);
@@ -3816,11 +3818,11 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses, · 6 unmodified lines
3816 3818
3817static int3819static int
3818cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,3820cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3819 const char *devname)3821 const char *devname, bool is_smb3)
3820{3822{
3821 int rc = 0;3823 int rc = 0;
3822 3824
3823 if (cifs_parse_mount_options(mount_data, devname, volume_info))3825 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
3824 return -EINVAL;3826 return -EINVAL;
3825 3827
3826 if (volume_info->nullauth) {3828 if (volume_info->nullauth) {
@@ -3854,7 +3856,7 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, · 27 unmodified lines
3854}3856}
3855 3857
3856struct smb_vol *3858struct smb_vol *
3857cifs_get_volume_info(char *mount_data, const char *devname)3859cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
3858{3860{
3859 int rc;3861 int rc;
3860 struct smb_vol *volume_info;3862 struct smb_vol *volume_info;
@@ -3863,7 +3865,7 @@ cifs_get_volume_info(char *mount_data, const char *devname) · 2 unmodified lines
3863 if (!volume_info)3865 if (!volume_info)
3864 return ERR_PTR(-ENOMEM);3866 return ERR_PTR(-ENOMEM);
3865 3867
3866 rc = cifs_setup_volume_info(volume_info, mount_data, devname);3868 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
3867 if (rc) {3869 if (rc) {
3868 cifs_cleanup_volume_info(volume_info);3870 cifs_cleanup_volume_info(volume_info);
3869 volume_info = ERR_PTR(rc);3871 volume_info = ERR_PTR(rc);
fs/cifs/link.c+4−2
@@ -421,7 +421,8 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, · 420 unmodified lines
421 return -ENOMEM;421 return -ENOMEM;
422 }422 }
423 423
424 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL);424 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL,
425 NULL);
425 if (rc)426 if (rc)
426 goto qmf_out_open_fail;427 goto qmf_out_open_fail;
427 428
@@ -478,7 +479,8 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, · 50 unmodified lines
478 oparms.fid = &fid;479 oparms.fid = &fid;
479 oparms.reconnect = false;480 oparms.reconnect = false;
480 481
481 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);482 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
483 NULL);
482 if (rc) {484 if (rc) {
483 kfree(utf16_path);485 kfree(utf16_path);
484 return rc;486 return rc;
fs/cifs/misc.c+17−0
@@ -905,3 +905,20 @@ cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc) · 904 unmodified lines
905 crypto_free_shash(*shash);905 crypto_free_shash(*shash);
906 *shash = NULL;906 *shash = NULL;
907}907}
908
909/**
910 * rqst_page_get_length - obtain the length and offset for a page in smb_rqst
911 * Input: rqst - a smb_rqst, page - a page index for rqst
912 * Output: *len - the length for this page, *offset - the offset for this page
913 */
914void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
915 unsigned int *len, unsigned int *offset)
916{
917 *len = rqst->rq_pagesz;
918 *offset = (page == 0) ? rqst->rq_offset : 0;
919
920 if (rqst->rq_npages == 1 || page == rqst->rq_npages-1)
921 *len = rqst->rq_tailsz;
922 else if (page == 0)
923 *len = rqst->rq_pagesz - rqst->rq_offset;
924}
fs/cifs/smb2file.c+2−1
@@ -64,7 +64,8 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, · 63 unmodified lines
64 if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)64 if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
65 memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE);65 memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE);
66 66
67 rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL);67 rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL,
68 NULL);
68 if (rc)69 if (rc)
69 goto out;70 goto out;
70 71
fs/cifs/smb2inode.c+2−1
@@ -71,7 +71,8 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, · 70 unmodified lines
71 oparms.fid = &fid;71 oparms.fid = &fid;
72 oparms.reconnect = false;72 oparms.reconnect = false;
73 73
74 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);74 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
75 NULL);
75 if (rc) {76 if (rc) {
76 kfree(utf16_path);77 kfree(utf16_path);
77 return rc;78 return rc;
fs/cifs/smb2misc.c+3−1
@@ -453,8 +453,10 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb) · 452 unmodified lines
453 start_of_path = from + 1;453 start_of_path = from + 1;
454#ifdef CONFIG_CIFS_SMB311454#ifdef CONFIG_CIFS_SMB311
455 /* SMB311 POSIX extensions paths do not include leading slash */455 /* SMB311 POSIX extensions paths do not include leading slash */
456 else if (cifs_sb_master_tcon(cifs_sb)->posix_extensions)456 else if (cifs_sb_master_tlink(cifs_sb) &&
457 cifs_sb_master_tcon(cifs_sb)->posix_extensions) {
457 start_of_path = from + 1;458 start_of_path = from + 1;
459 }
458#endif /* 311 */460#endif /* 311 */
459 else461 else
460 start_of_path = from;462 start_of_path = from;
fs/cifs/smb2ops.c+42−31
@@ -348,7 +348,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) · 347 unmodified lines
348 oparams.fid = pfid;348 oparams.fid = pfid;
349 oparams.reconnect = false;349 oparams.reconnect = false;
350 350
351 rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL);351 rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL, NULL);
352 if (rc == 0) {352 if (rc == 0) {
353 memcpy(tcon->prfid, pfid, sizeof(struct cifs_fid));353 memcpy(tcon->prfid, pfid, sizeof(struct cifs_fid));
354 tcon->valid_root_fid = true;354 tcon->valid_root_fid = true;
@@ -375,7 +375,8 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) · 20 unmodified lines
375 oparms.reconnect = false;375 oparms.reconnect = false;
376 376
377 if (no_cached_open)377 if (no_cached_open)
378 rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);378 rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
379 NULL);
379 else380 else
380 rc = open_shroot(xid, tcon, &fid);381 rc = open_shroot(xid, tcon, &fid);
381 382
@@ -413,7 +414,7 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) · 31 unmodified lines
413 oparms.fid = &fid;414 oparms.fid = &fid;
414 oparms.reconnect = false;415 oparms.reconnect = false;
415 416
416 rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);417 rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
417 if (rc)418 if (rc)
418 return;419 return;
419 420
@@ -449,7 +450,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, · 29 unmodified lines
449 oparms.fid = &fid;450 oparms.fid = &fid;
450 oparms.reconnect = false;451 oparms.reconnect = false;
451 452
452 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);453 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
453 if (rc) {454 if (rc) {
454 kfree(utf16_path);455 kfree(utf16_path);
455 return rc;456 return rc;
@@ -598,7 +599,7 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, · 142 unmodified lines
598 oparms.fid = &fid;599 oparms.fid = &fid;
599 oparms.reconnect = false;600 oparms.reconnect = false;
600 601
601 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);602 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
602 kfree(utf16_path);603 kfree(utf16_path);
603 if (rc) {604 if (rc) {
604 cifs_dbg(FYI, "open failed rc=%d\n", rc);605 cifs_dbg(FYI, "open failed rc=%d\n", rc);
@@ -677,7 +678,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, · 72 unmodified lines
677 oparms.fid = &fid;678 oparms.fid = &fid;
678 oparms.reconnect = false;679 oparms.reconnect = false;
679 680
680 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);681 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
681 kfree(utf16_path);682 kfree(utf16_path);
682 if (rc) {683 if (rc) {
683 cifs_dbg(FYI, "open failed rc=%d\n", rc);684 cifs_dbg(FYI, "open failed rc=%d\n", rc);
@@ -1261,7 +1262,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, · 577 unmodified lines
1261 oparms.fid = fid;1262 oparms.fid = fid;
1262 oparms.reconnect = false;1263 oparms.reconnect = false;
1263 1264
1264 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);1265 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
1265 kfree(utf16_path);1266 kfree(utf16_path);
1266 if (rc) {1267 if (rc) {
1267 cifs_dbg(FYI, "open dir failed rc=%d\n", rc);1268 cifs_dbg(FYI, "open dir failed rc=%d\n", rc);
@@ -1361,7 +1362,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, · 93 unmodified lines
1361 oparms.fid = &fid;1362 oparms.fid = &fid;
1362 oparms.reconnect = false;1363 oparms.reconnect = false;
1363 1364
1364 rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);1365 rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
1365 if (rc)1366 if (rc)
1366 return rc;1367 return rc;
1367 buf->f_type = SMB2_MAGIC_NUMBER;1368 buf->f_type = SMB2_MAGIC_NUMBER;
@@ -1515,7 +1516,8 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, · 147 unmodified lines
1515 struct cifs_open_parms oparms;1516 struct cifs_open_parms oparms;
1516 struct cifs_fid fid;1517 struct cifs_fid fid;
1517 struct kvec err_iov = {NULL, 0};1518 struct kvec err_iov = {NULL, 0};
1518 struct smb2_err_rsp *err_buf;1519 struct smb2_err_rsp *err_buf = NULL;
1520 int resp_buftype;
1519 struct smb2_symlink_err_rsp *symlink;1521 struct smb2_symlink_err_rsp *symlink;
1520 unsigned int sub_len;1522 unsigned int sub_len;
1521 unsigned int sub_offset;1523 unsigned int sub_offset;
@@ -1535,18 +1537,18 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, · 13 unmodified lines
1535 oparms.fid = &fid;1537 oparms.fid = &fid;
1536 oparms.reconnect = false;1538 oparms.reconnect = false;
1537 1539
1538 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov);1540 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov,
1539 1541 &resp_buftype);
1540 if (!rc || !err_iov.iov_base) {1542 if (!rc || !err_iov.iov_base) {
1541 kfree(utf16_path);1543 rc = -ENOENT;
1542 return -ENOENT;1544 goto querty_exit;
1543 }1545 }
1544 1546
1545 err_buf = err_iov.iov_base;1547 err_buf = err_iov.iov_base;
1546 if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||1548 if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
1547 err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) {1549 err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) {
1548 kfree(utf16_path);1550 rc = -ENOENT;
1549 return -ENOENT;1551 goto querty_exit;
1550 }1552 }
1551 1553
1552 /* open must fail on symlink - reset rc */1554 /* open must fail on symlink - reset rc */
@@ -1558,25 +1560,28 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, · 5 unmodified lines
1558 print_offset = le16_to_cpu(symlink->PrintNameOffset);1560 print_offset = le16_to_cpu(symlink->PrintNameOffset);
1559 1561
1560 if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {1562 if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
1561 kfree(utf16_path);1563 rc = -ENOENT;
1562 return -ENOENT;1564 goto querty_exit;
1563 }1565 }
1564 1566
1565 if (err_iov.iov_len <1567 if (err_iov.iov_len <
1566 SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {1568 SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
1567 kfree(utf16_path);1569 rc = -ENOENT;
1568 return -ENOENT;1570 goto querty_exit;
1569 }1571 }
1570 1572
1571 *target_path = cifs_strndup_from_utf16(1573 *target_path = cifs_strndup_from_utf16(
1572 (char *)symlink->PathBuffer + sub_offset,1574 (char *)symlink->PathBuffer + sub_offset,
1573 sub_len, true, cifs_sb->local_nls);1575 sub_len, true, cifs_sb->local_nls);
1574 if (!(*target_path)) {1576 if (!(*target_path)) {
1575 kfree(utf16_path);1577 rc = -ENOMEM;
1576 return -ENOMEM;1578 goto querty_exit;
1577 }1579 }
1578 convert_delimiter(*target_path, '/');1580 convert_delimiter(*target_path, '/');
1579 cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);1581 cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
1582
1583 querty_exit:
1584 free_rsp_buf(resp_buftype, err_buf);
1580 kfree(utf16_path);1585 kfree(utf16_path);
1581 return rc;1586 return rc;
1582}1587}
@@ -1649,7 +1654,7 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb, · 66 unmodified lines
1649 oparms.fid = &fid;1654 oparms.fid = &fid;
1650 oparms.reconnect = false;1655 oparms.reconnect = false;
1651 1656
1652 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);1657 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
1653 kfree(utf16_path);1658 kfree(utf16_path);
1654 if (!rc) {1659 if (!rc) {
1655 rc = SMB2_query_acl(xid, tlink_tcon(tlink), fid.persistent_fid,1660 rc = SMB2_query_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
@@ -1712,7 +1717,7 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen, · 56 unmodified lines
1712 oparms.fid = &fid;1717 oparms.fid = &fid;
1713 oparms.reconnect = false;1718 oparms.reconnect = false;
1714 1719
1715 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);1720 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
1716 kfree(utf16_path);1721 kfree(utf16_path);
1717 if (!rc) {1722 if (!rc) {
1718 rc = SMB2_set_acl(xid, tlink_tcon(tlink), fid.persistent_fid,1723 rc = SMB2_set_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
@@ -2189,9 +2194,10 @@ init_sg(struct smb_rqst *rqst, u8 *sign) · 470 unmodified lines
2189 smb2_sg_set_buf(&sg[i], rqst->rq_iov[i+1].iov_base,2194 smb2_sg_set_buf(&sg[i], rqst->rq_iov[i+1].iov_base,
2190 rqst->rq_iov[i+1].iov_len);2195 rqst->rq_iov[i+1].iov_len);
2191 for (j = 0; i < sg_len - 1; i++, j++) {2196 for (j = 0; i < sg_len - 1; i++, j++) {
2192 unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz2197 unsigned int len, offset;
2193 : rqst->rq_tailsz;2198
2194 sg_set_page(&sg[i], rqst->rq_pages[j], len, 0);2199 rqst_page_get_length(rqst, j, &len, &offset);
2200 sg_set_page(&sg[i], rqst->rq_pages[j], len, offset);
2195 }2201 }
2196 smb2_sg_set_buf(&sg[sg_len - 1], sign, SMB2_SIGNATURE_SIZE);2202 smb2_sg_set_buf(&sg[sg_len - 1], sign, SMB2_SIGNATURE_SIZE);
2197 return sg;2203 return sg;
@@ -2229,7 +2235,7 @@ static int · 31 unmodified lines
2229crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)2235crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
2230{2236{
2231 struct smb2_transform_hdr *tr_hdr =2237 struct smb2_transform_hdr *tr_hdr =
2232 (struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base;2238 (struct smb2_transform_hdr *)rqst->rq_iov[1].iov_base;
2233 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;2239 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
2234 int rc = 0;2240 int rc = 0;
2235 struct scatterlist *sg;2241 struct scatterlist *sg;
@@ -2338,6 +2344,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq, · 102 unmodified lines
2338 return rc;2344 return rc;
2339 2345
2340 new_rq->rq_pages = pages;2346 new_rq->rq_pages = pages;
2347 new_rq->rq_offset = old_rq->rq_offset;
2341 new_rq->rq_npages = old_rq->rq_npages;2348 new_rq->rq_npages = old_rq->rq_npages;
2342 new_rq->rq_pagesz = old_rq->rq_pagesz;2349 new_rq->rq_pagesz = old_rq->rq_pagesz;
2343 new_rq->rq_tailsz = old_rq->rq_tailsz;2350 new_rq->rq_tailsz = old_rq->rq_tailsz;
@@ -2379,10 +2386,14 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq, · 35 unmodified lines
2379 2386
2380 /* copy pages form the old */2387 /* copy pages form the old */
2381 for (i = 0; i < npages; i++) {2388 for (i = 0; i < npages; i++) {
2382 char *dst = kmap(new_rq->rq_pages[i]);2389 char *dst, *src;
2383 char *src = kmap(old_rq->rq_pages[i]);2390 unsigned int offset, len;
2384 unsigned int len = (i < npages - 1) ? new_rq->rq_pagesz :2391
2385 new_rq->rq_tailsz;2392 rqst_page_get_length(new_rq, i, &len, &offset);
2393
2394 dst = (char *) kmap(new_rq->rq_pages[i]) + offset;
2395 src = (char *) kmap(old_rq->rq_pages[i]) + offset;
2396
2386 memcpy(dst, src, len);2397 memcpy(dst, src, len);
2387 kunmap(new_rq->rq_pages[i]);2398 kunmap(new_rq->rq_pages[i]);
2388 kunmap(old_rq->rq_pages[i]);2399 kunmap(old_rq->rq_pages[i]);
fs/cifs/smb2pdu.c+15−9
@@ -1889,7 +1889,7 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len, · 1888 unmodified lines
1889int1889int
1890SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,1890SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
1891 __u8 *oplock, struct smb2_file_all_info *buf,1891 __u8 *oplock, struct smb2_file_all_info *buf,
1892 struct kvec *err_iov)1892 struct kvec *err_iov, int *buftype)
1893{1893{
1894 struct smb2_create_req *req;1894 struct smb2_create_req *req;
1895 struct smb2_create_rsp *rsp;1895 struct smb2_create_rsp *rsp;
@@ -2052,6 +2052,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, · 156 unmodified lines
2052 cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);2052 cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
2053 if (err_iov && rsp) {2053 if (err_iov && rsp) {
2054 *err_iov = rsp_iov;2054 *err_iov = rsp_iov;
2055 *buftype = resp_buftype;
2055 resp_buftype = CIFS_NO_BUFFER;2056 resp_buftype = CIFS_NO_BUFFER;
2056 rsp = NULL;2057 rsp = NULL;
2057 }2058 }
@@ -2492,8 +2493,7 @@ SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon, · 434 unmodified lines
2492 2493
2493 return query_info(xid, tcon, persistent_fid, volatile_fid,2494 return query_info(xid, tcon, persistent_fid, volatile_fid,
2494 0, SMB2_O_INFO_SECURITY, additional_info,2495 0, SMB2_O_INFO_SECURITY, additional_info,
2495 SMB2_MAX_BUFFER_SIZE,2496 SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen);
2496 sizeof(struct smb2_file_all_info), data, plen);
2497}2497}
2498 2498
2499int2499int
@@ -2721,8 +2721,8 @@ smb2_new_read_req(void **buf, unsigned int *total_len, · 221 unmodified lines
2721 2721
2722 rdata->mr = smbd_register_mr(2722 rdata->mr = smbd_register_mr(
2723 server->smbd_conn, rdata->pages,2723 server->smbd_conn, rdata->pages,
2724 rdata->nr_pages, rdata->tailsz,2724 rdata->nr_pages, rdata->page_offset,
2725 true, need_invalidate);2725 rdata->tailsz, true, need_invalidate);
2726 if (!rdata->mr)2726 if (!rdata->mr)
2727 return -ENOBUFS;2727 return -ENOBUFS;
2728 2728
@@ -3108,16 +3108,22 @@ smb2_async_writev(struct cifs_writedata *wdata, · 379 unmodified lines
3108 3108
3109 wdata->mr = smbd_register_mr(3109 wdata->mr = smbd_register_mr(
3110 server->smbd_conn, wdata->pages,3110 server->smbd_conn, wdata->pages,
3111 wdata->nr_pages, wdata->tailsz,3111 wdata->nr_pages, wdata->page_offset,
3112 false, need_invalidate);3112 wdata->tailsz, false, need_invalidate);
3113 if (!wdata->mr) {3113 if (!wdata->mr) {
3114 rc = -ENOBUFS;3114 rc = -ENOBUFS;
3115 goto async_writev_out;3115 goto async_writev_out;
3116 }3116 }
3117 req->Length = 0;3117 req->Length = 0;
3118 req->DataOffset = 0;3118 req->DataOffset = 0;
3119 req->RemainingBytes =3119 if (wdata->nr_pages > 1)
3120 cpu_to_le32((wdata->nr_pages-1)*PAGE_SIZE + wdata->tailsz);3120 req->RemainingBytes =
3121 cpu_to_le32(
3122 (wdata->nr_pages - 1) * wdata->pagesz -
3123 wdata->page_offset + wdata->tailsz
3124 );
3125 else
3126 req->RemainingBytes = cpu_to_le32(wdata->tailsz);
3121 req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;3127 req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
3122 if (need_invalidate)3128 if (need_invalidate)
3123 req->Channel = SMB2_CHANNEL_RDMA_V1;3129 req->Channel = SMB2_CHANNEL_RDMA_V1;
fs/cifs/smb2proto.h+1−1
@@ -125,7 +125,7 @@ extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon); · 124 unmodified lines
125extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,125extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
126 __le16 *path, __u8 *oplock,126 __le16 *path, __u8 *oplock,
127 struct smb2_file_all_info *buf,127 struct smb2_file_all_info *buf,
128 struct kvec *err_iov);128 struct kvec *err_iov, int *resp_buftype);
129extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,129extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
130 u64 persistent_fid, u64 volatile_fid, u32 opcode,130 u64 persistent_fid, u64 volatile_fid, u32 opcode,
131 bool is_fsctl, char *in_data, u32 indatalen,131 bool is_fsctl, char *in_data, u32 indatalen,
fs/cifs/smb2transport.c+8−4
@@ -171,7 +171,9 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) · 170 unmodified lines
171 unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];171 unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
172 unsigned char *sigptr = smb2_signature;172 unsigned char *sigptr = smb2_signature;
173 struct kvec *iov = rqst->rq_iov;173 struct kvec *iov = rqst->rq_iov;
174 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;174 int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0;
175 struct smb2_sync_hdr *shdr =
176 (struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base;
175 struct cifs_ses *ses;177 struct cifs_ses *ses;
176 178
177 ses = smb2_find_smb_ses(server, shdr->SessionId);179 ses = smb2_find_smb_ses(server, shdr->SessionId);
@@ -202,7 +204,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) · 24 unmodified lines
202 return rc;204 return rc;
203 }205 }
204 206
205 rc = __cifs_calc_signature(rqst, server, sigptr,207 rc = __cifs_calc_signature(rqst, iov_hdr_index, server, sigptr,
206 &server->secmech.sdeschmacsha256->shash);208 &server->secmech.sdeschmacsha256->shash);
207 209
208 if (!rc)210 if (!rc)
@@ -412,7 +414,9 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) · 203 unmodified lines
412 unsigned char smb3_signature[SMB2_CMACAES_SIZE];414 unsigned char smb3_signature[SMB2_CMACAES_SIZE];
413 unsigned char *sigptr = smb3_signature;415 unsigned char *sigptr = smb3_signature;
414 struct kvec *iov = rqst->rq_iov;416 struct kvec *iov = rqst->rq_iov;
415 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;417 int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0;
418 struct smb2_sync_hdr *shdr =
419 (struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base;
416 struct cifs_ses *ses;420 struct cifs_ses *ses;
417 421
418 ses = smb2_find_smb_ses(server, shdr->SessionId);422 ses = smb2_find_smb_ses(server, shdr->SessionId);
@@ -443,7 +447,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) · 24 unmodified lines
443 return rc;447 return rc;
444 }448 }
445 449
446 rc = __cifs_calc_signature(rqst, server, sigptr,450 rc = __cifs_calc_signature(rqst, iov_hdr_index, server, sigptr,
447 &server->secmech.sdesccmacaes->shash);451 &server->secmech.sdesccmacaes->shash);
448 452
449 if (!rc)453 if (!rc)
fs/cifs/smbdirect.c+75−46
@@ -17,6 +17,7 @@ · 16 unmodified lines
17#include <linux/highmem.h>17#include <linux/highmem.h>
18#include "smbdirect.h"18#include "smbdirect.h"
19#include "cifs_debug.h"19#include "cifs_debug.h"
20#include "cifsproto.h"
20 21
21static struct smbd_response *get_empty_queue_buffer(22static struct smbd_response *get_empty_queue_buffer(
22 struct smbd_connection *info);23 struct smbd_connection *info);
@@ -2003,10 +2004,12 @@ read_rfc1002_done: · 1980 unmodified lines
2003 * return value: actual data read2004 * return value: actual data read
2004 */2005 */
2005static int smbd_recv_page(struct smbd_connection *info,2006static int smbd_recv_page(struct smbd_connection *info,
2006 struct page *page, unsigned int to_read)2007 struct page *page, unsigned int page_offset,
2008 unsigned int to_read)
2007{2009{
2008 int ret;2010 int ret;
2009 char *to_address;2011 char *to_address;
2012 void *page_address;
2010 2013
2011 /* make sure we have the page ready for read */2014 /* make sure we have the page ready for read */
2012 ret = wait_event_interruptible(2015 ret = wait_event_interruptible(
@@ -2014,16 +2017,17 @@ static int smbd_recv_page(struct smbd_connection *info, · 1 unmodified line
2014 info->reassembly_data_length >= to_read ||2017 info->reassembly_data_length >= to_read ||
2015 info->transport_status != SMBD_CONNECTED);2018 info->transport_status != SMBD_CONNECTED);
2016 if (ret)2019 if (ret)
2017 return 0;2020 return ret;
2018 2021
2019 /* now we can read from reassembly queue and not sleep */2022 /* now we can read from reassembly queue and not sleep */
2020 to_address = kmap_atomic(page);2023 page_address = kmap_atomic(page);
2024 to_address = (char *) page_address + page_offset;
2021 2025
2022 log_read(INFO, "reading from page=%p address=%p to_read=%d\n",2026 log_read(INFO, "reading from page=%p address=%p to_read=%d\n",
2023 page, to_address, to_read);2027 page, to_address, to_read);
2024 2028
2025 ret = smbd_recv_buf(info, to_address, to_read);2029 ret = smbd_recv_buf(info, to_address, to_read);
2026 kunmap_atomic(to_address);2030 kunmap_atomic(page_address);
2027 2031
2028 return ret;2032 return ret;
2029}2033}
@@ -2037,7 +2041,7 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg) · 7 unmodified lines
2037{2041{
2038 char *buf;2042 char *buf;
2039 struct page *page;2043 struct page *page;
2040 unsigned int to_read;2044 unsigned int to_read, page_offset;
2041 int rc;2045 int rc;
2042 2046
2043 info->smbd_recv_pending++;2047 info->smbd_recv_pending++;
@@ -2051,15 +2055,16 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg) · 7 unmodified lines
2051 2055
2052 case READ | ITER_BVEC:2056 case READ | ITER_BVEC:
2053 page = msg->msg_iter.bvec->bv_page;2057 page = msg->msg_iter.bvec->bv_page;
2058 page_offset = msg->msg_iter.bvec->bv_offset;
2054 to_read = msg->msg_iter.bvec->bv_len;2059 to_read = msg->msg_iter.bvec->bv_len;
2055 rc = smbd_recv_page(info, page, to_read);2060 rc = smbd_recv_page(info, page, page_offset, to_read);
2056 break;2061 break;
2057 2062
2058 default:2063 default:
2059 /* It's a bug in upper layer to get there */2064 /* It's a bug in upper layer to get there */
2060 cifs_dbg(VFS, "CIFS: invalid msg type %d\n",2065 cifs_dbg(VFS, "CIFS: invalid msg type %d\n",
2061 msg->msg_iter.type);2066 msg->msg_iter.type);
2062 rc = -EIO;2067 rc = -EINVAL;
2063 }2068 }
2064 2069
2065 info->smbd_recv_pending--;2070 info->smbd_recv_pending--;
@@ -2082,7 +2087,7 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst) · 16 unmodified lines
2082 struct kvec vec;2087 struct kvec vec;
2083 int nvecs;2088 int nvecs;
2084 int size;2089 int size;
2085 int buflen = 0, remaining_data_length;2090 unsigned int buflen = 0, remaining_data_length;
2086 int start, i, j;2091 int start, i, j;
2087 int max_iov_size =2092 int max_iov_size =
2088 info->max_send_size - sizeof(struct smbd_data_transfer);2093 info->max_send_size - sizeof(struct smbd_data_transfer);
@@ -2113,10 +2118,17 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst) · 24 unmodified lines
2113 buflen += iov[i].iov_len;2118 buflen += iov[i].iov_len;
2114 }2119 }
2115 2120
2116 /* add in the page array if there is one */2121 /*
2122 * Add in the page array if there is one. The caller needs to set
2123 * rq_tailsz to PAGE_SIZE when the buffer has multiple pages and
2124 * ends at page boundary
2125 */
2117 if (rqst->rq_npages) {2126 if (rqst->rq_npages) {
2118 buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);2127 if (rqst->rq_npages == 1)
2119 buflen += rqst->rq_tailsz;2128 buflen += rqst->rq_tailsz;
2129 else
2130 buflen += rqst->rq_pagesz * (rqst->rq_npages - 1) -
2131 rqst->rq_offset + rqst->rq_tailsz;
2120 }2132 }
2121 2133
2122 if (buflen + sizeof(struct smbd_data_transfer) >2134 if (buflen + sizeof(struct smbd_data_transfer) >
@@ -2213,8 +2225,9 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst) · 90 unmodified lines
2213 2225
2214 /* now sending pages if there are any */2226 /* now sending pages if there are any */
2215 for (i = 0; i < rqst->rq_npages; i++) {2227 for (i = 0; i < rqst->rq_npages; i++) {
2216 buflen = (i == rqst->rq_npages-1) ?2228 unsigned int offset;
2217 rqst->rq_tailsz : rqst->rq_pagesz;2229
2230 rqst_page_get_length(rqst, i, &buflen, &offset);
2218 nvecs = (buflen + max_iov_size - 1) / max_iov_size;2231 nvecs = (buflen + max_iov_size - 1) / max_iov_size;
2219 log_write(INFO, "sending pages buflen=%d nvecs=%d\n",2232 log_write(INFO, "sending pages buflen=%d nvecs=%d\n",
2220 buflen, nvecs);2233 buflen, nvecs);
@@ -2225,9 +2238,11 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst) · 4 unmodified lines
2225 remaining_data_length -= size;2238 remaining_data_length -= size;
2226 log_write(INFO, "sending pages i=%d offset=%d size=%d"2239 log_write(INFO, "sending pages i=%d offset=%d size=%d"
2227 " remaining_data_length=%d\n",2240 " remaining_data_length=%d\n",
2228 i, j*max_iov_size, size, remaining_data_length);2241 i, j*max_iov_size+offset, size,
2242 remaining_data_length);
2229 rc = smbd_post_send_page(2243 rc = smbd_post_send_page(
2230 info, rqst->rq_pages[i], j*max_iov_size,2244 info, rqst->rq_pages[i],
2245 j*max_iov_size + offset,
2231 size, remaining_data_length);2246 size, remaining_data_length);
2232 if (rc)2247 if (rc)
2233 goto done;2248 goto done;
@@ -2284,37 +2299,37 @@ static void smbd_mr_recovery_work(struct work_struct *work) · 50 unmodified lines
2284 if (smbdirect_mr->state == MR_INVALIDATED ||2299 if (smbdirect_mr->state == MR_INVALIDATED ||
2285 smbdirect_mr->state == MR_ERROR) {2300 smbdirect_mr->state == MR_ERROR) {
2286 2301
2287 if (smbdirect_mr->state == MR_INVALIDATED) {2302 /* recover this MR entry */
2303 rc = ib_dereg_mr(smbdirect_mr->mr);
2304 if (rc) {
2305 log_rdma_mr(ERR,
2306 "ib_dereg_mr failed rc=%x\n",
2307 rc);
2308 smbd_disconnect_rdma_connection(info);
2309 continue;
2310 }
2311
2312 smbdirect_mr->mr = ib_alloc_mr(
2313 info->pd, info->mr_type,
2314 info->max_frmr_depth);
2315 if (IS_ERR(smbdirect_mr->mr)) {
2316 log_rdma_mr(ERR,
2317 "ib_alloc_mr failed mr_type=%x "
2318 "max_frmr_depth=%x\n",
2319 info->mr_type,
2320 info->max_frmr_depth);
2321 smbd_disconnect_rdma_connection(info);
2322 continue;
2323 }
2324
2325 if (smbdirect_mr->state == MR_INVALIDATED)
2288 ib_dma_unmap_sg(2326 ib_dma_unmap_sg(
2289 info->id->device, smbdirect_mr->sgl,2327 info->id->device, smbdirect_mr->sgl,
2290 smbdirect_mr->sgl_count,2328 smbdirect_mr->sgl_count,
2291 smbdirect_mr->dir);2329 smbdirect_mr->dir);
2292 smbdirect_mr->state = MR_READY;
2293 } else if (smbdirect_mr->state == MR_ERROR) {
2294
2295 /* recover this MR entry */
2296 rc = ib_dereg_mr(smbdirect_mr->mr);
2297 if (rc) {
2298 log_rdma_mr(ERR,
2299 "ib_dereg_mr failed rc=%x\n",
2300 rc);
2301 smbd_disconnect_rdma_connection(info);
2302 }
2303 2330
2304 smbdirect_mr->mr = ib_alloc_mr(2331 smbdirect_mr->state = MR_READY;
2305 info->pd, info->mr_type,
2306 info->max_frmr_depth);
2307 if (IS_ERR(smbdirect_mr->mr)) {
2308 log_rdma_mr(ERR,
2309 "ib_alloc_mr failed mr_type=%x "
2310 "max_frmr_depth=%x\n",
2311 info->mr_type,
2312 info->max_frmr_depth);
2313 smbd_disconnect_rdma_connection(info);
2314 }
2315 2332
2316 smbdirect_mr->state = MR_READY;
2317 }
2318 /* smbdirect_mr->state is updated by this function2333 /* smbdirect_mr->state is updated by this function
2319 * and is read and updated by I/O issuing CPUs trying2334 * and is read and updated by I/O issuing CPUs trying
2320 * to get a MR, the call to atomic_inc_return2335 * to get a MR, the call to atomic_inc_return
@@ -2460,7 +2475,7 @@ again: · 139 unmodified lines
2460 */2475 */
2461struct smbd_mr *smbd_register_mr(2476struct smbd_mr *smbd_register_mr(
2462 struct smbd_connection *info, struct page *pages[], int num_pages,2477 struct smbd_connection *info, struct page *pages[], int num_pages,
2463 int tailsz, bool writing, bool need_invalidate)2478 int offset, int tailsz, bool writing, bool need_invalidate)
2464{2479{
2465 struct smbd_mr *smbdirect_mr;2480 struct smbd_mr *smbdirect_mr;
2466 int rc, i;2481 int rc, i;
@@ -2483,17 +2498,31 @@ struct smbd_mr *smbd_register_mr( · 16 unmodified lines
2483 smbdirect_mr->sgl_count = num_pages;2498 smbdirect_mr->sgl_count = num_pages;
2484 sg_init_table(smbdirect_mr->sgl, num_pages);2499 sg_init_table(smbdirect_mr->sgl, num_pages);
2485 2500
2486 for (i = 0; i < num_pages - 1; i++)2501 log_rdma_mr(INFO, "num_pages=0x%x offset=0x%x tailsz=0x%x\n",
2487 sg_set_page(&smbdirect_mr->sgl[i], pages[i], PAGE_SIZE, 0);2502 num_pages, offset, tailsz);
2503
2504 if (num_pages == 1) {
2505 sg_set_page(&smbdirect_mr->sgl[0], pages[0], tailsz, offset);
2506 goto skip_multiple_pages;
2507 }
2488 2508
2509 /* We have at least two pages to register */
2510 sg_set_page(
2511 &smbdirect_mr->sgl[0], pages[0], PAGE_SIZE - offset, offset);
2512 i = 1;
2513 while (i < num_pages - 1) {
2514 sg_set_page(&smbdirect_mr->sgl[i], pages[i], PAGE_SIZE, 0);
2515 i++;
2516 }
2489 sg_set_page(&smbdirect_mr->sgl[i], pages[i],2517 sg_set_page(&smbdirect_mr->sgl[i], pages[i],
2490 tailsz ? tailsz : PAGE_SIZE, 0);2518 tailsz ? tailsz : PAGE_SIZE, 0);
2491 2519
2520skip_multiple_pages:
2492 dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE;2521 dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
2493 smbdirect_mr->dir = dir;2522 smbdirect_mr->dir = dir;
2494 rc = ib_dma_map_sg(info->id->device, smbdirect_mr->sgl, num_pages, dir);2523 rc = ib_dma_map_sg(info->id->device, smbdirect_mr->sgl, num_pages, dir);
2495 if (!rc) {2524 if (!rc) {
2496 log_rdma_mr(INFO, "ib_dma_map_sg num_pages=%x dir=%x rc=%x\n",2525 log_rdma_mr(ERR, "ib_dma_map_sg num_pages=%x dir=%x rc=%x\n",
2497 num_pages, dir, rc);2526 num_pages, dir, rc);
2498 goto dma_map_error;2527 goto dma_map_error;
2499 }2528 }
@@ -2501,8 +2530,8 @@ struct smbd_mr *smbd_register_mr( · 1 unmodified line
2501 rc = ib_map_mr_sg(smbdirect_mr->mr, smbdirect_mr->sgl, num_pages,2530 rc = ib_map_mr_sg(smbdirect_mr->mr, smbdirect_mr->sgl, num_pages,
2502 NULL, PAGE_SIZE);2531 NULL, PAGE_SIZE);
2503 if (rc != num_pages) {2532 if (rc != num_pages) {
2504 log_rdma_mr(INFO,2533 log_rdma_mr(ERR,
2505 "ib_map_mr_sg failed rc = %x num_pages = %x\n",2534 "ib_map_mr_sg failed rc = %d num_pages = %x\n",
2506 rc, num_pages);2535 rc, num_pages);
2507 goto map_mr_error;2536 goto map_mr_error;
2508 }2537 }
fs/cifs/smbdirect.h+1−1
@@ -321,7 +321,7 @@ struct smbd_mr { · 320 unmodified lines
321/* Interfaces to register and deregister MR for RDMA read/write */321/* Interfaces to register and deregister MR for RDMA read/write */
322struct smbd_mr *smbd_register_mr(322struct smbd_mr *smbd_register_mr(
323 struct smbd_connection *info, struct page *pages[], int num_pages,323 struct smbd_connection *info, struct page *pages[], int num_pages,
324 int tailsz, bool writing, bool need_invalidate);324 int offset, int tailsz, bool writing, bool need_invalidate);
325int smbd_deregister_mr(struct smbd_mr *mr);325int smbd_deregister_mr(struct smbd_mr *mr);
326 326
327#else327#else
fs/cifs/transport.c+23−11
@@ -212,10 +212,24 @@ rqst_len(struct smb_rqst *rqst) · 211 unmodified lines
212 for (i = 0; i < rqst->rq_nvec; i++)212 for (i = 0; i < rqst->rq_nvec; i++)
213 buflen += iov[i].iov_len;213 buflen += iov[i].iov_len;
214 214
215 /* add in the page array if there is one */215 /*
216 * Add in the page array if there is one. The caller needs to make
217 * sure rq_offset and rq_tailsz are set correctly. If a buffer of
218 * multiple pages ends at page boundary, rq_tailsz needs to be set to
219 * PAGE_SIZE.
220 */
216 if (rqst->rq_npages) {221 if (rqst->rq_npages) {
217 buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);222 if (rqst->rq_npages == 1)
218 buflen += rqst->rq_tailsz;223 buflen += rqst->rq_tailsz;
224 else {
225 /*
226 * If there is more than one page, calculate the
227 * buffer length based on rq_offset and rq_tailsz
228 */
229 buflen += rqst->rq_pagesz * (rqst->rq_npages - 1) -
230 rqst->rq_offset;
231 buflen += rqst->rq_tailsz;
232 }
219 }233 }
220 234
221 return buflen;235 return buflen;
@@ -274,15 +288,13 @@ __smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) · 52 unmodified lines
274 288
275 /* now walk the page array and send each page in it */289 /* now walk the page array and send each page in it */
276 for (i = 0; i < rqst->rq_npages; i++) {290 for (i = 0; i < rqst->rq_npages; i++) {
277 size_t len = i == rqst->rq_npages - 1291 struct bio_vec bvec;
278 ? rqst->rq_tailsz292
279 : rqst->rq_pagesz;293 bvec.bv_page = rqst->rq_pages[i];
280 struct bio_vec bvec = {294 rqst_page_get_length(rqst, i, &bvec.bv_len, &bvec.bv_offset);
281 .bv_page = rqst->rq_pages[i],295
282 .bv_len = len
283 };
284 iov_iter_bvec(&smb_msg.msg_iter, WRITE | ITER_BVEC,296 iov_iter_bvec(&smb_msg.msg_iter, WRITE | ITER_BVEC,
285 &bvec, 1, len);297 &bvec, 1, bvec.bv_len);
286 rc = smb_send_kvec(server, &smb_msg, &sent);298 rc = smb_send_kvec(server, &smb_msg, &sent);
287 if (rc < 0)299 if (rc < 0)
288 break;300 break;