Re: [PATCH] ksmbd: fix out-of-bound read in deassemble_neg_contexts

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



2023-05-25 21:18 GMT+09:00, 張智諺 <cc85nod@xxxxxxxxx>:
> `len_of_ctxts` is signed and 4 bytes (int), and `sizeof(struct
> smb2_neg_context)` is unsigned and 8 bytes (unsigned long).
>
> When comparing values with different size and different sign, first
> compiler will add instruction cdqe to extend small one to 8 bytes,
> then casting signed one to unsigned, which is `len_of_ctxts` in this case.
> So a negative `len_of_ctxts` will be viewed
> as a large unsigned value, which is totally larger than `sizeof(struct
> smb2_neg_context)`.
Okay, Can you update this check instead of adding new check ?

>
> I use program below to verify my guess:
>
> ```
> #include <stdio.h>
>
> int main()
> {
>     int a = -4;
>     unsigned long b = 0x8;
>
>     if (a < b)
>         printf("expected\n"); // will not print
> }
> ```
>
> Namjae Jeon <linkinjeon@xxxxxxxxxx> 於 2023年5月25日 週四 下午7:49寫道:
>
>> 2023-05-25 14:31 GMT+09:00, 張智諺 <cc85nod@xxxxxxxxx>:
>> > From 16b1d22ae886206def5fc71b26584c329755c81c Mon Sep 17 00:00:00 2001
>> > From: Chih-Yen Chang <cc85nod@xxxxxxxxx>
>> > Date: Thu, 25 May 2023 13:17:27 +0800
>> > Subject: [PATCH] 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.
>> >
>> > [   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
>> > ...
>> >
>> > Signed-off-by: Chih-Yen Chang <cc85nod@xxxxxxxxx>
>> > ---
>> >  fs/ksmbd/smb2pdu.c | 3 +++
>> >  1 file changed, 3 insertions(+)
>> >
>> > diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
>> > index cb93fd231..2d2a2eb96 100644
>> > --- a/fs/ksmbd/smb2pdu.c
>> > +++ b/fs/ksmbd/smb2pdu.c
>> > @@ -1030,6 +1030,9 @@ static __le32 deassemble_neg_contexts(struct
>> > ksmbd_conn *conn,
>> >   clen = (clen + 7) & ~0x7;
>> >   offset = clen + sizeof(struct smb2_neg_context);
>> >   len_of_ctxts -= clen + sizeof(struct smb2_neg_context);
>> > +
>> > + if (len_of_ctxts < 0)
>> > + break;
>>
>> There is a condition to check len_of_ctxts in this loop. How is this
>> check not making a break ?
>>                 if (len_of_ctxts < sizeof(struct smb2_neg_context))
>>                         break;
>> Thanks.
>> >   }
>> >   return status;
>> >  }
>> > --
>> > 2.39.2 (Apple Git-143)
>> >
>>
>




[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux