⬢ DragonFlyBSD Kernel Audit
DF-5604 / fix.diff
← back to finding ↓ download raw
--- sys/bus/u4b/usb_util.c
+++ sys/bus/u4b/usb_util.c
@@ -66,6 +66,7 @@
 	struct usb_attach_arg *uaa;
 	struct usb_device *udev;
 	struct usb_interface *iface;
+	char buf[256];			/* stable snapshot of scratch string */
 	char *temp_p;
 	usb_error_t err;
 	uint8_t do_unlock;
@@ -108,11 +109,20 @@
 		    sizeof(udev->scratch.data));
 	}
 
+	/*
+	 * Snapshot the string while the enumeration lock is still held:
+	 * udev->scratch is shared by every enumeration path of this udev and
+	 * is only valid while the lock is owned.  Using it after the unlock
+	 * allows a concurrent usbd_req_get_string_any() to clobber the NUL
+	 * terminator, which makes the strlen()/strcpy() in
+	 * device_set_desc_copy() walk past the end of the scratch buffer.
+	 */
+	bcopy(temp_p, buf, sizeof(udev->scratch.data));
+	buf[sizeof(buf) - 1] = '\0';
+
 	if (do_unlock)
 		usbd_enum_unlock(udev);
 
-	device_set_desc_copy(dev, temp_p);
-	device_printf(dev, "<%s> on %s\n", temp_p,
+	device_set_desc_copy(dev, buf);
+	device_printf(dev, "<%s> on %s\n", buf,
 	    device_get_nameunit(udev->bus->bdev));
 }