Skip to content

Commit f1a4118

Browse files
namjaejeonSteve French
authored andcommitted
ksmbd: fix out-of-bound read in deassemble_neg_contexts()
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] <TASK> [ 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 <cc85nod@gmail.com> Tested-by: Chih-Yen Chang <cc85nod@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 8828003 commit f1a4118

File tree

1 file changed

+6
-7
lines changed

1 file changed

+6
-7
lines changed

fs/smb/server/smb2pdu.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -963,13 +963,13 @@ static void decode_sign_cap_ctxt(struct ksmbd_conn *conn,
963963

964964
static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
965965
struct smb2_negotiate_req *req,
966-
int len_of_smb)
966+
unsigned int len_of_smb)
967967
{
968968
/* +4 is to account for the RFC1001 len field */
969969
struct smb2_neg_context *pctx = (struct smb2_neg_context *)req;
970970
int i = 0, len_of_ctxts;
971-
int offset = le32_to_cpu(req->NegotiateContextOffset);
972-
int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);
971+
unsigned int offset = le32_to_cpu(req->NegotiateContextOffset);
972+
unsigned int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);
973973
__le32 status = STATUS_INVALID_PARAMETER;
974974

975975
ksmbd_debug(SMB, "decoding %d negotiate contexts\n", neg_ctxt_cnt);
@@ -983,7 +983,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
983983
while (i++ < neg_ctxt_cnt) {
984984
int clen, ctxt_len;
985985

986-
if (len_of_ctxts < sizeof(struct smb2_neg_context))
986+
if (len_of_ctxts < (int)sizeof(struct smb2_neg_context))
987987
break;
988988

989989
pctx = (struct smb2_neg_context *)((char *)pctx + offset);
@@ -1038,9 +1038,8 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
10381038
}
10391039

10401040
/* offsets must be 8 byte aligned */
1041-
clen = (clen + 7) & ~0x7;
1042-
offset = clen + sizeof(struct smb2_neg_context);
1043-
len_of_ctxts -= clen + sizeof(struct smb2_neg_context);
1041+
offset = (ctxt_len + 7) & ~0x7;
1042+
len_of_ctxts -= offset;
10441043
}
10451044
return status;
10461045
}

0 commit comments

Comments
 (0)