summaryrefslogtreecommitdiffstats
path: root/sys/geom/gate
diff options
context:
space:
mode:
authortrociny <trociny@FreeBSD.org>2011-03-27 19:56:55 +0000
committertrociny <trociny@FreeBSD.org>2011-03-27 19:56:55 +0000
commit42e994cbec564b754bf9f8246495852233198cae (patch)
tree74c038c0d8f0c581e8fad9b845988794253ba445 /sys/geom/gate
parentc0b9051b174edd52b1c981a25a28d77d5133a049 (diff)
downloadFreeBSD-src-42e994cbec564b754bf9f8246495852233198cae.zip
FreeBSD-src-42e994cbec564b754bf9f8246495852233198cae.tar.gz
In g_gate_create() there is a window between when g_gate_softc is
registered in g_gate_units array and when its sc_provider field is filled. If during this period g_gate_units is accessed by another thread that is checking for provider name collision the crash is possible. Fix this by adding sc_name field to struct g_gate_softc. In g_gate_create() when g_gate_softc is created but sc_provider is still not sc_name points to provider name stored in the local array. Approved by: pjd (mentor) Reported by: Freddie Cash <fjwcash@gmail.com> MFC after: 1 week
Diffstat (limited to 'sys/geom/gate')
-rw-r--r--sys/geom/gate/g_gate.c6
-rw-r--r--sys/geom/gate/g_gate.h2
2 files changed, 6 insertions, 2 deletions
diff --git a/sys/geom/gate/g_gate.c b/sys/geom/gate/g_gate.c
index 7951209..1eb02b6 100644
--- a/sys/geom/gate/g_gate.c
+++ b/sys/geom/gate/g_gate.c
@@ -409,13 +409,14 @@ g_gate_create(struct g_gate_ctl_create *ggio)
for (unit = 0; unit < g_gate_maxunits; unit++) {
if (g_gate_units[unit] == NULL)
continue;
- if (strcmp(name, g_gate_units[unit]->sc_provider->name) != 0)
+ if (strcmp(name, g_gate_units[unit]->sc_name) != 0)
continue;
mtx_unlock(&g_gate_units_lock);
mtx_destroy(&sc->sc_queue_mtx);
free(sc, M_GATE);
return (EEXIST);
}
+ sc->sc_name = name;
g_gate_units[sc->sc_unit] = sc;
g_gate_nunits++;
mtx_unlock(&g_gate_units_lock);
@@ -434,6 +435,9 @@ g_gate_create(struct g_gate_ctl_create *ggio)
sc->sc_provider = pp;
g_error_provider(pp, 0);
g_topology_unlock();
+ mtx_lock(&g_gate_units_lock);
+ sc->sc_name = sc->sc_provider->name;
+ mtx_unlock(&g_gate_units_lock);
if (sc->sc_timeout > 0) {
callout_reset(&sc->sc_callout, sc->sc_timeout * hz,
diff --git a/sys/geom/gate/g_gate.h b/sys/geom/gate/g_gate.h
index 4f41348..0a57ce3 100644
--- a/sys/geom/gate/g_gate.h
+++ b/sys/geom/gate/g_gate.h
@@ -76,6 +76,7 @@
* 'P:' means 'Protected by'.
*/
struct g_gate_softc {
+ char *sc_name; /* P: (read-only) */
int sc_unit; /* P: (read-only) */
int sc_ref; /* P: g_gate_list_mtx */
struct g_provider *sc_provider; /* P: (read-only) */
@@ -96,7 +97,6 @@ struct g_gate_softc {
LIST_ENTRY(g_gate_softc) sc_next; /* P: g_gate_list_mtx */
char sc_info[G_GATE_INFOSIZE]; /* P: (read-only) */
};
-#define sc_name sc_provider->geom->name
#define G_GATE_DEBUG(lvl, ...) do { \
if (g_gate_debug >= (lvl)) { \
OpenPOWER on IntegriCloud