diff mbox series

[Linux-kernel-mentees] Fix uninit-value in hci_chan_lookup_handle

Message ID 20200905020410.20350-1-anant.thazhemadam@gmail.com (mailing list archive)
State New, archived
Headers show
Series [Linux-kernel-mentees] Fix uninit-value in hci_chan_lookup_handle | expand

Commit Message

Anant Thazhemadam Sept. 5, 2020, 2:04 a.m. UTC
When the amount of data stored in the location corresponding to
iov_iter *from is less then 4, some data seems to go uninitialized.

Updating this condition accordingly, makes sense both intuitively and 
logically as well, since the other check for extreme condition done is if
len > HCI_MAX_FRAME_SIZE, which is HCI_MAX_ACL_SIZE (which is 1024) + 4;
which itself gives some idea about what must be the ideal mininum size.

Reported-and-tested by: syzbot+4c14a8f574461e1c3659@syzkaller.appspotmail.com
Signed-off-by: Anant Thazhemadam <anant.thazhemadam@gmail.com>
---
If there is some explicit reason why len < 4 doesn't work, and only len < 2 works, 
please do let me know.
The commit message that introduced the initial change 
(512b2268156a4e15ebf897f9a883bdee153a54b7) wasn't exactly very helpful in this 
respect, and I couldn't find a whole lot of discussion regarding this either.

 drivers/bluetooth/hci_vhci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Anant Thazhemadam Sept. 25, 2020, 6 p.m. UTC | #1
On 05/09/20 7:34 am, Anant Thazhemadam wrote:
> When the amount of data stored in the location corresponding to
> iov_iter *from is less then 4, some data seems to go uninitialized.
>
> Updating this condition accordingly, makes sense both intuitively and 
> logically as well, since the other check for extreme condition done is if
> len > HCI_MAX_FRAME_SIZE, which is HCI_MAX_ACL_SIZE (which is 1024) + 4;
> which itself gives some idea about what must be the ideal mininum size.
>
> Reported-and-tested by: syzbot+4c14a8f574461e1c3659@syzkaller.appspotmail.com
> Signed-off-by: Anant Thazhemadam <anant.thazhemadam@gmail.com>
> ---
> If there is some explicit reason why len < 4 doesn't work, and only len < 2 works, 
> please do let me know.
> The commit message that introduced the initial change 
> (512b2268156a4e15ebf897f9a883bdee153a54b7) wasn't exactly very helpful in this 
> respect, and I couldn't find a whole lot of discussion regarding this either.
>
>  drivers/bluetooth/hci_vhci.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
> index 8ab26dec5f6e..0c49821d7b98 100644
> --- a/drivers/bluetooth/hci_vhci.c
> +++ b/drivers/bluetooth/hci_vhci.c
> @@ -159,7 +159,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
>  	__u8 pkt_type, opcode;
>  	int ret;
>  
> -	if (len < 2 || len > HCI_MAX_FRAME_SIZE)
> +	if (len < 4 || len > HCI_MAX_FRAME_SIZE)
>  		return -EINVAL;
>  
>  	skb = bt_skb_alloc(len, GFP_KERNEL);
Hi,

Looks like this patch might have missed the attention of those
who can tell me if this works or why it might not.
For some more context; more details about the bug can be found at
    https://syzkaller.appspot.com/bug?id=287b84cc1c834c7878c4193d7b18760067f10a77
I should've highlighted that in my initial mail. My apologies.

Thanks,
Anant
Marcel Holtmann Sept. 26, 2020, 7:46 a.m. UTC | #2
Hi Anant,

