[1] If CONFIG_CIFS_DEBUG2 is set, then cifs_demultiplex_thread calls dump_detail. ``` static int cifs_demultiplex_thread(void *p) { ... for (i = 0; i < num_mids; i++) { if (mids[i] != NULL) { mids[i]->resp_buf_size = server->pdu_size; if (bufs[i] != NULL) { if (server->ops->is_network_name_deleted && server->ops->is_network_name_deleted(bufs[i], server)) { cifs_server_dbg(FYI, "Share deleted. Reconnect needed"); } } if (!mids[i]->multiRsp || mids[i]->multiEnd) mids[i]->callback(mids[i]); release_mid(mids[i]); } else if (server->ops->is_oplock_break && server->ops->is_oplock_break(bufs[i], server)) { smb2_add_credits_from_hdr(bufs[i], server); cifs_dbg(FYI, "Received oplock break\n"); } else { cifs_server_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n", atomic_read(&mid_count)); cifs_dump_mem("Received Data is: ", bufs[i], HEADER_SIZE(server)); smb2_add_credits_from_hdr(bufs[i], server); #ifdef CONFIG_CIFS_DEBUG2 if (server->ops->dump_detail) server->ops->dump_detail(bufs[i], server);//[1] cifs_dump_mids(server); #endif /* CIFS_DEBUG2 */ } } ``` //[2]In smb2_dump_detail, calc_smb_size is called, which refers to smb2_calc_size. ``` static void smb2_dump_detail(void *buf, struct TCP_Server_Info *server) { #ifdef CONFIG_CIFS_DEBUG2 struct smb2_hdr *shdr = (struct smb2_hdr *)buf; cifs_server_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n", shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId, shdr->Id.SyncId.ProcessId); cifs_server_dbg(VFS, "smb buf %p len %u\n", buf, server->ops->calc_smb_size(buf));//[2] #endif } ``` In has_smb2_data_area, it attempts to retrieve an element at the index le16_to_cpu(shdr->Command). If a value larger than the length of has_smb2_data_area is input, an OOB (Out-Of-Bounds) Read occurs." ``` unsigned int smb2_calc_size(void *buf) { struct smb2_pdu *pdu = buf; struct smb2_hdr *shdr = &pdu->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 = le16_to_cpu(shdr->StructureSize); /* * StructureSize2, ie length of fixed parameter area has already * been checked to make sure it is the correct length. */ len += le16_to_cpu(pdu->StructureSize2); if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false)//[3] goto calc_size_exit; ```
Created attachment 305537 [details] crash callstack
Created attachment 305618 [details] patch 1
Thanks for the report. Does the attached patch fix your problem?
Created attachment 305633 [details] patch v2 Follow v2 of this patch. Please verify.
This was fixed upstream by: commit 567320c46a60 ("smb: client: fix potential OOB in smb2_dump_detail()").