diff mbox series

[02/16] cifs: remove rfc1002 header from all SMB2 response structures

Message ID 20180322042407.7599-3-lsahlber@redhat.com
State New
Headers show
Series smb2 compounding | expand

Commit Message

Ronnie Sahlberg March 22, 2018, 4:23 a.m. UTC
Separate out all the 4 byte rfc1002 headers so that they are no longer
part of the SMB2 header structures to prepare for future work to add
compounding support.

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
---
 fs/cifs/cifsglob.h      |   3 +
 fs/cifs/cifssmb.c       |   2 +-
 fs/cifs/connect.c       |  10 +++-
 fs/cifs/misc.c          |   2 +-
 fs/cifs/smb2glob.h      |   5 --
 fs/cifs/smb2maperror.c  |   2 +-
 fs/cifs/smb2misc.c      |  90 +++++++++++++----------------
 fs/cifs/smb2ops.c       | 146 +++++++++++++++++++++++++++---------------------
 fs/cifs/smb2pdu.c       | 103 ++++++++++++++++------------------
 fs/cifs/smb2pdu.h       |  65 +++++++--------------
 fs/cifs/smb2proto.h     |   5 +-
 fs/cifs/smb2transport.c |  12 ++--
 fs/cifs/transport.c     |   3 +-
 13 files changed, 213 insertions(+), 235 deletions(-)

Comments

Pavel Shilovsky March 26, 2018, 11:10 p.m. UTC | #1
--
Best regards,
Pavel Shilovsky


2018-03-21 21:23 GMT-07:00 Ronnie Sahlberg <lsahlber@redhat.com>:
> Separate out all the 4 byte rfc1002 headers so that they are no longer
> part of the SMB2 header structures to prepare for future work to add
> compounding support.
>
> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
> ---
>  fs/cifs/cifsglob.h      |   3 +
>  fs/cifs/cifssmb.c       |   2 +-
>  fs/cifs/connect.c       |  10 +++-
>  fs/cifs/misc.c          |   2 +-
>  fs/cifs/smb2glob.h      |   5 --
>  fs/cifs/smb2maperror.c  |   2 +-
>  fs/cifs/smb2misc.c      |  90 +++++++++++++----------------
>  fs/cifs/smb2ops.c       | 146 +++++++++++++++++++++++++++---------------------
>  fs/cifs/smb2pdu.c       | 103 ++++++++++++++++------------------
>  fs/cifs/smb2pdu.h       |  65 +++++++--------------
>  fs/cifs/smb2proto.h     |   5 +-
>  fs/cifs/smb2transport.c |  12 ++--
>  fs/cifs/transport.c     |   3 +-
>  13 files changed, 213 insertions(+), 235 deletions(-)
>
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 3e3f86841372..0045d85ec76d 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -665,6 +665,8 @@ struct TCP_Server_Info {
>         struct delayed_work     echo; /* echo ping workqueue job */
>         char    *smallbuf;      /* pointer to current "small" buffer */
>         char    *bigbuf;        /* pointer to current "big" buffer */
> +       /* Total size of this PDU. Only valid from cifs_demultiplex_thread */
> +       unsigned int pdu_size;
>         unsigned int total_read; /* total amount of data read in this pass */
>  #ifdef CONFIG_CIFS_FSCACHE
>         struct fscache_cookie   *fscache; /* client index cache cookie */
> @@ -1373,6 +1375,7 @@ struct mid_q_entry {
>         mid_handle_t *handle; /* call handle mid callback */
>         void *callback_data;      /* general purpose pointer for callback */
>         void *resp_buf;         /* pointer to received SMB header */
> +       unsigned int resp_buf_size;
>         int mid_state;  /* wish this were enum but can not pass to wait_event */
>         unsigned int mid_flags;
>         __le16 command;         /* smb command code */
> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> index 59c09a596c0a..991e9d9ef90a 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -1454,7 +1454,7 @@ 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) +
> +       unsigned int buflen = server->pdu_size +
>                 server->vals->header_preamble_size;
>         bool use_rdma_mr = false;
>
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index 1f2e3b15b2b1..0fad48d081d8 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -772,7 +772,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>  {
>         int length;
>         char *buf = server->smallbuf;
> -       unsigned int pdu_length = get_rfc1002_length(buf);
> +       unsigned int pdu_length = server->pdu_size;
>
>         /* make sure this will fit in a large buffer */
>         if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
> @@ -874,13 +874,18 @@ cifs_demultiplex_thread(void *p)
>                 length = cifs_read_from_socket(server, buf, pdu_length);
>                 if (length < 0)
>                         continue;
> -               server->total_read = length;
> +
> +               if (server->vals->header_preamble_size == 0)
> +                       server->total_read = 0;
> +               else
> +                       server->total_read = length;
>
>                 /*
>                  * The right amount was read from socket - 4 bytes,
>                  * so we can now interpret the length field.
>                  */
>                 pdu_length = get_rfc1002_length(buf);
> +               server->pdu_size = pdu_length;
>
>                 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
>                 if (!is_smb_response(server, buf[0]))
> @@ -927,6 +932,7 @@ cifs_demultiplex_thread(void *p)
>
>                 server->lstrp = jiffies;
>                 if (mid_entry != NULL) {
> +                       mid_entry->resp_buf_size = server->pdu_size;
>                         if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
>                              mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
>                                         server->ops->handle_cancelled_mid)
> diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
> index 460084a8eac5..d5d7eb2ae3c4 100644
> --- a/fs/cifs/misc.c
> +++ b/fs/cifs/misc.c
> @@ -145,7 +145,7 @@ cifs_buf_get(void)
>          * SMB2 header is bigger than CIFS one - no problems to clean some
>          * more bytes for CIFS.
>          */
> -       size_t buf_size = sizeof(struct smb2_hdr);
> +       size_t buf_size = sizeof(struct smb2_sync_hdr);
>
>         /*
>          * We could use negotiated size instead of max_msgsize -
> diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h
> index 401a5d856636..0ffa18094335 100644
> --- a/fs/cifs/smb2glob.h
> +++ b/fs/cifs/smb2glob.h
> @@ -61,9 +61,4 @@
>  /* Maximum buffer size value we can send with 1 credit */
>  #define SMB2_MAX_BUFFER_SIZE 65536
>
> -static inline struct smb2_sync_hdr *get_sync_hdr(void *buf)
> -{
> -       return &(((struct smb2_hdr *)buf)->sync_hdr);
> -}
> -
>  #endif /* _SMB2_GLOB_H */
> diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c
> index 62c88dfed57b..8fe30288805f 100644
> --- a/fs/cifs/smb2maperror.c
> +++ b/fs/cifs/smb2maperror.c
> @@ -2450,7 +2450,7 @@ smb2_print_status(__le32 status)
>  int
>  map_smb2_to_linux_error(char *buf, bool log_err)
>  {
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>         unsigned int i;
>         int rc = -EIO;
>         __le32 smb2err = shdr->Status;
> diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
> index 566871185b98..cb79c2433844 100644
> --- a/fs/cifs/smb2misc.c
> +++ b/fs/cifs/smb2misc.c
> @@ -94,25 +94,20 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
>  };
>
>  int
> -smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
> +smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
>  {
> -       struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
> -       struct smb2_hdr *hdr = &pdu->hdr;
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
> +       struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr;
>         __u64 mid;
> -       __u32 len = get_rfc1002_length(buf);
>         __u32 clc_len;  /* calculated length */
>         int command;
> -
> -       /* BB disable following printk later */
> -       cifs_dbg(FYI, "%s length: 0x%x, smb_buf_length: 0x%x\n",
> -                __func__, length, len);
> +       int pdu_size = sizeof(struct smb2_sync_pdu);
> +       int hdr_size = sizeof(struct smb2_sync_hdr);
>
>         /*
>          * Add function to do table lookup of StructureSize by command
>          * ie Validate the wct via smb2_struct_sizes table above
>          */
> -
>         if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
>                 struct smb2_transform_hdr *thdr =
>                         (struct smb2_transform_hdr *)buf;
> @@ -136,8 +131,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>         }
>
>         mid = le64_to_cpu(shdr->MessageId);
> -       if (length < sizeof(struct smb2_pdu)) {
> -               if ((length >= sizeof(struct smb2_hdr))
> +       if (len < pdu_size) {
> +               if ((len >= hdr_size)
>                     && (shdr->Status != 0)) {
>                         pdu->StructureSize2 = 0;
>                         /*
> @@ -190,13 +185,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>                 }
>         }
>
> -       if (srvr->vals->header_preamble_size + len != length) {
> -               cifs_dbg(VFS, "Total length %u RFC1002 length %u mismatch mid %llu\n",
> -                        length, srvr->vals->header_preamble_size + len, mid);
> -               return 1;
> -       }
> -
> -       clc_len = smb2_calc_size(hdr);
> +       clc_len = smb2_calc_size(buf);
>
>         if (srvr->vals->header_preamble_size + len != clc_len) {
>                 cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
> @@ -206,7 +195,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>                     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 == len && command == SMB2_OPLOCK_BREAK_HE)

We have a srvr pointer here, so, we can use header_preamble_size
instead and move this to patch #1.

>                         return 0;
>                 /* server can return one byte more due to implied bcc[0] */
>                 if (clc_len == srvr->vals->header_preamble_size + len + 1)
> @@ -263,15 +252,14 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
>   * area and the offset to it (from the beginning of the smb are also returned.
>   */
>  char *
> -smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
> +smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr)
>  {
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
>         *off = 0;
>         *len = 0;
>
>         /* error responses do not have data area */
>         if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
> -           (((struct smb2_err_rsp *)hdr)->StructureSize) ==
> +           (((struct smb2_err_rsp *)shdr)->StructureSize) ==
>                                                 SMB2_ERROR_STRUCTURE_SIZE2)
>                 return NULL;
>
> @@ -283,42 +271,44 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
>         switch (shdr->Command) {
>         case SMB2_NEGOTIATE:
>                 *off = le16_to_cpu(
> -                   ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset);
> +                 ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset);
>                 *len = le16_to_cpu(
> -                   ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferLength);
> +                 ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength);
>                 break;
>         case SMB2_SESSION_SETUP:
>                 *off = le16_to_cpu(
> -                   ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferOffset);
> +                 ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset);
>                 *len = le16_to_cpu(
> -                   ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferLength);
> +                 ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength);
>                 break;
>         case SMB2_CREATE:
>                 *off = le32_to_cpu(
> -                   ((struct smb2_create_rsp *)hdr)->CreateContextsOffset);
> +                   ((struct smb2_create_rsp *)shdr)->CreateContextsOffset);
>                 *len = le32_to_cpu(
> -                   ((struct smb2_create_rsp *)hdr)->CreateContextsLength);
> +                   ((struct smb2_create_rsp *)shdr)->CreateContextsLength);
>                 break;
>         case SMB2_QUERY_INFO:
>                 *off = le16_to_cpu(
> -                   ((struct smb2_query_info_rsp *)hdr)->OutputBufferOffset);
> +                   ((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset);
>                 *len = le32_to_cpu(
> -                   ((struct smb2_query_info_rsp *)hdr)->OutputBufferLength);
> +                   ((struct smb2_query_info_rsp *)shdr)->OutputBufferLength);
>                 break;
>         case SMB2_READ:
> -               *off = ((struct smb2_read_rsp *)hdr)->DataOffset;
> -               *len = le32_to_cpu(((struct smb2_read_rsp *)hdr)->DataLength);
> +               /* TODO: is this a bug ? */
> +               *off = ((struct smb2_read_rsp *)shdr)->DataOffset;
> +               *len = le32_to_cpu(((struct smb2_read_rsp *)shdr)->DataLength);
>                 break;
>         case SMB2_QUERY_DIRECTORY:
>                 *off = le16_to_cpu(
> -                 ((struct smb2_query_directory_rsp *)hdr)->OutputBufferOffset);
> +                 ((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset);
>                 *len = le32_to_cpu(
> -                 ((struct smb2_query_directory_rsp *)hdr)->OutputBufferLength);
> +                 ((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength);
>                 break;
>         case SMB2_IOCTL:
>                 *off = le32_to_cpu(
> -                 ((struct smb2_ioctl_rsp *)hdr)->OutputOffset);
> -               *len = le32_to_cpu(((struct smb2_ioctl_rsp *)hdr)->OutputCount);
> +                 ((struct smb2_ioctl_rsp *)shdr)->OutputOffset);
> +               *len = le32_to_cpu(
> +                 ((struct smb2_ioctl_rsp *)shdr)->OutputCount);
>                 break;
>         case SMB2_CHANGE_NOTIFY:
>         default:
> @@ -363,13 +353,12 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
>  unsigned int
>  smb2_calc_size(void *buf)
>  {
> -       struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
> -       struct smb2_hdr *hdr = &pdu->hdr;
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
> +       struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)buf;
> +       struct smb2_sync_hdr *shdr = &pdu->sync_hdr;
>         int offset; /* the offset from the beginning of SMB to data area */
>         int data_length; /* the length of the variable length data area */
>         /* Structure Size has already been checked to make sure it is 64 */
> -       int len = 4 + le16_to_cpu(shdr->StructureSize);
> +       int len = le16_to_cpu(shdr->StructureSize);
>
>         /*
>          * StructureSize2, ie length of fixed parameter area has already
> @@ -380,7 +369,7 @@ smb2_calc_size(void *buf)
>         if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false)
>                 goto calc_size_exit;
>
> -       smb2_get_data_area_len(&offset, &data_length, hdr);
> +       smb2_get_data_area_len(&offset, &data_length, shdr);
>         cifs_dbg(FYI, "SMB2 data length %d offset %d\n", data_length, offset);
>
>         if (data_length > 0) {
> @@ -388,15 +377,14 @@ smb2_calc_size(void *buf)
>                  * Check to make sure that data area begins after fixed area,
>                  * Note that last byte of the fixed area is part of data area
>                  * for some commands, typically those with odd StructureSize,
> -                * so we must add one to the calculation (and 4 to account for
> -                * the size of the RFC1001 hdr.
> +                * so we must add one to the calculation.
>                  */
> -               if (offset + 4 + 1 < len) {
> +               if (offset + 1 < len) {
>                         cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d\n",
> -                                offset + 4 + 1, len);
> +                                offset + 1, len);
>                         data_length = 0;
>                 } else {
> -                       len = 4 + offset + data_length;
> +                       len = offset + data_length;
>                 }
>         }
>  calc_size_exit:
> @@ -579,7 +567,7 @@ smb2_is_valid_lease_break(char *buffer)
>  bool
>  smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
>  {
> -       struct smb2_oplock_break_rsp *rsp = (struct smb2_oplock_break_rsp *)buffer;
> +       struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer;
>         struct list_head *tmp, *tmp1, *tmp2;
>         struct cifs_ses *ses;
>         struct cifs_tcon *tcon;
> @@ -588,7 +576,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
>
>         cifs_dbg(FYI, "Checking for oplock break\n");
>
> -       if (rsp->hdr.sync_hdr.Command != SMB2_OPLOCK_BREAK)
> +       if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK)
>                 return false;
>
>         if (rsp->StructureSize !=
> @@ -679,8 +667,8 @@ smb2_cancelled_close_fid(struct work_struct *work)
>  int
>  smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
>  {
> -       struct smb2_sync_hdr *sync_hdr = get_sync_hdr(buffer);
> -       struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer;
> +       struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer;
> +       struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)sync_hdr;
>         struct cifs_tcon *tcon;
>         struct close_cancelled_open *cancelled;
>
> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> index 09d3a2912869..48ee237c3fdf 100644
> --- a/fs/cifs/smb2ops.c
> +++ b/fs/cifs/smb2ops.c
> @@ -123,7 +123,8 @@ smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
>  static unsigned int
>  smb2_get_credits(struct mid_q_entry *mid)
>  {
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(mid->resp_buf);
> +       char *buf = mid->resp_buf;
> +       struct smb2_sync_hdr *shdr  = (struct smb2_sync_hdr *)buf;
>
>         return le16_to_cpu(shdr->CreditRequest);
>  }
> @@ -190,7 +191,7 @@ static struct mid_q_entry *
>  smb2_find_mid(struct TCP_Server_Info *server, char *buf)
>  {
>         struct mid_q_entry *mid;
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>         __u64 wire_mid = le64_to_cpu(shdr->MessageId);
>
>         if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
> @@ -215,7 +216,7 @@ static void
>  smb2_dump_detail(void *buf)
>  {
>  #ifdef CONFIG_CIFS_DEBUG2
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>
>         cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n",
>                  shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId,
> @@ -1241,7 +1242,7 @@ smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
>  static bool
>  smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
>  {
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>
>         if (shdr->Status != STATUS_PENDING)
>                 return false;
> @@ -1259,7 +1260,7 @@ smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
>  static bool
>  smb2_is_session_expired(char *buf)
>  {
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>
>         if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED)
>                 return false;
> @@ -1451,6 +1452,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
>         __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
>         struct cifs_open_parms oparms;
>         struct cifs_fid fid;
> +       struct kvec err_iov = {NULL, 0};
>         struct smb2_err_rsp *err_buf = NULL;
>         struct smb2_symlink_err_rsp *symlink;
>         unsigned int sub_len;
> @@ -1473,15 +1475,16 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
>         oparms.fid = &fid;
>         oparms.reconnect = false;
>
> -       rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_buf);
> +       rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov);
>
>         if (!rc || !err_buf) {
>                 kfree(utf16_path);
>                 return -ENOENT;
>         }
>
> +       err_buf = err_iov.iov_base;
>         if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
> -           get_rfc1002_length(err_buf) + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
> +           err_iov.iov_len + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
>                 kfree(utf16_path);
>                 return -ENOENT;
>         }
> @@ -1494,13 +1497,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) + server->vals->header_preamble_size <
> +       if (err_iov.iov_len + server->vals->header_preamble_size <
>                         SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
>                 kfree(utf16_path);
>                 return -ENOENT;
>         }
>
> -       if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size <
> +       if (err_iov.iov_len + server->vals->header_preamble_size <
>                         SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
>                 kfree(utf16_path);
>                 return -ENOENT;
> @@ -2052,12 +2055,11 @@ smb2_dir_needs_close(struct cifsFileInfo *cfile)
>  }
>
>  static void
> -fill_transform_hdr(struct TCP_Server_Info *server,
> -                  struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
> +fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
> +                  struct smb_rqst *old_rq)
>  {
>         struct smb2_sync_hdr *shdr =
>                         (struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base;
> -       unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base);
>
>         memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr));
>         tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
> @@ -2065,8 +2067,6 @@ fill_transform_hdr(struct TCP_Server_Info *server,
>         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) - server->vals->header_preamble_size);
> -       inc_rfc1001_len(tr_hdr, orig_len);
>  }
>
>  /* We can not use the normal sg_set_buf() as we will sometimes pass a
> @@ -2078,11 +2078,16 @@ static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
>         sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
>  }
>
> +/* Assumes:
> + * rqst->rq_iov[0]  is rfc1002 length
> + * rqst->rq_iov[1]  is tranform header
> + * rqst->rq_iov[2+] data to be encrypted/decrypted
> + */
>  static struct scatterlist *
>  init_sg(struct smb_rqst *rqst, u8 *sign)
>  {
> -       unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages + 1;
> -       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
> +       unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages;
> +       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
>         struct scatterlist *sg;
>         unsigned int i;
>         unsigned int j;
> @@ -2092,10 +2097,10 @@ init_sg(struct smb_rqst *rqst, u8 *sign)
>                 return NULL;
>
>         sg_init_table(sg, sg_len);
> -       smb2_sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 24, assoc_data_len);
> -       for (i = 1; i < rqst->rq_nvec; i++)
> -               smb2_sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base,
> -                                               rqst->rq_iov[i].iov_len);
> +       smb2_sg_set_buf(&sg[0], rqst->rq_iov[1].iov_base + 20, assoc_data_len);
> +       for (i = 1; i < rqst->rq_nvec - 1; i++)
> +               smb2_sg_set_buf(&sg[i], rqst->rq_iov[i+1].iov_base,
> +                                               rqst->rq_iov[i+1].iov_len);
>         for (j = 0; i < sg_len - 1; i++, j++) {
>                 unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz
>                                                         : rqst->rq_tailsz;
> @@ -2127,17 +2132,18 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
>  }
>  /*
>   * Encrypt or decrypt @rqst message. @rqst has the following format:
> - * iov[0] - transform header (associate data),
> - * iov[1-N] and pages - data to encrypt.
> - * On success return encrypted data in iov[1-N] and pages, leave iov[0]
> + * iov[0] - rfc1002 length
> + * iov[1] - transform header (associate data),
> + * iov[2-N] and pages - data to encrypt.
> + * On success return encrypted data in iov[2-N] and pages, leave iov[0-1]
>   * untouched.
>   */
>  static int
>  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;
> +                       (struct smb2_transform_hdr *)rqst->rq_iov[1].iov_base;
> +       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;

