-- Best regards, Pavel Shilovsky 2018-03-21 21:23 GMT-07:00 Ronnie Sahlberg <lsahlber@xxxxxxxxxx>: > 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@xxxxxxxxxx> > --- > 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@xxxxxxxxxxxxxxx > 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@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html