summaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth/hci_vhci.c
diff options
context:
space:
mode:
authorDan Carpenter <error27@gmail.com>2023-04-06 10:55:17 +0200
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2023-04-24 07:02:57 +0200
commite4eea890369c00dd58d97b1c066dc2bddf0da2c7 (patch)
tree06001e06d7ba7fd6d036b529714ae9429d50cd1a /drivers/bluetooth/hci_vhci.c
parentBluetooth: hci_qca: mark OF related data as maybe unused (diff)
downloadlinux-e4eea890369c00dd58d97b1c066dc2bddf0da2c7.tar.xz
linux-e4eea890369c00dd58d97b1c066dc2bddf0da2c7.zip
Bluetooth: vhci: Fix info leak in force_devcd_write()
There are a number of bugs here: 1) If "count" is less than sizeof(dump_data.data) then it copies uninitialized data. 2) If simple_write_to_buffer() returns -EFAULT then we run into a problem "ret < count" comparison. "count" is an unsigned long so the comparison is type promoted to unsigned long and the negative returns become high positive values. That also results in copying uninitialized data. 3) If "*ppos" is non-zero then the first part of the dump_data buffer is uninitialized. Using copy_from_user() instead of simple_write_to_buffer() is more appropriate here. Fixes: d5d5df6da0aa ("Bluetooth: Add vhci devcoredump support") Signed-off-by: Dan Carpenter <error27@gmail.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Diffstat (limited to 'drivers/bluetooth/hci_vhci.c')
-rw-r--r--drivers/bluetooth/hci_vhci.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 691fe93b1976..40e2b9fa11a2 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -323,17 +323,21 @@ static ssize_t force_devcd_write(struct file *file, const char __user *user_buf,
struct hci_dev *hdev = data->hdev;
struct sk_buff *skb = NULL;
struct devcoredump_test_data dump_data;
+ size_t data_size;
int ret;
- ret = simple_write_to_buffer(&dump_data, sizeof(dump_data), ppos,
- user_buf, count);
- if (ret < count)
- return ret;
+ if (count < offsetof(struct devcoredump_test_data, data) ||
+ count > sizeof(dump_data))
+ return -EINVAL;
+
+ if (copy_from_user(&dump_data, user_buf, count))
+ return -EFAULT;
- skb = alloc_skb(sizeof(dump_data.data), GFP_ATOMIC);
+ data_size = count - offsetof(struct devcoredump_test_data, data);
+ skb = alloc_skb(data_size, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
- skb_put_data(skb, &dump_data.data, sizeof(dump_data.data));
+ skb_put_data(skb, &dump_data.data, data_size);
hci_devcd_register(hdev, vhci_coredump, vhci_coredump_hdr, NULL);