The same here: please use header_preamble_size.

>         int rc = 0;
>         struct scatterlist *sg;
>         u8 sign[SMB2_SIGNATURE_SIZE] = {};
> @@ -2224,6 +2230,9 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
>         return rc;
>  }
>
> +/* This is called from smb_send_rqst. At this point we have the rfc1002
> + * header as the first element in the vector.
> + */

The comment style should be:
/*
 * text
 */

>  static int
>  smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
>                        struct smb_rqst *old_rq)
> @@ -2232,6 +2241,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
>         struct page **pages;
>         struct smb2_transform_hdr *tr_hdr;
>         unsigned int npages = old_rq->rq_npages;
> +       unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base);
>         int i;
>         int rc = -ENOMEM;
>
> @@ -2250,24 +2260,34 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
>                         goto err_free_pages;
>         }
>
> -       iov = kmalloc_array(old_rq->rq_nvec, sizeof(struct kvec), GFP_KERNEL);
> +       /* Make space for one extra iov to hold the transform header */
> +       iov = kmalloc_array(old_rq->rq_nvec + 1, sizeof(struct kvec),
> +                           GFP_KERNEL);
>         if (!iov)
>                 goto err_free_pages;
>
>         /* copy all iovs from the old except the 1st one (rfc1002 length) */
> -       memcpy(&iov[1], &old_rq->rq_iov[1],
> +       memcpy(&iov[2], &old_rq->rq_iov[1],
>                                 sizeof(struct kvec) * (old_rq->rq_nvec - 1));
> +       /* copy the rfc1002 iov */
> +       iov[0].iov_base = old_rq->rq_iov[0].iov_base;
> +       iov[0].iov_len  = old_rq->rq_iov[0].iov_len;
> +
>         new_rq->rq_iov = iov;
> -       new_rq->rq_nvec = old_rq->rq_nvec;
> +       new_rq->rq_nvec = old_rq->rq_nvec + 1;
>
>         tr_hdr = kmalloc(sizeof(struct smb2_transform_hdr), GFP_KERNEL);
>         if (!tr_hdr)
>                 goto err_free_iov;
>
> -       /* fill the 1st iov with a transform header */
> -       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);
> +       /* fill the 2nd iov with a transform header */
> +       fill_transform_hdr(tr_hdr, orig_len, old_rq);
> +       new_rq->rq_iov[1].iov_base = tr_hdr;
> +       new_rq->rq_iov[1].iov_len = sizeof(struct smb2_transform_hdr);
> +
> +       /* Update rfc1002 header */
> +       inc_rfc1001_len(new_rq->rq_iov[0].iov_base,
> +                       sizeof(struct smb2_transform_hdr));
>
>         /* copy pages form the old */
>         for (i = 0; i < npages; i++) {
> @@ -2307,7 +2327,7 @@ smb3_free_transform_rq(struct smb_rqst *rqst)
>                 put_page(rqst->rq_pages[i]);
>         kfree(rqst->rq_pages);
>         /* free transform header */
> -       kfree(rqst->rq_iov[0].iov_base);
> +       kfree(rqst->rq_iov[1].iov_base);
>         kfree(rqst->rq_iov);
>  }
>
> @@ -2324,18 +2344,19 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
>                  unsigned int buf_data_size, struct page **pages,
>                  unsigned int npages, unsigned int page_data_size)
>  {
> -       struct kvec iov[2];
> +       struct kvec iov[3];
>         struct smb_rqst rqst = {NULL};
> -       struct smb2_hdr *hdr;
>         int rc;
>
> -       iov[0].iov_base = buf;
> -       iov[0].iov_len = sizeof(struct smb2_transform_hdr);
> -       iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr);
> -       iov[1].iov_len = buf_data_size;
> +       iov[0].iov_base = NULL;
> +       iov[0].iov_len = 0;
> +       iov[1].iov_base = buf;
> +       iov[1].iov_len = sizeof(struct smb2_transform_hdr);
> +       iov[2].iov_base = buf + sizeof(struct smb2_transform_hdr);
> +       iov[2].iov_len = buf_data_size;
>
>         rqst.rq_iov = iov;
> -       rqst.rq_nvec = 2;
> +       rqst.rq_nvec = 3;
>         rqst.rq_pages = pages;
>         rqst.rq_npages = npages;
>         rqst.rq_pagesz = PAGE_SIZE;
> @@ -2347,10 +2368,9 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
>         if (rc)
>                 return rc;
>
> -       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 + server->vals->header_preamble_size;
> +       memmove(buf + server->vals->header_preamble_size, iov[2].iov_base, buf_data_size);
> +
> +       server->total_read = buf_data_size + page_data_size;
>
>         return rc;
>  }
> @@ -2423,7 +2443,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
>         unsigned int cur_page_idx;
>         unsigned int pad_len;
>         struct cifs_readdata *rdata = mid->callback_data;
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>         struct bio_vec *bvec = NULL;
>         struct iov_iter iter;
>         struct kvec iov;
> @@ -2550,7 +2570,7 @@ 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) + server->vals->header_preamble_size;
> +       unsigned int buflen = server->pdu_size + server->vals->header_preamble_size;
>         int rc;
>         int i = 0;
>
> @@ -2624,7 +2644,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
>  {
>         int length;
>         char *buf = server->smallbuf;
> -       unsigned int pdu_length = get_rfc1002_length(buf);
> +       unsigned int pdu_length = server->pdu_size;
>         unsigned int buf_size;
>         struct mid_q_entry *mid_entry;
>
> @@ -2668,7 +2688,7 @@ static int
>  smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
>  {
>         char *buf = server->smallbuf;
> -       unsigned int pdu_length = get_rfc1002_length(buf);
> +       unsigned int pdu_length = server->pdu_size;
>         struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
>         unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
>
> @@ -2699,7 +2719,7 @@ 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) +
> +       return handle_read_data(server, mid, buf, server->total_read +

Should we use server->pdu_size here instead?

>                                 server->vals->header_preamble_size,
>                                 NULL, 0, 0);
>  }
> @@ -3104,8 +3124,8 @@ struct smb_version_values smb20_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3125,8 +3145,8 @@ struct smb_version_values smb21_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3146,8 +3166,8 @@ struct smb_version_values smb3any_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3167,8 +3187,8 @@ struct smb_version_values smbdefault_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3188,8 +3208,8 @@ struct smb_version_values smb30_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3209,8 +3229,8 @@ struct smb_version_values smb302_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3231,8 +3251,8 @@ struct smb_version_values smb311_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .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..b20348f72a6f 100644
> --- a/fs/cifs/smb2pdu.c
> +++ b/fs/cifs/smb2pdu.c
> @@ -591,7 +591,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
>         server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
>
>         security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
> -                                              &rsp->hdr);
> +                                              (struct smb2_sync_hdr *)rsp);
>         /*
>          * See MS-SMB2 section 2.2.4: if no blob, client picks default which
>          * for us will be
> @@ -942,7 +942,7 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
>                 goto out_put_spnego_key;
>
>         rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
> -       ses->Suid = rsp->hdr.sync_hdr.SessionId;
> +       ses->Suid = rsp->sync_hdr.SessionId;
>
>         ses->session_flags = le16_to_cpu(rsp->SessionFlags);
>
> @@ -1018,13 +1018,13 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
>
>         /* If true, rc here is expected and not an error */
>         if (sess_data->buf0_type != CIFS_NO_BUFFER &&
> -               rsp->hdr.sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
> +               rsp->sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
>                 rc = 0;
>
>         if (rc)
>                 goto out;
>
> -       if (offsetof(struct smb2_sess_setup_rsp, Buffer) - 4 !=
> +       if (offsetof(struct smb2_sess_setup_rsp, Buffer) !=
>                         le16_to_cpu(rsp->SecurityBufferOffset)) {
>                 cifs_dbg(VFS, "Invalid security buffer offset %d\n",
>                         le16_to_cpu(rsp->SecurityBufferOffset));
> @@ -1039,7 +1039,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
>         cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
>
>
> -       ses->Suid = rsp->hdr.sync_hdr.SessionId;
> +       ses->Suid = rsp->sync_hdr.SessionId;
>         ses->session_flags = le16_to_cpu(rsp->SessionFlags);
>
>  out:
> @@ -1097,7 +1097,7 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
>
>         rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
>
> -       ses->Suid = rsp->hdr.sync_hdr.SessionId;
> +       ses->Suid = rsp->sync_hdr.SessionId;
>         ses->session_flags = le16_to_cpu(rsp->SessionFlags);
>
>         rc = SMB2_sess_establish_session(sess_data);
> @@ -1340,7 +1340,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
>         tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess);
>         tcon->tidStatus = CifsGood;
>         tcon->need_reconnect = false;
> -       tcon->tid = rsp->hdr.sync_hdr.TreeId;
> +       tcon->tid = rsp->sync_hdr.TreeId;
>         strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
>
>         if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
> @@ -1360,7 +1360,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
>         return rc;
>
>  tcon_error_exit:
> -       if (rsp && rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
> +       if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
>                 cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
>         }
>         goto tcon_exit;
> @@ -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 + le32_to_cpu(rsp->CreateContextsOffset);

the same as above.

>         remaining = le32_to_cpu(rsp->CreateContextsLength);
>         cc = (struct create_context *)data_offset;
>         while (remaining >= sizeof(struct create_context)) {
> @@ -1694,7 +1694,7 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
>  int
>  SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
>           __u8 *oplock, struct smb2_file_all_info *buf,
> -         struct smb2_err_rsp **err_buf)
> +         struct kvec *err_iov)
>  {
>         struct smb2_create_req *req;
>         struct smb2_create_rsp *rsp;
> @@ -1834,9 +1834,10 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
>
>         if (rc != 0) {
>                 cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
> -               if (err_buf && rsp)
> -                       *err_buf = kmemdup(rsp, get_rfc1002_length(rsp) + 4,
> -                                          GFP_KERNEL);
> +               if (err_iov && rsp) {
> +                       *err_iov = rsp_iov;
> +                       rsp = NULL;
> +               }
>                 goto creat_exit;
>         }
>
> @@ -1875,7 +1876,6 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
>  {
>         struct smb2_ioctl_req *req;
>         struct smb2_ioctl_rsp *rsp;
> -       struct smb2_sync_hdr *shdr;
>         struct cifs_ses *ses;
>         struct kvec iov[2];
>         struct kvec rsp_iov;
> @@ -1996,7 +1996,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
>                 goto ioctl_exit;
>         }
>
> -       if (get_rfc1002_length(rsp) < le32_to_cpu(rsp->OutputOffset) + *plen) {
> +       if (rsp_iov.iov_len < le32_to_cpu(rsp->OutputOffset) + *plen) {
>                 cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen,
>                         le32_to_cpu(rsp->OutputOffset));
>                 *plen = 0;
> @@ -2010,8 +2010,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
>                 goto ioctl_exit;
>         }
>
> -       shdr = get_sync_hdr(rsp);
> -       memcpy(*out_data, (char *)shdr + le32_to_cpu(rsp->OutputOffset), *plen);
> +       memcpy(*out_data, (char *)rsp + le32_to_cpu(rsp->OutputOffset), *plen);
>  ioctl_exit:
>         free_rsp_buf(resp_buftype, rsp);
>         return rc;
> @@ -2091,13 +2090,12 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
>  }
>
>  static int
> -validate_buf(unsigned int offset, unsigned int buffer_length,
> -            struct smb2_hdr *hdr, unsigned int min_buf_size)
> -
> +validate_iov(unsigned int offset, unsigned int buffer_length,
> +            struct kvec *iov, unsigned int min_buf_size)
>  {
> -       unsigned int smb_len = be32_to_cpu(hdr->smb2_buf_length);
> -       char *end_of_smb = smb_len + 4 /* RFC1001 length field */ + (char *)hdr;
> -       char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr;
> +       unsigned int smb_len = iov->iov_len;
> +       char *end_of_smb = smb_len + (char *)iov->iov_base;
> +       char *begin_of_buf = offset + (char *)iov->iov_base;
>         char *end_of_buf = begin_of_buf + buffer_length;
>
>
> @@ -2127,18 +2125,17 @@ validate_buf(unsigned int offset, unsigned int buffer_length,
>   * Caller must free buffer.
>   */
>  static int
> -validate_and_copy_buf(unsigned int offset, unsigned int buffer_length,
> -                     struct smb2_hdr *hdr, unsigned int minbufsize,
> +validate_and_copy_iov(unsigned int offset, unsigned int buffer_length,
> +                     struct kvec *iov, unsigned int minbufsize,
>                       char *data)
> -
>  {
> -       char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr;
> +       char *begin_of_buf = offset + (char *)iov->iov_base;
>         int rc;
>
>         if (!data)
>                 return -EINVAL;
>
> -       rc = validate_buf(offset, buffer_length, hdr, minbufsize);
> +       rc = validate_iov(offset, buffer_length, iov, minbufsize);
>         if (rc)
>                 return rc;
>
> @@ -2216,9 +2213,9 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
>                 }
>         }
>
> -       rc = validate_and_copy_buf(le16_to_cpu(rsp->OutputBufferOffset),
> +       rc = validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset),
>                                    le32_to_cpu(rsp->OutputBufferLength),
> -                                  &rsp->hdr, min_len, *data);
> +                                  &rsp_iov, min_len, *data);
>
>  qinf_exit:
>         free_rsp_buf(resp_buftype, rsp);
> @@ -2287,7 +2284,7 @@ smb2_echo_callback(struct mid_q_entry *mid)
>         unsigned int credits_received = 1;
>
>         if (mid->mid_state == MID_RESPONSE_RECEIVED)
> -               credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest);
> +               credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
>
>         DeleteMidQEntry(mid);
>         add_credits(server, credits_received, CIFS_ECHO_OP);
> @@ -2684,7 +2681,6 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
>         int resp_buftype, rc = -EACCES;
>         struct smb2_read_plain_req *req = NULL;
>         struct smb2_read_rsp *rsp = NULL;
> -       struct smb2_sync_hdr *shdr;
>         struct kvec iov[1];
>         struct kvec rsp_iov;
>         unsigned int total_len;
> @@ -2725,10 +2721,8 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
>                 *nbytes = 0;
>         }
>
> -       shdr = get_sync_hdr(rsp);
> -
>         if (*buf) {
> -               memcpy(*buf, (char *)shdr + rsp->DataOffset, *nbytes);
> +               memcpy(*buf, (char *)rsp + rsp->DataOffset, *nbytes);
>                 free_rsp_buf(resp_buftype, rsp_iov.iov_base);
>         } else if (resp_buftype != CIFS_NO_BUFFER) {
>                 *buf = rsp_iov.iov_base;
> @@ -2755,7 +2749,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
>
>         switch (mid->mid_state) {
>         case MID_RESPONSE_RECEIVED:
> -               credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest);
> +               credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
>                 wdata->result = smb2_check_receive(mid, tcon->ses->server, 0);
>                 if (wdata->result != 0)
>                         break;
> @@ -3131,7 +3125,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
>
>         if (rc) {
>                 if (rc == -ENODATA &&
> -                   rsp->hdr.sync_hdr.Status == STATUS_NO_MORE_FILES) {
> +                   rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) {
>                         srch_inf->endOfSearch = true;
>                         rc = 0;
>                 }
> @@ -3139,8 +3133,8 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
>                 goto qdir_exit;
>         }
>
> -       rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset),
> -                         le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr,
> +       rc = validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
> +                         le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
>                           info_buf_size);
>         if (rc)
>                 goto qdir_exit;
> @@ -3154,10 +3148,9 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
>                         cifs_buf_release(srch_inf->ntwrk_buf_start);
>         }
>         srch_inf->ntwrk_buf_start = (char *)rsp;
> -       srch_inf->srch_entries_start = srch_inf->last_entry = 4 /* rfclen */ +
> -               (char *)&rsp->hdr + le16_to_cpu(rsp->OutputBufferOffset);
> -       /* 4 for rfc1002 length field */
> -       end_of_smb = get_rfc1002_length(rsp) + 4 + (char *)&rsp->hdr;
> +       srch_inf->srch_entries_start = srch_inf->last_entry =
> +               (char *)rsp + le16_to_cpu(rsp->OutputBufferOffset);
> +       end_of_smb = rsp_iov.iov_len + (char *)rsp;
>         srch_inf->entries_in_buffer =
>                         num_entries(srch_inf->srch_entries_start, end_of_smb,
>                                     &srch_inf->last_entry, info_buf_size);
> @@ -3393,7 +3386,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
>                   __u8 oplock_level)
>  {
>         int rc;
> -       struct smb2_oplock_break_req *req = NULL;
> +       struct smb2_oplock_break *req = NULL;
>         struct cifs_ses *ses = tcon->ses;
>         int flags = CIFS_OBREAK_OP;
>         unsigned int total_len;
> @@ -3469,7 +3462,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);

