diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2017-06-14 16:57:48 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2017-06-14 16:57:48 +0000 |
commit | 729e7a304f7bf0a1d31e61b02820c2cfcbe66641 (patch) | |
tree | ae724aa9f9a3df7e5955ea21d8c1fa48e0908334 | |
parent | 2e237754baf486576ff69c2ac5e4f6e1230643f0 (diff) |
When a task in iwm(4) obtains an rwlock(9), bail out if the device was
reset while the task was asleep waiting for the lock.
ok deraadt@
-rw-r--r-- | sys/dev/pci/if_iwm.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c index 1edfdd72179..71145d801ad 100644 --- a/sys/dev/pci/if_iwm.c +++ b/sys/dev/pci/if_iwm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwm.c,v 1.194 2017/06/14 16:56:50 stsp Exp $ */ +/* $OpenBSD: if_iwm.c,v 1.195 2017/06/14 16:57:47 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh <info@genua.de> @@ -6268,16 +6268,19 @@ iwm_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct iwm_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; struct ifreq *ifr; - int s, err = 0; + int s, err = 0, generation = sc->sc_generation; /* * Prevent processes from entering this function while another * process is tsleep'ing in it. */ err = rw_enter(&sc->ioctl_rwl, RW_WRITE | RW_INTR); + if (err == 0 && generation != sc->sc_generation) { + rw_exit(&sc->ioctl_rwl); + return ENXIO; + } if (err) return err; - s = splnet(); switch (cmd) { @@ -7438,8 +7441,13 @@ iwm_init_task(void *arg1) struct iwm_softc *sc = arg1; struct ifnet *ifp = &sc->sc_ic.ic_if; int s; + int generation = sc->sc_generation; rw_enter_write(&sc->ioctl_rwl); + if (generation != sc->sc_generation) { + rw_exit(&sc->ioctl_rwl); + return; + } s = splnet(); if (sc->sc_flags & IWM_FLAG_HW_INITED) |