DragonFlyBSD Kernel Audit
DF-2346 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/bus/u4b/usb_dev.c b/sys/bus/u4b/usb_dev.c
--- a/sys/bus/u4b/usb_dev.c
+++ b/sys/bus/u4b/usb_dev.c
@@ -798,6 +798,7 @@
 	if (f->async_p != NULL && lwkt_trytoken(&f->async_p->p_token)) {
 		ksignal(f->async_p, SIGIO);
 		lwkt_reltoken(&f->async_p->p_token);
+		PRELE(f->async_p);
 		f->async_p = NULL;
 	}
 	/* remove FWRITE and FREAD flags */
@@ -1037,13 +1038,22 @@
 
 	case FIOASYNC:
 		if (*(int *)addr) {
+			struct proc *p;
 			if (f->async_p != NULL) {
 				error = EBUSY;
 				break;
 			}
-			f->async_p = USB_TD_GET_PROC(td);
+			/* Take a reference so the proc cannot be reaped while a
+			 * FIFO still async-signals it (defense-in-depth until USB
+			 * adopts the refcounted struct sigio mechanism). */
+			p = USB_TD_GET_PROC(td);
+			PHOLD(p);
+			f->async_p = p;
 		} else {
+			struct proc *p = f->async_p;
 			f->async_p = NULL;
+			if (p != NULL)
+				PRELE(p);
 		}
 		break;