the same.

>
>         iov->iov_base = (char *)req;
>         iov->iov_len = total_len;
> @@ -3506,10 +3499,10 @@ 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 */ +

here as well.

> -               le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr);
> -       rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset),
> -                         le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr,
> +       info = (struct smb2_fs_full_size_info *)(
> +               le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
> +       rc = validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
> +                         le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
>                           sizeof(struct smb2_fs_full_size_info));
>         if (!rc)
>                 copy_fs_info_to_kstatfs(info, fsdata);
> @@ -3564,20 +3557,20 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
>
>         rsp_len = le32_to_cpu(rsp->OutputBufferLength);
>         offset = le16_to_cpu(rsp->OutputBufferOffset);
> -       rc = validate_buf(offset, rsp_len, &rsp->hdr, min_len);
> +       rc = validate_iov(offset, rsp_len, &rsp_iov, min_len);
>         if (rc)
>                 goto qfsattr_exit;
>
>         if (level == FS_ATTRIBUTE_INFORMATION)
> -               memcpy(&tcon->fsAttrInfo, 4 /* RFC1001 len */ + offset
> -                       + (char *)&rsp->hdr, min_t(unsigned int,
> +               memcpy(&tcon->fsAttrInfo, offset
> +                       + (char *)rsp, min_t(unsigned int,
>                         rsp_len, max_len));
>         else if (level == FS_DEVICE_INFORMATION)
> -               memcpy(&tcon->fsDevInfo, 4 /* RFC1001 len */ + offset

the same as above.

> -                       + (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO));
> +               memcpy(&tcon->fsDevInfo, offset
> +                       + (char *)rsp, 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);
> +                       (offset + (char *)rsp);
>                 tcon->ss_flags = le32_to_cpu(ss_info->Flags);
>                 tcon->perf_sector_size =
>                         le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
> diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
> index 8b901c69a65a..6bf243a45d64 100644
> --- a/fs/cifs/smb2pdu.h
> +++ b/fs/cifs/smb2pdu.h
> @@ -122,25 +122,10 @@ struct smb2_sync_pdu {
>         __le16 StructureSize2; /* size of wct area (varies, request specific) */
>  } __packed;
>
> -struct smb2_hdr {
> -       __be32 smb2_buf_length; /* big endian on wire */
> -                               /* length is only two or three bytes - with */
> -                               /* one or two byte type preceding it that MBZ */
> -       struct smb2_sync_hdr sync_hdr;
> -} __packed;
> -
> -struct smb2_pdu {
> -       struct smb2_hdr hdr;
> -       __le16 StructureSize2; /* size of wct area (varies, request specific) */
> -} __packed;
> -
>  #define SMB3_AES128CMM_NONCE 11
>  #define SMB3_AES128GCM_NONCE 12
>
>  struct smb2_transform_hdr {
> -       __be32 smb2_buf_length; /* big endian on wire */
> -                               /* length is only two or three bytes - with
> -                                one or two byte type preceding it that MBZ */
>         __le32 ProtocolId;      /* 0xFD 'S' 'M' 'B' */
>         __u8   Signature[16];
>         __u8   Nonce[16];
> @@ -171,7 +156,7 @@ struct smb2_transform_hdr {
>  #define SMB2_ERROR_STRUCTURE_SIZE2 cpu_to_le16(9)
>
>  struct smb2_err_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;
>         __le16 Reserved; /* MBZ */
>         __le32 ByteCount;  /* even if zero, at least one byte follows */
> @@ -289,7 +274,7 @@ struct smb2_encryption_neg_context {
>  } __packed;
>
>  struct smb2_negotiate_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 65 */
>         __le16 SecurityMode;
>         __le16 DialectRevision;
> @@ -329,7 +314,7 @@ struct smb2_sess_setup_req {
>  #define SMB2_SESSION_FLAG_IS_NULL      0x0002
>  #define SMB2_SESSION_FLAG_ENCRYPT_DATA 0x0004
>  struct smb2_sess_setup_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 9 */
>         __le16 SessionFlags;
>         __le16 SecurityBufferOffset;
> @@ -344,7 +329,7 @@ struct smb2_logoff_req {
>  } __packed;
>
>  struct smb2_logoff_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 4 */
>         __le16 Reserved;
>  } __packed;
> @@ -440,7 +425,7 @@ struct smb2_tree_connect_req_extension {
>  } __packed;
>
>  struct smb2_tree_connect_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 16 */
>         __u8   ShareType;  /* see below */
>         __u8   Reserved;
> @@ -491,7 +476,7 @@ struct smb2_tree_disconnect_req {
>  } __packed;
>
>  struct smb2_tree_disconnect_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 4 */
>         __le16 Reserved;
>  } __packed;
> @@ -626,7 +611,7 @@ struct smb2_create_req {
>  } __packed;
>
>  struct smb2_create_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 89 */
>         __u8   OplockLevel;
>         __u8   Reserved;
> @@ -882,7 +867,7 @@ struct smb2_ioctl_req {
>  } __packed;
>
>  struct smb2_ioctl_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 57 */
>         __u16 Reserved;
>         __le32 CtlCode;
> @@ -909,7 +894,7 @@ struct smb2_close_req {
>  } __packed;
>
>  struct smb2_close_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* 60 */
>         __le16 Flags;
>         __le32 Reserved;
> @@ -932,7 +917,7 @@ struct smb2_flush_req {
>  } __packed;
>
>  struct smb2_flush_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;
>         __le16 Reserved;
>  } __packed;
> @@ -964,7 +949,7 @@ struct smb2_read_plain_req {
>  } __packed;
>
>  struct smb2_read_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 17 */
>         __u8   DataOffset;
>         __u8   Reserved;
> @@ -995,7 +980,7 @@ struct smb2_write_req {
>  } __packed;
>
>  struct smb2_write_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 17 */
>         __u8   DataOffset;
>         __u8   Reserved;
> @@ -1029,7 +1014,7 @@ struct smb2_lock_req {
>  } __packed;
>
>  struct smb2_lock_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 4 */
>         __le16 Reserved;
>  } __packed;
> @@ -1041,7 +1026,7 @@ struct smb2_echo_req {
>  } __packed;
>
>  struct smb2_echo_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 4 */
>         __u16  Reserved;
>  } __packed;
> @@ -1067,7 +1052,7 @@ struct smb2_query_directory_req {
>  } __packed;
>
>  struct smb2_query_directory_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 9 */
>         __le16 OutputBufferOffset;
>         __le32 OutputBufferLength;
> @@ -1116,7 +1101,7 @@ struct smb2_query_info_req {
>  } __packed;
>
>  struct smb2_query_info_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 9 */
>         __le16 OutputBufferOffset;
>         __le32 OutputBufferLength;
> @@ -1138,12 +1123,11 @@ struct smb2_set_info_req {
>  } __packed;
>
>  struct smb2_set_info_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 2 */
>  } __packed;
>
> -/* oplock break without an rfc1002 header */
> -struct smb2_oplock_break_req {
> +struct smb2_oplock_break {
>         struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 24 */
>         __u8   OplockLevel;
> @@ -1153,21 +1137,10 @@ struct smb2_oplock_break_req {
>         __u64  VolatileFid;
>  } __packed;
>
> -/* oplock break with an rfc1002 header */
> -struct smb2_oplock_break_rsp {
> -       struct smb2_hdr hdr;
> -       __le16 StructureSize; /* Must be 24 */
> -       __u8   OplockLevel;
> -       __u8   Reserved;
> -       __le32 Reserved2;
> -       __u64  PersistentFid;
> -       __u64  VolatileFid;
> -} __packed;
> -
>  #define SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED cpu_to_le32(0x01)
>
>  struct smb2_lease_break {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 44 */
>         __le16 Reserved;
>         __le32 Flags;
> diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
> index cbcce3f7e86f..30cdc0aa4e8e 100644
> --- a/fs/cifs/smb2proto.h
> +++ b/fs/cifs/smb2proto.h
> @@ -37,7 +37,8 @@ extern int map_smb2_to_linux_error(char *buf, bool log_err);
>  extern int smb2_check_message(char *buf, unsigned int length,
>                               struct TCP_Server_Info *server);
>  extern unsigned int smb2_calc_size(void *buf);
> -extern char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr);
> +extern char *smb2_get_data_area_len(int *off, int *len,
> +                                   struct smb2_sync_hdr *shdr);
>  extern __le16 *cifs_convert_path_to_utf16(const char *from,
>                                           struct cifs_sb_info *cifs_sb);
>
> @@ -122,7 +123,7 @@ extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
>  extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
>                      __le16 *path, __u8 *oplock,
>                      struct smb2_file_all_info *buf,
> -                    struct smb2_err_rsp **err_buf);
> +                    struct kvec *err_iov);
>  extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
>                      u64 persistent_fid, u64 volatile_fid, u32 opcode,
>                      bool is_fsctl, char *in_data, u32 indatalen,
> diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
> index bf49cb73b9e6..8372a0cecdb0 100644
> --- a/fs/cifs/smb2transport.c
> +++ b/fs/cifs/smb2transport.c
> @@ -480,7 +480,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
>         unsigned int rc;
>         char server_response_sig[16];
>         struct smb2_sync_hdr *shdr =
> -                       (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
> +                       (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
>
>         if ((shdr->Command == SMB2_NEGOTIATE) ||
>             (shdr->Command == SMB2_SESSION_SETUP) ||
> @@ -604,15 +604,13 @@ int
>  smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
>                    bool log_error)
>  {
> -       unsigned int len = get_rfc1002_length(mid->resp_buf);
> -       struct kvec iov[2];
> +       unsigned int len = server->total_read;
> +       struct kvec iov[1];
>         struct smb_rqst rqst = { .rq_iov = iov,
> -                                .rq_nvec = 2 };
> +                                .rq_nvec = 1 };
>
>         iov[0].iov_base = (char *)mid->resp_buf;
> -       iov[0].iov_len = 4;
> -       iov[1].iov_base = (char *)mid->resp_buf + 4;
> -       iov[1].iov_len = len;
> +       iov[0].iov_len = mid->resp_buf_size;
>
>         dump_smb(mid->resp_buf, min_t(u32, 80, len));
>         /* convert the length into a more usable form */
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index 279718dcb2ed..3abce580b056 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -790,8 +790,9 @@ 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) +
> +       resp_iov->iov_len = midQ->resp_buf_size +
>                 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
--
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
ronnie sahlberg March 27, 2018, 3:22 a.m. UTC | #2
On Tue, Mar 27, 2018 at 9:10 AM, Pavel Shilovsky <piastryyy@gmail.com> wrote:
> --
> Best regards,
> Pavel Shilovsky
>
>
> 2018-03-21 21:23 GMT-07:00 Ronnie Sahlberg <lsahlber@redhat.com>:
>> Separate out all the 4 byte rfc1002 headers so that they are no longer
>> part of the SMB2 header structures to prepare for future work to add
>> compounding support.
>>
>> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
>> ---
>>  fs/cifs/cifsglob.h      |   3 +
>>  fs/cifs/cifssmb.c       |   2 +-
>>  fs/cifs/connect.c       |  10 +++-
>>  fs/cifs/misc.c          |   2 +-
>>  fs/cifs/smb2glob.h      |   5 --
>>  fs/cifs/smb2maperror.c  |   2 +-
>>  fs/cifs/smb2misc.c      |  90 +++++++++++++----------------
>>  fs/cifs/smb2ops.c       | 146 +++++++++++++++++++++++++++---------------------
>>  fs/cifs/smb2pdu.c       | 103 ++++++++++++++++------------------
>>  fs/cifs/smb2pdu.h       |  65 +++++++--------------
>>  fs/cifs/smb2proto.h     |   5 +-
>>  fs/cifs/smb2transport.c |  12 ++--
>>  fs/cifs/transport.c     |   3 +-
>>  13 files changed, 213 insertions(+), 235 deletions(-)
>>
>> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
>> index 3e3f86841372..0045d85ec76d 100644
>> --- a/fs/cifs/cifsglob.h
>> +++ b/fs/cifs/cifsglob.h
>> @@ -665,6 +665,8 @@ struct TCP_Server_Info {
>>         struct delayed_work     echo; /* echo ping workqueue job */
>>         char    *smallbuf;      /* pointer to current "small" buffer */
>>         char    *bigbuf;        /* pointer to current "big" buffer */
>> +       /* Total size of this PDU. Only valid from cifs_demultiplex_thread */
>> +       unsigned int pdu_size;
>>         unsigned int total_read; /* total amount of data read in this pass */
>>  #ifdef CONFIG_CIFS_FSCACHE
>>         struct fscache_cookie   *fscache; /* client index cache cookie */
>> @@ -1373,6 +1375,7 @@ struct mid_q_entry {
>>         mid_handle_t *handle; /* call handle mid callback */
>>         void *callback_data;      /* general purpose pointer for callback */
>>         void *resp_buf;         /* pointer to received SMB header */
>> +       unsigned int resp_buf_size;
>>         int mid_state;  /* wish this were enum but can not pass to wait_event */
>>         unsigned int mid_flags;
>>         __le16 command;         /* smb command code */
>> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
>> index 59c09a596c0a..991e9d9ef90a 100644
>> --- a/fs/cifs/cifssmb.c
>> +++ b/fs/cifs/cifssmb.c
>> @@ -1454,7 +1454,7 @@ 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) +
>> +       unsigned int buflen = server->pdu_size +
>>                 server->vals->header_preamble_size;
>>         bool use_rdma_mr = false;
>>
>> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
>> index 1f2e3b15b2b1..0fad48d081d8 100644
>> --- a/fs/cifs/connect.c
>> +++ b/fs/cifs/connect.c
>> @@ -772,7 +772,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>>  {
>>         int length;
>>         char *buf = server->smallbuf;
>> -       unsigned int pdu_length = get_rfc1002_length(buf);
>> +       unsigned int pdu_length = server->pdu_size;
>>
>>         /* make sure this will fit in a large buffer */
>>         if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
>> @@ -874,13 +874,18 @@ cifs_demultiplex_thread(void *p)
>>                 length = cifs_read_from_socket(server, buf, pdu_length);
>>                 if (length < 0)
>>                         continue;
>> -               server->total_read = length;
>> +
>> +               if (server->vals->header_preamble_size == 0)
>> +                       server->total_read = 0;
>> +               else
>> +                       server->total_read = length;
>>
>>                 /*
>>                  * The right amount was read from socket - 4 bytes,
>>                  * so we can now interpret the length field.
>>                  */
>>                 pdu_length = get_rfc1002_length(buf);
>> +               server->pdu_size = pdu_length;
>>
>>                 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
>>                 if (!is_smb_response(server, buf[0]))
>> @@ -927,6 +932,7 @@ cifs_demultiplex_thread(void *p)
>>
>>                 server->lstrp = jiffies;
>>                 if (mid_entry != NULL) {
>> +                       mid_entry->resp_buf_size = server->pdu_size;
>>                         if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
>>                              mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
>>                                         server->ops->handle_cancelled_mid)
>> diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
>> index 460084a8eac5..d5d7eb2ae3c4 100644
>> --- a/fs/cifs/misc.c
>> +++ b/fs/cifs/misc.c
>> @@ -145,7 +145,7 @@ cifs_buf_get(void)
>>          * SMB2 header is bigger than CIFS one - no problems to clean some
>>          * more bytes for CIFS.
>>          */
>> -       size_t buf_size = sizeof(struct smb2_hdr);
>> +       size_t buf_size = sizeof(struct smb2_sync_hdr);
>>
>>         /*
>>          * We could use negotiated size instead of max_msgsize -
>> diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h
>> index 401a5d856636..0ffa18094335 100644
>> --- a/fs/cifs/smb2glob.h
>> +++ b/fs/cifs/smb2glob.h
>> @@ -61,9 +61,4 @@
>>  /* Maximum buffer size value we can send with 1 credit */
>>  #define SMB2_MAX_BUFFER_SIZE 65536
>>
>> -static inline struct smb2_sync_hdr *get_sync_hdr(void *buf)
>> -{
>> -       return &(((struct smb2_hdr *)buf)->sync_hdr);
>> -}
>> -
>>  #endif /* _SMB2_GLOB_H */
>> diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c
>> index 62c88dfed57b..8fe30288805f 100644
>> --- a/fs/cifs/smb2maperror.c
>> +++ b/fs/cifs/smb2maperror.c
>> @@ -2450,7 +2450,7 @@ smb2_print_status(__le32 status)
>>  int
>>  map_smb2_to_linux_error(char *buf, bool log_err)
>>  {
>> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
>> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>>         unsigned int i;
>>         int rc = -EIO;
>>         __le32 smb2err = shdr->Status;
>> diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
>> index 566871185b98..cb79c2433844 100644
>> --- a/fs/cifs/smb2misc.c
>> +++ b/fs/cifs/smb2misc.c
>> @@ -94,25 +94,20 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
>>  };
>>
>>  int
>> -smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>> +smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
>>  {
>> -       struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
>> -       struct smb2_hdr *hdr = &pdu->hdr;
>> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
>> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>> +       struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr;
>>         __u64 mid;
>> -       __u32 len = get_rfc1002_length(buf);
>>         __u32 clc_len;  /* calculated length */
>>         int command;
>> -
>> -       /* BB disable following printk later */
>> -       cifs_dbg(FYI, "%s length: 0x%x, smb_buf_length: 0x%x\n",
>> -                __func__, length, len);
>> +       int pdu_size = sizeof(struct smb2_sync_pdu);
>> +       int hdr_size = sizeof(struct smb2_sync_hdr);
>>
>>         /*
>>          * Add function to do table lookup of StructureSize by command
>>          * ie Validate the wct via smb2_struct_sizes table above
>>          */
>> -
>>         if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
>>                 struct smb2_transform_hdr *thdr =
>>                         (struct smb2_transform_hdr *)buf;
>> @@ -136,8 +131,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>>         }
>>
>>         mid = le64_to_cpu(shdr->MessageId);
>> -       if (length < sizeof(struct smb2_pdu)) {
>> -               if ((length >= sizeof(struct smb2_hdr))
>> +       if (len < pdu_size) {
>> +               if ((len >= hdr_size)
>>                     && (shdr->Status != 0)) {
>>                         pdu->StructureSize2 = 0;
>>                         /*
>> @@ -190,13 +185,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>>                 }
>>         }
>>
>> -       if (srvr->vals->header_preamble_size + len != length) {
>> -               cifs_dbg(VFS, "Total length %u RFC1002 length %u mismatch mid %llu\n",
>> -                        length, srvr->vals->header_preamble_size + len, mid);
>> -               return 1;
>> -       }
>> -
>> -       clc_len = smb2_calc_size(hdr);
>> +       clc_len = smb2_calc_size(buf);
>>
>>         if (srvr->vals->header_preamble_size + len != clc_len) {
>>                 cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
>> @@ -206,7 +195,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>>                     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 == len && command == SMB2_OPLOCK_BREAK_HE)
>
> We have a srvr pointer here, so, we can use header_preamble_size
> instead and move this to patch #1.
>
>>                         return 0;
>>                 /* server can return one byte more due to implied bcc[0] */
>>                 if (clc_len == srvr->vals->header_preamble_size + len + 1)
>> @@ -263,15 +252,14 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
>>   * area and the offset to it (from the beginning of the smb are also returned.
>>   */
>>  char *
>> -smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
>> +smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr)
>>  {
>> -       struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
>>         *off = 0;
>>         *len = 0;
>>
>>         /* error responses do not have data area */
>>         if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
>> -           (((struct smb2_err_rsp *)hdr)->StructureSize) ==
>> +           (((struct smb2_err_rsp *)shdr)->StructureSize) ==
>>                                                 SMB2_ERROR_STRUCTURE_SIZE2)
>>                 return NULL;
>>
>> @@ -283,42 +271,44 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
>>         switch (shdr->Command) {
>>         case SMB2_NEGOTIATE:
>>                 *off = le16_to_cpu(
>> -                   ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset);
>> +                 ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset);
>>                 *len = le16_to_cpu(
>> -                   ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferLength);
>> +                 ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength);
>>                 break;
>>         case SMB2_SESSION_SETUP:
>>                 *off = le16_to_cpu(
>> -                   ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferOffset);
>> +                 ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset);
>>                 *len = le16_to_cpu(
>> -                   ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferLength);
>> +                 ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength);
>>                 break;
>>         case SMB2_CREATE:
>>                 *off = le32_to_cpu(
>> -                   ((struct smb2_create_rsp *)hdr)->CreateContextsOffset);
>> +                   ((struct smb2_create_rsp *)shdr)->CreateContextsOffset);
>>                 *len = le32_to_cpu(
>> -                   ((struct smb2_create_rsp *)hdr)->CreateContextsLength);
>> +                   ((struct smb2_create_rsp *)shdr)->CreateContextsLength);
>>                 break;
>>         case SMB2_QUERY_INFO:
>>                 *off = le16_to_cpu(
>> -                   ((struct smb2_query_info_rsp *)hdr)->OutputBufferOffset);
>> +                   ((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset);
>>                 *len = le32_to_cpu(
>> -                   ((struct smb2_query_info_rsp *)hdr)->OutputBufferLength);
>> +                   ((struct smb2_query_info_rsp *)shdr)->OutputBufferLength);
>>                 break;
>>         case SMB2_READ:
>> -               *off = ((struct smb2_read_rsp *)hdr)->DataOffset;
>> -               *len = le32_to_cpu(((struct smb2_read_rsp *)hdr)->DataLength);
>> +               /* TODO: is this a bug ? */
>> +               *off = ((struct smb2_read_rsp *)shdr)->DataOffset;
>> +               *len = le32_to_cpu(((struct smb2_read_rsp *)shdr)->DataLength);
>>                 break;
>>         case SMB2_QUERY_DIRECTORY:
>>                 *off = le16_to_cpu(
>> -                 ((struct smb2_query_directory_rsp *)hdr)->OutputBufferOffset);
>> +                 ((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset);
>>                 *len = le32_to_cpu(
>> -                 ((struct smb2_query_directory_rsp *)hdr)->OutputBufferLength);
>> +                 ((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength);
>>                 break;
>>         case SMB2_IOCTL:
>>                 *off = le32_to_cpu(
>> -                 ((struct smb2_ioctl_rsp *)hdr)->OutputOffset);
>> -               *len = le32_to_cpu(((struct smb2_ioctl_rsp *)hdr)->OutputCount);
>> +                 ((struct smb2_ioctl_rsp *)shdr)->OutputOffset);
>> +               *len = le32_to_cpu(
>> +                 ((struct smb2_ioctl_rsp *)shdr)->OutputCount);
>>                 break;
>>         case SMB2_CHANGE_NOTIFY:
>>         default:
>> @@ -363,13 +353,12 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
>>  unsigned int
>>  smb2_calc_size(void *buf)
>>  {
>> -       struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
>> -       struct smb2_hdr *hdr = &pdu->hdr;
>> -       struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
>> +       struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)buf;
>> +       struct smb2_sync_hdr *shdr = &pdu->sync_hdr;
>>         int offset; /* the offset from the beginning of SMB to data area */
>>         int data_length; /* the length of the variable length data area */
>>         /* Structure Size has already been checked to make sure it is 64 */
>> -       int len = 4 + le16_to_cpu(shdr->StructureSize);
>> +       int len = le16_to_cpu(shdr->StructureSize);
>>
>>         /*
>>          * StructureSize2, ie length of fixed parameter area has already
>> @@ -380,7 +369,7 @@ smb2_calc_size(void *buf)
>>         if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false)
>>                 goto calc_size_exit;
>>
>> -       smb2_get_data_area_len(&offset, &data_length, hdr);
>> +       smb2_get_data_area_len(&offset, &data_length, shdr);
>>         cifs_dbg(FYI, "SMB2 data length %d offset %d\n", data_length, offset);
>>
>>         if (data_length > 0) {
>> @@ -388,15 +377,14 @@ smb2_calc_size(void *buf)
>>                  * Check to make sure that data area begins after fixed area,
>>                  * Note that last byte of the fixed area is part of data area
>>                  * for some commands, typically those with odd StructureSize,
>> -                * so we must add one to the calculation (and 4 to account for
>> -                * the size of the RFC1001 hdr.
>> +                * so we must add one to the calculation.
>>                  */
>> -               if (offset + 4 + 1 < len) {
>> +               if (offset + 1 < len) {
>>                         cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d\n",
>> -                                offset + 4 + 1, len);
>> +                                offset + 1, len);
>>                         data_length = 0;
>>                 } else {
>> -                       len = 4 + offset + data_length;
>> +                       len = offset + data_length;
>>                 }
>>         }
>>  calc_size_exit:
>> @@ -579,7 +567,7 @@ smb2_is_valid_lease_break(char *buffer)
>>  bool
>>  smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
>>  {
>> -       struct smb2_oplock_break_rsp *rsp = (struct smb2_oplock_break_rsp *)buffer;
>> +       struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer;
>>         struct list_head *tmp, *tmp1, *tmp2;
>>         struct cifs_ses *ses;
>>         struct cifs_tcon *tcon;
>> @@ -588,7 +576,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
>>
>>         cifs_dbg(FYI, "Checking for oplock break\n");
>>
>> -       if (rsp->hdr.sync_hdr.Command != SMB2_OPLOCK_BREAK)
>> +       if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK)
>>                 return false;
>>
>>         if (rsp->StructureSize !=
>> @@ -679,8 +667,8 @@ smb2_cancelled_close_fid(struct work_struct *work)
>>  int
>>  smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
>>  {
>> -       struct smb2_sync_hdr *sync_hdr = get_sync_hdr(buffer);
>> -       struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer;
>> +       struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer;
>> +       struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)sync_hdr;
>>         struct cifs_tcon *tcon;
>>         struct close_cancelled_open *cancelled;
>>
>> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
>> index 09d3a2912869..48ee237c3fdf 100644
>> --- a/fs/cifs/smb2ops.c
>> +++ b/fs/cifs/smb2ops.c
>> @@ -123,7 +123,8 @@ smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
>>  static unsigned int
>>  smb2_get_credits(struct mid_q_entry *mid)
>>  {
>> -       struct smb2_sync_hdr *shdr = get_sync_hdr(mid->resp_buf);
>> +       char *buf = mid->resp_buf;
>> +       struct smb2_sync_hdr *shdr  = (struct smb2_sync_hdr *)buf;
>>
>>         return le16_to_cpu(shdr->CreditRequest);
>>  }
>> @@ -190,7 +191,7 @@ static struct mid_q_entry *
>>  smb2_find_mid(struct TCP_Server_Info *server, char *buf)
>>  {
>>         struct mid_q_entry *mid;
>> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
>> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>>         __u64 wire_mid = le64_to_cpu(shdr->MessageId);
>>
>>         if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
>> @@ -215,7 +216,7 @@ static void
>>  smb2_dump_detail(void *buf)
>>  {
>>  #ifdef CONFIG_CIFS_DEBUG2
>> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
>> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>>
>>         cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n",
>>                  shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId,
>> @@ -1241,7 +1242,7 @@ smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
>>  static bool
>>  smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
>>  {
>> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
>> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>>
>>         if (shdr->Status != STATUS_PENDING)
>>                 return false;
>> @@ -1259,7 +1260,7 @@ smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
>>  static bool
>>  smb2_is_session_expired(char *buf)
>>  {
>> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
>> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>>
>>         if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED)
>>                 return false;
>> @@ -1451,6 +1452,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
>>         __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
>>         struct cifs_open_parms oparms;
>>         struct cifs_fid fid;
>> +       struct kvec err_iov = {NULL, 0};
>>         struct smb2_err_rsp *err_buf = NULL;
>>         struct smb2_symlink_err_rsp *symlink;
>>         unsigned int sub_len;
>> @@ -1473,15 +1475,16 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
>>         oparms.fid = &fid;
>>         oparms.reconnect = false;
>>
>> -       rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_buf);
>> +       rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov);
>>
>>         if (!rc || !err_buf) {
>>                 kfree(utf16_path);
>>                 return -ENOENT;
>>         }
>>
>> +       err_buf = err_iov.iov_base;
>>         if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
>> -           get_rfc1002_length(err_buf) + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
>> +           err_iov.iov_len + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
>>                 kfree(utf16_path);
>>                 return -ENOENT;
>>         }
>> @@ -1494,13 +1497,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) + server->vals->header_preamble_size <
>> +       if (err_iov.iov_len + server->vals->header_preamble_size <
>>                         SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
>>                 kfree(utf16_path);
>>                 return -ENOENT;
>>         }
>>
>> -       if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size <
>> +       if (err_iov.iov_len + server->vals->header_preamble_size <
>>                         SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
>>                 kfree(utf16_path);
>>                 return -ENOENT;
>> @@ -2052,12 +2055,11 @@ smb2_dir_needs_close(struct cifsFileInfo *cfile)
>>  }
>>
>>  static void
>> -fill_transform_hdr(struct TCP_Server_Info *server,
>> -                  struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
>> +fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
>> +                  struct smb_rqst *old_rq)
>>  {
>>         struct smb2_sync_hdr *shdr =
>>                         (struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base;
>> -       unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base);
>>
>>         memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr));
>>         tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
>> @@ -2065,8 +2067,6 @@ fill_transform_hdr(struct TCP_Server_Info *server,
>>         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) - server->vals->header_preamble_size);
>> -       inc_rfc1001_len(tr_hdr, orig_len);
>>  }
>>
>>  /* We can not use the normal sg_set_buf() as we will sometimes pass a
>> @@ -2078,11 +2078,16 @@ static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
>>         sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
>>  }
>>
>> +/* Assumes:
>> + * rqst->rq_iov[0]  is rfc1002 length
>> + * rqst->rq_iov[1]  is tranform header
>> + * rqst->rq_iov[2+] data to be encrypted/decrypted
>> + */
>>  static struct scatterlist *
>>  init_sg(struct smb_rqst *rqst, u8 *sign)
>>  {
>> -       unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages + 1;
>> -       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
>> +       unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages;
>> +       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
>>         struct scatterlist *sg;
>>         unsigned int i;
>>         unsigned int j;
>> @@ -2092,10 +2097,10 @@ init_sg(struct smb_rqst *rqst, u8 *sign)
>>                 return NULL;
>>
>>         sg_init_table(sg, sg_len);
>> -       smb2_sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 24, assoc_data_len);
>> -       for (i = 1; i < rqst->rq_nvec; i++)
>> -               smb2_sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base,
>> -                                               rqst->rq_iov[i].iov_len);
>> +       smb2_sg_set_buf(&sg[0], rqst->rq_iov[1].iov_base + 20, assoc_data_len);
>> +       for (i = 1; i < rqst->rq_nvec - 1; i++)
>> +               smb2_sg_set_buf(&sg[i], rqst->rq_iov[i+1].iov_base,
>> +                                               rqst->rq_iov[i+1].iov_len);
>>         for (j = 0; i < sg_len - 1; i++, j++) {
>>                 unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz
>>                                                         : rqst->rq_tailsz;
>> @@ -2127,17 +2132,18 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
>>  }
>>  /*
>>   * Encrypt or decrypt @rqst message. @rqst has the following format:
>> - * iov[0] - transform header (associate data),
>> - * iov[1-N] and pages - data to encrypt.
>> - * On success return encrypted data in iov[1-N] and pages, leave iov[0]
>> + * iov[0] - rfc1002 length
>> + * iov[1] - transform header (associate data),
>> + * iov[2-N] and pages - data to encrypt.
>> + * On success return encrypted data in iov[2-N] and pages, leave iov[0-1]
>>   * untouched.
>>   */
>>  static int
>>  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;
>> +                       (struct smb2_transform_hdr *)rqst->rq_iov[1].iov_base;
>> +       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
>
> The same here: please use header_preamble_size.
>
>>         int rc = 0;
>>         struct scatterlist *sg;
>>         u8 sign[SMB2_SIGNATURE_SIZE] = {};
>> @@ -2224,6 +2230,9 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
>>         return rc;
>>  }
>>
>> +/* This is called from smb_send_rqst. At this point we have the rfc1002
>> + * header as the first element in the vector.
>> + */
>
> The comment style should be:
> /*
>  * text
>  */
>
>>  static int
>>  smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
>>                        struct smb_rqst *old_rq)
>> @@ -2232,6 +2241,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
>>         struct page **pages;
>>         struct smb2_transform_hdr *tr_hdr;
>>         unsigned int npages = old_rq->rq_npages;
>> +       unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base);
>>         int i;
>>         int rc = -ENOMEM;
>>
>> @@ -2250,24 +2260,34 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
>>                         goto err_free_pages;
>>         }
>>
>> -       iov = kmalloc_array(old_rq->rq_nvec, sizeof(struct kvec), GFP_KERNEL);
>> +       /* Make space for one extra iov to hold the transform header */
>> +       iov = kmalloc_array(old_rq->rq_nvec + 1, sizeof(struct kvec),
>> +                           GFP_KERNEL);
>>         if (!iov)
>>                 goto err_free_pages;
>>
>>         /* copy all iovs from the old except the 1st one (rfc1002 length) */
>> -       memcpy(&iov[1], &old_rq->rq_iov[1],
>> +       memcpy(&iov[2], &old_rq->rq_iov[1],
>>                                 sizeof(struct kvec) * (old_rq->rq_nvec - 1));
>> +       /* copy the rfc1002 iov */
>> +       iov[0].iov_base = old_rq->rq_iov[0].iov_base;
>> +       iov[0].iov_len  = old_rq->rq_iov[0].iov_len;
>> +
>>         new_rq->rq_iov = iov;
>> -       new_rq->rq_nvec = old_rq->rq_nvec;
>> +       new_rq->rq_nvec = old_rq->rq_nvec + 1;
>>
>>         tr_hdr = kmalloc(sizeof(struct smb2_transform_hdr), GFP_KERNEL);
>>         if (!tr_hdr)
>>                 goto err_free_iov;
>>
>> -       /* fill the 1st iov with a transform header */
>> -       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);
>> +       /* fill the 2nd iov with a transform header */
>> +       fill_transform_hdr(tr_hdr, orig_len, old_rq);
>> +       new_rq->rq_iov[1].iov_base = tr_hdr;
>> +       new_rq->rq_iov[1].iov_len = sizeof(struct smb2_transform_hdr);
>> +
>> +       /* Update rfc1002 header */
>> +       inc_rfc1001_len(new_rq->rq_iov[0].iov_base,
>> +                       sizeof(struct smb2_transform_hdr));
>>
>>         /* copy pages form the old */
>>         for (i = 0; i < npages; i++) {
>> @@ -2307,7 +2327,7 @@ smb3_free_transform_rq(struct smb_rqst *rqst)
>>                 put_page(rqst->rq_pages[i]);
>>         kfree(rqst->rq_pages);
>>         /* free transform header */
>> -       kfree(rqst->rq_iov[0].iov_base);
>> +       kfree(rqst->rq_iov[1].iov_base);
>>         kfree(rqst->rq_iov);
>>  }
>>
>> @@ -2324,18 +2344,19 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
>>                  unsigned int buf_data_size, struct page **pages,
>>                  unsigned int npages, unsigned int page_data_size)
>>  {
>> -       struct kvec iov[2];
>> +       struct kvec iov[3];
>>         struct smb_rqst rqst = {NULL};
>> -       struct smb2_hdr *hdr;
>>         int rc;
>>
>> -       iov[0].iov_base = buf;
>> -       iov[0].iov_len = sizeof(struct smb2_transform_hdr);
>> -       iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr);
>> -       iov[1].iov_len = buf_data_size;
>> +       iov[0].iov_base = NULL;
>> +       iov[0].iov_len = 0;
>> +       iov[1].iov_base = buf;
>> +       iov[1].iov_len = sizeof(struct smb2_transform_hdr);
>> +       iov[2].iov_base = buf + sizeof(struct smb2_transform_hdr);
>> +       iov[2].iov_len = buf_data_size;
>>
>>         rqst.rq_iov = iov;
>> -       rqst.rq_nvec = 2;
>> +       rqst.rq_nvec = 3;
>>         rqst.rq_pages = pages;
>>         rqst.rq_npages = npages;
>>         rqst.rq_pagesz = PAGE_SIZE;
>> @@ -2347,10 +2368,9 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
>>         if (rc)
>>                 return rc;
>>
>> -       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 + server->vals->header_preamble_size;
>> +       memmove(buf + server->vals->header_preamble_size, iov[2].iov_base, buf_data_size);
>> +
>> +       server->total_read = buf_data_size + page_data_size;
>>
>>         return rc;
>>  }
>> @@ -2423,7 +2443,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
>>         unsigned int cur_page_idx;
>>         unsigned int pad_len;
>>         struct cifs_readdata *rdata = mid->callback_data;
>> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
>> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>>         struct bio_vec *bvec = NULL;
>>         struct iov_iter iter;
>>         struct kvec iov;
>> @@ -2550,7 +2570,7 @@ 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) + server->vals->header_preamble_size;
>> +       unsigned int buflen = server->pdu_size + server->vals->header_preamble_size;
>>         int rc;
>>         int i = 0;
>>
>> @@ -2624,7 +2644,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
>>  {
>>         int length;
>>         char *buf = server->smallbuf;
>> -       unsigned int pdu_length = get_rfc1002_length(buf);
>> +       unsigned int pdu_length = server->pdu_size;
>>         unsigned int buf_size;
>>         struct mid_q_entry *mid_entry;
>>
>> @@ -2668,7 +2688,7 @@ static int
>>  smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
>>  {
>>         char *buf = server->smallbuf;
>> -       unsigned int pdu_length = get_rfc1002_length(buf);
>> +       unsigned int pdu_length = server->pdu_size;
>>         struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
>>         unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
>>
>> @@ -2699,7 +2719,7 @@ 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) +
>> +       return handle_read_data(server, mid, buf, server->total_read +
>
> Should we use server->pdu_size here instead?

Yes. I have fixed this and the other things you suggested and will
resend tomorrow.

>
>>                                 server->vals->header_preamble_size,
>>                                 NULL, 0, 0);
>>  }
>> @@ -3104,8 +3124,8 @@ struct smb_version_values smb20_values = {
>>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>> -       .header_size = sizeof(struct smb2_hdr),
>> -       .header_preamble_size = 4,
>> +       .header_size = sizeof(struct smb2_sync_hdr),
>> +       .header_preamble_size = 0,
>>         .max_header_size = MAX_SMB2_HDR_SIZE,
>>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>>         .lock_cmd = SMB2_LOCK,
>> @@ -3125,8 +3145,8 @@ struct smb_version_values smb21_values = {
>>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>> -       .header_size = sizeof(struct smb2_hdr),
>> -       .header_preamble_size = 4,
>> +       .header_size = sizeof(struct smb2_sync_hdr),
>> +       .header_preamble_size = 0,
>>         .max_header_size = MAX_SMB2_HDR_SIZE,
>>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>>         .lock_cmd = SMB2_LOCK,
>> @@ -3146,8 +3166,8 @@ struct smb_version_values smb3any_values = {
>>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>> -       .header_size = sizeof(struct smb2_hdr),
>> -       .header_preamble_size = 4,
>> +       .header_size = sizeof(struct smb2_sync_hdr),
>> +       .header_preamble_size = 0,
>>         .max_header_size = MAX_SMB2_HDR_SIZE,
>>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>>         .lock_cmd = SMB2_LOCK,
>> @@ -3167,8 +3187,8 @@ struct smb_version_values smbdefault_values = {
>>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>> -       .header_size = sizeof(struct smb2_hdr),
>> -       .header_preamble_size = 4,
>> +       .header_size = sizeof(struct smb2_sync_hdr),
>> +       .header_preamble_size = 0,
>>         .max_header_size = MAX_SMB2_HDR_SIZE,
>>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>>         .lock_cmd = SMB2_LOCK,
>> @@ -3188,8 +3208,8 @@ struct smb_version_values smb30_values = {
>>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>> -       .header_size = sizeof(struct smb2_hdr),
>> -       .header_preamble_size = 4,
>> +       .header_size = sizeof(struct smb2_sync_hdr),
>> +       .header_preamble_size = 0,
>>         .max_header_size = MAX_SMB2_HDR_SIZE,
>>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>>         .lock_cmd = SMB2_LOCK,
>> @@ -3209,8 +3229,8 @@ struct smb_version_values smb302_values = {
>>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>> -       .header_size = sizeof(struct smb2_hdr),
>> -       .header_preamble_size = 4,
>> +       .header_size = sizeof(struct smb2_sync_hdr),
>> +       .header_preamble_size = 0,
>>         .max_header_size = MAX_SMB2_HDR_SIZE,
>>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>>         .lock_cmd = SMB2_LOCK,
>> @@ -3231,8 +3251,8 @@ struct smb_version_values smb311_values = {
>>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
>> -       .header_size = sizeof(struct smb2_hdr),
>> -       .header_preamble_size = 4,
>> +       .header_size = sizeof(struct smb2_sync_hdr),
>> +       .header_preamble_size = 0,
>>         .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..b20348f72a6f 100644
>> --- a/fs/cifs/smb2pdu.c
>> +++ b/fs/cifs/smb2pdu.c
>> @@ -591,7 +591,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
>>         server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
>>
>>         security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
>> -                                              &rsp->hdr);
>> +                                              (struct smb2_sync_hdr *)rsp);
>>         /*
>>          * See MS-SMB2 section 2.2.4: if no blob, client picks default which
>>          * for us will be
>> @@ -942,7 +942,7 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
>>                 goto out_put_spnego_key;
>>
>>         rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
>> -       ses->Suid = rsp->hdr.sync_hdr.SessionId;
>> +       ses->Suid = rsp->sync_hdr.SessionId;
>>
>>         ses->session_flags = le16_to_cpu(rsp->SessionFlags);
>>
>> @@ -1018,13 +1018,13 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
>>
>>         /* If true, rc here is expected and not an error */
>>         if (sess_data->buf0_type != CIFS_NO_BUFFER &&
>> -               rsp->hdr.sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
>> +               rsp->sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
>>                 rc = 0;
>>
>>         if (rc)
>>                 goto out;
>>
>> -       if (offsetof(struct smb2_sess_setup_rsp, Buffer) - 4 !=
>> +       if (offsetof(struct smb2_sess_setup_rsp, Buffer) !=
>>                         le16_to_cpu(rsp->SecurityBufferOffset)) {
>>                 cifs_dbg(VFS, "Invalid security buffer offset %d\n",
>>                         le16_to_cpu(rsp->SecurityBufferOffset));
>> @@ -1039,7 +1039,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
>>         cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
>>
>>
>> -       ses->Suid = rsp->hdr.sync_hdr.SessionId;
>> +       ses->Suid = rsp->sync_hdr.SessionId;
>>         ses->session_flags = le16_to_cpu(rsp->SessionFlags);
>>
>>  out:
>> @@ -1097,7 +1097,7 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
>>
>>         rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
>>
>> -       ses->Suid = rsp->hdr.sync_hdr.SessionId;
>> +       ses->Suid = rsp->sync_hdr.SessionId;
>>         ses->session_flags = le16_to_cpu(rsp->SessionFlags);
>>
>>         rc = SMB2_sess_establish_session(sess_data);
>> @@ -1340,7 +1340,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
>>         tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess);
>>         tcon->tidStatus = CifsGood;
>>         tcon->need_reconnect = false;
>> -       tcon->tid = rsp->hdr.sync_hdr.TreeId;
>> +       tcon->tid = rsp->sync_hdr.TreeId;
>>         strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
>>
>>         if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
>> @@ -1360,7 +1360,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
>>         return rc;
>>
>>  tcon_error_exit:
>> -       if (rsp && rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
>> +       if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
>>                 cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
>>         }
>>         goto tcon_exit;
>> @@ -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 + le32_to_cpu(rsp->CreateContextsOffset);
>
> the same as above.
>
>>         remaining = le32_to_cpu(rsp->CreateContextsLength);
>>         cc = (struct create_context *)data_offset;
>>         while (remaining >= sizeof(struct create_context)) {
>> @@ -1694,7 +1694,7 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
>>  int
>>  SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
>>           __u8 *oplock, struct smb2_file_all_info *buf,
>> -         struct smb2_err_rsp **err_buf)
>> +         struct kvec *err_iov)
>>  {
>>         struct smb2_create_req *req;
>>         struct smb2_create_rsp *rsp;
>> @@ -1834,9 +1834,10 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
>>
>>         if (rc != 0) {
>>                 cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
>> -               if (err_buf && rsp)
>> -                       *err_buf = kmemdup(rsp, get_rfc1002_length(rsp) + 4,
>> -                                          GFP_KERNEL);
>> +               if (err_iov && rsp) {
>> +                       *err_iov = rsp_iov;
>> +                       rsp = NULL;
>> +               }
>>                 goto creat_exit;
>>         }
>>
>> @@ -1875,7 +1876,6 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
>>  {
>>         struct smb2_ioctl_req *req;
>>         struct smb2_ioctl_rsp *rsp;
>> -       struct smb2_sync_hdr *shdr;
>>         struct cifs_ses *ses;
>>         struct kvec iov[2];
>>         struct kvec rsp_iov;
>> @@ -1996,7 +1996,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
>>                 goto ioctl_exit;
>>         }
>>
>> -       if (get_rfc1002_length(rsp) < le32_to_cpu(rsp->OutputOffset) + *plen) {
>> +       if (rsp_iov.iov_len < le32_to_cpu(rsp->OutputOffset) + *plen) {
>>                 cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen,
>>                         le32_to_cpu(rsp->OutputOffset));
>>                 *plen = 0;
>> @@ -2010,8 +2010,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
>>                 goto ioctl_exit;
>>         }
>>
>> -       shdr = get_sync_hdr(rsp);
>> -       memcpy(*out_data, (char *)shdr + le32_to_cpu(rsp->OutputOffset), *plen);
>> +       memcpy(*out_data, (char *)rsp + le32_to_cpu(rsp->OutputOffset), *plen);
>>  ioctl_exit:
>>         free_rsp_buf(resp_buftype, rsp);
>>         return rc;
>> @@ -2091,13 +2090,12 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
>>  }
>>
>>  static int
>> -validate_buf(unsigned int offset, unsigned int buffer_length,
>> -            struct smb2_hdr *hdr, unsigned int min_buf_size)
>> -
>> +validate_iov(unsigned int offset, unsigned int buffer_length,
>> +            struct kvec *iov, unsigned int min_buf_size)
>>  {
>> -       unsigned int smb_len = be32_to_cpu(hdr->smb2_buf_length);
>> -       char *end_of_smb = smb_len + 4 /* RFC1001 length field */ + (char *)hdr;
>> -       char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr;
>> +       unsigned int smb_len = iov->iov_len;
>> +       char *end_of_smb = smb_len + (char *)iov->iov_base;
>> +       char *begin_of_buf = offset + (char *)iov->iov_base;
>>         char *end_of_buf = begin_of_buf + buffer_length;
>>
>>
>> @@ -2127,18 +2125,17 @@ validate_buf(unsigned int offset, unsigned int buffer_length,
>>   * Caller must free buffer.
>>   */
>>  static int
>> -validate_and_copy_buf(unsigned int offset, unsigned int buffer_length,
>> -                     struct smb2_hdr *hdr, unsigned int minbufsize,
>> +validate_and_copy_iov(unsigned int offset, unsigned int buffer_length,
>> +                     struct kvec *iov, unsigned int minbufsize,
>>                       char *data)
>> -
>>  {
>> -       char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr;
>> +       char *begin_of_buf = offset + (char *)iov->iov_base;
>>         int rc;
>>
>>         if (!data)
>>                 return -EINVAL;
>>
>> -       rc = validate_buf(offset, buffer_length, hdr, minbufsize);
>> +       rc = validate_iov(offset, buffer_length, iov, minbufsize);
>>         if (rc)
>>                 return rc;
>>
>> @@ -2216,9 +2213,9 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
>>                 }
>>         }
>>
>> -       rc = validate_and_copy_buf(le16_to_cpu(rsp->OutputBufferOffset),
>> +       rc = validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset),
>>                                    le32_to_cpu(rsp->OutputBufferLength),
>> -                                  &rsp->hdr, min_len, *data);
>> +                                  &rsp_iov, min_len, *data);
>>
>>  qinf_exit:
>>         free_rsp_buf(resp_buftype, rsp);
>> @@ -2287,7 +2284,7 @@ smb2_echo_callback(struct mid_q_entry *mid)
>>         unsigned int credits_received = 1;
>>
>>         if (mid->mid_state == MID_RESPONSE_RECEIVED)
>> -               credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest);
>> +               credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
>>
>>         DeleteMidQEntry(mid);
>>         add_credits(server, credits_received, CIFS_ECHO_OP);
>> @@ -2684,7 +2681,6 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
>>         int resp_buftype, rc = -EACCES;
>>         struct smb2_read_plain_req *req = NULL;
>>         struct smb2_read_rsp *rsp = NULL;
>> -       struct smb2_sync_hdr *shdr;
>>         struct kvec iov[1];
>>         struct kvec rsp_iov;
>>         unsigned int total_len;
>> @@ -2725,10 +2721,8 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
>>                 *nbytes = 0;
>>         }
>>
>> -       shdr = get_sync_hdr(rsp);
>> -
>>         if (*buf) {
>> -               memcpy(*buf, (char *)shdr + rsp->DataOffset, *nbytes);
>> +               memcpy(*buf, (char *)rsp + rsp->DataOffset, *nbytes);
>>                 free_rsp_buf(resp_buftype, rsp_iov.iov_base);
>>         } else if (resp_buftype != CIFS_NO_BUFFER) {
>>                 *buf = rsp_iov.iov_base;
>> @@ -2755,7 +2749,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
>>
>>         switch (mid->mid_state) {
>>         case MID_RESPONSE_RECEIVED:
>> -               credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest);
>> +               credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
>>                 wdata->result = smb2_check_receive(mid, tcon->ses->server, 0);
>>                 if (wdata->result != 0)
>>                         break;
>> @@ -3131,7 +3125,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
>>
>>         if (rc) {
>>                 if (rc == -ENODATA &&
>> -                   rsp->hdr.sync_hdr.Status == STATUS_NO_MORE_FILES) {
>> +                   rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) {
>>                         srch_inf->endOfSearch = true;
>>                         rc = 0;
>>                 }
>> @@ -3139,8 +3133,8 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
>>                 goto qdir_exit;
>>         }
>>
>> -       rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset),
>> -                         le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr,
>> +       rc = validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
>> +                         le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
>>                           info_buf_size);
>>         if (rc)
>>                 goto qdir_exit;
>> @@ -3154,10 +3148,9 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
>>                         cifs_buf_release(srch_inf->ntwrk_buf_start);
>>         }
>>         srch_inf->ntwrk_buf_start = (char *)rsp;
>> -       srch_inf->srch_entries_start = srch_inf->last_entry = 4 /* rfclen */ +
>> -               (char *)&rsp->hdr + le16_to_cpu(rsp->OutputBufferOffset);
>> -       /* 4 for rfc1002 length field */
>> -       end_of_smb = get_rfc1002_length(rsp) + 4 + (char *)&rsp->hdr;
>> +       srch_inf->srch_entries_start = srch_inf->last_entry =
>> +               (char *)rsp + le16_to_cpu(rsp->OutputBufferOffset);
>> +       end_of_smb = rsp_iov.iov_len + (char *)rsp;
>>         srch_inf->entries_in_buffer =
>>                         num_entries(srch_inf->srch_entries_start, end_of_smb,
>>                                     &srch_inf->last_entry, info_buf_size);
>> @@ -3393,7 +3386,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
>>                   __u8 oplock_level)
>>  {
>>         int rc;
>> -       struct smb2_oplock_break_req *req = NULL;
>> +       struct smb2_oplock_break *req = NULL;
>>         struct cifs_ses *ses = tcon->ses;
>>         int flags = CIFS_OBREAK_OP;
>>         unsigned int total_len;
>> @@ -3469,7 +3462,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);
>
> the same.
>
>>
>>         iov->iov_base = (char *)req;
>>         iov->iov_len = total_len;
>> @@ -3506,10 +3499,10 @@ 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 */ +
>
> here as well.
>
>> -               le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr);
>> -       rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset),
>> -                         le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr,
>> +       info = (struct smb2_fs_full_size_info *)(
>> +               le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
>> +       rc = validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
>> +                         le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
>>                           sizeof(struct smb2_fs_full_size_info));
>>         if (!rc)
>>                 copy_fs_info_to_kstatfs(info, fsdata);
>> @@ -3564,20 +3557,20 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
>>
>>         rsp_len = le32_to_cpu(rsp->OutputBufferLength);
>>         offset = le16_to_cpu(rsp->OutputBufferOffset);
>> -       rc = validate_buf(offset, rsp_len, &rsp->hdr, min_len);
>> +       rc = validate_iov(offset, rsp_len, &rsp_iov, min_len);
>>         if (rc)
>>                 goto qfsattr_exit;
>>
>>         if (level == FS_ATTRIBUTE_INFORMATION)
>> -               memcpy(&tcon->fsAttrInfo, 4 /* RFC1001 len */ + offset
>> -                       + (char *)&rsp->hdr, min_t(unsigned int,
>> +               memcpy(&tcon->fsAttrInfo, offset
>> +                       + (char *)rsp, min_t(unsigned int,
>>                         rsp_len, max_len));
>>         else if (level == FS_DEVICE_INFORMATION)
>> -               memcpy(&tcon->fsDevInfo, 4 /* RFC1001 len */ + offset
>
> the same as above.
>
>> -                       + (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO));
>> +               memcpy(&tcon->fsDevInfo, offset
>> +                       + (char *)rsp, 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);
>> +                       (offset + (char *)rsp);
>>                 tcon->ss_flags = le32_to_cpu(ss_info->Flags);
>>                 tcon->perf_sector_size =
>>                         le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
>> diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
>> index 8b901c69a65a..6bf243a45d64 100644
>> --- a/fs/cifs/smb2pdu.h
>> +++ b/fs/cifs/smb2pdu.h
>> @@ -122,25 +122,10 @@ struct smb2_sync_pdu {
>>         __le16 StructureSize2; /* size of wct area (varies, request specific) */
>>  } __packed;
>>
>> -struct smb2_hdr {
>> -       __be32 smb2_buf_length; /* big endian on wire */
>> -                               /* length is only two or three bytes - with */
>> -                               /* one or two byte type preceding it that MBZ */
>> -       struct smb2_sync_hdr sync_hdr;
>> -} __packed;
>> -
>> -struct smb2_pdu {
>> -       struct smb2_hdr hdr;
>> -       __le16 StructureSize2; /* size of wct area (varies, request specific) */
>> -} __packed;
>> -
>>  #define SMB3_AES128CMM_NONCE 11
>>  #define SMB3_AES128GCM_NONCE 12
>>
>>  struct smb2_transform_hdr {
>> -       __be32 smb2_buf_length; /* big endian on wire */
>> -                               /* length is only two or three bytes - with
>> -                                one or two byte type preceding it that MBZ */
>>         __le32 ProtocolId;      /* 0xFD 'S' 'M' 'B' */
>>         __u8   Signature[16];
>>         __u8   Nonce[16];
>> @@ -171,7 +156,7 @@ struct smb2_transform_hdr {
>>  #define SMB2_ERROR_STRUCTURE_SIZE2 cpu_to_le16(9)
>>
>>  struct smb2_err_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize;
>>         __le16 Reserved; /* MBZ */
>>         __le32 ByteCount;  /* even if zero, at least one byte follows */
>> @@ -289,7 +274,7 @@ struct smb2_encryption_neg_context {
>>  } __packed;
>>
>>  struct smb2_negotiate_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize;   /* Must be 65 */
>>         __le16 SecurityMode;
>>         __le16 DialectRevision;
>> @@ -329,7 +314,7 @@ struct smb2_sess_setup_req {
>>  #define SMB2_SESSION_FLAG_IS_NULL      0x0002
>>  #define SMB2_SESSION_FLAG_ENCRYPT_DATA 0x0004
>>  struct smb2_sess_setup_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize; /* Must be 9 */
>>         __le16 SessionFlags;
>>         __le16 SecurityBufferOffset;
>> @@ -344,7 +329,7 @@ struct smb2_logoff_req {
>>  } __packed;
>>
>>  struct smb2_logoff_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize;   /* Must be 4 */
>>         __le16 Reserved;
>>  } __packed;
>> @@ -440,7 +425,7 @@ struct smb2_tree_connect_req_extension {
>>  } __packed;
>>
>>  struct smb2_tree_connect_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize;   /* Must be 16 */
>>         __u8   ShareType;  /* see below */
>>         __u8   Reserved;
>> @@ -491,7 +476,7 @@ struct smb2_tree_disconnect_req {
>>  } __packed;
>>
>>  struct smb2_tree_disconnect_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize;   /* Must be 4 */
>>         __le16 Reserved;
>>  } __packed;
>> @@ -626,7 +611,7 @@ struct smb2_create_req {
>>  } __packed;
>>
>>  struct smb2_create_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize;   /* Must be 89 */
>>         __u8   OplockLevel;
>>         __u8   Reserved;
>> @@ -882,7 +867,7 @@ struct smb2_ioctl_req {
>>  } __packed;
>>
>>  struct smb2_ioctl_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize;   /* Must be 57 */
>>         __u16 Reserved;
>>         __le32 CtlCode;
>> @@ -909,7 +894,7 @@ struct smb2_close_req {
>>  } __packed;
>>
>>  struct smb2_close_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize; /* 60 */
>>         __le16 Flags;
>>         __le32 Reserved;
>> @@ -932,7 +917,7 @@ struct smb2_flush_req {
>>  } __packed;
>>
>>  struct smb2_flush_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize;
>>         __le16 Reserved;
>>  } __packed;
>> @@ -964,7 +949,7 @@ struct smb2_read_plain_req {
>>  } __packed;
>>
>>  struct smb2_read_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize; /* Must be 17 */
>>         __u8   DataOffset;
>>         __u8   Reserved;
>> @@ -995,7 +980,7 @@ struct smb2_write_req {
>>  } __packed;
>>
>>  struct smb2_write_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize; /* Must be 17 */
>>         __u8   DataOffset;
>>         __u8   Reserved;
>> @@ -1029,7 +1014,7 @@ struct smb2_lock_req {
>>  } __packed;
>>
>>  struct smb2_lock_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize; /* Must be 4 */
>>         __le16 Reserved;
>>  } __packed;
>> @@ -1041,7 +1026,7 @@ struct smb2_echo_req {
>>  } __packed;
>>
>>  struct smb2_echo_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize;   /* Must be 4 */
>>         __u16  Reserved;
>>  } __packed;
>> @@ -1067,7 +1052,7 @@ struct smb2_query_directory_req {
>>  } __packed;
>>
>>  struct smb2_query_directory_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize; /* Must be 9 */
>>         __le16 OutputBufferOffset;
>>         __le32 OutputBufferLength;
>> @@ -1116,7 +1101,7 @@ struct smb2_query_info_req {
>>  } __packed;
>>
>>  struct smb2_query_info_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize; /* Must be 9 */
>>         __le16 OutputBufferOffset;
>>         __le32 OutputBufferLength;
>> @@ -1138,12 +1123,11 @@ struct smb2_set_info_req {
>>  } __packed;
>>
>>  struct smb2_set_info_rsp {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize; /* Must be 2 */
>>  } __packed;
>>
>> -/* oplock break without an rfc1002 header */
>> -struct smb2_oplock_break_req {
>> +struct smb2_oplock_break {
>>         struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize; /* Must be 24 */
>>         __u8   OplockLevel;
>> @@ -1153,21 +1137,10 @@ struct smb2_oplock_break_req {
>>         __u64  VolatileFid;
>>  } __packed;
>>
>> -/* oplock break with an rfc1002 header */
>> -struct smb2_oplock_break_rsp {
>> -       struct smb2_hdr hdr;
>> -       __le16 StructureSize; /* Must be 24 */
>> -       __u8   OplockLevel;
>> -       __u8   Reserved;
>> -       __le32 Reserved2;
>> -       __u64  PersistentFid;
>> -       __u64  VolatileFid;
>> -} __packed;
>> -
>>  #define SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED cpu_to_le32(0x01)
>>
>>  struct smb2_lease_break {
>> -       struct smb2_hdr hdr;
>> +       struct smb2_sync_hdr sync_hdr;
>>         __le16 StructureSize; /* Must be 44 */
>>         __le16 Reserved;
>>         __le32 Flags;
>> diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
>> index cbcce3f7e86f..30cdc0aa4e8e 100644
>> --- a/fs/cifs/smb2proto.h
>> +++ b/fs/cifs/smb2proto.h
>> @@ -37,7 +37,8 @@ extern int map_smb2_to_linux_error(char *buf, bool log_err);
>>  extern int smb2_check_message(char *buf, unsigned int length,
>>                               struct TCP_Server_Info *server);
>>  extern unsigned int smb2_calc_size(void *buf);
>> -extern char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr);
>> +extern char *smb2_get_data_area_len(int *off, int *len,
>> +                                   struct smb2_sync_hdr *shdr);
>>  extern __le16 *cifs_convert_path_to_utf16(const char *from,
>>                                           struct cifs_sb_info *cifs_sb);
>>
>> @@ -122,7 +123,7 @@ extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
>>  extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
>>                      __le16 *path, __u8 *oplock,
>>                      struct smb2_file_all_info *buf,
>> -                    struct smb2_err_rsp **err_buf);
>> +                    struct kvec *err_iov);
>>  extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
>>                      u64 persistent_fid, u64 volatile_fid, u32 opcode,
>>                      bool is_fsctl, char *in_data, u32 indatalen,
>> diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
>> index bf49cb73b9e6..8372a0cecdb0 100644
>> --- a/fs/cifs/smb2transport.c
>> +++ b/fs/cifs/smb2transport.c
>> @@ -480,7 +480,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
>>         unsigned int rc;
>>         char server_response_sig[16];
>>         struct smb2_sync_hdr *shdr =
>> -                       (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
>> +                       (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
>>
>>         if ((shdr->Command == SMB2_NEGOTIATE) ||
>>             (shdr->Command == SMB2_SESSION_SETUP) ||
>> @@ -604,15 +604,13 @@ int
>>  smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
>>                    bool log_error)
>>  {
>> -       unsigned int len = get_rfc1002_length(mid->resp_buf);
>> -       struct kvec iov[2];
>> +       unsigned int len = server->total_read;
>> +       struct kvec iov[1];
>>         struct smb_rqst rqst = { .rq_iov = iov,
>> -                                .rq_nvec = 2 };
>> +                                .rq_nvec = 1 };
>>
>>         iov[0].iov_base = (char *)mid->resp_buf;
>> -       iov[0].iov_len = 4;
>> -       iov[1].iov_base = (char *)mid->resp_buf + 4;
>> -       iov[1].iov_len = len;
>> +       iov[0].iov_len = mid->resp_buf_size;
>>
>>         dump_smb(mid->resp_buf, min_t(u32, 80, len));
>>         /* convert the length into a more usable form */
>> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
>> index 279718dcb2ed..3abce580b056 100644
>> --- a/fs/cifs/transport.c
>> +++ b/fs/cifs/transport.c
>> @@ -790,8 +790,9 @@ 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) +
>> +       resp_iov->iov_len = midQ->resp_buf_size +
>>                 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
> --
> 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
--
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 3e3f86841372..0045d85ec76d 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -665,6 +665,8 @@  struct TCP_Server_Info {
 	struct delayed_work	echo; /* echo ping workqueue job */
 	char	*smallbuf;	/* pointer to current "small" buffer */
 	char	*bigbuf;	/* pointer to current "big" buffer */
+	/* Total size of this PDU. Only valid from cifs_demultiplex_thread */
+	unsigned int pdu_size;
 	unsigned int total_read; /* total amount of data read in this pass */
 #ifdef CONFIG_CIFS_FSCACHE
 	struct fscache_cookie   *fscache; /* client index cache cookie */
@@ -1373,6 +1375,7 @@  struct mid_q_entry {
 	mid_handle_t *handle; /* call handle mid callback */
 	void *callback_data;	  /* general purpose pointer for callback */
 	void *resp_buf;		/* pointer to received SMB header */
+	unsigned int resp_buf_size;
 	int mid_state;	/* wish this were enum but can not pass to wait_event */
 	unsigned int mid_flags;
 	__le16 command;		/* smb command code */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 59c09a596c0a..991e9d9ef90a 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1454,7 +1454,7 @@  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) +
+	unsigned int buflen = server->pdu_size +
 		server->vals->header_preamble_size;
 	bool use_rdma_mr = false;
 
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 1f2e3b15b2b1..0fad48d081d8 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -772,7 +772,7 @@  standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 {
 	int length;
 	char *buf = server->smallbuf;
-	unsigned int pdu_length = get_rfc1002_length(buf);
+	unsigned int pdu_length = server->pdu_size;
 
 	/* make sure this will fit in a large buffer */
 	if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
@@ -874,13 +874,18 @@  cifs_demultiplex_thread(void *p)
 		length = cifs_read_from_socket(server, buf, pdu_length);
 		if (length < 0)
 			continue;
-		server->total_read = length;
+
+		if (server->vals->header_preamble_size == 0)
+			server->total_read = 0;
+		else
+			server->total_read = length;
 
 		/*
 		 * The right amount was read from socket - 4 bytes,
 		 * so we can now interpret the length field.
 		 */
 		pdu_length = get_rfc1002_length(buf);
+		server->pdu_size = pdu_length;
 
 		cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
 		if (!is_smb_response(server, buf[0]))
@@ -927,6 +932,7 @@  cifs_demultiplex_thread(void *p)
 
 		server->lstrp = jiffies;
 		if (mid_entry != NULL) {
+			mid_entry->resp_buf_size = server->pdu_size;
 			if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
 			     mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
 					server->ops->handle_cancelled_mid)
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 460084a8eac5..d5d7eb2ae3c4 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -145,7 +145,7 @@  cifs_buf_get(void)
 	 * SMB2 header is bigger than CIFS one - no problems to clean some
 	 * more bytes for CIFS.
 	 */
-	size_t buf_size = sizeof(struct smb2_hdr);
+	size_t buf_size = sizeof(struct smb2_sync_hdr);
 
 	/*
 	 * We could use negotiated size instead of max_msgsize -
diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h
index 401a5d856636..0ffa18094335 100644
--- a/fs/cifs/smb2glob.h
+++ b/fs/cifs/smb2glob.h
@@ -61,9 +61,4 @@ 
 /* Maximum buffer size value we can send with 1 credit */
 #define SMB2_MAX_BUFFER_SIZE 65536
 
-static inline struct smb2_sync_hdr *get_sync_hdr(void *buf)
-{
-	return &(((struct smb2_hdr *)buf)->sync_hdr);
-}
-
 #endif	/* _SMB2_GLOB_H */
diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c
index 62c88dfed57b..8fe30288805f 100644
--- a/fs/cifs/smb2maperror.c
+++ b/fs/cifs/smb2maperror.c
@@ -2450,7 +2450,7 @@  smb2_print_status(__le32 status)
 int
 map_smb2_to_linux_error(char *buf, bool log_err)
 {
-	struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
+	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
 	unsigned int i;
 	int rc = -EIO;
 	__le32 smb2err = shdr->Status;
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 566871185b98..cb79c2433844 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -94,25 +94,20 @@  static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
 };
 
 int
-smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
+smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
 {
-	struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
-	struct smb2_hdr *hdr = &pdu->hdr;
-	struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
+	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
+	struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr;
 	__u64 mid;
-	__u32 len = get_rfc1002_length(buf);
 	__u32 clc_len;  /* calculated length */
 	int command;
-
-	/* BB disable following printk later */
-	cifs_dbg(FYI, "%s length: 0x%x, smb_buf_length: 0x%x\n",
-		 __func__, length, len);
+	int pdu_size = sizeof(struct smb2_sync_pdu);
+	int hdr_size = sizeof(struct smb2_sync_hdr);
 
 	/*
 	 * Add function to do table lookup of StructureSize by command
 	 * ie Validate the wct via smb2_struct_sizes table above
 	 */
-
 	if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
 		struct smb2_transform_hdr *thdr =
 			(struct smb2_transform_hdr *)buf;
@@ -136,8 +131,8 @@  smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
 	}
 
 	mid = le64_to_cpu(shdr->MessageId);
-	if (length < sizeof(struct smb2_pdu)) {
-		if ((length >= sizeof(struct smb2_hdr))
+	if (len < pdu_size) {
+		if ((len >= hdr_size)
 		    && (shdr->Status != 0)) {
 			pdu->StructureSize2 = 0;
 			/*
@@ -190,13 +185,7 @@  smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
 		}
 	}
 
-	if (srvr->vals->header_preamble_size + len != length) {
-		cifs_dbg(VFS, "Total length %u RFC1002 length %u mismatch mid %llu\n",
-			 length, srvr->vals->header_preamble_size + len, mid);
-		return 1;
-	}
-
-	clc_len = smb2_calc_size(hdr);
+	clc_len = smb2_calc_size(buf);
 
 	if (srvr->vals->header_preamble_size + len != clc_len) {
 		cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
@@ -206,7 +195,7 @@  smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
 		    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 == len && command == SMB2_OPLOCK_BREAK_HE)
 			return 0;
 		/* server can return one byte more due to implied bcc[0] */
 		if (clc_len == srvr->vals->header_preamble_size + len + 1)
@@ -263,15 +252,14 @@  static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
  * area and the offset to it (from the beginning of the smb are also returned.
  */
 char *
-smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
+smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr)
 {
-	struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
 	*off = 0;
 	*len = 0;
 
 	/* error responses do not have data area */
 	if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
-	    (((struct smb2_err_rsp *)hdr)->StructureSize) ==
+	    (((struct smb2_err_rsp *)shdr)->StructureSize) ==
 						SMB2_ERROR_STRUCTURE_SIZE2)
 		return NULL;
 
@@ -283,42 +271,44 @@  smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
 	switch (shdr->Command) {
 	case SMB2_NEGOTIATE:
 		*off = le16_to_cpu(
-		    ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset);
+		  ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset);
 		*len = le16_to_cpu(
-		    ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferLength);
+		  ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength);
 		break;
 	case SMB2_SESSION_SETUP:
 		*off = le16_to_cpu(
-		    ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferOffset);
+		  ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset);
 		*len = le16_to_cpu(
-		    ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferLength);
+		  ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength);
 		break;
 	case SMB2_CREATE:
 		*off = le32_to_cpu(
-		    ((struct smb2_create_rsp *)hdr)->CreateContextsOffset);
+		    ((struct smb2_create_rsp *)shdr)->CreateContextsOffset);
 		*len = le32_to_cpu(
-		    ((struct smb2_create_rsp *)hdr)->CreateContextsLength);
+		    ((struct smb2_create_rsp *)shdr)->CreateContextsLength);
 		break;
 	case SMB2_QUERY_INFO:
 		*off = le16_to_cpu(
-		    ((struct smb2_query_info_rsp *)hdr)->OutputBufferOffset);
+		    ((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset);
 		*len = le32_to_cpu(
-		    ((struct smb2_query_info_rsp *)hdr)->OutputBufferLength);
+		    ((struct smb2_query_info_rsp *)shdr)->OutputBufferLength);
 		break;
 	case SMB2_READ:
-		*off = ((struct smb2_read_rsp *)hdr)->DataOffset;
-		*len = le32_to_cpu(((struct smb2_read_rsp *)hdr)->DataLength);
+		/* TODO: is this a bug ? */
+		*off = ((struct smb2_read_rsp *)shdr)->DataOffset;
+		*len = le32_to_cpu(((struct smb2_read_rsp *)shdr)->DataLength);
 		break;
 	case SMB2_QUERY_DIRECTORY:
 		*off = le16_to_cpu(
-		  ((struct smb2_query_directory_rsp *)hdr)->OutputBufferOffset);
+		  ((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset);
 		*len = le32_to_cpu(
-		  ((struct smb2_query_directory_rsp *)hdr)->OutputBufferLength);
+		  ((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength);
 		break;
 	case SMB2_IOCTL:
 		*off = le32_to_cpu(
-		  ((struct smb2_ioctl_rsp *)hdr)->OutputOffset);
-		*len = le32_to_cpu(((struct smb2_ioctl_rsp *)hdr)->OutputCount);
+		  ((struct smb2_ioctl_rsp *)shdr)->OutputOffset);
+		*len = le32_to_cpu(
+		  ((struct smb2_ioctl_rsp *)shdr)->OutputCount);
 		break;
 	case SMB2_CHANGE_NOTIFY:
 	default:
@@ -363,13 +353,12 @@  smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
 unsigned int
 smb2_calc_size(void *buf)
 {
-	struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
-	struct smb2_hdr *hdr = &pdu->hdr;
-	struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
+	struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)buf;
+	struct smb2_sync_hdr *shdr = &pdu->sync_hdr;
 	int offset; /* the offset from the beginning of SMB to data area */
 	int data_length; /* the length of the variable length data area */
 	/* Structure Size has already been checked to make sure it is 64 */
-	int len = 4 + le16_to_cpu(shdr->StructureSize);
+	int len = le16_to_cpu(shdr->StructureSize);
 
 	/*
 	 * StructureSize2, ie length of fixed parameter area has already
@@ -380,7 +369,7 @@  smb2_calc_size(void *buf)
 	if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false)
 		goto calc_size_exit;
 
-	smb2_get_data_area_len(&offset, &data_length, hdr);
+	smb2_get_data_area_len(&offset, &data_length, shdr);
 	cifs_dbg(FYI, "SMB2 data length %d offset %d\n", data_length, offset);
 
 	if (data_length > 0) {
@@ -388,15 +377,14 @@  smb2_calc_size(void *buf)
 		 * Check to make sure that data area begins after fixed area,
 		 * Note that last byte of the fixed area is part of data area
 		 * for some commands, typically those with odd StructureSize,
-		 * so we must add one to the calculation (and 4 to account for
-		 * the size of the RFC1001 hdr.
+		 * so we must add one to the calculation.
 		 */
-		if (offset + 4 + 1 < len) {
+		if (offset + 1 < len) {
 			cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d\n",
-				 offset + 4 + 1, len);
+				 offset + 1, len);
 			data_length = 0;
 		} else {
-			len = 4 + offset + data_length;
+			len = offset + data_length;
 		}
 	}
 calc_size_exit:
@@ -579,7 +567,7 @@  smb2_is_valid_lease_break(char *buffer)
 bool
 smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
 {
-	struct smb2_oplock_break_rsp *rsp = (struct smb2_oplock_break_rsp *)buffer;
+	struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer;
 	struct list_head *tmp, *tmp1, *tmp2;
 	struct cifs_ses *ses;
 	struct cifs_tcon *tcon;
@@ -588,7 +576,7 @@  smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
 
 	cifs_dbg(FYI, "Checking for oplock break\n");
 
-	if (rsp->hdr.sync_hdr.Command != SMB2_OPLOCK_BREAK)
+	if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK)
 		return false;
 
 	if (rsp->StructureSize !=
@@ -679,8 +667,8 @@  smb2_cancelled_close_fid(struct work_struct *work)
 int
 smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
 {
-	struct smb2_sync_hdr *sync_hdr = get_sync_hdr(buffer);
-	struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer;
+	struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer;
+	struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)sync_hdr;
 	struct cifs_tcon *tcon;
 	struct close_cancelled_open *cancelled;
 
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 09d3a2912869..48ee237c3fdf 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -123,7 +123,8 @@  smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
 static unsigned int
 smb2_get_credits(struct mid_q_entry *mid)
 {
-	struct smb2_sync_hdr *shdr = get_sync_hdr(mid->resp_buf);
+	char *buf = mid->resp_buf;
+	struct smb2_sync_hdr *shdr  = (struct smb2_sync_hdr *)buf;
 
 	return le16_to_cpu(shdr->CreditRequest);
 }
@@ -190,7 +191,7 @@  static struct mid_q_entry *
 smb2_find_mid(struct TCP_Server_Info *server, char *buf)
 {
 	struct mid_q_entry *mid;
-	struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
+	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
 	__u64 wire_mid = le64_to_cpu(shdr->MessageId);
 
 	if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
@@ -215,7 +216,7 @@  static void
 smb2_dump_detail(void *buf)
 {
 #ifdef CONFIG_CIFS_DEBUG2
-	struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
+	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
 
 	cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n",
 		 shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId,
@@ -1241,7 +1242,7 @@  smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
 static bool
 smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
 {
-	struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
+	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
 
 	if (shdr->Status != STATUS_PENDING)
 		return false;
@@ -1259,7 +1260,7 @@  smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
 static bool
 smb2_is_session_expired(char *buf)
 {
-	struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
+	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
 
 	if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED)
 		return false;
@@ -1451,6 +1452,7 @@  smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 	__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
 	struct cifs_open_parms oparms;
 	struct cifs_fid fid;
+	struct kvec err_iov = {NULL, 0};
 	struct smb2_err_rsp *err_buf = NULL;
 	struct smb2_symlink_err_rsp *symlink;
 	unsigned int sub_len;
@@ -1473,15 +1475,16 @@  smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 	oparms.fid = &fid;
 	oparms.reconnect = false;
 
-	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_buf);
+	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov);
 
 	if (!rc || !err_buf) {
 		kfree(utf16_path);
 		return -ENOENT;
 	}
 
+	err_buf = err_iov.iov_base;
 	if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
-	    get_rfc1002_length(err_buf) + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
+	    err_iov.iov_len + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
 		kfree(utf16_path);
 		return -ENOENT;
 	}
@@ -1494,13 +1497,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) + server->vals->header_preamble_size <
+	if (err_iov.iov_len + server->vals->header_preamble_size <
 			SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
 		kfree(utf16_path);
 		return -ENOENT;
 	}
 
-	if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size <
+	if (err_iov.iov_len + server->vals->header_preamble_size <
 			SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
 		kfree(utf16_path);
 		return -ENOENT;
@@ -2052,12 +2055,11 @@  smb2_dir_needs_close(struct cifsFileInfo *cfile)
 }
 
 static void
-fill_transform_hdr(struct TCP_Server_Info *server,
-		   struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
+fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
+		   struct smb_rqst *old_rq)
 {
 	struct smb2_sync_hdr *shdr =
 			(struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base;
-	unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base);
 
 	memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr));
 	tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
