From: Namjae Jeon linkinjeon@kernel.org
mainline inclusion from mainline-5.15-rc3 commit 18a015bccf9e8927008d0a255c9f14b8ec15a648 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I60T7G CVE: NA
Reference: https://git.kernel.org/torvalds/linux/c/18a015bccf9e
-------------------------------
When second smb2 pdu has invalid protocol id, ksmbd doesn't detect it and allow to process smb2 request. This patch add the check it in ksmbd_verify_smb_message() and don't use protocol id of smb2 request as protocol id of response.
Reviewed-by: Ronnie Sahlberg ronniesahlberg@gmail.com Reviewed-by: Ralph Böhme slow@samba.org Reported-by: Ronnie Sahlberg lsahlber@redhat.com Signed-off-by: Namjae Jeon linkinjeon@kernel.org Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Jason Yan yanaijie@huawei.com Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com --- fs/ksmbd/smb2pdu.c | 2 +- fs/ksmbd/smb_common.c | 13 +++++++++---- fs/ksmbd/smb_common.h | 1 + 3 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 0fe4d2c5bea1..e816f9ce77a7 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -433,7 +433,7 @@ static void init_chained_smb2_rsp(struct ksmbd_work *work) work->compound_pfid = KSMBD_NO_FID; } memset((char *)rsp_hdr + 4, 0, sizeof(struct smb2_hdr) + 2); - rsp_hdr->ProtocolId = rcv_hdr->ProtocolId; + rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER; rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE; rsp_hdr->Command = rcv_hdr->Command;
diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c index b2370d0f08c6..7ea15d77d50e 100644 --- a/fs/ksmbd/smb_common.c +++ b/fs/ksmbd/smb_common.c @@ -129,16 +129,22 @@ int ksmbd_lookup_protocol_idx(char *str) * * check for valid smb signature and packet direction(request/response) * - * Return: 0 on success, otherwise 1 + * Return: 0 on success, otherwise -EINVAL */ int ksmbd_verify_smb_message(struct ksmbd_work *work) { - struct smb2_hdr *smb2_hdr = work->request_buf; + struct smb2_hdr *smb2_hdr = work->request_buf + work->next_smb2_rcv_hdr_off; + struct smb_hdr *hdr;
if (smb2_hdr->ProtocolId == SMB2_PROTO_NUMBER) return ksmbd_smb2_check_message(work);
- return 0; + hdr = work->request_buf; + if (*(__le32 *)hdr->Protocol == SMB1_PROTO_NUMBER && + hdr->Command == SMB_COM_NEGOTIATE) + return 0; + + return -EINVAL; }
/** @@ -265,7 +271,6 @@ static int ksmbd_negotiate_smb_dialect(void *buf) return BAD_PROT_ID; }
-#define SMB_COM_NEGOTIATE 0x72 int ksmbd_init_smb_server(struct ksmbd_work *work) { struct ksmbd_conn *conn = work->conn; diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h index 57c667c1be06..0a6af447cc45 100644 --- a/fs/ksmbd/smb_common.h +++ b/fs/ksmbd/smb_common.h @@ -210,6 +210,7 @@ FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)
#define SMB1_PROTO_NUMBER cpu_to_le32(0x424d53ff) +#define SMB_COM_NEGOTIATE 0x72
#define SMB1_CLIENT_GUID_SIZE (16) struct smb_hdr {