diff mbox series

[01/16] cifs: add server->vals->header_preamble_size

Message ID 20180331004536.27346-2-lsahlber@redhat.com
State New
Headers show
Series [01/16] cifs: add server->vals->header_preamble_size | expand

Commit Message

Ronnie Sahlberg March 31, 2018, 12:45 a.m. UTC
This variable is set to 4 for all protocol versions and replaces
the hardcoded constant 4 throughought the code.
This will later be updated to reflect whether a response packet
has a 4 byte length preamble or not once we start removing this
field from the SMB2+ dialects.

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
---
 fs/cifs/cifsglob.h  |  1 +
 fs/cifs/cifssmb.c   |  6 ++++--
 fs/cifs/connect.c   | 16 ++++++++++-----
 fs/cifs/smb1ops.c   |  1 +
 fs/cifs/smb2misc.c  | 19 +++++++++--------
 fs/cifs/smb2ops.c   | 59 +++++++++++++++++++++++++++++++++--------------------
 fs/cifs/smb2pdu.c   | 15 ++++++++------
 fs/cifs/transport.c |  3 ++-
 8 files changed, 75 insertions(+), 45 deletions(-)

Comments

Pavel Shilovsky April 2, 2018, 5:56 p.m. UTC | #1
2018-03-30 17:45 GMT-07:00 Ronnie Sahlberg <lsahlber@redhat.com>:
> This variable is set to 4 for all protocol versions and replaces
> the hardcoded constant 4 throughought the code.
> This will later be updated to reflect whether a response packet
> has a 4 byte length preamble or not once we start removing this
> field from the SMB2+ dialects.
>
> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
> ---
>  fs/cifs/cifsglob.h  |  1 +
>  fs/cifs/cifssmb.c   |  6 ++++--
>  fs/cifs/connect.c   | 16 ++++++++++-----
>  fs/cifs/smb1ops.c   |  1 +
>  fs/cifs/smb2misc.c  | 19 +++++++++--------
>  fs/cifs/smb2ops.c   | 59 +++++++++++++++++++++++++++++++++--------------------
>  fs/cifs/smb2pdu.c   | 15 ++++++++------
>  fs/cifs/transport.c |  3 ++-
>  8 files changed, 75 insertions(+), 45 deletions(-)
>
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index c294093f04d5..3e3f86841372 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -468,6 +468,7 @@ struct smb_version_values {
>         __u32           exclusive_lock_type;
>         __u32           shared_lock_type;
>         __u32           unlock_lock_type;
> +       size_t          header_preamble_size;
>         size_t          header_size;
>         size_t          max_header_size;
>         size_t          read_rsp_size;
> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> index 9ceebf30eb22..59c09a596c0a 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -1454,7 +1454,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>         unsigned int data_offset, data_len;
>         struct cifs_readdata *rdata = mid->callback_data;
>         char *buf = server->smallbuf;
> -       unsigned int buflen = get_rfc1002_length(buf) + 4;
> +       unsigned int buflen = get_rfc1002_length(buf) +
> +               server->vals->header_preamble_size;
>         bool use_rdma_mr = false;
>
>         cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
> @@ -1504,7 +1505,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>                 return cifs_readv_discard(server, mid);
>         }
>
> -       data_offset = server->ops->read_data_offset(buf) + 4;
> +       data_offset = server->ops->read_data_offset(buf) +
> +               server->vals->header_preamble_size;
>         if (data_offset < server->total_read) {
>                 /*
>                  * win2k8 sometimes sends an offset of 0 when the read
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index a726f524fb84..1f2e3b15b2b1 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -775,7 +775,8 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>         unsigned int pdu_length = get_rfc1002_length(buf);
>
>         /* make sure this will fit in a large buffer */
> -       if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
> +       if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
> +               server->vals->header_preamble_size) {
>                 cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
>                 cifs_reconnect(server);
>                 wake_up(&server->response_q);
> @@ -791,7 +792,9 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>
>         /* now read the rest */
>         length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
> -                               pdu_length - HEADER_SIZE(server) + 1 + 4);
> +                                      pdu_length - HEADER_SIZE(server) + 1
> +                                      + server->vals->header_preamble_size);
> +
>         if (length < 0)
>                 return length;
>         server->total_read += length;
> @@ -884,7 +887,8 @@ cifs_demultiplex_thread(void *p)
>                         continue;
>
>                 /* make sure we have enough to get to the MID */
> -               if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
> +               if (pdu_length < HEADER_SIZE(server) - 1 -
> +                   server->vals->header_preamble_size) {
>                         cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
>                                  pdu_length);
>                         cifs_reconnect(server);
> @@ -893,8 +897,10 @@ cifs_demultiplex_thread(void *p)
>                 }
>
>                 /* read down to the MID */
> -               length = cifs_read_from_socket(server, buf + 4,
> -                                              HEADER_SIZE(server) - 1 - 4);
> +               length = cifs_read_from_socket(server,
> +                            buf + server->vals->header_preamble_size,
> +                            HEADER_SIZE(server) - 1
> +                            - server->vals->header_preamble_size);
>                 if (length < 0)
>                         continue;
>                 server->total_read += length;
> diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
> index 3d495e440c87..aff8ce8ba34d 100644
> --- a/fs/cifs/smb1ops.c
> +++ b/fs/cifs/smb1ops.c
> @@ -1122,6 +1122,7 @@ struct smb_version_values smb1_values = {
>         .exclusive_lock_type = 0,
>         .shared_lock_type = LOCKING_ANDX_SHARED_LOCK,
>         .unlock_lock_type = 0,
> +       .header_preamble_size = 4,
>         .header_size = sizeof(struct smb_hdr),
>         .max_header_size = MAX_CIFS_HDR_SIZE,
>         .read_rsp_size = sizeof(READ_RSP),
> diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
> index da012c3ab700..dfa5d9f4e00b 100644
> --- a/fs/cifs/smb2misc.c
> +++ b/fs/cifs/smb2misc.c
> @@ -150,7 +150,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>                 }
>                 return 1;
>         }
> -       if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - 4) {
> +       if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE -
> +           srvr->vals->header_preamble_size) {
>                 cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu\n",
>                          mid);
>                 return 1;
> @@ -189,26 +190,26 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>                 }
>         }
>
> -       if (4 + len != length) {
> +       if (srvr->vals->header_preamble_size + len != length) {
>                 cifs_dbg(VFS, "Total length %u RFC1002 length %u mismatch mid %llu\n",
> -                        length, 4 + len, mid);
> +                        length, srvr->vals->header_preamble_size + len, mid);
>                 return 1;
>         }
>
>         clc_len = smb2_calc_size(hdr);
>
> -       if (4 + len != clc_len) {
> +       if (srvr->vals->header_preamble_size + len != clc_len) {
>                 cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
> -                        clc_len, 4 + len, mid);
> +                        clc_len, srvr->vals->header_preamble_size + len, mid);
>                 /* create failed on symlink */
>                 if (command == SMB2_CREATE_HE &&
>                     shdr->Status == STATUS_STOPPED_ON_SYMLINK)
>                         return 0;
>                 /* Windows 7 server returns 24 bytes more */
> -               if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE)
> +               if (clc_len + 24 - srvr->vals->header_preamble_size == len && command == SMB2_OPLOCK_BREAK_HE)
>                         return 0;
>                 /* server can return one byte more due to implied bcc[0] */
> -               if (clc_len == 4 + len + 1)
> +               if (clc_len == srvr->vals->header_preamble_size + len + 1)
>                         return 0;
>
>                 /*
> @@ -218,10 +219,10 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>                  * Log the server error (once), but allow it and continue
>                  * since the frame is parseable.
>                  */
> -               if (clc_len < 4 /* RFC1001 header size */ + len) {
> +               if (clc_len < srvr->vals->header_preamble_size /* RFC1001 header size */ + len) {
>                         printk_once(KERN_WARNING
>                                 "SMB2 server sent bad RFC1001 len %d not %d\n",
> -                               len, clc_len - 4);
> +                               len, clc_len - srvr->vals->header_preamble_size);
>                         return 0;
>                 }
>
> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> index dfd6fb02b7a3..04a70e78fefa 100644
> --- a/fs/cifs/smb2ops.c
> +++ b/fs/cifs/smb2ops.c
> @@ -1457,6 +1457,8 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
>         unsigned int sub_offset;
>         unsigned int print_len;
>         unsigned int print_offset;
> +       struct cifs_ses *ses = tcon->ses;
> +       struct TCP_Server_Info *server = ses->server;
>
>         cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
>
> @@ -1479,7 +1481,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
>         }
>
>         if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
> -           get_rfc1002_length(err_buf) + 4 < SMB2_SYMLINK_STRUCT_SIZE) {
> +           get_rfc1002_length(err_buf) + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
>                 kfree(utf16_path);
>                 return -ENOENT;
>         }
> @@ -1492,13 +1494,13 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
>         print_len = le16_to_cpu(symlink->PrintNameLength);
>         print_offset = le16_to_cpu(symlink->PrintNameOffset);
>
> -       if (get_rfc1002_length(err_buf) + 4 <
> +       if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size <
>                         SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
>                 kfree(utf16_path);
>                 return -ENOENT;
>         }
>
> -       if (get_rfc1002_length(err_buf) + 4 <
> +       if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size <
>                         SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
>                 kfree(utf16_path);
>                 return -ENOENT;
> @@ -2050,7 +2052,8 @@ smb2_dir_needs_close(struct cifsFileInfo *cfile)
>  }
>
>  static void
> -fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
> +fill_transform_hdr(struct TCP_Server_Info *server,
> +                  struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
>  {
>         struct smb2_sync_hdr *shdr =
>                         (struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base;
> @@ -2062,7 +2065,7 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
>         tr_hdr->Flags = cpu_to_le16(0x01);
>         get_random_bytes(&tr_hdr->Nonce, SMB3_AES128CMM_NONCE);
>         memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8);
> -       inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - 4);
> +       inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - server->vals->header_preamble_size);
>         inc_rfc1001_len(tr_hdr, orig_len);
>  }
>
> @@ -2134,7 +2137,7 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
>  {
>         struct smb2_transform_hdr *tr_hdr =
>                         (struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base;
> -       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
> +       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20 - server->vals->header_preamble_size;
>         int rc = 0;
>         struct scatterlist *sg;
>         u8 sign[SMB2_SIGNATURE_SIZE] = {};
> @@ -2262,7 +2265,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
>                 goto err_free_iov;
>
>         /* fill the 1st iov with a transform header */
> -       fill_transform_hdr(tr_hdr, old_rq);
> +       fill_transform_hdr(server, tr_hdr, old_rq);
>         new_rq->rq_iov[0].iov_base = tr_hdr;
>         new_rq->rq_iov[0].iov_len = sizeof(struct smb2_transform_hdr);
>
> @@ -2344,10 +2347,10 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
>         if (rc)
>                 return rc;
>
> -       memmove(buf + 4, iov[1].iov_base, buf_data_size);
> +       memmove(buf + server->vals->header_preamble_size, iov[1].iov_base, buf_data_size);
>         hdr = (struct smb2_hdr *)buf;
>         hdr->smb2_buf_length = cpu_to_be32(buf_data_size + page_data_size);
> -       server->total_read = buf_data_size + page_data_size + 4;
> +       server->total_read = buf_data_size + page_data_size + server->vals->header_preamble_size;
>
>         return rc;
>  }
> @@ -2451,7 +2454,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
>                 return 0;
>         }
>
> -       data_offset = server->ops->read_data_offset(buf) + 4;
> +       data_offset = server->ops->read_data_offset(buf) + server->vals->header_preamble_size;
>  #ifdef CONFIG_CIFS_SMB_DIRECT
>         use_rdma_mr = rdata->mr;
>  #endif
> @@ -2547,11 +2550,12 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
>         unsigned int npages;
>         struct page **pages;
>         unsigned int len;
> -       unsigned int buflen = get_rfc1002_length(buf) + 4;
> +       unsigned int buflen = get_rfc1002_length(buf) + server->vals->header_preamble_size;
>         int rc;
>         int i = 0;
>
> -       len = min_t(unsigned int, buflen, server->vals->read_rsp_size - 4 +
> +       len = min_t(unsigned int, buflen, server->vals->read_rsp_size -
> +               server->vals->header_preamble_size +
>                 sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1;
>
>         rc = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len);
> @@ -2559,8 +2563,9 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
>                 return rc;
>         server->total_read += rc;
>
> -       len = le32_to_cpu(tr_hdr->OriginalMessageSize) + 4 -
> -                                               server->vals->read_rsp_size;
> +       len = le32_to_cpu(tr_hdr->OriginalMessageSize) +
> +               server->vals->header_preamble_size -
> +               server->vals->read_rsp_size;
>         npages = DIV_ROUND_UP(len, PAGE_SIZE);
>
>         pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
> @@ -2586,7 +2591,8 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
>         if (rc)
>                 goto free_pages;
>
> -       rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size - 4,
> +       rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size -
> +                             server->vals->header_preamble_size,
>                               pages, npages, len);
>         if (rc)
>                 goto free_pages;
> @@ -2623,7 +2629,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
>         struct mid_q_entry *mid_entry;
>
>         /* switch to large buffer if too big for a small one */
> -       if (pdu_length + 4 > MAX_CIFS_SMALL_BUFFER_SIZE) {
> +       if (pdu_length + server->vals->header_preamble_size > MAX_CIFS_SMALL_BUFFER_SIZE) {
>                 server->large_buf = true;
>                 memcpy(server->bigbuf, buf, server->total_read);
>                 buf = server->bigbuf;
> @@ -2631,12 +2637,13 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
>
>         /* now read the rest */
>         length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
> -                               pdu_length - HEADER_SIZE(server) + 1 + 4);
> +                               pdu_length - HEADER_SIZE(server) + 1 +
> +                               server->vals->header_preamble_size);
>         if (length < 0)
>                 return length;
>         server->total_read += length;
>
> -       buf_size = pdu_length + 4 - sizeof(struct smb2_transform_hdr);
> +       buf_size = pdu_length + server->vals->header_preamble_size - sizeof(struct smb2_transform_hdr);
>         length = decrypt_raw_data(server, buf, buf_size, NULL, 0, 0);
>         if (length)
>                 return length;
> @@ -2665,7 +2672,7 @@ smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
>         struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
>         unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
>
> -       if (pdu_length + 4 < sizeof(struct smb2_transform_hdr) +
> +       if (pdu_length + server->vals->header_preamble_size < sizeof(struct smb2_transform_hdr) +
>                                                 sizeof(struct smb2_sync_hdr)) {
>                 cifs_dbg(VFS, "Transform message is too small (%u)\n",
>                          pdu_length);
> @@ -2674,14 +2681,14 @@ smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
>                 return -ECONNABORTED;
>         }
>
> -       if (pdu_length + 4 < orig_len + sizeof(struct smb2_transform_hdr)) {
> +       if (pdu_length + server->vals->header_preamble_size < orig_len + sizeof(struct smb2_transform_hdr)) {
>                 cifs_dbg(VFS, "Transform message is broken\n");
>                 cifs_reconnect(server);
>                 wake_up(&server->response_q);
>                 return -ECONNABORTED;
>         }
>
> -       if (pdu_length + 4 > CIFSMaxBufSize + MAX_HEADER_SIZE(server))
> +       if (pdu_length + server->vals->header_preamble_size > CIFSMaxBufSize + MAX_HEADER_SIZE(server))
>                 return receive_encrypted_read(server, mid);
>
>         return receive_encrypted_standard(server, mid);
> @@ -2692,7 +2699,8 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>  {
>         char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
>
> -       return handle_read_data(server, mid, buf, get_rfc1002_length(buf) + 4,
> +       return handle_read_data(server, mid, buf, get_rfc1002_length(buf) +
> +                               server->vals->header_preamble_size,
>                                 NULL, 0, 0);
>  }
>
> @@ -3097,6 +3105,7 @@ struct smb_version_values smb20_values = {
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>         .header_size = sizeof(struct smb2_hdr),
> +       .header_preamble_size = 4,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3117,6 +3126,7 @@ struct smb_version_values smb21_values = {
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>         .header_size = sizeof(struct smb2_hdr),
> +       .header_preamble_size = 4,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3137,6 +3147,7 @@ struct smb_version_values smb3any_values = {
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>         .header_size = sizeof(struct smb2_hdr),
> +       .header_preamble_size = 4,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3157,6 +3168,7 @@ struct smb_version_values smbdefault_values = {
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>         .header_size = sizeof(struct smb2_hdr),
> +       .header_preamble_size = 4,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3177,6 +3189,7 @@ struct smb_version_values smb30_values = {
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>         .header_size = sizeof(struct smb2_hdr),
> +       .header_preamble_size = 4,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3197,6 +3210,7 @@ struct smb_version_values smb302_values = {
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>         .header_size = sizeof(struct smb2_hdr),
> +       .header_preamble_size = 4,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3218,6 +3232,7 @@ struct smb_version_values smb311_values = {
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>         .header_size = sizeof(struct smb2_hdr),
> +       .header_preamble_size = 4,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
> index 4b6920de2541..1e765b31eb88 100644
> --- a/fs/cifs/smb2pdu.c
> +++ b/fs/cifs/smb2pdu.c
> @@ -1466,7 +1466,7 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp,
>         unsigned int remaining;
>         char *name;
>
> -       data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset);
> +       data_offset = (char *)rsp + server->vals->header_preamble_size + le32_to_cpu(rsp->CreateContextsOffset);
>         remaining = le32_to_cpu(rsp->CreateContextsLength);
>         cc = (struct create_context *)data_offset;
>         while (remaining >= sizeof(struct create_context)) {
> @@ -3447,6 +3447,7 @@ static int
>  build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
>                    int outbuf_len, u64 persistent_fid, u64 volatile_fid)
>  {
> +       struct TCP_Server_Info *server = tcon->ses->server;
>         int rc;
>         struct smb2_query_info_req *req;
>         unsigned int total_len;
> @@ -3469,7 +3470,7 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
>         req->InputBufferOffset =
>                         cpu_to_le16(sizeof(struct smb2_query_info_req) - 1);
>         req->OutputBufferLength = cpu_to_le32(
> -               outbuf_len + sizeof(struct smb2_query_info_rsp) - 1 - 4);
> +               outbuf_len + sizeof(struct smb2_query_info_rsp) - 1 - server->vals->header_preamble_size);
>
>         iov->iov_base = (char *)req;
>         iov->iov_len = total_len;
> @@ -3486,6 +3487,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
>         int rc = 0;
>         int resp_buftype;
>         struct cifs_ses *ses = tcon->ses;
> +       struct TCP_Server_Info *server = ses->server;
>         struct smb2_fs_full_size_info *info = NULL;
>         int flags = 0;
>
> @@ -3506,7 +3508,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
>         }
>         rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
>
> -       info = (struct smb2_fs_full_size_info *)(4 /* RFC1001 len */ +
> +       info = (struct smb2_fs_full_size_info *)(server->vals->header_preamble_size +
>                 le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr);
>         rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset),
>                           le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr,
> @@ -3529,6 +3531,7 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
>         int rc = 0;
>         int resp_buftype, max_len, min_len;
>         struct cifs_ses *ses = tcon->ses;
> +       struct TCP_Server_Info *server = ses->server;
>         unsigned int rsp_len, offset;
>         int flags = 0;
>
> @@ -3569,15 +3572,15 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
>                 goto qfsattr_exit;
>
>         if (level == FS_ATTRIBUTE_INFORMATION)
> -               memcpy(&tcon->fsAttrInfo, 4 /* RFC1001 len */ + offset
> +               memcpy(&tcon->fsAttrInfo, server->vals->header_preamble_size + offset
>                         + (char *)&rsp->hdr, min_t(unsigned int,
>                         rsp_len, max_len));
>         else if (level == FS_DEVICE_INFORMATION)
> -               memcpy(&tcon->fsDevInfo, 4 /* RFC1001 len */ + offset
> +               memcpy(&tcon->fsDevInfo, server->vals->header_preamble_size + offset
>                         + (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO));
>         else if (level == FS_SECTOR_SIZE_INFORMATION) {
>                 struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *)
> -                       (4 /* RFC1001 len */ + offset + (char *)&rsp->hdr);
> +                       (server->vals->header_preamble_size + offset + (char *)&rsp->hdr);
>                 tcon->ss_flags = le32_to_cpu(ss_info->Flags);
>                 tcon->perf_sector_size =
>                         le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index 665661464067..279718dcb2ed 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -790,7 +790,8 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
>
>         buf = (char *)midQ->resp_buf;
>         resp_iov->iov_base = buf;
> -       resp_iov->iov_len = get_rfc1002_length(buf) + 4;
> +       resp_iov->iov_len = get_rfc1002_length(buf) +
> +               ses->server->vals->header_preamble_size;
>         if (midQ->large_buf)
>                 *resp_buf_type = CIFS_LARGE_BUFFER;
>         else
> --
> 2.13.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Looks good. We need to try looking for other ways to split patch #2.

Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>

--
Best regards,
Pavel Shilovsky
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox series

Patch

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index c294093f04d5..3e3f86841372 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -468,6 +468,7 @@  struct smb_version_values {
 	__u32		exclusive_lock_type;
 	__u32		shared_lock_type;
 	__u32		unlock_lock_type;
+	size_t		header_preamble_size;
 	size_t		header_size;
 	size_t		max_header_size;
 	size_t		read_rsp_size;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 9ceebf30eb22..59c09a596c0a 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1454,7 +1454,8 @@  cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 	unsigned int data_offset, data_len;
 	struct cifs_readdata *rdata = mid->callback_data;
 	char *buf = server->smallbuf;
-	unsigned int buflen = get_rfc1002_length(buf) + 4;
+	unsigned int buflen = get_rfc1002_length(buf) +
+		server->vals->header_preamble_size;
 	bool use_rdma_mr = false;
 
 	cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
@@ -1504,7 +1505,8 @@  cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 		return cifs_readv_discard(server, mid);
 	}
 
-	data_offset = server->ops->read_data_offset(buf) + 4;
+	data_offset = server->ops->read_data_offset(buf) +
+		server->vals->header_preamble_size;
 	if (data_offset < server->total_read) {
 		/*
 		 * win2k8 sometimes sends an offset of 0 when the read
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index a726f524fb84..1f2e3b15b2b1 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -775,7 +775,8 @@  standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 	unsigned int pdu_length = get_rfc1002_length(buf);
 
 	/* make sure this will fit in a large buffer */
-	if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
+	if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
+		server->vals->header_preamble_size) {
 		cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
 		cifs_reconnect(server);
 		wake_up(&server->response_q);
@@ -791,7 +792,9 @@  standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 
 	/* now read the rest */
 	length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
-				pdu_length - HEADER_SIZE(server) + 1 + 4);
+				       pdu_length - HEADER_SIZE(server) + 1
+				       + server->vals->header_preamble_size);
+
 	if (length < 0)
 		return length;
 	server->total_read += length;
@@ -884,7 +887,8 @@  cifs_demultiplex_thread(void *p)
 			continue;
 
 		/* make sure we have enough to get to the MID */
-		if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
+		if (pdu_length < HEADER_SIZE(server) - 1 -
+		    server->vals->header_preamble_size) {
 			cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
 				 pdu_length);
 			cifs_reconnect(server);
@@ -893,8 +897,10 @@  cifs_demultiplex_thread(void *p)
 		}
 
 		/* read down to the MID */
-		length = cifs_read_from_socket(server, buf + 4,
-					       HEADER_SIZE(server) - 1 - 4);
+		length = cifs_read_from_socket(server,
+			     buf + server->vals->header_preamble_size,
+			     HEADER_SIZE(server) - 1
+			     - server->vals->header_preamble_size);
 		if (length < 0)
 			continue;
 		server->total_read += length;
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 3d495e440c87..aff8ce8ba34d 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -1122,6 +1122,7 @@  struct smb_version_values smb1_values = {
 	.exclusive_lock_type = 0,
 	.shared_lock_type = LOCKING_ANDX_SHARED_LOCK,
 	.unlock_lock_type = 0,
+	.header_preamble_size = 4,
 	.header_size = sizeof(struct smb_hdr),
 	.max_header_size = MAX_CIFS_HDR_SIZE,
 	.read_rsp_size = sizeof(READ_RSP),
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index da012c3ab700..dfa5d9f4e00b 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -150,7 +150,8 @@  smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
 		}
 		return 1;
 	}
-	if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - 4) {
+	if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE -
+	    srvr->vals->header_preamble_size) {
 		cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu\n",
 			 mid);
 		return 1;
@@ -189,26 +190,26 @@  smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
 		}
 	}
 
-	if (4 + len != length) {
+	if (srvr->vals->header_preamble_size + len != length) {
 		cifs_dbg(VFS, "Total length %u RFC1002 length %u mismatch mid %llu\n",
-			 length, 4 + len, mid);
+			 length, srvr->vals->header_preamble_size + len, mid);
 		return 1;
 	}
 
 	clc_len = smb2_calc_size(hdr);
 
-	if (4 + len != clc_len) {
+	if (srvr->vals->header_preamble_size + len != clc_len) {
 		cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
-			 clc_len, 4 + len, mid);
+			 clc_len, srvr->vals->header_preamble_size + len, mid);
 		/* create failed on symlink */
 		if (command == SMB2_CREATE_HE &&
 		    shdr->Status == STATUS_STOPPED_ON_SYMLINK)
 			return 0;
 		/* Windows 7 server returns 24 bytes more */
-		if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE)
+		if (clc_len + 24 - srvr->vals->header_preamble_size == len && command == SMB2_OPLOCK_BREAK_HE)
 			return 0;
 		/* server can return one byte more due to implied bcc[0] */
-		if (clc_len == 4 + len + 1)
+		if (clc_len == srvr->vals->header_preamble_size + len + 1)
 			return 0;
 
 		/*
@@ -218,10 +219,10 @@  smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
 		 * Log the server error (once), but allow it and continue
 		 * since the frame is parseable.
 		 */
-		if (clc_len < 4 /* RFC1001 header size */ + len) {
+		if (clc_len < srvr->vals->header_preamble_size /* RFC1001 header size */ + len) {
 			printk_once(KERN_WARNING
 				"SMB2 server sent bad RFC1001 len %d not %d\n",
-				len, clc_len - 4);
+				len, clc_len - srvr->vals->header_preamble_size);
 			return 0;
 		}
 
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index dfd6fb02b7a3..04a70e78fefa 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1457,6 +1457,8 @@  smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 	unsigned int sub_offset;
 	unsigned int print_len;
 	unsigned int print_offset;
+	struct cifs_ses *ses = tcon->ses;
+	struct TCP_Server_Info *server = ses->server;
 
 	cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
 
@@ -1479,7 +1481,7 @@  smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 	}
 
 	if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
-	    get_rfc1002_length(err_buf) + 4 < SMB2_SYMLINK_STRUCT_SIZE) {
+	    get_rfc1002_length(err_buf) + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
 		kfree(utf16_path);
 		return -ENOENT;
 	}
@@ -1492,13 +1494,13 @@  smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 	print_len = le16_to_cpu(symlink->PrintNameLength);
 	print_offset = le16_to_cpu(symlink->PrintNameOffset);
 
-	if (get_rfc1002_length(err_buf) + 4 <
+	if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size <
 			SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
 		kfree(utf16_path);
 		return -ENOENT;
 	}
 
-	if (get_rfc1002_length(err_buf) + 4 <
+	if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size <
 			SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
 		kfree(utf16_path);
 		return -ENOENT;
@@ -2050,7 +2052,8 @@  smb2_dir_needs_close(struct cifsFileInfo *cfile)
 }
 
 static void
-fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
+fill_transform_hdr(struct TCP_Server_Info *server,
+		   struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
 {
 	struct smb2_sync_hdr *shdr =
 			(struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base;
@@ -2062,7 +2065,7 @@  fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
 	tr_hdr->Flags = cpu_to_le16(0x01);
 	get_random_bytes(&tr_hdr->Nonce, SMB3_AES128CMM_NONCE);
 	memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8);
-	inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - 4);
+	inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - server->vals->header_preamble_size);
 	inc_rfc1001_len(tr_hdr, orig_len);
 }
 
