| From 27595e80a573667ee8954defa3be9ee701eee729 Mon Sep 17 00:00:00 2001 |
| From: Dan Carpenter <dan.carpenter@oracle.com> |
| Date: Tue, 26 Mar 2019 01:12:07 -0400 |
| Subject: media: wl128x: prevent two potential buffer overflows |
| |
| [ Upstream commit 9c2ccc324b3a6cbc865ab8b3e1a09e93d3c8ade9 ] |
| |
| Smatch marks skb->data as untrusted so it warns that "evt_hdr->dlen" |
| can copy up to 255 bytes and we only have room for two bytes. Even |
| if this comes from the firmware and we trust it, the new policy |
| generally is just to fix it as kernel hardenning. |
| |
| I can't test this code so I tried to be very conservative. I considered |
| not allowing "evt_hdr->dlen == 1" because it doesn't initialize the |
| whole variable but in the end I decided to allow it and manually |
| initialized "asic_id" and "asic_ver" to zero. |
| |
| Fixes: e8454ff7b9a4 ("[media] drivers:media:radio: wl128x: FM Driver Common sources") |
| |
| Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> |
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/media/radio/wl128x/fmdrv_common.c | 7 +++++-- |
| 1 file changed, 5 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c |
| index ebc73b0342496..51639a3f7abe4 100644 |
| --- a/drivers/media/radio/wl128x/fmdrv_common.c |
| +++ b/drivers/media/radio/wl128x/fmdrv_common.c |
| @@ -494,7 +494,8 @@ int fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload, |
| return -EIO; |
| } |
| /* Send response data to caller */ |
| - if (response != NULL && response_len != NULL && evt_hdr->dlen) { |
| + if (response != NULL && response_len != NULL && evt_hdr->dlen && |
| + evt_hdr->dlen <= payload_len) { |
| /* Skip header info and copy only response data */ |
| skb_pull(skb, sizeof(struct fm_event_msg_hdr)); |
| memcpy(response, skb->data, evt_hdr->dlen); |
| @@ -590,6 +591,8 @@ static void fm_irq_handle_flag_getcmd_resp(struct fmdev *fmdev) |
| return; |
| |
| fm_evt_hdr = (void *)skb->data; |
| + if (fm_evt_hdr->dlen > sizeof(fmdev->irq_info.flag)) |
| + return; |
| |
| /* Skip header info and copy only response data */ |
| skb_pull(skb, sizeof(struct fm_event_msg_hdr)); |
| @@ -1315,7 +1318,7 @@ static int load_default_rx_configuration(struct fmdev *fmdev) |
| static int fm_power_up(struct fmdev *fmdev, u8 mode) |
| { |
| u16 payload; |
| - __be16 asic_id, asic_ver; |
| + __be16 asic_id = 0, asic_ver = 0; |
| int resp_len, ret; |
| u8 fw_name[50]; |
| |
| -- |
| 2.20.1 |
| |