mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
misc: bcm-vk: validate write size before allocation
bcm_vk_write() uses the user-supplied write count to size a flexible-array work entry and then copies count bytes into that array. The allocation expression is evaluated before any overflow check, so a very large count can wrap the allocation smaller than the subsequent copy. Reject empty writes, check the allocation arithmetic before kzalloc(), and initialize the __counted_by field before copying into to_v_msg[]. Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com> Link: https://patch.msgid.link/20260629160605.29412-1-alhouseenyousef@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
808e530654
commit
f66c40cd90
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
|
@ -1090,6 +1091,7 @@ ssize_t bcm_vk_write(struct file *p_file,
|
|||
u32 q_num;
|
||||
u32 msg_size;
|
||||
u32 msgq_size;
|
||||
size_t entry_size;
|
||||
|
||||
if (!bcm_vk_drv_access_ok(vk))
|
||||
return -EPERM;
|
||||
|
|
@ -1097,20 +1099,26 @@ ssize_t bcm_vk_write(struct file *p_file,
|
|||
dev_dbg(dev, "Msg count %zu\n", count);
|
||||
|
||||
/* first, do sanity check where count should be multiple of basic blk */
|
||||
if (count & (VK_MSGQ_BLK_SIZE - 1)) {
|
||||
dev_err(dev, "Failure with size %zu not multiple of %zu\n",
|
||||
if (!count || count & (VK_MSGQ_BLK_SIZE - 1)) {
|
||||
dev_err(dev, "Failure with size %zu not a positive multiple of %zu\n",
|
||||
count, VK_MSGQ_BLK_SIZE);
|
||||
rc = -EINVAL;
|
||||
goto write_err;
|
||||
}
|
||||
|
||||
if (check_add_overflow(sizeof(*entry), count, &entry_size) ||
|
||||
check_add_overflow(entry_size, vk->ib_sgl_size, &entry_size)) {
|
||||
rc = -EOVERFLOW;
|
||||
goto write_err;
|
||||
}
|
||||
|
||||
/* allocate the work entry + buffer for size count and inband sgl */
|
||||
entry = kzalloc(sizeof(*entry) + count + vk->ib_sgl_size,
|
||||
GFP_KERNEL);
|
||||
entry = kzalloc(entry_size, GFP_KERNEL);
|
||||
if (!entry) {
|
||||
rc = -ENOMEM;
|
||||
goto write_err;
|
||||
}
|
||||
entry->to_v_blks = count >> VK_MSGQ_BLK_SZ_SHIFT;
|
||||
|
||||
/* now copy msg from user space, and then formulate the work entry */
|
||||
if (copy_from_user(&entry->to_v_msg[0], buf, count)) {
|
||||
|
|
@ -1118,7 +1126,6 @@ ssize_t bcm_vk_write(struct file *p_file,
|
|||
goto write_free_ent;
|
||||
}
|
||||
|
||||
entry->to_v_blks = count >> VK_MSGQ_BLK_SZ_SHIFT;
|
||||
entry->ctx = ctx;
|
||||
|
||||
/* do a check on the blk size which could not exceed queue space */
|
||||
|
|
@ -1355,4 +1362,3 @@ void bcm_vk_msg_remove(struct bcm_vk *vk)
|
|||
bcm_vk_drain_all_pend(&vk->pdev->dev, &vk->to_v_msg_chan, NULL);
|
||||
bcm_vk_drain_all_pend(&vk->pdev->dev, &vk->to_h_msg_chan, NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user