Bug 218219

Summary: OOB Access in smb2_dump_detail
Product: File System Reporter: j51569436
Component: CIFSAssignee: fs_cifs (fs_cifs)
Status: RESOLVED CODE_FIX    
Severity: normal CC: hissrna11, lsahlber, pc, smfrench
Priority: P3    
Hardware: All   
OS: Linux   
Kernel Version: 6.7.0 Subsystem:
Regression: No Bisected commit-id:
Attachments: crash callstack
patch 1
patch v2

Description j51569436 2023-12-04 10:54:26 UTC
[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;
```
Comment 1 j51569436 2023-12-04 10:54:49 UTC
Created attachment 305537 [details]
crash callstack
Comment 2 Paulo Alcantara 2023-12-16 13:49:30 UTC
Created attachment 305618 [details]
patch 1
Comment 3 Paulo Alcantara 2023-12-16 13:49:51 UTC
Thanks for the report.

Does the attached patch fix your problem?
Comment 4 Paulo Alcantara 2023-12-19 16:19:56 UTC
Created attachment 305633 [details]
patch v2

Follow v2 of this patch.  Please verify.
Comment 6 Steve French 2024-10-03 17:11:17 UTC
This was fixed upstream by:
commit 567320c46a60 ("smb: client: fix potential OOB in
smb2_dump_detail()").