aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-10 13:53:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-10 13:53:31 -0400
commit0c14e43a42e4e44f70963f8ccf89461290c4e4da (patch)
treee747675cc238a22995bcddc08a32035bd2bd7823
parentbbaa10130301a5fba168df71c31e8d0eef967182 (diff)
parent9d874c36552afbd08778687aeaff24a8a7260f20 (diff)
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
-rw-r--r--fs/cifs/cifsacl.h14
-rw-r--r--fs/cifs/cifsencrypt.c17
-rw-r--r--fs/cifs/cifsfs.c22
-rw-r--r--fs/cifs/cifsglob.h6
-rw-r--r--fs/cifs/cifsproto.h7
-rw-r--r--fs/cifs/connect.c32
-rw-r--r--fs/cifs/link.c6
-rw-r--r--fs/cifs/misc.c17
-rw-r--r--fs/cifs/smb2file.c3
-rw-r--r--fs/cifs/smb2inode.c3
-rw-r--r--fs/cifs/smb2misc.c4
-rw-r--r--fs/cifs/smb2ops.c73
-rw-r--r--fs/cifs/smb2pdu.c24
-rw-r--r--fs/cifs/smb2proto.h2
-rw-r--r--fs/cifs/smb2transport.c12
-rw-r--r--fs/cifs/smbdirect.c121
-rw-r--r--fs/cifs/smbdirect.h2
-rw-r--r--fs/cifs/transport.c34
18 files changed, 261 insertions, 138 deletions
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
index 4f3884835267..dd95a6fa24bf 100644
--- a/fs/cifs/cifsacl.h
+++ b/fs/cifs/cifsacl.h
@@ -98,4 +98,18 @@ struct cifs_ace {
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 */
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index a6ef088e057b..937251cc61c0 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -37,6 +37,7 @@
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,
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,
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,
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
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index eb7b6573f322..d5aa7ae917bf 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -698,8 +698,8 @@ static int cifs_set_super(struct super_block *sb, void *data)
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,
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:
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_t 807static 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");
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};
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 08d1cdd96701..1efa2e65bc1a 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1019,6 +1019,12 @@ tlink_tcon(struct tcon_link *tlink)
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 *
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 7933c5f9c076..4e0d183c3d10 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -211,7 +211,7 @@ extern int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
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,
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,
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 */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e5a2fe7f0dd4..96645a7d8f27 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -320,7 +320,7 @@ static int generic_ip_connect(struct TCP_Server_Info *server);
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 reconnection 326 * cifs tcp session reconnection
@@ -1166,7 +1166,7 @@ cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1166} 1166}
1167 1167
1168static int 1168static 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)
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)
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)
1272 1280
1273static int 1281static 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,
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)
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 int 3127static 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,
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,
3816 3818
3817static int 3819static 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,
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)
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);
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 889a840172eb..de41f96aba49 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -421,7 +421,8 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
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,
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;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index aba3fc3058da..f90d4ad6624c 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -905,3 +905,20 @@ cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc)
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}
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c
index 12af5dba742b..788412675723 100644
--- a/fs/cifs/smb2file.c
+++ b/fs/cifs/smb2file.c
@@ -64,7 +64,8 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
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
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index a6e786e39248..d01ad706d7fc 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -71,7 +71,8 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
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;
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index cb5728e3d87d..e2bec47c6845 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -453,8 +453,10 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
453 start_of_path = from + 1; 453 start_of_path = from + 1;
454#ifdef CONFIG_CIFS_SMB311 454#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 else 461 else
460 start_of_path = from; 462 start_of_path = from;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 950d0ab2cc61..b15f5957d645 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -348,7 +348,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
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)
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 else 380 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)
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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)
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_pagesz 2197 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
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,
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,
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]);
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 281fbc1dc720..48e2004c75fb 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1889,7 +1889,7 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
1889int 1889int
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,
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,
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
2499int 2499int
@@ -2721,8 +2721,8 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
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,
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;
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 908555b1c6b5..c84020057bd8 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -125,7 +125,7 @@ extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
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,
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index 2c671123a6bf..349d5ccf854c 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -171,7 +171,9 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
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)
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)
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)
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)
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index c62f7c95683c..e459c97151b3 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -17,6 +17,7 @@
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:
2003 * return value: actual data read 2004 * 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,
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)
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)
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)
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)
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)
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)
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)
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 function 2333 /* smbdirect_mr->state is updated by this function
2319 * and is read and updated by I/O issuing CPUs trying 2334 * and is read and updated by I/O issuing CPUs trying
2320 * to get a MR, the call to atomic_inc_return 2335 * to get a MR, the call to atomic_inc_return
@@ -2460,7 +2475,7 @@ again:
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(
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(
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 }
diff --git a/fs/cifs/smbdirect.h b/fs/cifs/smbdirect.h
index f9038daea194..1e419c21dc60 100644
--- a/fs/cifs/smbdirect.h
+++ b/fs/cifs/smbdirect.h
@@ -321,7 +321,7 @@ struct smbd_mr {
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#else 327#else
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index e7254e386b79..24887a0898c0 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -212,10 +212,24 @@ rqst_len(struct smb_rqst *rqst)
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)
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 - 1 291 struct bio_vec bvec;
278 ? rqst->rq_tailsz 292
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;