DF-5104 / fix.diff
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; |