> When the amount of data stored in the location corresponding to
> iov_iter *from is less then 4, some data seems to go uninitialized.
> 
> Updating this condition accordingly, makes sense both intuitively and 
> logically as well, since the other check for extreme condition done is if
> len > HCI_MAX_FRAME_SIZE, which is HCI_MAX_ACL_SIZE (which is 1024) + 4;
> which itself gives some idea about what must be the ideal mininum size.
> 
> Reported-and-tested by: syzbot+4c14a8f574461e1c3659@syzkaller.appspotmail.com
> Signed-off-by: Anant Thazhemadam <anant.thazhemadam@gmail.com>
> ---
> If there is some explicit reason why len < 4 doesn't work, and only len < 2 works, 
> please do let me know.
> The commit message that introduced the initial change 
> (512b2268156a4e15ebf897f9a883bdee153a54b7) wasn't exactly very helpful in this 
> respect, and I couldn't find a whole lot of discussion regarding this either.
> 
> drivers/bluetooth/hci_vhci.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
> index 8ab26dec5f6e..0c49821d7b98 100644
> --- a/drivers/bluetooth/hci_vhci.c
> +++ b/drivers/bluetooth/hci_vhci.c
> @@ -159,7 +159,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
> 	__u8 pkt_type, opcode;
> 	int ret;
> 
> -	if (len < 2 || len > HCI_MAX_FRAME_SIZE)
> +	if (len < 4 || len > HCI_MAX_FRAME_SIZE)
> 		return -EINVAL;

so the minimum requirement is to have an 1 octet packet indicator. If some other functions are missing length checks, then it should be fixed there. I see that in case of HCI_VENDOR_PKT we need to check for the 2nd octet to be present, but I have no idea why you require 3 octets minimum. As I said, if so, then the other functions that get called require proper range checks.

Regards

Marcel
Anant Thazhemadam Oct. 1, 2020, 7:14 a.m. UTC | #3
On 26/09/20 1:16 pm, Marcel Holtmann wrote:
> Hi Anant,
>
>> When the amount of data stored in the location corresponding to
>> iov_iter *from is less then 4, some data seems to go uninitialized.
>>
>> Updating this condition accordingly, makes sense both intuitively and 
>> logically as well, since the other check for extreme condition done is if
>> len > HCI_MAX_FRAME_SIZE, which is HCI_MAX_ACL_SIZE (which is 1024) + 4;
>> which itself gives some idea about what must be the ideal mininum size.
>>
>> Reported-and-tested by: syzbot+4c14a8f574461e1c3659@syzkaller.appspotmail.com
>> Signed-off-by: Anant Thazhemadam <anant.thazhemadam@gmail.com>
>> ---
>> If there is some explicit reason why len < 4 doesn't work, and only len < 2 works, 
>> please do let me know.
>> The commit message that introduced the initial change 
>> (512b2268156a4e15ebf897f9a883bdee153a54b7) wasn't exactly very helpful in this 
>> respect, and I couldn't find a whole lot of discussion regarding this either.
>>
>> drivers/bluetooth/hci_vhci.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
>> index 8ab26dec5f6e..0c49821d7b98 100644
>> --- a/drivers/bluetooth/hci_vhci.c
>> +++ b/drivers/bluetooth/hci_vhci.c
>> @@ -159,7 +159,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
>> 	__u8 pkt_type, opcode;
>> 	int ret;
>>
>> -	if (len < 2 || len > HCI_MAX_FRAME_SIZE)
>> +	if (len < 4 || len > HCI_MAX_FRAME_SIZE)
>> 		return -EINVAL;
> so the minimum requirement is to have an 1 octet packet indicator. If some other functions are missing length checks, then it should be fixed there. I see that in case of HCI_VENDOR_PKT we need to check for the 2nd octet to be present, but I have no idea why you require 3 octets minimum. As I said, if so, then the other functions that get called require proper range checks.
>
> Regards
>
> Marcel

Ah, I see. That makes sense, and I'm sorry for this. I just thought since
HCI_MAX_FRAME_SIZE was 4 more than 1024, min. len might have to be 4.
Taking a look at the reproducer, it becomes evident that the only reason this
patch didn't trigger an issue was because the reproducer ran with len = 3.

I don't really have a strong enough clue yet about where things are going wrong, so I'd
appreciate any guidance/insight into this, and where I should be looking. :/

Also, although the bug says it is only an uninit-value, it eventually ends up triggering
a kernel panic (looking at a log rather than a report shows that as well).

Thanks,
Anant
diff mbox series

Patch

diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 8ab26dec5f6e..0c49821d7b98 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -159,7 +159,7 @@  static inline ssize_t vhci_get_user(struct vhci_data *data,
 	__u8 pkt_type, opcode;
 	int ret;
 
-	if (len < 2 || len > HCI_MAX_FRAME_SIZE)
+	if (len < 4 || len > HCI_MAX_FRAME_SIZE)
 		return -EINVAL;
 
 	skb = bt_skb_alloc(len, GFP_KERNEL);