@@ -2065,8 +2067,6 @@  fill_transform_hdr(struct TCP_Server_Info *server,
 	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) - server->vals->header_preamble_size);
-	inc_rfc1001_len(tr_hdr, orig_len);
 }
 
 /* We can not use the normal sg_set_buf() as we will sometimes pass a
@@ -2078,11 +2078,16 @@  static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
 	sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
 }
 
+/* Assumes:
+ * rqst->rq_iov[0]  is rfc1002 length
+ * rqst->rq_iov[1]  is tranform header
+ * rqst->rq_iov[2+] data to be encrypted/decrypted
+ */
 static struct scatterlist *
 init_sg(struct smb_rqst *rqst, u8 *sign)
 {
-	unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages + 1;
-	unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
+	unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages;
+	unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
 	struct scatterlist *sg;
 	unsigned int i;
 	unsigned int j;
@@ -2092,10 +2097,10 @@  init_sg(struct smb_rqst *rqst, u8 *sign)
 		return NULL;
 
 	sg_init_table(sg, sg_len);
-	smb2_sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 24, assoc_data_len);
-	for (i = 1; i < rqst->rq_nvec; i++)
-		smb2_sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base,
-						rqst->rq_iov[i].iov_len);
+	smb2_sg_set_buf(&sg[0], rqst->rq_iov[1].iov_base + 20, assoc_data_len);
+	for (i = 1; i < rqst->rq_nvec - 1; i++)
+		smb2_sg_set_buf(&sg[i], rqst->rq_iov[i+1].iov_base,
+						rqst->rq_iov[i+1].iov_len);
 	for (j = 0; i < sg_len - 1; i++, j++) {
 		unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz
 							: rqst->rq_tailsz;
@@ -2127,17 +2132,18 @@  smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
 }
 /*
  * Encrypt or decrypt @rqst message. @rqst has the following format:
- * iov[0] - transform header (associate data),
- * iov[1-N] and pages - data to encrypt.
- * On success return encrypted data in iov[1-N] and pages, leave iov[0]
+ * iov[0] - rfc1002 length
+ * iov[1] - transform header (associate data),
+ * iov[2-N] and pages - data to encrypt.
+ * On success return encrypted data in iov[2-N] and pages, leave iov[0-1]
  * untouched.
  */
 static int
 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;