@@ -2134,7 +2137,7 @@  crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
 {
 	struct smb2_transform_hdr *tr_hdr =
 			(struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base;
-	unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
+	unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20 - server->vals->header_preamble_size;
 	int rc = 0;
 	struct scatterlist *sg;
 	u8 sign[SMB2_SIGNATURE_SIZE] = {};
@@ -2262,7 +2265,7 @@  smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
 		goto err_free_iov;
 
 	/* fill the 1st iov with a transform header */
-	fill_transform_hdr(tr_hdr, old_rq);
+	fill_transform_hdr(server, tr_hdr, old_rq);
 	new_rq->rq_iov[0].iov_base = tr_hdr;
 	new_rq->rq_iov[0].iov_len = sizeof(struct smb2_transform_hdr);
 
@@ -2344,10 +2347,10 @@  decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
 	if (rc)
 		return rc;
 
-	memmove(buf + 4, iov[1].iov_base, buf_data_size);
+	memmove(buf + server->vals->header_preamble_size, iov[1].iov_base, buf_data_size);
 	hdr = (struct smb2_hdr *)buf;
 	hdr->smb2_buf_length = cpu_to_be32(buf_data_size + page_data_size);
-	server->total_read = buf_data_size + page_data_size + 4;
+	server->total_read = buf_data_size + page_data_size + server->vals->header_preamble_size;
 
 	return rc;
 }
@@ -2451,7 +2454,7 @@  handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
 		return 0;
 	}
 
