From 05e7c07b9e38277dfd3c13d301456ab2ac07b875 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Wed, 23 Aug 2023 06:27:18 +0000 Subject: [PATCH] dk(4): Globally serialize dkwedge_add. There are too many intermediate unlocked states of dkwedge_add that can stomp on each other, and this is not likely to be a bottleneck even if serialized. Reported-by: syzbot+adb5376ba7044368655f@syzkaller.appspotmail.com --- sys/dev/dkwedge/dk.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sys/dev/dkwedge/dk.c b/sys/dev/dkwedge/dk.c index c201cdf815fc..2c5eb36d6608 100644 --- a/sys/dev/dkwedge/dk.c +++ b/sys/dev/dkwedge/dk.c @@ -73,7 +73,8 @@ typedef enum { /* * Lock order: * - * sc->sc_dk.dk_openlock + * dkwedge_add_lock + * => sc->sc_dk.dk_openlock * => sc->sc_parent->dk_rawlock * => sc->sc_parent->dk_openlock * => dkwedges_lock @@ -201,6 +202,7 @@ const struct cdevsw dk_cdevsw = { static struct dkwedge_softc **dkwedges; static u_int ndkwedges; static krwlock_t dkwedges_lock; +static kmutex_t dkwedge_add_lock; static LIST_HEAD(, dkwedge_discovery_method) dkwedge_discovery_methods; static krwlock_t dkwedge_discovery_methods_lock; @@ -439,6 +441,8 @@ dkwedge_add(struct dkwedge_info *dkw) if (dkw->dkw_offset < 0) return EINVAL; + mutex_enter(&dkwedge_add_lock); + /* * Check for an existing wedge at the same disk offset. Allow * updating a wedge if the only change is the size, and the new @@ -535,6 +539,7 @@ dkwedge_add(struct dkwedge_info *dkw) bufq_free(sc->sc_bufq); dkwedge_size_fini(sc); free(sc, M_DKWEDGE); + mutex_exit(&dkwedge_add_lock); return error; } @@ -592,6 +597,7 @@ dkwedge_add(struct dkwedge_info *dkw) bufq_free(sc->sc_bufq); dkwedge_size_fini(sc); free(sc, M_DKWEDGE); + mutex_exit(&dkwedge_add_lock); return error; } @@ -621,6 +627,7 @@ dkwedge_add(struct dkwedge_info *dkw) bufq_free(sc->sc_bufq); dkwedge_size_fini(sc); free(sc, M_DKWEDGE); + mutex_exit(&dkwedge_add_lock); return ENOMEM; } @@ -640,6 +647,7 @@ announce: sizeof(dkw->dkw_devname)); device_release(sc->sc_dev); + mutex_exit(&dkwedge_add_lock); return 0; } @@ -1024,6 +1032,7 @@ dkwedge_init(void) struct dkwedge_discovery_method *lddm, *ddm; rw_init(&dkwedges_lock); + mutex_init(&dkwedge_add_lock, MUTEX_DEFAULT, IPL_NONE); rw_init(&dkwedge_discovery_methods_lock); if (config_cfdriver_attach(&dk_cd) != 0)