⬢ DragonFlyBSD Kernel Audit
DF-5104 / fix.diff
← back to finding ↓ download raw
fix.diff — DF-5104: never hand consumers a raw integer as a pointer, and
bound the LED name copy. Authored post-verification against the read-only
sys/ tree; NOT applied there.

- gpio.c (GPIOATTACH): translate GPIO_TYPE_INT to a decimal string before
  entering the consumer API, so `void *arg` is always a real, NUL-terminated
  kernel string pointer.
- gpio_led.c (led_attach): replace the unbounded kstrdup() with an explicit
  bounded copy of the 32-byte GPIOATTACH string field (which the framework
  guarantees is a valid pointer to >=32 readable bytes after the gpio.c
  change), force-terminated at 32.

--- a/sys/dev/misc/gpio/gpio.c
+++ b/sys/dev/misc/gpio/gpio.c
@@ -468,11 +468,20 @@ gpio_master_ioctl(struct dev_ioctl_args *ap)
 	case GPIOATTACH:
 		gpaa = (struct gpio_attach_args *)ap->a_data;
-		error = gpio_consumer_attach(gpaa->consumer_name,
-		    (gpaa->arg_type == GPIO_TYPE_INT)?
-		    ((void *)gpaa->consumer_arg.lint):
-		    (gpaa->consumer_arg.string),
-		    gp, gpaa->pin_offset, gpaa->pin_mask);
+		if (gpaa->arg_type == GPIO_TYPE_INT) {
+			/* Never pass a raw integer to consumers as a pointer. */
+			char buf[24];
+			ksnprintf(buf, sizeof(buf), "%ld",
+			    gpaa->consumer_arg.lint);
+			error = gpio_consumer_attach(gpaa->consumer_name, buf,
+			    gp, gpaa->pin_offset, gpaa->pin_mask);
+		} else {
+			error = gpio_consumer_attach(gpaa->consumer_name,
+			    gpaa->consumer_arg.string, gp,
+			    gpaa->pin_offset, gpaa->pin_mask);
+		}
 		break;

--- a/sys/dev/misc/gpio/gpio_led.c
+++ b/sys/dev/misc/gpio/gpio_led.c
@@ -190,8 +190,11 @@ led_attach(struct gpio *gp, void *arg, int pin, u_int32_t mask)
 	lockmgr(&led_lock, LK_EXCLUSIVE);
 	sc = kmalloc(sizeof(struct ledsc), M_LED, M_WAITOK);

 	/* XXX: check for name collisions */
-	sc->name = kstrdup((char *)arg, M_LED);
+	/* arg is the 32-byte, not necessarily NUL-terminated GPIOATTACH
+	 * string; copy bounded and force termination. */
+	sc->name = kmalloc(32 + 1, M_LED, M_WAITOK);
+	memcpy(sc->name, (const char *)arg, 32);
+	sc->name[32] = '\0';
 	sc->pin = pin;