-	data_offset = server->ops->read_data_offset(buf) + 4;
+	data_offset = server->ops->read_data_offset(buf) + server->vals->header_preamble_size;
 #ifdef CONFIG_CIFS_SMB_DIRECT
 	use_rdma_mr = rdata->mr;
 #endif
@@ -2547,11 +2550,12 @@  receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
 	unsigned int npages;
 	struct page **pages;
 	unsigned int len;
-	unsigned int buflen = get_rfc1002_length(buf) + 4;
+	unsigned int buflen = get_rfc1002_length(buf) + server->vals->header_preamble_size;
 	int rc;
 	int i = 0;
 
-	len = min_t(unsigned int, buflen, server->vals->read_rsp_size - 4 +
+	len = min_t(unsigned int, buflen, server->vals->read_rsp_size -
+		server->vals->header_preamble_size +
 		sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1;
 
 	rc = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len);
@@ -2559,8 +2563,9 @@  receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
 		return rc;
 	server->total_read += rc;
 
-	len = le32_to_cpu(tr_hdr->OriginalMessageSize) + 4 -
-						server->vals->read_rsp_size;
+	len = le32_to_cpu(tr_hdr->OriginalMessageSize) +
+		server->vals->header_preamble_size -
+		server->vals->read_rsp_size;
 	npages = DIV_ROUND_UP(len, PAGE_SIZE);
 
 	pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
@@ -2586,7 +2591,8 @@  receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
 	if (rc)
 		goto free_pages;
 
-	rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size - 4,
+	rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size -
+			      server->vals->header_preamble_size,
 			      pages, npages, len);
 	if (rc)
 		goto free_pages;