+			(struct smb2_transform_hdr *)rqst->rq_iov[1].iov_base;
+	unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
 	int rc = 0;
 	struct scatterlist *sg;
 	u8 sign[SMB2_SIGNATURE_SIZE] = {};
@@ -2224,6 +2230,9 @@  crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
 	return rc;
 }
 
+/* This is called from smb_send_rqst. At this point we have the rfc1002
+ * header as the first element in the vector.
+ */
 static int
 smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
 		       struct smb_rqst *old_rq)
@@ -2232,6 +2241,7 @@  smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
 	struct page **pages;
 	struct smb2_transform_hdr *tr_hdr;
 	unsigned int npages = old_rq->rq_npages;
+	unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base);
 	int i;
 	int rc = -ENOMEM;
 
@@ -2250,24 +2260,34 @@  smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
 			goto err_free_pages;
 	}
 
-	iov = kmalloc_array(old_rq->rq_nvec, sizeof(struct kvec), GFP_KERNEL);
+	/* Make space for one extra iov to hold the transform header */
+	iov = kmalloc_array(old_rq->rq_nvec + 1, sizeof(struct kvec),
+			    GFP_KERNEL);
 	if (!iov)
 		goto err_free_pages;
 
 	/* copy all iovs from the old except the 1st one (rfc1002 length) */
