On Tue, Mar 27, 2018 at 9:10 AM, Pavel Shilovsky <piastryyy@xxxxxxxxx> wrote: > -- > Best regards, > Pavel Shilovsky > > > 2018-03-21 21:23 GMT-07:00 Ronnie Sahlberg <lsahlber@xxxxxxxxxx>: >> Separate out all the 4 byte rfc1002 headers so that they are no longer >> part of the SMB2 header structures to prepare for future work to add >> compounding support. >> >> Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> >> --- >> fs/cifs/cifsglob.h | 3 + >> fs/cifs/cifssmb.c | 2 +- >> fs/cifs/connect.c | 10 +++- >> fs/cifs/misc.c | 2 +- >> fs/cifs/smb2glob.h | 5 -- >> fs/cifs/smb2maperror.c | 2 +- >> fs/cifs/smb2misc.c | 90 +++++++++++++---------------- >> fs/cifs/smb2ops.c | 146 +++++++++++++++++++++++++++--------------------- >> fs/cifs/smb2pdu.c | 103 ++++++++++++++++------------------ >> fs/cifs/smb2pdu.h | 65 +++++++-------------- >> fs/cifs/smb2proto.h | 5 +- >> fs/cifs/smb2transport.c | 12 ++-- >> fs/cifs/transport.c | 3 +- >> 13 files changed, 213 insertions(+), 235 deletions(-) >> >> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h >> index 3e3f86841372..0045d85ec76d 100644 >> --- a/fs/cifs/cifsglob.h >> +++ b/fs/cifs/cifsglob.h >> @@ -665,6 +665,8 @@ struct TCP_Server_Info { >> struct delayed_work echo; /* echo ping workqueue job */ >> char *smallbuf; /* pointer to current "small" buffer */ >> char *bigbuf; /* pointer to current "big" buffer */ >> + /* Total size of this PDU. Only valid from cifs_demultiplex_thread */ >> + unsigned int pdu_size; >> unsigned int total_read; /* total amount of data read in this pass */ >> #ifdef CONFIG_CIFS_FSCACHE >> struct fscache_cookie *fscache; /* client index cache cookie */ >> @@ -1373,6 +1375,7 @@ struct mid_q_entry { >> mid_handle_t *handle; /* call handle mid callback */ >> void *callback_data; /* general purpose pointer for callback */ >> void *resp_buf; /* pointer to received SMB header */ >> + unsigned int resp_buf_size; >> int mid_state; /* wish this were enum but can not pass to wait_event */ >> unsigned int mid_flags; >> __le16 command; /* smb command code */ >> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c >> index 59c09a596c0a..991e9d9ef90a 100644 >> --- a/fs/cifs/cifssmb.c >> +++ b/fs/cifs/cifssmb.c >> @@ -1454,7 +1454,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) >> unsigned int data_offset, data_len; >> struct cifs_readdata *rdata = mid->callback_data; >> char *buf = server->smallbuf; >> - unsigned int buflen = get_rfc1002_length(buf) + >> + unsigned int buflen = server->pdu_size + >> server->vals->header_preamble_size; >> bool use_rdma_mr = false; >> >> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c >> index 1f2e3b15b2b1..0fad48d081d8 100644 >> --- a/fs/cifs/connect.c >> +++ b/fs/cifs/connect.c >> @@ -772,7 +772,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) >> { >> int length; >> char *buf = server->smallbuf; >> - unsigned int pdu_length = get_rfc1002_length(buf); >> + unsigned int pdu_length = server->pdu_size; >> >> /* make sure this will fit in a large buffer */ >> if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - >> @@ -874,13 +874,18 @@ cifs_demultiplex_thread(void *p) >> length = cifs_read_from_socket(server, buf, pdu_length); >> if (length < 0) >> continue; >> - server->total_read = length; >> + >> + if (server->vals->header_preamble_size == 0) >> + server->total_read = 0; >> + else >> + server->total_read = length; >> >> /* >> * The right amount was read from socket - 4 bytes, >> * so we can now interpret the length field. >> */ >> pdu_length = get_rfc1002_length(buf); >> + server->pdu_size = pdu_length; >> >> cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length); >> if (!is_smb_response(server, buf[0])) >> @@ -927,6 +932,7 @@ cifs_demultiplex_thread(void *p) >> >> server->lstrp = jiffies; >> if (mid_entry != NULL) { >> + mid_entry->resp_buf_size = server->pdu_size; >> if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) && >> mid_entry->mid_state == MID_RESPONSE_RECEIVED && >> server->ops->handle_cancelled_mid) >> diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c >> index 460084a8eac5..d5d7eb2ae3c4 100644 >> --- a/fs/cifs/misc.c >> +++ b/fs/cifs/misc.c >> @@ -145,7 +145,7 @@ cifs_buf_get(void) >> * SMB2 header is bigger than CIFS one - no problems to clean some >> * more bytes for CIFS. >> */ >> - size_t buf_size = sizeof(struct smb2_hdr); >> + size_t buf_size = sizeof(struct smb2_sync_hdr); >> >> /* >> * We could use negotiated size instead of max_msgsize - >> diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h >> index 401a5d856636..0ffa18094335 100644 >> --- a/fs/cifs/smb2glob.h >> +++ b/fs/cifs/smb2glob.h >> @@ -61,9 +61,4 @@ >> /* Maximum buffer size value we can send with 1 credit */ >> #define SMB2_MAX_BUFFER_SIZE 65536 >> >> -static inline struct smb2_sync_hdr *get_sync_hdr(void *buf) >> -{ >> - return &(((struct smb2_hdr *)buf)->sync_hdr); >> -} >> - >> #endif /* _SMB2_GLOB_H */ >> diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c >> index 62c88dfed57b..8fe30288805f 100644 >> --- a/fs/cifs/smb2maperror.c >> +++ b/fs/cifs/smb2maperror.c >> @@ -2450,7 +2450,7 @@ smb2_print_status(__le32 status) >> int >> map_smb2_to_linux_error(char *buf, bool log_err) >> { >> - struct smb2_sync_hdr *shdr = get_sync_hdr(buf); >> + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; >> unsigned int i; >> int rc = -EIO; >> __le32 smb2err = shdr->Status; >> diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c >> index 566871185b98..cb79c2433844 100644 >> --- a/fs/cifs/smb2misc.c >> +++ b/fs/cifs/smb2misc.c >> @@ -94,25 +94,20 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { >> }; >> >> int >> -smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) >> +smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) >> { >> - struct smb2_pdu *pdu = (struct smb2_pdu *)buf; >> - struct smb2_hdr *hdr = &pdu->hdr; >> - struct smb2_sync_hdr *shdr = get_sync_hdr(buf); >> + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; >> + struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr; >> __u64 mid; >> - __u32 len = get_rfc1002_length(buf); >> __u32 clc_len; /* calculated length */ >> int command; >> - >> - /* BB disable following printk later */ >> - cifs_dbg(FYI, "%s length: 0x%x, smb_buf_length: 0x%x\n", >> - __func__, length, len); >> + int pdu_size = sizeof(struct smb2_sync_pdu); >> + int hdr_size = sizeof(struct smb2_sync_hdr); >> >> /* >> * Add function to do table lookup of StructureSize by command >> * ie Validate the wct via smb2_struct_sizes table above >> */ >> - >> if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { >> struct smb2_transform_hdr *thdr = >> (struct smb2_transform_hdr *)buf; >> @@ -136,8 +131,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) >> } >> >> mid = le64_to_cpu(shdr->MessageId); >> - if (length < sizeof(struct smb2_pdu)) { >> - if ((length >= sizeof(struct smb2_hdr)) >> + if (len < pdu_size) { >> + if ((len >= hdr_size) >> && (shdr->Status != 0)) { >> pdu->StructureSize2 = 0; >> /* >> @@ -190,13 +185,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) >> } >> } >> >> - if (srvr->vals->header_preamble_size + len != length) { >> - cifs_dbg(VFS, "Total length %u RFC1002 length %u mismatch mid %llu\n", >> - length, srvr->vals->header_preamble_size + len, mid); >> - return 1; >> - } >> - >> - clc_len = smb2_calc_size(hdr); >> + clc_len = smb2_calc_size(buf); >> >> if (srvr->vals->header_preamble_size + len != clc_len) { >> cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n", >> @@ -206,7 +195,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) >> shdr->Status == STATUS_STOPPED_ON_SYMLINK) >> return 0; >> /* Windows 7 server returns 24 bytes more */ >> - if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE) >> + if (clc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE) > > We have a srvr pointer here, so, we can use header_preamble_size > instead and move this to patch #1. > >> return 0; >> /* server can return one byte more due to implied bcc[0] */ >> if (clc_len == srvr->vals->header_preamble_size + len + 1) >> @@ -263,15 +252,14 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = { >> * area and the offset to it (from the beginning of the smb are also returned. >> */ >> char * >> -smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) >> +smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr) >> { >> - struct smb2_sync_hdr *shdr = get_sync_hdr(hdr); >> *off = 0; >> *len = 0; >> >> /* error responses do not have data area */ >> if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED && >> - (((struct smb2_err_rsp *)hdr)->StructureSize) == >> + (((struct smb2_err_rsp *)shdr)->StructureSize) == >> SMB2_ERROR_STRUCTURE_SIZE2) >> return NULL; >> >> @@ -283,42 +271,44 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) >> switch (shdr->Command) { >> case SMB2_NEGOTIATE: >> *off = le16_to_cpu( >> - ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset); >> + ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset); >> *len = le16_to_cpu( >> - ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferLength); >> + ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength); >> break; >> case SMB2_SESSION_SETUP: >> *off = le16_to_cpu( >> - ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferOffset); >> + ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset); >> *len = le16_to_cpu( >> - ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferLength); >> + ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength); >> break; >> case SMB2_CREATE: >> *off = le32_to_cpu( >> - ((struct smb2_create_rsp *)hdr)->CreateContextsOffset); >> + ((struct smb2_create_rsp *)shdr)->CreateContextsOffset); >> *len = le32_to_cpu( >> - ((struct smb2_create_rsp *)hdr)->CreateContextsLength); >> + ((struct smb2_create_rsp *)shdr)->CreateContextsLength); >> break; >> case SMB2_QUERY_INFO: >> *off = le16_to_cpu( >> - ((struct smb2_query_info_rsp *)hdr)->OutputBufferOffset); >> + ((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset); >> *len = le32_to_cpu( >> - ((struct smb2_query_info_rsp *)hdr)->OutputBufferLength); >> + ((struct smb2_query_info_rsp *)shdr)->OutputBufferLength); >> break; >> case SMB2_READ: >> - *off = ((struct smb2_read_rsp *)hdr)->DataOffset; >> - *len = le32_to_cpu(((struct smb2_read_rsp *)hdr)->DataLength); >> + /* TODO: is this a bug ? */ >> + *off = ((struct smb2_read_rsp *)shdr)->DataOffset; >> + *len = le32_to_cpu(((struct smb2_read_rsp *)shdr)->DataLength); >> break; >> case SMB2_QUERY_DIRECTORY: >> *off = le16_to_cpu( >> - ((struct smb2_query_directory_rsp *)hdr)->OutputBufferOffset); >> + ((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset); >> *len = le32_to_cpu( >> - ((struct smb2_query_directory_rsp *)hdr)->OutputBufferLength); >> + ((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength); >> break; >> case SMB2_IOCTL: >> *off = le32_to_cpu( >> - ((struct smb2_ioctl_rsp *)hdr)->OutputOffset); >> - *len = le32_to_cpu(((struct smb2_ioctl_rsp *)hdr)->OutputCount); >> + ((struct smb2_ioctl_rsp *)shdr)->OutputOffset); >> + *len = le32_to_cpu( >> + ((struct smb2_ioctl_rsp *)shdr)->OutputCount); >> break; >> case SMB2_CHANGE_NOTIFY: >> default: >> @@ -363,13 +353,12 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) >> unsigned int >> smb2_calc_size(void *buf) >> { >> - struct smb2_pdu *pdu = (struct smb2_pdu *)buf; >> - struct smb2_hdr *hdr = &pdu->hdr; >> - struct smb2_sync_hdr *shdr = get_sync_hdr(hdr); >> + struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)buf; >> + struct smb2_sync_hdr *shdr = &pdu->sync_hdr; >> int offset; /* the offset from the beginning of SMB to data area */ >> int data_length; /* the length of the variable length data area */ >> /* Structure Size has already been checked to make sure it is 64 */ >> - int len = 4 + le16_to_cpu(shdr->StructureSize); >> + int len = le16_to_cpu(shdr->StructureSize); >> >> /* >> * StructureSize2, ie length of fixed parameter area has already >> @@ -380,7 +369,7 @@ smb2_calc_size(void *buf) >> if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false) >> goto calc_size_exit; >> >> - smb2_get_data_area_len(&offset, &data_length, hdr); >> + smb2_get_data_area_len(&offset, &data_length, shdr); >> cifs_dbg(FYI, "SMB2 data length %d offset %d\n", data_length, offset); >> >> if (data_length > 0) { >> @@ -388,15 +377,14 @@ smb2_calc_size(void *buf) >> * Check to make sure that data area begins after fixed area, >> * Note that last byte of the fixed area is part of data area >> * for some commands, typically those with odd StructureSize, >> - * so we must add one to the calculation (and 4 to account for >> - * the size of the RFC1001 hdr. >> + * so we must add one to the calculation. >> */ >> - if (offset + 4 + 1 < len) { >> + if (offset + 1 < len) { >> cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d\n", >> - offset + 4 + 1, len); >> + offset + 1, len); >> data_length = 0; >> } else { >> - len = 4 + offset + data_length; >> + len = offset + data_length; >> } >> } >> calc_size_exit: >> @@ -579,7 +567,7 @@ smb2_is_valid_lease_break(char *buffer) >> bool >> smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) >> { >> - struct smb2_oplock_break_rsp *rsp = (struct smb2_oplock_break_rsp *)buffer; >> + struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer; >> struct list_head *tmp, *tmp1, *tmp2; >> struct cifs_ses *ses; >> struct cifs_tcon *tcon; >> @@ -588,7 +576,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) >> >> cifs_dbg(FYI, "Checking for oplock break\n"); >> >> - if (rsp->hdr.sync_hdr.Command != SMB2_OPLOCK_BREAK) >> + if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK) >> return false; >> >> if (rsp->StructureSize != >> @@ -679,8 +667,8 @@ smb2_cancelled_close_fid(struct work_struct *work) >> int >> smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server) >> { >> - struct smb2_sync_hdr *sync_hdr = get_sync_hdr(buffer); >> - struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer; >> + struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer; >> + struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)sync_hdr; >> struct cifs_tcon *tcon; >> struct close_cancelled_open *cancelled; >> >> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c >> index 09d3a2912869..48ee237c3fdf 100644 >> --- a/fs/cifs/smb2ops.c >> +++ b/fs/cifs/smb2ops.c >> @@ -123,7 +123,8 @@ smb2_get_credits_field(struct TCP_Server_Info *server, const int optype) >> static unsigned int >> smb2_get_credits(struct mid_q_entry *mid) >> { >> - struct smb2_sync_hdr *shdr = get_sync_hdr(mid->resp_buf); >> + char *buf = mid->resp_buf; >> + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; >> >> return le16_to_cpu(shdr->CreditRequest); >> } >> @@ -190,7 +191,7 @@ static struct mid_q_entry * >> smb2_find_mid(struct TCP_Server_Info *server, char *buf) >> { >> struct mid_q_entry *mid; >> - struct smb2_sync_hdr *shdr = get_sync_hdr(buf); >> + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; >> __u64 wire_mid = le64_to_cpu(shdr->MessageId); >> >> if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { >> @@ -215,7 +216,7 @@ static void >> smb2_dump_detail(void *buf) >> { >> #ifdef CONFIG_CIFS_DEBUG2 >> - struct smb2_sync_hdr *shdr = get_sync_hdr(buf); >> + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; >> >> cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n", >> shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId, >> @@ -1241,7 +1242,7 @@ smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon, >> static bool >> smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length) >> { >> - struct smb2_sync_hdr *shdr = get_sync_hdr(buf); >> + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; >> >> if (shdr->Status != STATUS_PENDING) >> return false; >> @@ -1259,7 +1260,7 @@ smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length) >> static bool >> smb2_is_session_expired(char *buf) >> { >> - struct smb2_sync_hdr *shdr = get_sync_hdr(buf); >> + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; >> >> if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED) >> return false; >> @@ -1451,6 +1452,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, >> __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; >> struct cifs_open_parms oparms; >> struct cifs_fid fid; >> + struct kvec err_iov = {NULL, 0}; >> struct smb2_err_rsp *err_buf = NULL; >> struct smb2_symlink_err_rsp *symlink; >> unsigned int sub_len; >> @@ -1473,15 +1475,16 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, >> oparms.fid = &fid; >> oparms.reconnect = false; >> >> - rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_buf); >> + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov); >> >> if (!rc || !err_buf) { >> kfree(utf16_path); >> return -ENOENT; >> } >> >> + err_buf = err_iov.iov_base; >> if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) || >> - get_rfc1002_length(err_buf) + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) { >> + err_iov.iov_len + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) { >> kfree(utf16_path); >> return -ENOENT; >> } >> @@ -1494,13 +1497,13 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, >> print_len = le16_to_cpu(symlink->PrintNameLength); >> print_offset = le16_to_cpu(symlink->PrintNameOffset); >> >> - if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size < >> + if (err_iov.iov_len + server->vals->header_preamble_size < >> SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) { >> kfree(utf16_path); >> return -ENOENT; >> } >> >> - if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size < >> + if (err_iov.iov_len + server->vals->header_preamble_size < >> SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) { >> kfree(utf16_path); >> return -ENOENT; >> @@ -2052,12 +2055,11 @@ smb2_dir_needs_close(struct cifsFileInfo *cfile) >> } >> >> static void >> -fill_transform_hdr(struct TCP_Server_Info *server, >> - struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq) >> +fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len, >> + struct smb_rqst *old_rq) >> { >> struct smb2_sync_hdr *shdr = >> (struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base; >> - unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base); >> >> memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr)); >> tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM; >> @@ -2065,8 +2067,6 @@ fill_transform_hdr(struct TCP_Server_Info *server, >> tr_hdr->Flags = cpu_to_le16(0x01); >> get_random_bytes(&tr_hdr->Nonce, SMB3_AES128CMM_NONCE); >> memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8); >> - inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - server->vals->header_preamble_size); >> - inc_rfc1001_len(tr_hdr, orig_len); >> } >> >> /* We can not use the normal sg_set_buf() as we will sometimes pass a >> @@ -2078,11 +2078,16 @@ static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf, >> sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); >> } >> >> +/* Assumes: >> + * rqst->rq_iov[0] is rfc1002 length >> + * rqst->rq_iov[1] is tranform header >> + * rqst->rq_iov[2+] data to be encrypted/decrypted >> + */ >> static struct scatterlist * >> init_sg(struct smb_rqst *rqst, u8 *sign) >> { >> - unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages + 1; >> - unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24; >> + unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages; >> + unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20; >> struct scatterlist *sg; >> unsigned int i; >> unsigned int j; >> @@ -2092,10 +2097,10 @@ init_sg(struct smb_rqst *rqst, u8 *sign) >> return NULL; >> >> sg_init_table(sg, sg_len); >> - smb2_sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 24, assoc_data_len); >> - for (i = 1; i < rqst->rq_nvec; i++) >> - smb2_sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base, >> - rqst->rq_iov[i].iov_len); >> + smb2_sg_set_buf(&sg[0], rqst->rq_iov[1].iov_base + 20, assoc_data_len); >> + for (i = 1; i < rqst->rq_nvec - 1; i++) >> + smb2_sg_set_buf(&sg[i], rqst->rq_iov[i+1].iov_base, >> + rqst->rq_iov[i+1].iov_len); >> for (j = 0; i < sg_len - 1; i++, j++) { >> unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz >> : rqst->rq_tailsz; >> @@ -2127,17 +2132,18 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key) >> } >> /* >> * Encrypt or decrypt @rqst message. @rqst has the following format: >> - * iov[0] - transform header (associate data), >> - * iov[1-N] and pages - data to encrypt. >> - * On success return encrypted data in iov[1-N] and pages, leave iov[0] >> + * iov[0] - rfc1002 length >> + * iov[1] - transform header (associate data), >> + * iov[2-N] and pages - data to encrypt. >> + * On success return encrypted data in iov[2-N] and pages, leave iov[0-1] >> * untouched. >> */ >> static int >> crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc) >> { >> struct smb2_transform_hdr *tr_hdr = >> - (struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base; >> - unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24; >> + (struct smb2_transform_hdr *)rqst->rq_iov[1].iov_base; >> + unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20; > > The same here: please use header_preamble_size. > >> int rc = 0; >> struct scatterlist *sg; >> u8 sign[SMB2_SIGNATURE_SIZE] = {}; >> @@ -2224,6 +2230,9 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc) >> return rc; >> } >> >> +/* This is called from smb_send_rqst. At this point we have the rfc1002 >> + * header as the first element in the vector. >> + */ > > The comment style should be: > /* > * text > */ > >> static int >> smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq, >> struct smb_rqst *old_rq) >> @@ -2232,6 +2241,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq, >> struct page **pages; >> struct smb2_transform_hdr *tr_hdr; >> unsigned int npages = old_rq->rq_npages; >> + unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base); >> int i; >> int rc = -ENOMEM; >> >> @@ -2250,24 +2260,34 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq, >> goto err_free_pages; >> } >> >> - iov = kmalloc_array(old_rq->rq_nvec, sizeof(struct kvec), GFP_KERNEL); >> + /* Make space for one extra iov to hold the transform header */ >> + iov = kmalloc_array(old_rq->rq_nvec + 1, sizeof(struct kvec), >> + GFP_KERNEL); >> if (!iov) >> goto err_free_pages; >> >> /* copy all iovs from the old except the 1st one (rfc1002 length) */ >> - memcpy(&iov[1], &old_rq->rq_iov[1], >> + memcpy(&iov[2], &old_rq->rq_iov[1], >> sizeof(struct kvec) * (old_rq->rq_nvec - 1)); >> + /* copy the rfc1002 iov */ >> + iov[0].iov_base = old_rq->rq_iov[0].iov_base; >> + iov[0].iov_len = old_rq->rq_iov[0].iov_len; >> + >> new_rq->rq_iov = iov; >> - new_rq->rq_nvec = old_rq->rq_nvec; >> + new_rq->rq_nvec = old_rq->rq_nvec + 1; >> >> tr_hdr = kmalloc(sizeof(struct smb2_transform_hdr), GFP_KERNEL); >> if (!tr_hdr) >> goto err_free_iov; >> >> - /* fill the 1st iov with a transform header */ >> - fill_transform_hdr(server, tr_hdr, old_rq); >> - new_rq->rq_iov[0].iov_base = tr_hdr; >> - new_rq->rq_iov[0].iov_len = sizeof(struct smb2_transform_hdr); >> + /* fill the 2nd iov with a transform header */ >> + fill_transform_hdr(tr_hdr, orig_len, old_rq); >> + new_rq->rq_iov[1].iov_base = tr_hdr; >> + new_rq->rq_iov[1].iov_len = sizeof(struct smb2_transform_hdr); >> + >> + /* Update rfc1002 header */ >> + inc_rfc1001_len(new_rq->rq_iov[0].iov_base, >> + sizeof(struct smb2_transform_hdr)); >> >> /* copy pages form the old */ >> for (i = 0; i < npages; i++) { >> @@ -2307,7 +2327,7 @@ smb3_free_transform_rq(struct smb_rqst *rqst) >> put_page(rqst->rq_pages[i]); >> kfree(rqst->rq_pages); >> /* free transform header */ >> - kfree(rqst->rq_iov[0].iov_base); >> + kfree(rqst->rq_iov[1].iov_base); >> kfree(rqst->rq_iov); >> } >> >> @@ -2324,18 +2344,19 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf, >> unsigned int buf_data_size, struct page **pages, >> unsigned int npages, unsigned int page_data_size) >> { >> - struct kvec iov[2]; >> + struct kvec iov[3]; >> struct smb_rqst rqst = {NULL}; >> - struct smb2_hdr *hdr; >> int rc; >> >> - iov[0].iov_base = buf; >> - iov[0].iov_len = sizeof(struct smb2_transform_hdr); >> - iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr); >> - iov[1].iov_len = buf_data_size; >> + iov[0].iov_base = NULL; >> + iov[0].iov_len = 0; >> + iov[1].iov_base = buf; >> + iov[1].iov_len = sizeof(struct smb2_transform_hdr); >> + iov[2].iov_base = buf + sizeof(struct smb2_transform_hdr); >> + iov[2].iov_len = buf_data_size; >> >> rqst.rq_iov = iov; >> - rqst.rq_nvec = 2; >> + rqst.rq_nvec = 3; >> rqst.rq_pages = pages; >> rqst.rq_npages = npages; >> rqst.rq_pagesz = PAGE_SIZE; >> @@ -2347,10 +2368,9 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf, >> if (rc) >> return rc; >> >> - memmove(buf + server->vals->header_preamble_size, iov[1].iov_base, buf_data_size); >> - hdr = (struct smb2_hdr *)buf; >> - hdr->smb2_buf_length = cpu_to_be32(buf_data_size + page_data_size); >> - server->total_read = buf_data_size + page_data_size + server->vals->header_preamble_size; >> + memmove(buf + server->vals->header_preamble_size, iov[2].iov_base, buf_data_size); >> + >> + server->total_read = buf_data_size + page_data_size; >> >> return rc; >> } >> @@ -2423,7 +2443,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, >> unsigned int cur_page_idx; >> unsigned int pad_len; >> struct cifs_readdata *rdata = mid->callback_data; >> - struct smb2_sync_hdr *shdr = get_sync_hdr(buf); >> + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; >> struct bio_vec *bvec = NULL; >> struct iov_iter iter; >> struct kvec iov; >> @@ -2550,7 +2570,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid) >> unsigned int npages; >> struct page **pages; >> unsigned int len; >> - unsigned int buflen = get_rfc1002_length(buf) + server->vals->header_preamble_size; >> + unsigned int buflen = server->pdu_size + server->vals->header_preamble_size; >> int rc; >> int i = 0; >> >> @@ -2624,7 +2644,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server, >> { >> int length; >> char *buf = server->smallbuf; >> - unsigned int pdu_length = get_rfc1002_length(buf); >> + unsigned int pdu_length = server->pdu_size; >> unsigned int buf_size; >> struct mid_q_entry *mid_entry; >> >> @@ -2668,7 +2688,7 @@ static int >> smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid) >> { >> char *buf = server->smallbuf; >> - unsigned int pdu_length = get_rfc1002_length(buf); >> + unsigned int pdu_length = server->pdu_size; >> struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; >> unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize); >> >> @@ -2699,7 +2719,7 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid) >> { >> char *buf = server->large_buf ? server->bigbuf : server->smallbuf; >> >> - return handle_read_data(server, mid, buf, get_rfc1002_length(buf) + >> + return handle_read_data(server, mid, buf, server->total_read + > > Should we use server->pdu_size here instead? 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@xxxxxxxxxxxxxxx >> More majordomo info at http://vger.kernel.org/majordomo-info.html > -- > To unsubscribe from this list: send the line "unsubscribe linux-cifs" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html