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
9898 struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
9999 } __attribute__((packed));
100100
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+
101115 #endif /* _CIFSACL_H */
fs/cifs/cifsencrypt.c+8−9
@@ -37,6 +37,7 @@ · 36 unmodified lines
3737 #include <crypto/aead.h>
3838
3939 int __cifs_calc_signature(struct smb_rqst *rqst,
40+ int start,
4041 struct TCP_Server_Info *server, char *signature,
4142 struct shash_desc *shash)
4243 {
@@ -45,10 +46,7 @@ int __cifs_calc_signature(struct smb_rqst *rqst, · 2 unmodified lines
4546 struct kvec *iov = rqst->rq_iov;
4647 int n_vec = rqst->rq_nvec;
4748
48− if (n_vec < 2 || iov[0].iov_len != 4)
49− return -EIO;
50−
51− for (i = 1; i < n_vec; i++) {
49+ for (i = start; i < n_vec; i++) {
5250 if (iov[i].iov_len == 0)
5351 continue;
5452 if (iov[i].iov_base == NULL) {
@@ -68,11 +66,12 @@ int __cifs_calc_signature(struct smb_rqst *rqst, · 13 unmodified lines
6866
6967 /* now hash over the rq_pages array */
7068 for (i = 0; i < rqst->rq_npages; i++) {
71− void *kaddr = kmap(rqst->rq_pages[i]);
72− size_t len = rqst->rq_pagesz;
69+ void *kaddr;
70+ unsigned int len, offset;
71+
72+ rqst_page_get_length(rqst, i, &len, &offset);
7373
74− if (i == rqst->rq_npages - 1)
75− len = rqst->rq_tailsz;
74+ kaddr = (char *) kmap(rqst->rq_pages[i]) + offset;
7675
7776 crypto_shash_update(shash, kaddr, len);
7877
@@ -119,7 +118,7 @@ static int cifs_calc_signature(struct smb_rqst *rqst, · 40 unmodified lines
119118 return rc;
120119 }
121120
122− return __cifs_calc_signature(rqst, server, signature,
121+ return __cifs_calc_signature(rqst, 1, server, signature,
123122 &server->secmech.sdescmd5->shash);
124123 }
125124
fs/cifs/cifsfs.c+18−4
@@ -698,8 +698,8 @@ static int cifs_set_super(struct super_block *sb, void *data) · 697 unmodified lines
698698 }
699699
700700 static struct dentry *
701−cifs_do_mount(struct file_system_type *fs_type,
702− int flags, const char *dev_name, void *data)
701+cifs_smb3_do_mount(struct file_system_type *fs_type,
702+ int flags, const char *dev_name, void *data, bool is_smb3)
703703 {
704704 int rc;
705705 struct super_block *sb;
@@ -710,7 +710,7 @@ cifs_do_mount(struct file_system_type *fs_type, · 4 unmodified lines
710710
711711 cifs_dbg(FYI, "Devname: %s flags: %d\n", dev_name, flags);
712712
713− volume_info = cifs_get_volume_info((char *)data, dev_name);
713+ volume_info = cifs_get_volume_info((char *)data, dev_name, is_smb3);
714714 if (IS_ERR(volume_info))
715715 return ERR_CAST(volume_info);
716716
@@ -790,6 +790,20 @@ out_nls: · 73 unmodified lines
790790 goto out;
791791 }
792792
793+static struct dentry *
794+smb3_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+
800+static struct dentry *
801+cifs_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+
793807 static ssize_t
794808 cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)
795809 {
@@ -925,7 +939,7 @@ MODULE_ALIAS_FS("cifs"); · 129 unmodified lines
925939 static struct file_system_type smb3_fs_type = {
926940 .owner = THIS_MODULE,
927941 .name = "smb3",
928− .mount = cifs_do_mount,
942+ .mount = smb3_do_mount,
929943 .kill_sb = cifs_kill_sb,
930944 /* .fs_flags */
931945 };
fs/cifs/cifsglob.h+6−0
@@ -1019,6 +1019,12 @@ tlink_tcon(struct tcon_link *tlink) · 1018 unmodified lines
10191019 return tlink->tl_tcon;
10201020 }
10211021
1022+static inline struct tcon_link *
1023+cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
1024+{
1025+ return cifs_sb->master_tlink;
1026+}
1027+
10221028 extern void cifs_put_tlink(struct tcon_link *tlink);
10231029
10241030 static 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
211211 extern int cifs_match_super(struct super_block *, void *);
212212 extern void cifs_cleanup_volume_info(struct smb_vol *pvolume_info);
213213 extern struct smb_vol *cifs_get_volume_info(char *mount_data,
214− const char *devname);
214+ const char *devname, bool is_smb3);
215215 extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *);
216216 extern void cifs_umount(struct cifs_sb_info *);
217217 extern 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
544544 struct cifs_sb_info *cifs_sb,
545545 const unsigned char *path, char *pbuf,
546546 unsigned int *pbytes_written);
547−int __cifs_calc_signature(struct smb_rqst *rqst,
547+int __cifs_calc_signature(struct smb_rqst *rqst, int start,
548548 struct TCP_Server_Info *server, char *signature,
549549 struct shash_desc *shash);
550550 enum 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
557557 struct sdesc **sdesc);
558558 void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc);
559559
560+extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
561+ unsigned int *len, unsigned int *offset);
562+
560563 #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
320320 static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
321321 static void cifs_prune_tlinks(struct work_struct *work);
322322 static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
323− const char *devname);
323+ const char *devname, bool is_smb3);
324324
325325 /*
326326 * cifs tcp session reconnection
@@ -1166,7 +1166,7 @@ cifs_parse_cache_flavor(char *value, struct smb_vol *vol) · 839 unmodified lines
11661166 }
11671167
11681168 static int
1169−cifs_parse_smb_version(char *value, struct smb_vol *vol)
1169+cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
11701170 {
11711171 substring_t args[MAX_OPT_ARGS];
11721172
@@ -1176,6 +1176,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol) · 3 unmodified lines
11761176 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
11771177 return 1;
11781178 }
1179+ if (is_smb3) {
1180+ cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1181+ return 1;
1182+ }
11791183 vol->ops = &smb1_operations;
11801184 vol->vals = &smb1_values;
11811185 break;
@@ -1184,6 +1188,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol) · 2 unmodified lines
11841188 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
11851189 return 1;
11861190 }
1191+ if (is_smb3) {
1192+ cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1193+ return 1;
1194+ }
11871195 vol->ops = &smb20_operations;
11881196 vol->vals = &smb20_values;
11891197 break;
@@ -1272,7 +1280,7 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol) · 82 unmodified lines
12721280
12731281 static int
12741282 cifs_parse_mount_options(const char *mountdata, const char *devname,
1275− struct smb_vol *vol)
1283+ struct smb_vol *vol, bool is_smb3)
12761284 {
12771285 char *data, *end;
12781286 char *mountdata_copy = NULL, *options;
@@ -1985,7 +1993,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, · 706 unmodified lines
19851993 if (string == NULL)
19861994 goto out_nomem;
19871995
1988− if (cifs_parse_smb_version(string, vol) != 0)
1996+ if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
19891997 goto cifs_parse_mount_err;
19901998 got_version = true;
19911999 break;
@@ -3116,12 +3124,6 @@ cifs_put_tlink(struct tcon_link *tlink) · 1124 unmodified lines
31163124 return;
31173125 }
31183126
3119−static inline struct tcon_link *
3120−cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
3121−{
3122− return cifs_sb->master_tlink;
3123−}
3124−
31253127 static int
31263128 compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
31273129 {
@@ -3803,7 +3805,7 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses, · 675 unmodified lines
38033805 } else {
38043806 cleanup_volume_info_contents(volume_info);
38053807 rc = cifs_setup_volume_info(volume_info, mdata,
3806− fake_devname);
3808+ fake_devname, false);
38073809 }
38083810 kfree(fake_devname);
38093811 kfree(cifs_sb->mountdata);
@@ -3816,11 +3818,11 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses, · 6 unmodified lines
38163818
38173819 static int
38183820 cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3819− const char *devname)
3821+ const char *devname, bool is_smb3)
38203822 {
38213823 int rc = 0;
38223824
3823− if (cifs_parse_mount_options(mount_data, devname, volume_info))
3825+ if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
38243826 return -EINVAL;
38253827
38263828 if (volume_info->nullauth) {
@@ -3854,7 +3856,7 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, · 27 unmodified lines
38543856 }
38553857
38563858 struct smb_vol *
3857−cifs_get_volume_info(char *mount_data, const char *devname)
3859+cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
38583860 {
38593861 int rc;
38603862 struct smb_vol *volume_info;
@@ -3863,7 +3865,7 @@ cifs_get_volume_info(char *mount_data, const char *devname) · 2 unmodified lines
38633865 if (!volume_info)
38643866 return ERR_PTR(-ENOMEM);
38653867
3866− rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3868+ rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
38673869 if (rc) {
38683870 cifs_cleanup_volume_info(volume_info);
38693871 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
421421 return -ENOMEM;
422422 }
423423
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);
425426 if (rc)
426427 goto qmf_out_open_fail;
427428
@@ -478,7 +479,8 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, · 50 unmodified lines
478479 oparms.fid = &fid;
479480 oparms.reconnect = false;
480481
481− rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
482+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
483+ NULL);
482484 if (rc) {
483485 kfree(utf16_path);
484486 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
905905 crypto_free_shash(*shash);
906906 *shash = NULL;
907907 }
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+ */
914+void 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
6464 if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
6565 memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE);
6666
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);
6869 if (rc)
6970 goto out;
7071
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
7171 oparms.fid = &fid;
7272 oparms.reconnect = false;
7373
74− rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
74+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
75+ NULL);
7576 if (rc) {
7677 kfree(utf16_path);
7778 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
453453 start_of_path = from + 1;
454454 #ifdef CONFIG_CIFS_SMB311
455455 /* 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) {
457458 start_of_path = from + 1;
459+ }
458460 #endif /* 311 */
459461 else
460462 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
348348 oparams.fid = pfid;
349349 oparams.reconnect = false;
350350
351− rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL);
351+ rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL, NULL);
352352 if (rc == 0) {
353353 memcpy(tcon->prfid, pfid, sizeof(struct cifs_fid));
354354 tcon->valid_root_fid = true;
@@ -375,7 +375,8 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) · 20 unmodified lines
375375 oparms.reconnect = false;
376376
377377 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);
379380 else
380381 rc = open_shroot(xid, tcon, &fid);
381382
@@ -413,7 +414,7 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) · 31 unmodified lines
413414 oparms.fid = &fid;
414415 oparms.reconnect = false;
415416
416− rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
417+ rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
417418 if (rc)
418419 return;
419420
@@ -449,7 +450,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, · 29 unmodified lines
449450 oparms.fid = &fid;
450451 oparms.reconnect = false;
451452
452− rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
453+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
453454 if (rc) {
454455 kfree(utf16_path);
455456 return rc;
@@ -598,7 +599,7 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, · 142 unmodified lines
598599 oparms.fid = &fid;
599600 oparms.reconnect = false;
600601
601− rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
602+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
602603 kfree(utf16_path);
603604 if (rc) {
604605 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
677678 oparms.fid = &fid;
678679 oparms.reconnect = false;
679680
680− rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
681+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
681682 kfree(utf16_path);
682683 if (rc) {
683684 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
12611262 oparms.fid = fid;
12621263 oparms.reconnect = false;
12631264
1264− rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
1265+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
12651266 kfree(utf16_path);
12661267 if (rc) {
12671268 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
13611362 oparms.fid = &fid;
13621363 oparms.reconnect = false;
13631364
1364− rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
1365+ rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
13651366 if (rc)
13661367 return rc;
13671368 buf->f_type = SMB2_MAGIC_NUMBER;
@@ -1515,7 +1516,8 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, · 147 unmodified lines
15151516 struct cifs_open_parms oparms;
15161517 struct cifs_fid fid;
15171518 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;
15191521 struct smb2_symlink_err_rsp *symlink;
15201522 unsigned int sub_len;
15211523 unsigned int sub_offset;
@@ -1535,18 +1537,18 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, · 13 unmodified lines
15351537 oparms.fid = &fid;
15361538 oparms.reconnect = false;
15371539
1538− rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov);
1539−
1540+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov,
1541+ &resp_buftype);
15401542 if (!rc || !err_iov.iov_base) {
1541− kfree(utf16_path);
1542− return -ENOENT;
1543+ rc = -ENOENT;
1544+ goto querty_exit;
15431545 }
15441546
15451547 err_buf = err_iov.iov_base;
15461548 if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
15471549 err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) {
1548− kfree(utf16_path);
1549− return -ENOENT;
1550+ rc = -ENOENT;
1551+ goto querty_exit;
15501552 }
15511553
15521554 /* 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
15581560 print_offset = le16_to_cpu(symlink->PrintNameOffset);
15591561
15601562 if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
1561− kfree(utf16_path);
1562− return -ENOENT;
1563+ rc = -ENOENT;
1564+ goto querty_exit;
15631565 }
15641566
15651567 if (err_iov.iov_len <
15661568 SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
1567− kfree(utf16_path);
1568− return -ENOENT;
1569+ rc = -ENOENT;
1570+ goto querty_exit;
15691571 }
15701572
15711573 *target_path = cifs_strndup_from_utf16(
15721574 (char *)symlink->PathBuffer + sub_offset,
15731575 sub_len, true, cifs_sb->local_nls);
15741576 if (!(*target_path)) {
1575− kfree(utf16_path);
1576− return -ENOMEM;
1577+ rc = -ENOMEM;
1578+ goto querty_exit;
15771579 }
15781580 convert_delimiter(*target_path, '/');
15791581 cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
1582+
1583+ querty_exit:
1584+ free_rsp_buf(resp_buftype, err_buf);
15801585 kfree(utf16_path);
15811586 return rc;
15821587 }
@@ -1649,7 +1654,7 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb, · 66 unmodified lines
16491654 oparms.fid = &fid;
16501655 oparms.reconnect = false;
16511656
1652− rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
1657+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
16531658 kfree(utf16_path);
16541659 if (!rc) {
16551660 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
17121717 oparms.fid = &fid;
17131718 oparms.reconnect = false;
17141719
1715− rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
1720+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
17161721 kfree(utf16_path);
17171722 if (!rc) {
17181723 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
21892194 smb2_sg_set_buf(&sg[i], rqst->rq_iov[i+1].iov_base,
21902195 rqst->rq_iov[i+1].iov_len);
21912196 for (j = 0; i < sg_len - 1; i++, j++) {
2192− unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz
2193− : rqst->rq_tailsz;
2194− sg_set_page(&sg[i], rqst->rq_pages[j], len, 0);
2197+ unsigned int len, offset;
2198+
2199+ rqst_page_get_length(rqst, j, &len, &offset);
2200+ sg_set_page(&sg[i], rqst->rq_pages[j], len, offset);
21952201 }
21962202 smb2_sg_set_buf(&sg[sg_len - 1], sign, SMB2_SIGNATURE_SIZE);
21972203 return sg;
@@ -2229,7 +2235,7 @@ static int · 31 unmodified lines
22292235 crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
22302236 {
22312237 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;
22332239 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
22342240 int rc = 0;
22352241 struct scatterlist *sg;
@@ -2338,6 +2344,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq, · 102 unmodified lines
23382344 return rc;
23392345
23402346 new_rq->rq_pages = pages;
2347+ new_rq->rq_offset = old_rq->rq_offset;
23412348 new_rq->rq_npages = old_rq->rq_npages;
23422349 new_rq->rq_pagesz = old_rq->rq_pagesz;
23432350 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
23792386
23802387 /* copy pages form the old */
23812388 for (i = 0; i < npages; i++) {
2382− char *dst = kmap(new_rq->rq_pages[i]);
2383− char *src = kmap(old_rq->rq_pages[i]);
2384− unsigned int len = (i < npages - 1) ? new_rq->rq_pagesz :
2385− new_rq->rq_tailsz;
2389+ char *dst, *src;
2390+ unsigned int offset, len;
2391+
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+
23862397 memcpy(dst, src, len);
23872398 kunmap(new_rq->rq_pages[i]);
23882399 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
18891889 int
18901890 SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
18911891 __u8 *oplock, struct smb2_file_all_info *buf,
1892− struct kvec *err_iov)
1892+ struct kvec *err_iov, int *buftype)
18931893 {
18941894 struct smb2_create_req *req;
18951895 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
20522052 cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
20532053 if (err_iov && rsp) {
20542054 *err_iov = rsp_iov;
2055+ *buftype = resp_buftype;
20552056 resp_buftype = CIFS_NO_BUFFER;
20562057 rsp = NULL;
20572058 }
@@ -2492,8 +2493,7 @@ SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon, · 434 unmodified lines
24922493
24932494 return query_info(xid, tcon, persistent_fid, volatile_fid,
24942495 0, SMB2_O_INFO_SECURITY, additional_info,
2495− SMB2_MAX_BUFFER_SIZE,
2496− sizeof(struct smb2_file_all_info), data, plen);
2496+ SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen);
24972497 }
24982498
24992499 int
@@ -2721,8 +2721,8 @@ smb2_new_read_req(void **buf, unsigned int *total_len, · 221 unmodified lines
27212721
27222722 rdata->mr = smbd_register_mr(
27232723 server->smbd_conn, rdata->pages,
2724− rdata->nr_pages, rdata->tailsz,
2725− true, need_invalidate);
2724+ rdata->nr_pages, rdata->page_offset,
2725+ rdata->tailsz, true, need_invalidate);
27262726 if (!rdata->mr)
27272727 return -ENOBUFS;
27282728
@@ -3108,16 +3108,22 @@ smb2_async_writev(struct cifs_writedata *wdata, · 379 unmodified lines
31083108
31093109 wdata->mr = smbd_register_mr(
31103110 server->smbd_conn, wdata->pages,
3111− wdata->nr_pages, wdata->tailsz,
3112− false, need_invalidate);
3111+ wdata->nr_pages, wdata->page_offset,
3112+ wdata->tailsz, false, need_invalidate);
31133113 if (!wdata->mr) {
31143114 rc = -ENOBUFS;
31153115 goto async_writev_out;
31163116 }
31173117 req->Length = 0;
31183118 req->DataOffset = 0;
3119− req->RemainingBytes =
3120− cpu_to_le32((wdata->nr_pages-1)*PAGE_SIZE + wdata->tailsz);
3119+ if (wdata->nr_pages > 1)
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);
31213127 req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
31223128 if (need_invalidate)
31233129 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
125125 extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
126126 __le16 *path, __u8 *oplock,
127127 struct smb2_file_all_info *buf,
128− struct kvec *err_iov);
128+ struct kvec *err_iov, int *resp_buftype);
129129 extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
130130 u64 persistent_fid, u64 volatile_fid, u32 opcode,
131131 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
171171 unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
172172 unsigned char *sigptr = smb2_signature;
173173 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;
175177 struct cifs_ses *ses;
176178
177179 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
202204 return rc;
203205 }
204206
205− rc = __cifs_calc_signature(rqst, server, sigptr,
207+ rc = __cifs_calc_signature(rqst, iov_hdr_index, server, sigptr,
206208 &server->secmech.sdeschmacsha256->shash);
207209
208210 if (!rc)
@@ -412,7 +414,9 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) · 203 unmodified lines
412414 unsigned char smb3_signature[SMB2_CMACAES_SIZE];
413415 unsigned char *sigptr = smb3_signature;
414416 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;
416420 struct cifs_ses *ses;
417421
418422 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
443447 return rc;
444448 }
445449
446− rc = __cifs_calc_signature(rqst, server, sigptr,
450+ rc = __cifs_calc_signature(rqst, iov_hdr_index, server, sigptr,
447451 &server->secmech.sdesccmacaes->shash);
448452
449453 if (!rc)
fs/cifs/smbdirect.c+75−46
@@ -17,6 +17,7 @@ · 16 unmodified lines
1717 #include <linux/highmem.h>
1818 #include "smbdirect.h"
1919 #include "cifs_debug.h"
20+#include "cifsproto.h"
2021
2122 static struct smbd_response *get_empty_queue_buffer(
2223 struct smbd_connection *info);
@@ -2003,10 +2004,12 @@ read_rfc1002_done: · 1980 unmodified lines
20032004 * return value: actual data read
20042005 */
20052006 static 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)
20072009 {
20082010 int ret;
20092011 char *to_address;
2012+ void *page_address;
20102013
20112014 /* make sure we have the page ready for read */
20122015 ret = wait_event_interruptible(
@@ -2014,16 +2017,17 @@ static int smbd_recv_page(struct smbd_connection *info, · 1 unmodified line
20142017 info->reassembly_data_length >= to_read ||
20152018 info->transport_status != SMBD_CONNECTED);
20162019 if (ret)
2017− return 0;
2020+ return ret;
20182021
20192022 /* 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;
20212025
20222026 log_read(INFO, "reading from page=%p address=%p to_read=%d\n",
20232027 page, to_address, to_read);
20242028
20252029 ret = smbd_recv_buf(info, to_address, to_read);
2026− kunmap_atomic(to_address);
2030+ kunmap_atomic(page_address);
20272031
20282032 return ret;
20292033 }
@@ -2037,7 +2041,7 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg) · 7 unmodified lines
20372041 {
20382042 char *buf;
20392043 struct page *page;
2040− unsigned int to_read;
2044+ unsigned int to_read, page_offset;
20412045 int rc;
20422046
20432047 info->smbd_recv_pending++;
@@ -2051,15 +2055,16 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg) · 7 unmodified lines
20512055
20522056 case READ | ITER_BVEC:
20532057 page = msg->msg_iter.bvec->bv_page;
2058+ page_offset = msg->msg_iter.bvec->bv_offset;
20542059 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);
20562061 break;
20572062
20582063 default:
20592064 /* It's a bug in upper layer to get there */
20602065 cifs_dbg(VFS, "CIFS: invalid msg type %d\n",
20612066 msg->msg_iter.type);
2062− rc = -EIO;
2067+ rc = -EINVAL;
20632068 }
20642069
20652070 info->smbd_recv_pending--;
@@ -2082,7 +2087,7 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst) · 16 unmodified lines
20822087 struct kvec vec;
20832088 int nvecs;
20842089 int size;
2085− int buflen = 0, remaining_data_length;
2090+ unsigned int buflen = 0, remaining_data_length;
20862091 int start, i, j;
20872092 int max_iov_size =
20882093 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
21132118 buflen += iov[i].iov_len;
21142119 }
21152120
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+ */
21172126 if (rqst->rq_npages) {
2118− buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);
2119− buflen += rqst->rq_tailsz;
2127+ if (rqst->rq_npages == 1)
2128+ buflen += rqst->rq_tailsz;
2129+ else
2130+ buflen += rqst->rq_pagesz * (rqst->rq_npages - 1) -
2131+ rqst->rq_offset + rqst->rq_tailsz;
21202132 }
21212133
21222134 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
22132225
22142226 /* now sending pages if there are any */
22152227 for (i = 0; i < rqst->rq_npages; i++) {
2216− buflen = (i == rqst->rq_npages-1) ?
2217− rqst->rq_tailsz : rqst->rq_pagesz;
2228+ unsigned int offset;
2229+
2230+ rqst_page_get_length(rqst, i, &buflen, &offset);
22182231 nvecs = (buflen + max_iov_size - 1) / max_iov_size;
22192232 log_write(INFO, "sending pages buflen=%d nvecs=%d\n",
22202233 buflen, nvecs);
@@ -2225,9 +2238,11 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst) · 4 unmodified lines
22252238 remaining_data_length -= size;
22262239 log_write(INFO, "sending pages i=%d offset=%d size=%d"
22272240 " 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);
22292243 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,
22312246 size, remaining_data_length);
22322247 if (rc)
22332248 goto done;
@@ -2284,37 +2299,37 @@ static void smbd_mr_recovery_work(struct work_struct *work) · 50 unmodified lines
22842299 if (smbdirect_mr->state == MR_INVALIDATED ||
22852300 smbdirect_mr->state == MR_ERROR) {
22862301
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)
22882326 ib_dma_unmap_sg(
22892327 info->id->device, smbdirect_mr->sgl,
22902328 smbdirect_mr->sgl_count,
22912329 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− }
23032330
2304− smbdirect_mr->mr = ib_alloc_mr(
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− }
2331+ smbdirect_mr->state = MR_READY;
23152332
2316− smbdirect_mr->state = MR_READY;
2317− }
23182333 /* smbdirect_mr->state is updated by this function
23192334 * and is read and updated by I/O issuing CPUs trying
23202335 * to get a MR, the call to atomic_inc_return
@@ -2460,7 +2475,7 @@ again: · 139 unmodified lines
24602475 */
24612476 struct smbd_mr *smbd_register_mr(
24622477 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)
24642479 {
24652480 struct smbd_mr *smbdirect_mr;
24662481 int rc, i;
@@ -2483,17 +2498,31 @@ struct smbd_mr *smbd_register_mr( · 16 unmodified lines
24832498 smbdirect_mr->sgl_count = num_pages;
24842499 sg_init_table(smbdirect_mr->sgl, num_pages);
24852500
2486− for (i = 0; i < num_pages - 1; i++)
2487− sg_set_page(&smbdirect_mr->sgl[i], pages[i], PAGE_SIZE, 0);
2501+ log_rdma_mr(INFO, "num_pages=0x%x offset=0x%x tailsz=0x%x\n",
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+ }
24882508
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+ }
24892517 sg_set_page(&smbdirect_mr->sgl[i], pages[i],
24902518 tailsz ? tailsz : PAGE_SIZE, 0);
24912519
2520+skip_multiple_pages:
24922521 dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
24932522 smbdirect_mr->dir = dir;
24942523 rc = ib_dma_map_sg(info->id->device, smbdirect_mr->sgl, num_pages, dir);
24952524 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",
24972526 num_pages, dir, rc);
24982527 goto dma_map_error;
24992528 }
@@ -2501,8 +2530,8 @@ struct smbd_mr *smbd_register_mr( · 1 unmodified line
25012530 rc = ib_map_mr_sg(smbdirect_mr->mr, smbdirect_mr->sgl, num_pages,
25022531 NULL, PAGE_SIZE);
25032532 if (rc != num_pages) {
2504− log_rdma_mr(INFO,
2505− "ib_map_mr_sg failed rc = %x num_pages = %x\n",
2533+ log_rdma_mr(ERR,
2534+ "ib_map_mr_sg failed rc = %d num_pages = %x\n",
25062535 rc, num_pages);
25072536 goto map_mr_error;
25082537 }
fs/cifs/smbdirect.h+1−1
@@ -321,7 +321,7 @@ struct smbd_mr { · 320 unmodified lines
321321 /* Interfaces to register and deregister MR for RDMA read/write */
322322 struct smbd_mr *smbd_register_mr(
323323 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);
325325 int smbd_deregister_mr(struct smbd_mr *mr);
326326
327327 #else
fs/cifs/transport.c+23−11
@@ -212,10 +212,24 @@ rqst_len(struct smb_rqst *rqst) · 211 unmodified lines
212212 for (i = 0; i < rqst->rq_nvec; i++)
213213 buflen += iov[i].iov_len;
214214
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+ */
216221 if (rqst->rq_npages) {
217− buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);
218− buflen += rqst->rq_tailsz;
222+ if (rqst->rq_npages == 1)
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+ }
219233 }
220234
221235 return buflen;
@@ -274,15 +288,13 @@ __smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) · 52 unmodified lines
274288
275289 /* now walk the page array and send each page in it */
276290 for (i = 0; i < rqst->rq_npages; i++) {
277− size_t len = i == rqst->rq_npages - 1
278− ? rqst->rq_tailsz
279− : rqst->rq_pagesz;
280− struct bio_vec bvec = {
281− .bv_page = rqst->rq_pages[i],
282− .bv_len = len
283− };
291+ struct bio_vec bvec;
292+
293+ bvec.bv_page = rqst->rq_pages[i];
294+ rqst_page_get_length(rqst, i, &bvec.bv_len, &bvec.bv_offset);
295+
284296 iov_iter_bvec(&smb_msg.msg_iter, WRITE | ITER_BVEC,
285− &bvec, 1, len);
297+ &bvec, 1, bvec.bv_len);
286298 rc = smb_send_kvec(server, &smb_msg, &sent);
287299 if (rc < 0)
288300 break;