lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260130170416.49994-2-abbotti@mev.co.uk>
Date: Fri, 30 Jan 2026 16:47:26 +0000
From: Ian Abbott <abbotti@....co.uk>
To: linux-kernel@...r.kernel.org
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
	Ian Abbott <abbotti@....co.uk>,
	H Hartley Sweeten <hsweeten@...ionengravers.com>
Subject: [PATCH 01/46] comedi: add comedi_check_request_region()

There is an existing comedi_request_region(dev, start, len) function
used by COMEDI drivers for legacy devices to request an I/O port region
starting at a specified base address (which must be non-zero) and with a
specified length.  It uses request_region().  On success, it sets
dev->iobase and dev->iolen and returns 0.  There is a alternative
function __comedi_request_region(dev, start, len) which does the same
thing without setting dev->iobase and dev->iolen.

Most hardware devices have restrictions on the allowed I/O port base
address and alignment, so add new functions
comedi_check_request_region(dev, start, len, minstart, maxend, minalign)
and __comedi_check_request_region(dev, start, len, minstart, maxend,
minalign) to perform these additional checks.  Turn the original
functions into static inline wrapper functions that call the new
functions.

Signed-off-by: Ian Abbott <abbotti@....co.uk>
---
 drivers/comedi/drivers.c         | 46 ++++++++++++++++++++-------
 include/linux/comedi/comedidev.h | 53 +++++++++++++++++++++++++++++---
 2 files changed, 84 insertions(+), 15 deletions(-)

diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
index 69cd2a253c66..316cb510b89b 100644
--- a/drivers/comedi/drivers.c
+++ b/drivers/comedi/drivers.c
@@ -933,19 +933,24 @@ int comedi_load_firmware(struct comedi_device *dev,
 EXPORT_SYMBOL_GPL(comedi_load_firmware);
 
 /**
- * __comedi_request_region() - Request an I/O region for a legacy driver
+ * __comedi_check_request_region() - Request an I/O region for a legacy driver
  * @dev: COMEDI device.
  * @start: Base address of the I/O region.
  * @len: Length of the I/O region.
+ * @minstart: Minimum allowed start address of region.
+ * @maxend: Maximum allowed region end address of region.
+ * @minalign: Required alignment for base address.
  *
  * Requests the specified I/O port region which must start at a non-zero
- * address.
+ * address, must fall within specified bounds, and must be correctly aligned.
  *
  * Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request
  * fails.
  */
-int __comedi_request_region(struct comedi_device *dev,
-			    unsigned long start, unsigned long len)
+int __comedi_check_request_region(struct comedi_device *dev,
+				  unsigned long start, unsigned long len,
+				  unsigned long minstart, unsigned long maxend,
+				  unsigned long minalign)
 {
 	if (!start) {
 		dev_warn(dev->class_dev,
@@ -954,6 +959,19 @@ int __comedi_request_region(struct comedi_device *dev,
 		return -EINVAL;
 	}
 
+	if (start < minstart || start > maxend || maxend - start < len - 1) {
+		dev_warn(dev->class_dev,
+			 "%s: I/O base address or length out of range\n",
+			 dev->board_name);
+		return -EINVAL;
+	}
+	if (!IS_ALIGNED(start, minalign)) {
+		dev_warn(dev->class_dev,
+			 "%s: I/O base address not correctly aligned\n",
+			 dev->board_name);
+		return -EINVAL;
+	}
+
 	if (!request_region(start, len, dev->board_name)) {
 		dev_warn(dev->class_dev, "%s: I/O port conflict (%#lx,%lu)\n",
 			 dev->board_name, start, len);
@@ -962,16 +980,19 @@ int __comedi_request_region(struct comedi_device *dev,
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(__comedi_request_region);
+EXPORT_SYMBOL_GPL(__comedi_check_request_region);
 
 /**
- * comedi_request_region() - Request an I/O region for a legacy driver
+ * comedi_check_request_region() - Request an I/O region for a legacy driver
  * @dev: COMEDI device.
  * @start: Base address of the I/O region.
  * @len: Length of the I/O region.
+ * @minstart: Minimum allowed start address of region.
+ * @maxend: Maximum allowed region end address of region.
+ * @minalign: Required alignment for base address.
  *
  * Requests the specified I/O port region which must start at a non-zero
- * address.
+ * address, must fall within specified bounds, and must be correctly aligned.
  *
  * On success, @dev->iobase is set to the base address of the region and
  * @dev->iolen is set to its length.
@@ -979,12 +1000,15 @@ EXPORT_SYMBOL_GPL(__comedi_request_region);
  * Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request
  * fails.
  */
-int comedi_request_region(struct comedi_device *dev,
-			  unsigned long start, unsigned long len)
+int comedi_check_request_region(struct comedi_device *dev,
+				unsigned long start, unsigned long len,
+				unsigned long minstart, unsigned long maxend,
+				unsigned long minalign)
 {
 	int ret;
 
-	ret = __comedi_request_region(dev, start, len);
+	ret = __comedi_check_request_region(dev, start, len, minstart, maxend,
+					    minalign);
 	if (ret == 0) {
 		dev->iobase = start;
 		dev->iolen = len;
@@ -992,7 +1016,7 @@ int comedi_request_region(struct comedi_device *dev,
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(comedi_request_region);
+EXPORT_SYMBOL_GPL(comedi_check_request_region);
 
 /**
  * comedi_legacy_detach() - A generic (*detach) function for legacy drivers
diff --git a/include/linux/comedi/comedidev.h b/include/linux/comedi/comedidev.h
index 35fdc41845ce..577a08f37aee 100644
--- a/include/linux/comedi/comedidev.h
+++ b/include/linux/comedi/comedidev.h
@@ -1026,10 +1026,55 @@ int comedi_load_firmware(struct comedi_device *dev, struct device *hw_dev,
 				   unsigned long context),
 			 unsigned long context);
 
-int __comedi_request_region(struct comedi_device *dev,
-			    unsigned long start, unsigned long len);
-int comedi_request_region(struct comedi_device *dev,
-			  unsigned long start, unsigned long len);
+int __comedi_check_request_region(struct comedi_device *dev,
+				  unsigned long start, unsigned long len,
+				  unsigned long minstart, unsigned long maxend,
+				  unsigned long minalign);
+int comedi_check_request_region(struct comedi_device *dev,
+				unsigned long start, unsigned long len,
+				unsigned long minstart, unsigned long maxend,
+				unsigned long minalign);
+
+/**
+ * __comedi_request_region() - Request an I/O region for a legacy driver
+ * @dev: COMEDI device.
+ * @start: Base address of the I/O region.
+ * @len: Length of the I/O region.
+ *
+ * Requests the specified I/O port region which must start at a non-zero
+ * address.
+ *
+ * Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request
+ * fails.
+ */
+static inline int __comedi_request_region(struct comedi_device *dev,
+					  unsigned long start,
+					  unsigned long len)
+{
+	return __comedi_check_request_region(dev, start, len, 0, ~0ul, 1);
+}
+
+/**
+ * comedi_request_region() - Request an I/O region for a legacy driver
+ * @dev: COMEDI device.
+ * @start: Base address of the I/O region.
+ * @len: Length of the I/O region.
+ *
+ * Requests the specified I/O port region which must start at a non-zero
+ * address.
+ *
+ * On success, @dev->iobase is set to the base address of the region and
+ * @dev->iolen is set to its length.
+ *
+ * Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request
+ * fails.
+ */
+static inline int comedi_request_region(struct comedi_device *dev,
+					unsigned long start, unsigned long len)
+{
+	return comedi_check_request_region(dev, start, len, 0, ~0ul, 1);
+}
+
 void comedi_legacy_detach(struct comedi_device *dev);
 
 int comedi_auto_config(struct device *hardware_device,
-- 
2.51.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