FAILED: patch "[PATCH] ksmbd: fix out-of-bound read in parse_lease_state()" failed to apply to 5.15-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x fc6c6a3c324c1b3e93a03d0cfa3749c781f23de0
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2023061210-shaft-wrangle-7b2d@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From fc6c6a3c324c1b3e93a03d0cfa3749c781f23de0 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <[email protected]>
Date: Sun, 28 May 2023 00:23:41 +0900
Subject: [PATCH] ksmbd: fix out-of-bound read in parse_lease_state()
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] <TASK> [ 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.
fs/smb/server/oplock.c +24 -42
@@ -1415,56 +1415,38 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)*/ 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 (sizeof (struct lease_context_v2 ) ==le32_to_cpu (cc->DataLength)) { +struct create_lease_v2 *lc = (struct create_lease_v2 *)cc; -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; -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; +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 ; } - -kfree (lreq); -return NULL ; +return lreq; }/**