-	memcpy(&iov[1], &old_rq->rq_iov[1],
+	memcpy(&iov[2], &old_rq->rq_iov[1],
 				sizeof(struct kvec) * (old_rq->rq_nvec - 1));
+	/* copy the rfc1002 iov */
+	iov[0].iov_base = old_rq->rq_iov[0].iov_base;
+	iov[0].iov_len  = old_rq->rq_iov[0].iov_len;
+
 	new_rq->rq_iov = iov;
-	new_rq->rq_nvec = old_rq->rq_nvec;
+	new_rq->rq_nvec = old_rq->rq_nvec + 1;
 
 	tr_hdr = kmalloc(sizeof(struct smb2_transform_hdr), GFP_KERNEL);
 	if (!tr_hdr)
 		goto err_free_iov;
 
-	/* fill the 1st iov with a transform header */
-	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);
+	/* fill the 2nd iov with a transform header */
+	fill_transform_hdr(tr_hdr, orig_len, old_rq);
+	new_rq->rq_iov[1].iov_base = tr_hdr;
+	new_rq->rq_iov[1].iov_len = sizeof(struct smb2_transform_hdr);
+
+	/* Update rfc1002 header */
+	inc_rfc1001_len(new_rq->rq_iov[0].iov_base,
+			sizeof(struct smb2_transform_hdr));
 
 	/* copy pages form the old */
 	for (i = 0; i < npages; i++) {
@@ -2307,7 +2327,7 @@  smb3_free_transform_rq(struct smb_rqst *rqst)
 		put_page(rqst->rq_pages[i]);
 	kfree(rqst->rq_pages);
 	/* free transform header */
-	kfree(rqst->rq_iov[0].iov_base);
+	kfree(rqst->rq_iov[1].iov_base);
 	kfree(rqst->rq_iov);
 }
 
