diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index b5d4a168f2ff..f996b0608561 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -391,11 +391,12 @@ static struct dev_softc int inuse; int nonblock; int queued; + int async; struct mtx mtx; struct cv cv; struct selinfo sel; struct devq devq; - struct proc *async_proc; + struct sigio *sigio; } devsoftc; static struct cdev *devctl_dev; @@ -422,7 +423,7 @@ devopen(struct cdev *dev, int oflags, int devtype, struct thread *td) /* move to init */ devsoftc.inuse = 1; devsoftc.nonblock = 0; - devsoftc.async_proc = NULL; + devsoftc.async = 0; mtx_unlock(&devsoftc.mtx); return (0); } @@ -433,8 +434,8 @@ devclose(struct cdev *dev, int fflag, int devtype, struct thread *td) mtx_lock(&devsoftc.mtx); devsoftc.inuse = 0; - devsoftc.async_proc = NULL; cv_broadcast(&devsoftc.cv); + funsetown(&devsoftc.sigio); mtx_unlock(&devsoftc.mtx); return (0); } @@ -490,33 +491,21 @@ devioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *t devsoftc.nonblock = 0; return (0); case FIOASYNC: - /* - * FIXME: - * Since this is a simple assignment there is no guarantee that - * devsoftc.async_proc consumers will get a valid pointer. - * - * Example scenario where things break (processes A and B): - * 1. A opens devctl - * 2. A sends fd to B - * 3. B sets itself as async_proc - * 4. B exits - * - * However, normally this requires root privileges and the only - * in-tree consumer does not behave in a dangerous way so the - * issue is not critical. - */ if (*(int*)data) - devsoftc.async_proc = td->td_proc; + devsoftc.async = 1; else - devsoftc.async_proc = NULL; + devsoftc.async = 0; + return (0); + case FIOSETOWN: + return fsetown(*(int *)data, &devsoftc.sigio); + case FIOGETOWN: + *(int *)data = fgetown(&devsoftc.sigio); return (0); /* (un)Support for other fcntl() calls. */ case FIOCLEX: case FIONCLEX: case FIONREAD: - case FIOSETOWN: - case FIOGETOWN: default: break; } @@ -560,7 +549,6 @@ void devctl_queue_data_f(char *data, int flags) { struct dev_event_info *n1 = NULL, *n2 = NULL; - struct proc *p; if (strlen(data) == 0) goto out; @@ -590,13 +578,8 @@ devctl_queue_data_f(char *data, int flags) cv_broadcast(&devsoftc.cv); mtx_unlock(&devsoftc.mtx); selwakeup(&devsoftc.sel); - /* XXX see a comment in devioctl */ - p = devsoftc.async_proc; - if (p != NULL) { - PROC_LOCK(p); - kern_psignal(p, SIGIO); - PROC_UNLOCK(p); - } + if (devsoftc.async && devsoftc.sigio != NULL) + pgsigio(&devsoftc.sigio, SIGIO, 0); return; out: /*