mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
char: xillybus: Add defensive sanity checks
Add validation checks for values derived from hardware or user input to prevent incorrect behavior with malformed data. Assisted-by: Deepseek:v4-pro Kimi:K2.6 ChatGPT:GPT-5.5 Claude:Sonnet-4.6 Signed-off-by: Eli Billauer <eli.billauer@gmail.com> Link: https://patch.msgid.link/20261009074557.19996-7-eli.billauer@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
04b47d2005
commit
1ce74f6f22
|
|
@ -57,6 +57,9 @@ int xillybus_init_chrdev(struct device *dev,
|
|||
size_t namelen;
|
||||
struct xilly_unit *unit, *u;
|
||||
|
||||
if (num_nodes <= 0 || num_nodes > XILLYBUS_MAX_NODES || !idt || !prefix || !dev)
|
||||
return -ENODEV;
|
||||
|
||||
unit = kzalloc_obj(*unit);
|
||||
|
||||
if (!unit)
|
||||
|
|
@ -68,6 +71,12 @@ int xillybus_init_chrdev(struct device *dev,
|
|||
snprintf(unit->name, UNITNAMELEN, "%s", prefix);
|
||||
|
||||
for (i = 0; enumerate; i++) {
|
||||
if (i > 99) {
|
||||
dev_err(dev, "Failed to obtain unique unit name\n");
|
||||
rc = -ENODEV;
|
||||
goto fail_obtain;
|
||||
}
|
||||
|
||||
snprintf(unit->name, UNITNAMELEN, "%s_%02d",
|
||||
prefix, i);
|
||||
|
||||
|
|
@ -215,10 +224,15 @@ EXPORT_SYMBOL(xillybus_cleanup_chrdev);
|
|||
int xillybus_find_inode(struct inode *inode,
|
||||
void **private_data, int *index)
|
||||
{
|
||||
int minor = iminor(inode);
|
||||
int major = imajor(inode);
|
||||
int minor, major;
|
||||
struct xilly_unit *unit = NULL, *iter;
|
||||
|
||||
if (!inode || !private_data || !index)
|
||||
return -ENODEV;
|
||||
|
||||
minor = iminor(inode);
|
||||
major = imajor(inode);
|
||||
|
||||
mutex_lock(&unit_mutex);
|
||||
|
||||
list_for_each_entry(iter, &unit_list, list_entry)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
#ifndef __XILLYBUS_CLASS_H
|
||||
#define __XILLYBUS_CLASS_H
|
||||
|
||||
#define XILLYBUS_MAX_NODES 1024
|
||||
#define XILLYBUS_MAX_IDT 1048576
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/sizes.h>
|
||||
#include "xillybus.h"
|
||||
#include "xillybus_class.h"
|
||||
|
||||
|
|
@ -351,6 +352,12 @@ static int xilly_get_dma_buffers(struct xilly_endpoint *ep,
|
|||
struct device *dev = ep->dev;
|
||||
struct xilly_buffer *this_buffer = NULL; /* Init to silence warning */
|
||||
|
||||
if (bytebufsize == 0 || bytebufsize > SZ_1G) {
|
||||
dev_err(ep->dev,
|
||||
"Illegal buffer size requested in IDT. Aborting.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (buffers) { /* Not the message buffer */
|
||||
this_buffer = devm_kcalloc(dev, bufnum,
|
||||
sizeof(struct xilly_buffer),
|
||||
|
|
@ -623,6 +630,12 @@ static int xilly_scan_idt(struct xilly_endpoint *endpoint,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (count == 0 || count > XILLYBUS_MAX_NODES) {
|
||||
dev_err(endpoint->dev,
|
||||
"Unreasonable number of channels. Aborting.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
idt_handle->entries = len >> 2;
|
||||
endpoint->num_channels = count;
|
||||
|
||||
|
|
@ -725,8 +738,18 @@ static ssize_t xillybus_read(struct file *filp, char __user *userbuf,
|
|||
bufidx = channel->wr_host_buf_idx;
|
||||
bufpos = channel->wr_host_buf_pos;
|
||||
howmany = ((channel->wr_buffers[bufidx]->end_offset
|
||||
+ 1) << channel->log2_element_size)
|
||||
- bufpos;
|
||||
+ 1) << channel->log2_element_size);
|
||||
|
||||
if (howmany > channel->wr_buf_size ||
|
||||
howmany < bufpos) {
|
||||
dev_err(channel->endpoint->dev,
|
||||
"Illegal buffer fill level from hardware\n");
|
||||
channel->endpoint->fatal_error = 1;
|
||||
spin_unlock_irqrestore(&channel->wr_spinlock, flags);
|
||||
break;
|
||||
}
|
||||
|
||||
howmany -= bufpos;
|
||||
|
||||
/* Update wr_host_* to its post-operation state */
|
||||
if (howmany > bytes_to_do) {
|
||||
|
|
@ -1902,6 +1925,11 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (endpoint->idtlen < 4 || endpoint->idtlen > XILLYBUS_MAX_IDT) {
|
||||
dev_err(endpoint->dev, "Invalid IDT length. Aborting.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Enable DMA */
|
||||
iowrite32((u32) (0x0002 | (endpoint->dma_using_dac & 0x0001)),
|
||||
endpoint->registers + fpga_dma_control_reg);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ static int xilly_drv_probe(struct platform_device *op)
|
|||
|
||||
irq = platform_get_irq(op, 0);
|
||||
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
rc = devm_request_irq(dev, irq, xillybus_isr, 0, xillyname, endpoint);
|
||||
|
||||
if (rc)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/delay.h>
|
||||
|
|
@ -389,6 +390,12 @@ static int fifo_init(struct xillyfifo *fifo,
|
|||
fifo->bufnum = 1 << log2_bufnum;
|
||||
fifo->size = fifo->bufnum * fifo->bufsize;
|
||||
|
||||
if (!fifo->size || /* Unsigned integer overflow */
|
||||
fifo->size > SZ_1G) { /* Avoid signed int issues */
|
||||
mutex_unlock(&fifo_buf_order_mutex);
|
||||
return -ENOMEM; /* Reported as greed for memory */
|
||||
}
|
||||
|
||||
fifo->mem = kmalloc_array(fifo->bufnum, sizeof(void *), GFP_KERNEL);
|
||||
|
||||
if (!fifo->mem) {
|
||||
|
|
@ -882,6 +889,7 @@ static int process_in_opcode(struct xillyusb_dev *xdev,
|
|||
struct xillyusb_channel *chan;
|
||||
struct device *dev = xdev->dev;
|
||||
int chan_idx = chan_num >> 1;
|
||||
struct xillyfifo *in_fifo;
|
||||
|
||||
if (chan_idx >= xdev->num_channels) {
|
||||
dev_err(dev, "Received illegal channel ID %d from FPGA\n",
|
||||
|
|
@ -906,7 +914,10 @@ static int process_in_opcode(struct xillyusb_dev *xdev,
|
|||
*/
|
||||
smp_wmb();
|
||||
WRITE_ONCE(chan->read_data_ok, 0);
|
||||
wake_up_interruptible(&chan->in_fifo->waitq);
|
||||
|
||||
in_fifo = READ_ONCE(chan->in_fifo);
|
||||
if (in_fifo)
|
||||
wake_up_interruptible(&in_fifo->waitq);
|
||||
break;
|
||||
|
||||
case OPCODE_REACHED_CHECKPOINT:
|
||||
|
|
@ -2066,6 +2077,13 @@ static int xillyusb_discovery(struct usb_interface *interface)
|
|||
}
|
||||
|
||||
idt_len = READ_ONCE(idt_fifo.fill);
|
||||
|
||||
if (idt_len < 4 || idt_len > XILLYBUS_MAX_IDT) {
|
||||
rc = -ENODEV;
|
||||
dev_err(&interface->dev, "Invalid IDT length. Aborting.\n");
|
||||
goto unfifo;
|
||||
}
|
||||
|
||||
idt = kmalloc(idt_len, GFP_KERNEL);
|
||||
|
||||
if (!idt) {
|
||||
|
|
@ -2100,6 +2118,12 @@ static int xillyusb_discovery(struct usb_interface *interface)
|
|||
goto unidt;
|
||||
}
|
||||
|
||||
if (num_channels == 0 || num_channels > XILLYBUS_MAX_NODES) {
|
||||
dev_err(&interface->dev, "Unreasonable number of channels. Aborting.\n");
|
||||
rc = -ENODEV;
|
||||
goto unidt;
|
||||
}
|
||||
|
||||
rc = setup_channels(xdev, (void *)idt + 3, num_channels);
|
||||
|
||||
if (rc)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user