@@ -2324,18 +2344,19 @@  decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
 		 unsigned int buf_data_size, struct page **pages,
 		 unsigned int npages, unsigned int page_data_size)
 {
-	struct kvec iov[2];
+	struct kvec iov[3];
 	struct smb_rqst rqst = {NULL};
-	struct smb2_hdr *hdr;
 	int rc;
 
-	iov[0].iov_base = buf;
-	iov[0].iov_len = sizeof(struct smb2_transform_hdr);
-	iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr);
-	iov[1].iov_len = buf_data_size;
+	iov[0].iov_base = NULL;
+	iov[0].iov_len = 0;
+	iov[1].iov_base = buf;
+	iov[1].iov_len = sizeof(struct smb2_transform_hdr);
+	iov[2].iov_base = buf + sizeof(struct smb2_transform_hdr);
+	iov[2].iov_len = buf_data_size;
 
 	rqst.rq_iov = iov;
-	rqst.rq_nvec = 2;
+	rqst.rq_nvec = 3;
 	rqst.rq_pages = pages;
 	rqst.rq_npages = npages;
 	rqst.rq_pagesz = PAGE_SIZE;
@@ -2347,10 +2368,9 @@  decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
 	if (rc)
 		return rc;
 
-	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 + server->vals->header_preamble_size;
+	memmove(buf + server->vals->header_preamble_size, iov[2].iov_base, buf_data_size);
+
+	server->total_read = buf_data_size + page_data_size;
 
 	return rc;
 }
@@ -2423,7 +2443,7 @@  handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
 	unsigned int cur_page_idx;
 	unsigned int pad_len;
 	struct cifs_readdata *rdata = mid->callback_data;
-	struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
+	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
 	struct bio_vec *bvec = NULL;
 	struct iov_iter iter;
 	struct kvec iov;
@@ -2550,7 +2570,7 @@  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) + server->vals->header_preamble_size;
+	unsigned int buflen = server->pdu_size + server->vals->header_preamble_size;
 	int rc;
 	int i = 0;
 
