From: Greg Kroah-Hartman Date: Mon, 12 Jun 2023 06:42:55 +0000 (+0200) Subject: 6.1-stable patches X-Git-Tag: v4.14.318~30 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f0d342c537745176a509d2153266bf95e7e1cbf0;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: ksmbd-check-the-validation-of-pdu_size-in-ksmbd_conn_handler_loop.patch ksmbd-fix-out-of-bound-read-in-deassemble_neg_contexts.patch ksmbd-fix-out-of-bound-read-in-parse_lease_state.patch --- diff --git a/queue-6.1/ksmbd-check-the-validation-of-pdu_size-in-ksmbd_conn_handler_loop.patch b/queue-6.1/ksmbd-check-the-validation-of-pdu_size-in-ksmbd_conn_handler_loop.patch new file mode 100644 index 00000000000..b2774286eec --- /dev/null +++ b/queue-6.1/ksmbd-check-the-validation-of-pdu_size-in-ksmbd_conn_handler_loop.patch @@ -0,0 +1,73 @@ +From 368ba06881c395f1c9a7ba22203cf8d78b4addc0 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Tue, 30 May 2023 23:10:31 +0900 +Subject: ksmbd: check the validation of pdu_size in ksmbd_conn_handler_loop + +From: Namjae Jeon + +commit 368ba06881c395f1c9a7ba22203cf8d78b4addc0 upstream. + +The length field of netbios header must be greater than the SMB header +sizes(smb1 or smb2 header), otherwise the packet is an invalid SMB packet. + +If `pdu_size` is 0, ksmbd allocates a 4 bytes chunk to `conn->request_buf`. +In the function `get_smb2_cmd_val` ksmbd will read cmd from +`rcv_hdr->Command`, which is `conn->request_buf + 12`, causing the KASAN +detector to print the following error message: + +[ 7.205018] BUG: KASAN: slab-out-of-bounds in get_smb2_cmd_val+0x45/0x60 +[ 7.205423] Read of size 2 at addr ffff8880062d8b50 by task ksmbd:42632/248 +... +[ 7.207125] +[ 7.209191] get_smb2_cmd_val+0x45/0x60 +[ 7.209426] ksmbd_conn_enqueue_request+0x3a/0x100 +[ 7.209712] ksmbd_server_process_request+0x72/0x160 +[ 7.210295] ksmbd_conn_handler_loop+0x30c/0x550 +[ 7.212280] kthread+0x160/0x190 +[ 7.212762] ret_from_fork+0x1f/0x30 +[ 7.212981] + +Cc: stable@vger.kernel.org +Reported-by: Chih-Yen Chang +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/connection.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/fs/ksmbd/connection.c ++++ b/fs/ksmbd/connection.c +@@ -296,6 +296,9 @@ bool ksmbd_conn_alive(struct ksmbd_conn + return true; + } + ++#define SMB1_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb_hdr)) ++#define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr) + 4) ++ + /** + * ksmbd_conn_handler_loop() - session thread to listen on new smb requests + * @p: connection instance +@@ -352,6 +355,9 @@ int ksmbd_conn_handler_loop(void *p) + if (pdu_size > MAX_STREAM_PROT_LEN) + break; + ++ if (pdu_size < SMB1_MIN_SUPPORTED_HEADER_SIZE) ++ break; ++ + /* 4 for rfc1002 length field */ + /* 1 for implied bcc[0] */ + size = pdu_size + 4 + 1; +@@ -379,6 +385,12 @@ int ksmbd_conn_handler_loop(void *p) + continue; + } + ++ if (((struct smb2_hdr *)smb2_get_msg(conn->request_buf))->ProtocolId == ++ SMB2_PROTO_NUMBER) { ++ if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE) ++ break; ++ } ++ + if (!default_conn_ops.process_fn) { + pr_err("No connection request callback\n"); + break; diff --git a/queue-6.1/ksmbd-fix-out-of-bound-read-in-deassemble_neg_contexts.patch b/queue-6.1/ksmbd-fix-out-of-bound-read-in-deassemble_neg_contexts.patch new file mode 100644 index 00000000000..516aaad3814 --- /dev/null +++ b/queue-6.1/ksmbd-fix-out-of-bound-read-in-deassemble_neg_contexts.patch @@ -0,0 +1,83 @@ +From f1a411873c85b642f13b01f21b534c2bab81fc1b Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Sun, 28 May 2023 00:23:09 +0900 +Subject: ksmbd: fix out-of-bound read in deassemble_neg_contexts() + +From: Namjae Jeon + +commit f1a411873c85b642f13b01f21b534c2bab81fc1b upstream. + +The check in the beginning is +`clen + sizeof(struct smb2_neg_context) <= len_of_ctxts`, +but in the end of loop, `len_of_ctxts` will subtract +`((clen + 7) & ~0x7) + sizeof(struct smb2_neg_context)`, which causes +integer underflow when clen does the 8 alignment. We should use +`(clen + 7) & ~0x7` in the check to avoid underflow from happening. + +Then there are some variables that need to be declared unsigned +instead of signed. + +[ 11.671070] BUG: KASAN: slab-out-of-bounds in smb2_handle_negotiate+0x799/0x1610 +[ 11.671533] Read of size 2 at addr ffff888005e86cf2 by task kworker/0:0/7 +... +[ 11.673383] Call Trace: +[ 11.673541] +[ 11.673679] dump_stack_lvl+0x33/0x50 +[ 11.673913] print_report+0xcc/0x620 +[ 11.674671] kasan_report+0xae/0xe0 +[ 11.675171] kasan_check_range+0x35/0x1b0 +[ 11.675412] smb2_handle_negotiate+0x799/0x1610 +[ 11.676217] ksmbd_smb_negotiate_common+0x526/0x770 +[ 11.676795] handle_ksmbd_work+0x274/0x810 +... + +Cc: stable@vger.kernel.org +Signed-off-by: Chih-Yen Chang +Tested-by: Chih-Yen Chang +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/smb2pdu.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -979,13 +979,13 @@ static void decode_sign_cap_ctxt(struct + + static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn, + struct smb2_negotiate_req *req, +- int len_of_smb) ++ unsigned int len_of_smb) + { + /* +4 is to account for the RFC1001 len field */ + struct smb2_neg_context *pctx = (struct smb2_neg_context *)req; + int i = 0, len_of_ctxts; +- int offset = le32_to_cpu(req->NegotiateContextOffset); +- int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount); ++ unsigned int offset = le32_to_cpu(req->NegotiateContextOffset); ++ unsigned int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount); + __le32 status = STATUS_INVALID_PARAMETER; + + ksmbd_debug(SMB, "decoding %d negotiate contexts\n", neg_ctxt_cnt); +@@ -999,7 +999,7 @@ static __le32 deassemble_neg_contexts(st + while (i++ < neg_ctxt_cnt) { + int clen, ctxt_len; + +- if (len_of_ctxts < sizeof(struct smb2_neg_context)) ++ if (len_of_ctxts < (int)sizeof(struct smb2_neg_context)) + break; + + pctx = (struct smb2_neg_context *)((char *)pctx + offset); +@@ -1054,9 +1054,8 @@ static __le32 deassemble_neg_contexts(st + } + + /* offsets must be 8 byte aligned */ +- clen = (clen + 7) & ~0x7; +- offset = clen + sizeof(struct smb2_neg_context); +- len_of_ctxts -= clen + sizeof(struct smb2_neg_context); ++ offset = (ctxt_len + 7) & ~0x7; ++ len_of_ctxts -= offset; + } + return status; + } diff --git a/queue-6.1/ksmbd-fix-out-of-bound-read-in-parse_lease_state.patch b/queue-6.1/ksmbd-fix-out-of-bound-read-in-parse_lease_state.patch new file mode 100644 index 00000000000..ead9c9d15ba --- /dev/null +++ b/queue-6.1/ksmbd-fix-out-of-bound-read-in-parse_lease_state.patch @@ -0,0 +1,125 @@ +From fc6c6a3c324c1b3e93a03d0cfa3749c781f23de0 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Sun, 28 May 2023 00:23:41 +0900 +Subject: ksmbd: fix out-of-bound read in parse_lease_state() + +From: Namjae Jeon + +commit fc6c6a3c324c1b3e93a03d0cfa3749c781f23de0 upstream. + +This bug is in parse_lease_state, and it is caused by the missing check +of `struct create_context`. When the ksmbd traverses the create_contexts, +it doesn't check if the field of `NameOffset` and `Next` is valid, +The KASAN message is following: + +[ 6.664323] BUG: KASAN: slab-out-of-bounds in parse_lease_state+0x7d/0x280 +[ 6.664738] Read of size 2 at addr ffff888005c08988 by task kworker/0:3/103 +... +[ 6.666644] Call Trace: +[ 6.666796] +[ 6.666933] dump_stack_lvl+0x33/0x50 +[ 6.667167] print_report+0xcc/0x620 +[ 6.667903] kasan_report+0xae/0xe0 +[ 6.668374] kasan_check_range+0x35/0x1b0 +[ 6.668621] parse_lease_state+0x7d/0x280 +[ 6.668868] smb2_open+0xbe8/0x4420 +[ 6.675137] handle_ksmbd_work+0x282/0x820 + +Use smb2_find_context_vals() to find smb2 create request lease context. +smb2_find_context_vals validate create context fields. + +Cc: stable@vger.kernel.org +Reported-by: Chih-Yen Chang +Tested-by: Chih-Yen Chang +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/oplock.c | 70 ++++++++++++++++++++---------------------------------- + 1 file changed, 26 insertions(+), 44 deletions(-) + +--- a/fs/ksmbd/oplock.c ++++ b/fs/ksmbd/oplock.c +@@ -1415,56 +1415,38 @@ void create_lease_buf(u8 *rbuf, struct l + */ + struct lease_ctx_info *parse_lease_state(void *open_req) + { +- char *data_offset; + struct create_context *cc; +- unsigned int next = 0; +- char *name; +- bool found = false; + struct smb2_create_req *req = (struct smb2_create_req *)open_req; +- struct lease_ctx_info *lreq = kzalloc(sizeof(struct lease_ctx_info), +- GFP_KERNEL); ++ struct lease_ctx_info *lreq; ++ ++ cc = smb2_find_context_vals(req, SMB2_CREATE_REQUEST_LEASE, 4); ++ if (IS_ERR_OR_NULL(cc)) ++ return NULL; ++ ++ lreq = kzalloc(sizeof(struct lease_ctx_info), GFP_KERNEL); + if (!lreq) + return NULL; + +- data_offset = (char *)req + le32_to_cpu(req->CreateContextsOffset); +- cc = (struct create_context *)data_offset; +- do { +- cc = (struct create_context *)((char *)cc + next); +- name = le16_to_cpu(cc->NameOffset) + (char *)cc; +- if (le16_to_cpu(cc->NameLength) != 4 || +- strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4)) { +- next = le32_to_cpu(cc->Next); +- continue; +- } +- found = true; +- break; +- } while (next != 0); +- +- if (found) { +- if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) { +- struct create_lease_v2 *lc = (struct create_lease_v2 *)cc; +- +- memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); +- lreq->req_state = lc->lcontext.LeaseState; +- lreq->flags = lc->lcontext.LeaseFlags; +- lreq->duration = lc->lcontext.LeaseDuration; +- memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey, +- SMB2_LEASE_KEY_SIZE); +- lreq->version = 2; +- } else { +- struct create_lease *lc = (struct create_lease *)cc; +- +- memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); +- lreq->req_state = lc->lcontext.LeaseState; +- lreq->flags = lc->lcontext.LeaseFlags; +- lreq->duration = lc->lcontext.LeaseDuration; +- lreq->version = 1; +- } +- return lreq; +- } ++ if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) { ++ struct create_lease_v2 *lc = (struct create_lease_v2 *)cc; + +- kfree(lreq); +- return NULL; ++ memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); ++ lreq->req_state = lc->lcontext.LeaseState; ++ lreq->flags = lc->lcontext.LeaseFlags; ++ lreq->duration = lc->lcontext.LeaseDuration; ++ memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey, ++ SMB2_LEASE_KEY_SIZE); ++ lreq->version = 2; ++ } else { ++ struct create_lease *lc = (struct create_lease *)cc; ++ ++ memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); ++ lreq->req_state = lc->lcontext.LeaseState; ++ lreq->flags = lc->lcontext.LeaseFlags; ++ lreq->duration = lc->lcontext.LeaseDuration; ++ lreq->version = 1; ++ } ++ return lreq; + } + + /** diff --git a/queue-6.1/series b/queue-6.1/series index 3d958ce88ab..03d6c7287ce 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -122,3 +122,6 @@ riscv-fix-kprobe-__user-string-arg-print-fault-issue.patch vduse-avoid-empty-string-for-dev-name.patch vhost-support-packed-when-setting-getting-vring_base.patch vhost_vdpa-support-packed-when-setting-getting-vring.patch +ksmbd-fix-out-of-bound-read-in-deassemble_neg_contexts.patch +ksmbd-fix-out-of-bound-read-in-parse_lease_state.patch +ksmbd-check-the-validation-of-pdu_size-in-ksmbd_conn_handler_loop.patch