Message ID | 20180322042407.7599-3-lsahlber@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
-- 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
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 --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
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(-)