⬢ DragonFlyBSD Kernel Audit
DF-5381 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/u4b/usb_busdma.c
+++ b/sys/bus/u4b/usb_busdma.c
@@ -86,6 +86,16 @@
 	if (pc->page_start) {
 		/* Case 1 - something has been loaded into DMA */
 
+		/* DF-5381: bound the offset by the loaded extent */
+		if (offset >= (usb_frlength_t)(pc->page_offset_end -
+		    pc->page_offset_buf)) {
+			res->buffer = NULL;
+			res->length = 0;
+#if USB_HAVE_BUSDMA
+			res->physaddr = 0;
+#endif
+			return;
+		}
 		if (pc->buffer) {
 			/* Case 1a - Kernel Virtual Address */
 
@@ -137,6 +147,9 @@
 	while (len != 0) {
 		usbd_get_page(cache, offset, &buf_res);
 
+		if (buf_res.length == 0)
+			break;		/* DF-5381: out of extent */
+
 		if (buf_res.length > len) {
 			buf_res.length = len;
 		}
@@ -166,6 +179,9 @@
 	while (len != 0) {
 		usbd_get_page(cache, offset, &buf_res);
 
+		if (buf_res.length == 0)
+			return (EFAULT);	/* DF-5381: out of extent */
+
 		if (buf_res.length > len) {
 			buf_res.length = len;
 		}
@@ -223,6 +239,11 @@
 	while (len != 0) {
 		usbd_get_page(pc, pc_offset, &res);
 
+		if (res.length == 0) {
+			error = EFAULT;		/* DF-5381: out of extent */
+			break;
+		}
+
 		if (res.length > len) {
 			res.length = len;
 		}
@@ -254,6 +275,9 @@
 	while (len != 0) {
 		usbd_get_page(cache, offset, &res);
 
+		if (res.length == 0)
+			break;		/* DF-5381: out of extent */
+
 		if (res.length > len) {
 			res.length = len;
 		}
@@ -283,6 +307,9 @@
 	while (len != 0) {
 		usbd_get_page(cache, offset, &res);
 
+		if (res.length == 0)
+			return (EFAULT);	/* DF-5381: out of extent */
+
 		if (res.length > len) {
 			res.length = len;
 		}
@@ -310,6 +337,9 @@
 	while (len != 0) {
 		usbd_get_page(cache, offset, &res);
 
+		if (res.length == 0)
+			break;		/* DF-5381: out of extent */
+
 		if (res.length > len) {
 			res.length = len;
 		}