@@ -2623,7 +2629,7 @@  receive_encrypted_standard(struct TCP_Server_Info *server,
 	struct mid_q_entry *mid_entry;
 
 	/* switch to large buffer if too big for a small one */
-	if (pdu_length + 4 > MAX_CIFS_SMALL_BUFFER_SIZE) {
+	if (pdu_length + server->vals->header_preamble_size > MAX_CIFS_SMALL_BUFFER_SIZE) {
 		server->large_buf = true;
 		memcpy(server->bigbuf, buf, server->total_read);
 		buf = server->bigbuf;
@@ -2631,12 +2637,13 @@  receive_encrypted_standard(struct TCP_Server_Info *server,
 
 	/* now read the rest */
 	length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
-				pdu_length - HEADER_SIZE(server) + 1 + 4);
+				pdu_length - HEADER_SIZE(server) + 1 +
+				server->vals->header_preamble_size);
 	if (length < 0)
 		return length;
 	server->total_read += length;
 
-	buf_size = pdu_length + 4 - sizeof(struct smb2_transform_hdr);
+	buf_size = pdu_length + server->vals->header_preamble_size - sizeof(struct smb2_transform_hdr);
 	length = decrypt_raw_data(server, buf, buf_size, NULL, 0, 0);
 	if (length)
 		return length;
@@ -2665,7 +2672,7 @@  smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
 	struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
 	unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
 
-	if (pdu_length + 4 < sizeof(struct smb2_transform_hdr) +
+	if (pdu_length + server->vals->header_preamble_size < sizeof(struct smb2_transform_hdr) +
 						sizeof(struct smb2_sync_hdr)) {
 		cifs_dbg(VFS, "Transform message is too small (%u)\n",
 			 pdu_length);
@@ -2674,14 +2681,14 @@  smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
 		return -ECONNABORTED;
 	}
 
-	if (pdu_length + 4 < orig_len + sizeof(struct smb2_transform_hdr)) {
+	if (pdu_length + server->vals->header_preamble_size < orig_len + sizeof(struct smb2_transform_hdr)) {
 		cifs_dbg(VFS, "Transform message is broken\n");
 		cifs_reconnect(server);
 		wake_up(&server->response_q);
 		return -ECONNABORTED;
 	}
 
-	if (pdu_length + 4 > CIFSMaxBufSize + MAX_HEADER_SIZE(server))
+	if (pdu_length + server->vals->header_preamble_size > CIFSMaxBufSize + MAX_HEADER_SIZE(server))
 		return receive_encrypted_read(server, mid);
 
 	return receive_encrypted_standard(server, mid);
@@ -2692,7 +2699,8 @@  smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 {
 	char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
 
-	return handle_read_data(server, mid, buf, get_rfc1002_length(buf) + 4,
+	return handle_read_data(server, mid, buf, get_rfc1002_length(buf) +
+				server->vals->header_preamble_size,
 				NULL, 0, 0);
 }
 
@@ -3097,6 +3105,7 @@  struct smb_version_values smb20_values = {
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
 	.header_size = sizeof(struct smb2_hdr),
+	.header_preamble_size = 4,
 	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 	.lock_cmd = SMB2_LOCK,
@@ -3117,6 +3126,7 @@  struct smb_version_values smb21_values = {
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
 	.header_size = sizeof(struct smb2_hdr),
+	.header_preamble_size = 4,
 	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 	.lock_cmd = SMB2_LOCK,
@@ -3137,6 +3147,7 @@  struct smb_version_values smb3any_values = {
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
 	.header_size = sizeof(struct smb2_hdr),
+	.header_preamble_size = 4,
 	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 	.lock_cmd = SMB2_LOCK,
@@ -3157,6 +3168,7 @@  struct smb_version_values smbdefault_values = {
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
 	.header_size = sizeof(struct smb2_hdr),
+	.header_preamble_size = 4,
 	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 	.lock_cmd = SMB2_LOCK,
@@ -3177,6 +3189,7 @@  struct smb_version_values smb30_values = {
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
 	.header_size = sizeof(struct smb2_hdr),
+	.header_preamble_size = 4,
 	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 	.lock_cmd = SMB2_LOCK,
@@ -3197,6 +3210,7 @@  struct smb_version_values smb302_values = {
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
 	.header_size = sizeof(struct smb2_hdr),
+	.header_preamble_size = 4,
 	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 	.lock_cmd = SMB2_LOCK,
@@ -3218,6 +3232,7 @@  struct smb_version_values smb311_values = {
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
 	.header_size = sizeof(struct smb2_hdr),
+	.header_preamble_size = 4,
 	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 	.lock_cmd = SMB2_LOCK,
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 4b6920de2541..1e765b31eb88 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1466,7 +1466,7 @@  parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp,
 	unsigned int remaining;
 	char *name;
 
-	data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset);
+	data_offset = (char *)rsp + server->vals->header_preamble_size + le32_to_cpu(rsp->CreateContextsOffset);
 	remaining = le32_to_cpu(rsp->CreateContextsLength);
 	cc = (struct create_context *)data_offset;
 	while (remaining >= sizeof(struct create_context)) {
@@ -3447,6 +3447,7 @@  static int
 build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
 		   int outbuf_len, u64 persistent_fid, u64 volatile_fid)
 {
+	struct TCP_Server_Info *server = tcon->ses->server;
 	int rc;
 	struct smb2_query_info_req *req;
 	unsigned int total_len;
@@ -3469,7 +3470,7 @@  build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
 	req->InputBufferOffset =
 			cpu_to_le16(sizeof(struct smb2_query_info_req) - 1);
 	req->OutputBufferLength = cpu_to_le32(
-		outbuf_len + sizeof(struct smb2_query_info_rsp) - 1 - 4);
+		outbuf_len + sizeof(struct smb2_query_info_rsp) - 1 - server->vals->header_preamble_size);
 
 	iov->iov_base = (char *)req;
 	iov->iov_len = total_len;
@@ -3486,6 +3487,7 @@  SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
 	int rc = 0;
 	int resp_buftype;
 	struct cifs_ses *ses = tcon->ses;
+	struct TCP_Server_Info *server = ses->server;
 	struct smb2_fs_full_size_info *info = NULL;
 	int flags = 0;
 
@@ -3506,7 +3508,7 @@  SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
 	}
 	rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
 
-	info = (struct smb2_fs_full_size_info *)(4 /* RFC1001 len */ +
+	info = (struct smb2_fs_full_size_info *)(server->vals->header_preamble_size +
 		le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr);
 	rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset),
 			  le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr,
@@ -3529,6 +3531,7 @@  SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
 	int rc = 0;
 	int resp_buftype, max_len, min_len;
 	struct cifs_ses *ses = tcon->ses;
+	struct TCP_Server_Info *server = ses->server;
 	unsigned int rsp_len, offset;
 	int flags = 0;
 
@@ -3569,15 +3572,15 @@  SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
 		goto qfsattr_exit;
 
 	if (level == FS_ATTRIBUTE_INFORMATION)
-		memcpy(&tcon->fsAttrInfo, 4 /* RFC1001 len */ + offset
+		memcpy(&tcon->fsAttrInfo, server->vals->header_preamble_size + offset
 			+ (char *)&rsp->hdr, min_t(unsigned int,
 			rsp_len, max_len));
 	else if (level == FS_DEVICE_INFORMATION)
-		memcpy(&tcon->fsDevInfo, 4 /* RFC1001 len */ + offset
+		memcpy(&tcon->fsDevInfo, server->vals->header_preamble_size + offset
 			+ (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO));
 	else if (level == FS_SECTOR_SIZE_INFORMATION) {
 		struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *)
-			(4 /* RFC1001 len */ + offset + (char *)&rsp->hdr);
+			(server->vals->header_preamble_size + offset + (char *)&rsp->hdr);
 		tcon->ss_flags = le32_to_cpu(ss_info->Flags);
 		tcon->perf_sector_size =
 			le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 665661464067..279718dcb2ed 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -790,7 +790,8 @@  cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
 
 	buf = (char *)midQ->resp_buf;
 	resp_iov->iov_base = buf;
-	resp_iov->iov_len = get_rfc1002_length(buf) + 4;
+	resp_iov->iov_len = get_rfc1002_length(buf) +
+		ses->server->vals->header_preamble_size;
 	if (midQ->large_buf)
 		*resp_buf_type = CIFS_LARGE_BUFFER;
 	else