[PATCH] scsi: 3w-9xxx: validate ioctl data buffer sizes
From: Yousef Alhouseen
Date: Wed Jun 24 2026 - 15:29:36 EST
Several 3w-9xxx character ioctls read or write fixed-size structures in
the ioctl data buffer, but allocation is based only on the user supplied
buffer_length. A short buffer can make event, compatibility, or lock
commands access beyond the allocated coherent ioctl buffer.
Require the data buffer to be large enough for the fixed payload used by
each local ioctl before allocating and copying the full request.
Signed-off-by: Yousef Alhouseen <alhouseenyousef@xxxxxxxxx>
---
drivers/scsi/3w-9xxx.c | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 9b93a2440..a125801e3 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -653,6 +653,7 @@ static long twa_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long
ktime_t current_time;
TW_Device_Extension *tw_dev = twa_device_extension_list[iminor(inode)];
int retval = TW_IOCTL_ERROR_OS_EFAULT;
+ unsigned int min_data_length = 0;
void __user *argp = (void __user *)arg;
mutex_lock(&twa_chrdev_mutex);
@@ -673,6 +674,26 @@ static long twa_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long
goto out2;
}
+ switch (cmd) {
+ case TW_IOCTL_GET_COMPATIBILITY_INFO:
+ min_data_length = sizeof(TW_Compatibility_Info);
+ break;
+ case TW_IOCTL_GET_LAST_EVENT:
+ case TW_IOCTL_GET_FIRST_EVENT:
+ case TW_IOCTL_GET_NEXT_EVENT:
+ case TW_IOCTL_GET_PREVIOUS_EVENT:
+ min_data_length = sizeof(TW_Event);
+ break;
+ case TW_IOCTL_GET_LOCK:
+ min_data_length = sizeof(TW_Lock);
+ break;
+ }
+
+ if (driver_command.buffer_length < min_data_length) {
+ retval = TW_IOCTL_ERROR_OS_EINVAL;
+ goto out2;
+ }
+
/* Hardware can only do multiple of 512 byte transfers */
data_buffer_length_adjusted = (driver_command.buffer_length + 511) & ~511;
@@ -2302,4 +2323,3 @@ static void __exit twa_exit(void)
module_init(twa_init);
module_exit(twa_exit);
-
--
2.54.0