From: Eli Billauer <eli.billauer@gmail.com>
To: gregkh@linuxfoundation.org
Cc: arnd@arndb.de, linux-kernel@vger.kernel.org, corbet@lwn.net,
Eli Billauer <eli.billauer@gmail.com>
Subject: [PATCH v4 6/7] char: xillybus: Add defensive sanity checks
Date: Wed, 5 Aug 2026 11:34:35 +0200 [thread overview]
Message-ID: <20260805093436.59740-7-eli.billauer@gmail.com> (raw)
In-Reply-To: <20260805093436.59740-1-eli.billauer@gmail.com>
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>
---
Notes:
Changelog:
=========
Changes v3->v4:
-- xillyusb.c: Use mutex_unlock() in response to sanity check failure
in fifo_init(), as guard() isn't used anymore on this
mutex.
-- xillyusb.c and xillybus_core.c: Remove sanity check on data count on
read() and write() fops methods, as this check is already
done by the kernel's vfs_read() and vfs_write().
Changes v2->v3:
-- Add Assisted-by tag to description
Changes v1->v2:
-- xillybus_class.c: Assign @rc a value before goto in
xillybus_init_chrdev().
-- xillybus_class.c: Improve check on @inode in xillybus_find_inode().
-- xillybus_of.c: Remove redundant dev_err(), as platform_get_irq()
outputs an error message if necessary.
drivers/char/xillybus/xillybus_class.c | 18 +++++++++++++--
drivers/char/xillybus/xillybus_class.h | 3 +++
drivers/char/xillybus/xillybus_core.c | 31 ++++++++++++++++++++++++--
drivers/char/xillybus/xillybus_of.c | 3 +++
drivers/char/xillybus/xillyusb.c | 25 ++++++++++++++++++++-
5 files changed, 75 insertions(+), 5 deletions(-)
diff --git a/drivers/char/xillybus/xillybus_class.c b/drivers/char/xillybus/xillybus_class.c
index 5e8f03b77064..f7e0da233e2a 100644
--- a/drivers/char/xillybus/xillybus_class.c
+++ b/drivers/char/xillybus/xillybus_class.c
@@ -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)
diff --git a/drivers/char/xillybus/xillybus_class.h b/drivers/char/xillybus/xillybus_class.h
index 5dbfdfc95c65..4dbed9adcaf8 100644
--- a/drivers/char/xillybus/xillybus_class.h
+++ b/drivers/char/xillybus/xillybus_class.h
@@ -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>
diff --git a/drivers/char/xillybus/xillybus_core.c b/drivers/char/xillybus/xillybus_core.c
index b264578b2572..6bc72d9dfb16 100644
--- a/drivers/char/xillybus/xillybus_core.c
+++ b/drivers/char/xillybus/xillybus_core.c
@@ -351,6 +351,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 > 0x40000000) {
+ 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 +629,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 +737,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 +1924,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);
diff --git a/drivers/char/xillybus/xillybus_of.c b/drivers/char/xillybus/xillybus_of.c
index 46e1046abfca..44b0c754deb2 100644
--- a/drivers/char/xillybus/xillybus_of.c
+++ b/drivers/char/xillybus/xillybus_of.c
@@ -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)
diff --git a/drivers/char/xillybus/xillyusb.c b/drivers/char/xillybus/xillyusb.c
index e2270a64b659..5b6a15962885 100644
--- a/drivers/char/xillybus/xillyusb.c
+++ b/drivers/char/xillybus/xillyusb.c
@@ -396,6 +396,12 @@ static int fifo_init(struct xillyfifo *fifo,
fifo->size = fifo->bufnum * fifo->bufsize;
fifo->buf_order = buf_order;
+ if (!fifo->size || /* Unsigned integer overflow */
+ fifo->size > 0x40000000) { /* 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) {
@@ -893,6 +899,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",
@@ -917,7 +924,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:
@@ -2077,6 +2087,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) {
@@ -2111,6 +2128,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)
--
2.34.1
next prev parent reply other threads:[~2026-08-05 9:35 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-05 9:34 [PATCH v4 0/7] char: xillybus: Harden driver and improve code quality Eli Billauer
2026-08-05 9:34 ` [PATCH v4 1/7] char: xillybus: Improve control of execution flow with mutexes Eli Billauer
2026-08-05 9:34 ` [PATCH v4 2/7] char: xillybus: Remove duplicate error path code Eli Billauer
2026-08-05 9:34 ` [PATCH v4 3/7] char: xillybus: Avoid possible bandwidth inefficiency Eli Billauer
2026-08-05 9:34 ` [PATCH v4 4/7] char: xillybus: Use unsigned arithmetic for jiffies differences Eli Billauer
2026-08-05 9:34 ` [PATCH v4 5/7] char: xillybus: Integer arithmetic improvements Eli Billauer
2026-08-05 9:34 ` Eli Billauer [this message]
2026-08-05 9:34 ` [PATCH v4 7/7] char: xillybus: Ignore and report unsolicited interrupts Eli Billauer
2026-08-05 11:03 ` [PATCH v4 0/7] char: xillybus: Harden driver and improve code quality Eli Billauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260805093436.59740-7-eli.billauer@gmail.com \
--to=eli.billauer@gmail.com \
--cc=arnd@arndb.de \
--cc=corbet@lwn.net \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox