Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pad pad(4): Explain what's wrong with using device p...
details: https://anonhg.NetBSD.org/src/rev/d910f8935247
branches: trunk
changeset: 1021721:d910f8935247
user: riastradh <riastradh%NetBSD.org@localhost>
date: Mon Jun 14 18:44:53 2021 +0000
description:
pad(4): Explain what's wrong with using device pointers like this.
...and why the kernel lock is not enough.
diffstat:
sys/dev/pad/pad.c | 34 ++++++++++++++++++++++++++++++++--
1 files changed, 32 insertions(+), 2 deletions(-)
diffs (55 lines):
diff -r 39123708e787 -r d910f8935247 sys/dev/pad/pad.c
--- a/sys/dev/pad/pad.c Mon Jun 14 18:44:45 2021 +0000
+++ b/sys/dev/pad/pad.c Mon Jun 14 18:44:53 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pad.c,v 1.74 2021/06/14 18:44:45 riastradh Exp $ */
+/* $NetBSD: pad.c,v 1.75 2021/06/14 18:44:53 riastradh Exp $ */
/*-
* Copyright (c) 2007 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.74 2021/06/14 18:44:45 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.75 2021/06/14 18:44:53 riastradh Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -386,6 +386,36 @@
device_t self = sc->sc_dev;
cfdata_t cf = device_cfdata(self);
+ /*
+ * XXX This is not quite enough to prevent racing with drvctl
+ * detach. What can happen:
+ *
+ * cpu0 cpu1
+ *
+ * pad_close
+ * take kernel lock
+ * sc->sc_open = 0
+ * drop kernel lock
+ * wait for config_misc_lock
+ * drvctl detach
+ * take kernel lock
+ * drop kernel lock
+ * wait for config_misc_lock
+ * retake kernel lock
+ * drop config_misc_lock
+ * take config_misc_lock
+ * wait for kernel lock
+ * pad_detach (sc_open=0 already)
+ * free device
+ * drop kernel lock
+ * use device after free
+ *
+ * We need a way to grab a reference to the device so it won't
+ * be freed until we're done -- it's OK if we config_detach
+ * twice as long as it's idempotent, but not OK if the first
+ * config_detach frees the struct device before the second one
+ * has finished handling it.
+ */
KERNEL_LOCK(1, NULL);
KASSERT(sc->sc_open);
sc->sc_open = 0;
Home |
Main Index |
Thread Index |
Old Index