@@ -2624,7 +2644,7 @@  receive_encrypted_standard(struct TCP_Server_Info *server,
 {
 	int length;
 	char *buf = server->smallbuf;
-	unsigned int pdu_length = get_rfc1002_length(buf);
+	unsigned int pdu_length = server->pdu_size;
 	unsigned int buf_size;
 	struct mid_q_entry *mid_entry;
 
@@ -2668,7 +2688,7 @@  static int
 smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
 {
 	char *buf = server->smallbuf;
-	unsigned int pdu_length = get_rfc1002_length(buf);
+	unsigned int pdu_length = server->pdu_size;
 	struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
 	unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
 
@@ -2699,7 +2719,7 @@  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) +
+	return handle_read_data(server, mid, buf, server->total_read +
 				server->vals->header_preamble_size,
 				NULL, 0, 0);
 }
@@ -3104,8 +3124,8 @@  struct smb_version_values smb20_values = {
 	.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-	.header_size = sizeof(struct smb2_hdr),
-	.header_preamble_size = 4,
+	.header_size = sizeof(struct smb2_sync_hdr),
+	.header_preamble_size = 0,
 	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 	.lock_cmd = SMB2_LOCK,
@@ -3125,8 +3145,8 @@  struct smb_version_values smb21_values = {
 	.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-	.header_size = sizeof(struct smb2_hdr),
-	.header_preamble_size = 4,
+	.header_size = sizeof(struct smb2_sync_hdr),
+	.header_preamble_size = 0,
 	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 	.lock_cmd = SMB2_LOCK,
@@ -3146,8 +3166,8 @@  struct smb_version_values smb3any_values = {
 	.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-	.header_size = sizeof(struct smb2_hdr),
-	.header_preamble_size = 4,
+	.header_size = sizeof(struct smb2_sync_hdr),
+	.header_preamble_size = 0,
 	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 	.lock_cmd = SMB2_LOCK,
@@ -3167,8 +3187,8 @@  struct smb_version_values smbdefault_values = {
 	.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-	.header_size = sizeof(struct smb2_hdr),
-	.header_preamble_size = 4,
+	.header_size = sizeof(struct smb2_sync_hdr),
+	.header_preamble_size = 0,
 	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 	.lock_cmd = SMB2_LOCK,
@@ -3188,8 +3208,8 @@  struct smb_version_values smb30_values = {
 	.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-	.header_size = sizeof(struct smb2_hdr),
-	.header_preamble_size = 4,
+	.header_size = sizeof(struct smb2_sync_hdr),
+	.header_preamble_size = 0,
 	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 	.lock_cmd = SMB2_LOCK,
@@ -3209,8 +3229,8 @@  struct smb_version_values smb302_values = {
 	.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-	.header_size = sizeof(struct smb2_hdr),
-	.header_preamble_size = 4,
+	.header_size = sizeof(struct smb2_sync_hdr),
+	.header_preamble_size = 0,
 	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 	.lock_cmd = SMB2_LOCK,
@@ -3231,8 +3251,8 @@  struct smb_version_values smb311_values = {
 	.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
 	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-	.header_size = sizeof(struct smb2_hdr),
-	.header_preamble_size = 4,
+	.header_size = sizeof(struct smb2_sync_hdr),
+	.header_preamble_size = 0,
 	.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..b20348f72a6f 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -591,7 +591,7 @@  SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
 	server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
 
 	security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
-					       &rsp->hdr);
+					       (struct smb2_sync_hdr *)rsp);
 	/*
 	 * See MS-SMB2 section 2.2.4: if no blob, client picks default which
 	 * for us will be
@@ -942,7 +942,7 @@  SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
 		goto out_put_spnego_key;
 
 	rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
-	ses->Suid = rsp->hdr.sync_hdr.SessionId;
+	ses->Suid = rsp->sync_hdr.SessionId;
 
 	ses->session_flags = le16_to_cpu(rsp->SessionFlags);
 
@@ -1018,13 +1018,13 @@  SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
 
 	/* If true, rc here is expected and not an error */
 	if (sess_data->buf0_type != CIFS_NO_BUFFER &&
-		rsp->hdr.sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
+		rsp->sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
 		rc = 0;
 
 	if (rc)
 		goto out;
 
-	if (offsetof(struct smb2_sess_setup_rsp, Buffer) - 4 !=
+	if (offsetof(struct smb2_sess_setup_rsp, Buffer) !=
 			le16_to_cpu(rsp->SecurityBufferOffset)) {
 		cifs_dbg(VFS, "Invalid security buffer offset %d\n",
 			le16_to_cpu(rsp->SecurityBufferOffset));
@@ -1039,7 +1039,7 @@  SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
 	cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
 
 
-	ses->Suid = rsp->hdr.sync_hdr.SessionId;
+	ses->Suid = rsp->sync_hdr.SessionId;
 	ses->session_flags = le16_to_cpu(rsp->SessionFlags);
 
 out:
@@ -1097,7 +1097,7 @@  SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
 
 	rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
 
-	ses->Suid = rsp->hdr.sync_hdr.SessionId;
+	ses->Suid = rsp->sync_hdr.SessionId;
 	ses->session_flags = le16_to_cpu(rsp->SessionFlags);
 
 	rc = SMB2_sess_establish_session(sess_data);
@@ -1340,7 +1340,7 @@  SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
 	tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess);
 	tcon->tidStatus = CifsGood;
 	tcon->need_reconnect = false;
-	tcon->tid = rsp->hdr.sync_hdr.TreeId;
+	tcon->tid = rsp->sync_hdr.TreeId;
 	strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
 
 	if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
@@ -1360,7 +1360,7 @@  SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
 	return rc;
 
 tcon_error_exit:
-	if (rsp && rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
+	if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
 		cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
 	}
 	goto tcon_exit;
@@ -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 + le32_to_cpu(rsp->CreateContextsOffset);
 	remaining = le32_to_cpu(rsp->CreateContextsLength);
 	cc = (struct create_context *)data_offset;
 	while (remaining >= sizeof(struct create_context)) {
@@ -1694,7 +1694,7 @@  alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
 int
 SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
 	  __u8 *oplock, struct smb2_file_all_info *buf,
-	  struct smb2_err_rsp **err_buf)
+	  struct kvec *err_iov)
 {
 	struct smb2_create_req *req;
 	struct smb2_create_rsp *rsp;
@@ -1834,9 +1834,10 @@  SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
 
 	if (rc != 0) {
 		cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
-		if (err_buf && rsp)
-			*err_buf = kmemdup(rsp, get_rfc1002_length(rsp) + 4,
-					   GFP_KERNEL);
+		if (err_iov && rsp) {
+			*err_iov = rsp_iov;
+			rsp = NULL;
+		}
 		goto creat_exit;
 	}
 
@@ -1875,7 +1876,6 @@  SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
 {
 	struct smb2_ioctl_req *req;
 	struct smb2_ioctl_rsp *rsp;
-	struct smb2_sync_hdr *shdr;
 	struct cifs_ses *ses;
 	struct kvec iov[2];
 	struct kvec rsp_iov;
@@ -1996,7 +1996,7 @@  SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
 		goto ioctl_exit;
 	}
 
-	if (get_rfc1002_length(rsp) < le32_to_cpu(rsp->OutputOffset) + *plen) {
+	if (rsp_iov.iov_len < le32_to_cpu(rsp->OutputOffset) + *plen) {
 		cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen,
 			le32_to_cpu(rsp->OutputOffset));
 		*plen = 0;
@@ -2010,8 +2010,7 @@  SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
 		goto ioctl_exit;
 	}
 
-	shdr = get_sync_hdr(rsp);
-	memcpy(*out_data, (char *)shdr + le32_to_cpu(rsp->OutputOffset), *plen);
+	memcpy(*out_data, (char *)rsp + le32_to_cpu(rsp->OutputOffset), *plen);
 ioctl_exit:
 	free_rsp_buf(resp_buftype, rsp);
 	return rc;
@@ -2091,13 +2090,12 @@  SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
 }
 
 static int
-validate_buf(unsigned int offset, unsigned int buffer_length,
-	     struct smb2_hdr *hdr, unsigned int min_buf_size)
-
+validate_iov(unsigned int offset, unsigned int buffer_length,
+	     struct kvec *iov, unsigned int min_buf_size)
 {
-	unsigned int smb_len = be32_to_cpu(hdr->smb2_buf_length);
-	char *end_of_smb = smb_len + 4 /* RFC1001 length field */ + (char *)hdr;
-	char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr;
+	unsigned int smb_len = iov->iov_len;
+	char *end_of_smb = smb_len + (char *)iov->iov_base;
+	char *begin_of_buf = offset + (char *)iov->iov_base;
 	char *end_of_buf = begin_of_buf + buffer_length;
 
 
@@ -2127,18 +2125,17 @@  validate_buf(unsigned int offset, unsigned int buffer_length,
  * Caller must free buffer.
  */
 static int
-validate_and_copy_buf(unsigned int offset, unsigned int buffer_length,
-		      struct smb2_hdr *hdr, unsigned int minbufsize,
+validate_and_copy_iov(unsigned int offset, unsigned int buffer_length,
+		      struct kvec *iov, unsigned int minbufsize,
 		      char *data)
-
 {
-	char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr;
+	char *begin_of_buf = offset + (char *)iov->iov_base;
 	int rc;
 
 	if (!data)
 		return -EINVAL;
 
-	rc = validate_buf(offset, buffer_length, hdr, minbufsize);
+	rc = validate_iov(offset, buffer_length, iov, minbufsize);
 	if (rc)
 		return rc;
 
@@ -2216,9 +2213,9 @@  query_info(const unsigned int xid, struct cifs_tcon *tcon,
 		}
 	}
 
-	rc = validate_and_copy_buf(le16_to_cpu(rsp->OutputBufferOffset),
+	rc = validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset),
 				   le32_to_cpu(rsp->OutputBufferLength),
-				   &rsp->hdr, min_len, *data);
+				   &rsp_iov, min_len, *data);
 
 qinf_exit:
 	free_rsp_buf(resp_buftype, rsp);
@@ -2287,7 +2284,7 @@  smb2_echo_callback(struct mid_q_entry *mid)
 	unsigned int credits_received = 1;
 
 	if (mid->mid_state == MID_RESPONSE_RECEIVED)
-		credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest);
+		credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
 
 	DeleteMidQEntry(mid);
 	add_credits(server, credits_received, CIFS_ECHO_OP);
@@ -2684,7 +2681,6 @@  SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
 	int resp_buftype, rc = -EACCES;
 	struct smb2_read_plain_req *req = NULL;
 	struct smb2_read_rsp *rsp = NULL;
-	struct smb2_sync_hdr *shdr;
 	struct kvec iov[1];
 	struct kvec rsp_iov;
 	unsigned int total_len;
@@ -2725,10 +2721,8 @@  SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
 		*nbytes = 0;
 	}
 
-	shdr = get_sync_hdr(rsp);
-
 	if (*buf) {
-		memcpy(*buf, (char *)shdr + rsp->DataOffset, *nbytes);
+		memcpy(*buf, (char *)rsp + rsp->DataOffset, *nbytes);
 		free_rsp_buf(resp_buftype, rsp_iov.iov_base);
 	} else if (resp_buftype != CIFS_NO_BUFFER) {
 		*buf = rsp_iov.iov_base;
@@ -2755,7 +2749,7 @@  smb2_writev_callback(struct mid_q_entry *mid)
 
 	switch (mid->mid_state) {
 	case MID_RESPONSE_RECEIVED:
-		credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest);
+		credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
 		wdata->result = smb2_check_receive(mid, tcon->ses->server, 0);
 		if (wdata->result != 0)
 			break;
@@ -3131,7 +3125,7 @@  SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
 
 	if (rc) {
 		if (rc == -ENODATA &&
-		    rsp->hdr.sync_hdr.Status == STATUS_NO_MORE_FILES) {
+		    rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) {
 			srch_inf->endOfSearch = true;
 			rc = 0;
 		}
@@ -3139,8 +3133,8 @@  SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
 		goto qdir_exit;
 	}
 
-	rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset),
-			  le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr,
+	rc = validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
+			  le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
 			  info_buf_size);
 	if (rc)
 		goto qdir_exit;
@@ -3154,10 +3148,9 @@  SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
 			cifs_buf_release(srch_inf->ntwrk_buf_start);
 	}
 	srch_inf->ntwrk_buf_start = (char *)rsp;
-	srch_inf->srch_entries_start = srch_inf->last_entry = 4 /* rfclen */ +
-		(char *)&rsp->hdr + le16_to_cpu(rsp->OutputBufferOffset);
-	/* 4 for rfc1002 length field */
-	end_of_smb = get_rfc1002_length(rsp) + 4 + (char *)&rsp->hdr;
+	srch_inf->srch_entries_start = srch_inf->last_entry =
+		(char *)rsp + le16_to_cpu(rsp->OutputBufferOffset);
+	end_of_smb = rsp_iov.iov_len + (char *)rsp;
 	srch_inf->entries_in_buffer =
 			num_entries(srch_inf->srch_entries_start, end_of_smb,
 				    &srch_inf->last_entry, info_buf_size);
@@ -3393,7 +3386,7 @@  SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
 		  __u8 oplock_level)
 {
 	int rc;
-	struct smb2_oplock_break_req *req = NULL;
+	struct smb2_oplock_break *req = NULL;
 	struct cifs_ses *ses = tcon->ses;
 	int flags = CIFS_OBREAK_OP;
 	unsigned int total_len;
@@ -3469,7 +3462,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);
 
 	iov->iov_base = (char *)req;
 	iov->iov_len = total_len;
@@ -3506,10 +3499,10 @@  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 */ +
-		le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr);
-	rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset),
-			  le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr,
+	info = (struct smb2_fs_full_size_info *)(
+		le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
+	rc = validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
+			  le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
 			  sizeof(struct smb2_fs_full_size_info));
 	if (!rc)
 		copy_fs_info_to_kstatfs(info, fsdata);
@@ -3564,20 +3557,20 @@  SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
 
 	rsp_len = le32_to_cpu(rsp->OutputBufferLength);
 	offset = le16_to_cpu(rsp->OutputBufferOffset);
-	rc = validate_buf(offset, rsp_len, &rsp->hdr, min_len);
+	rc = validate_iov(offset, rsp_len, &rsp_iov, min_len);
 	if (rc)
 		goto qfsattr_exit;
 
 	if (level == FS_ATTRIBUTE_INFORMATION)
-		memcpy(&tcon->fsAttrInfo, 4 /* RFC1001 len */ + offset
-			+ (char *)&rsp->hdr, min_t(unsigned int,
+		memcpy(&tcon->fsAttrInfo, offset
+			+ (char *)rsp, min_t(unsigned int,
 			rsp_len, max_len));
 	else if (level == FS_DEVICE_INFORMATION)
-		memcpy(&tcon->fsDevInfo, 4 /* RFC1001 len */ + offset
-			+ (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO));
+		memcpy(&tcon->fsDevInfo, offset
+			+ (char *)rsp, 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);
+			(offset + (char *)rsp);
 		tcon->ss_flags = le32_to_cpu(ss_info->Flags);
 		tcon->perf_sector_size =
 			le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 8b901c69a65a..6bf243a45d64 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -122,25 +122,10 @@  struct smb2_sync_pdu {
 	__le16 StructureSize2; /* size of wct area (varies, request specific) */
 } __packed;
 
-struct smb2_hdr {
-	__be32 smb2_buf_length;	/* big endian on wire */
-				/* length is only two or three bytes - with */
-				/* one or two byte type preceding it that MBZ */
-	struct smb2_sync_hdr sync_hdr;
-} __packed;
-
-struct smb2_pdu {
-	struct smb2_hdr hdr;
-	__le16 StructureSize2; /* size of wct area (varies, request specific) */
-} __packed;
-
 #define SMB3_AES128CMM_NONCE 11
 #define SMB3_AES128GCM_NONCE 12
 
 struct smb2_transform_hdr {
-	__be32 smb2_buf_length;	/* big endian on wire */
-				/* length is only two or three bytes - with
-				 one or two byte type preceding it that MBZ */
 	__le32 ProtocolId;	/* 0xFD 'S' 'M' 'B' */
 	__u8   Signature[16];
 	__u8   Nonce[16];
@@ -171,7 +156,7 @@  struct smb2_transform_hdr {
 #define SMB2_ERROR_STRUCTURE_SIZE2 cpu_to_le16(9)
 
 struct smb2_err_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize;
 	__le16 Reserved; /* MBZ */
 	__le32 ByteCount;  /* even if zero, at least one byte follows */
@@ -289,7 +274,7 @@  struct smb2_encryption_neg_context {
 } __packed;
 
 struct smb2_negotiate_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize;	/* Must be 65 */
 	__le16 SecurityMode;
 	__le16 DialectRevision;
@@ -329,7 +314,7 @@  struct smb2_sess_setup_req {
 #define SMB2_SESSION_FLAG_IS_NULL	0x0002
 #define SMB2_SESSION_FLAG_ENCRYPT_DATA	0x0004
 struct smb2_sess_setup_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize; /* Must be 9 */
 	__le16 SessionFlags;
 	__le16 SecurityBufferOffset;
@@ -344,7 +329,7 @@  struct smb2_logoff_req {
 } __packed;
 
 struct smb2_logoff_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize;	/* Must be 4 */
 	__le16 Reserved;
 } __packed;
@@ -440,7 +425,7 @@  struct smb2_tree_connect_req_extension {
 } __packed;
 
 struct smb2_tree_connect_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize;	/* Must be 16 */
 	__u8   ShareType;  /* see below */
 	__u8   Reserved;
@@ -491,7 +476,7 @@  struct smb2_tree_disconnect_req {
 } __packed;
 
 struct smb2_tree_disconnect_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize;	/* Must be 4 */
 	__le16 Reserved;
 } __packed;
@@ -626,7 +611,7 @@  struct smb2_create_req {
 } __packed;
 
 struct smb2_create_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize;	/* Must be 89 */
 	__u8   OplockLevel;
 	__u8   Reserved;
@@ -882,7 +867,7 @@  struct smb2_ioctl_req {
 } __packed;
 
 struct smb2_ioctl_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize;	/* Must be 57 */
 	__u16 Reserved;
 	__le32 CtlCode;
@@ -909,7 +894,7 @@  struct smb2_close_req {
 } __packed;
 
 struct smb2_close_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize; /* 60 */
 	__le16 Flags;
 	__le32 Reserved;
@@ -932,7 +917,7 @@  struct smb2_flush_req {
 } __packed;
 
 struct smb2_flush_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize;
 	__le16 Reserved;
 } __packed;
@@ -964,7 +949,7 @@  struct smb2_read_plain_req {
 } __packed;
 
 struct smb2_read_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize; /* Must be 17 */
 	__u8   DataOffset;
 	__u8   Reserved;
@@ -995,7 +980,7 @@  struct smb2_write_req {
 } __packed;
 
 struct smb2_write_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize; /* Must be 17 */
 	__u8   DataOffset;
 	__u8   Reserved;
@@ -1029,7 +1014,7 @@  struct smb2_lock_req {
 } __packed;
 
 struct smb2_lock_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize; /* Must be 4 */
 	__le16 Reserved;
 } __packed;
@@ -1041,7 +1026,7 @@  struct smb2_echo_req {
 } __packed;
 
 struct smb2_echo_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize;	/* Must be 4 */
 	__u16  Reserved;
 } __packed;
@@ -1067,7 +1052,7 @@  struct smb2_query_directory_req {
 } __packed;
 
 struct smb2_query_directory_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize; /* Must be 9 */
 	__le16 OutputBufferOffset;
 	__le32 OutputBufferLength;
@@ -1116,7 +1101,7 @@  struct smb2_query_info_req {
 } __packed;
 
 struct smb2_query_info_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize; /* Must be 9 */
 	__le16 OutputBufferOffset;
 	__le32 OutputBufferLength;
@@ -1138,12 +1123,11 @@  struct smb2_set_info_req {
 } __packed;
 
 struct smb2_set_info_rsp {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize; /* Must be 2 */
 } __packed;
 
-/* oplock break without an rfc1002 header */
-struct smb2_oplock_break_req {
+struct smb2_oplock_break {
 	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize; /* Must be 24 */
 	__u8   OplockLevel;
@@ -1153,21 +1137,10 @@  struct smb2_oplock_break_req {
 	__u64  VolatileFid;
 } __packed;
 
-/* oplock break with an rfc1002 header */
-struct smb2_oplock_break_rsp {
-	struct smb2_hdr hdr;
-	__le16 StructureSize; /* Must be 24 */
-	__u8   OplockLevel;
-	__u8   Reserved;
-	__le32 Reserved2;
-	__u64  PersistentFid;
-	__u64  VolatileFid;
-} __packed;
-
 #define SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED cpu_to_le32(0x01)
 
 struct smb2_lease_break {
-	struct smb2_hdr hdr;
+	struct smb2_sync_hdr sync_hdr;
 	__le16 StructureSize; /* Must be 44 */
 	__le16 Reserved;
 	__le32 Flags;
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index cbcce3f7e86f..30cdc0aa4e8e 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -37,7 +37,8 @@  extern int map_smb2_to_linux_error(char *buf, bool log_err);
 extern int smb2_check_message(char *buf, unsigned int length,
 			      struct TCP_Server_Info *server);
 extern unsigned int smb2_calc_size(void *buf);
-extern char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr);
+extern char *smb2_get_data_area_len(int *off, int *len,
+				    struct smb2_sync_hdr *shdr);
 extern __le16 *cifs_convert_path_to_utf16(const char *from,
 					  struct cifs_sb_info *cifs_sb);
 
@@ -122,7 +123,7 @@  extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
 extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
 		     __le16 *path, __u8 *oplock,
 		     struct smb2_file_all_info *buf,
-		     struct smb2_err_rsp **err_buf);
+		     struct kvec *err_iov);
 extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
 		     u64 persistent_fid, u64 volatile_fid, u32 opcode,
 		     bool is_fsctl, char *in_data, u32 indatalen,
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index bf49cb73b9e6..8372a0cecdb0 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -480,7 +480,7 @@  smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 	unsigned int rc;
 	char server_response_sig[16];
 	struct smb2_sync_hdr *shdr =
-			(struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
+			(struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
 
 	if ((shdr->Command == SMB2_NEGOTIATE) ||
 	    (shdr->Command == SMB2_SESSION_SETUP) ||
@@ -604,15 +604,13 @@  int
 smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 		   bool log_error)
 {
-	unsigned int len = get_rfc1002_length(mid->resp_buf);
-	struct kvec iov[2];
+	unsigned int len = server->total_read;
+	struct kvec iov[1];
 	struct smb_rqst rqst = { .rq_iov = iov,
-				 .rq_nvec = 2 };
+				 .rq_nvec = 1 };
 
 	iov[0].iov_base = (char *)mid->resp_buf;
-	iov[0].iov_len = 4;
-	iov[1].iov_base = (char *)mid->resp_buf + 4;
-	iov[1].iov_len = len;
+	iov[0].iov_len = mid->resp_buf_size;
 
 	dump_smb(mid->resp_buf, min_t(u32, 80, len));
 	/* convert the length into a more usable form */
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 279718dcb2ed..3abce580b056 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -790,8 +790,9 @@  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) +
+	resp_iov->iov_len = midQ->resp_buf_size +
 		ses->server->vals->header_preamble_size;
+
 	if (midQ->large_buf)
 		*resp_buf_type = CIFS_LARGE_BUFFER;
 	else