changeset 754:389216c34b53

synch: each rwlock should contain a magic number Much like the (mutex) lock and condition variable structures, this magic number is simply the pointer to the rwlock itself. This trivially catches three issues: (1) rwlocks getting clobbered (2) rwlocks getting moved around (via memmove/memcpy) (3) rwlocks used by lock/unlock after a destroy Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Thu, 25 Jul 2019 10:55:43 -0400
parents eadcec7390ee
children 607f480900f2
files include/jeffpc/synch.h synch.c
diffstat 2 files changed, 65 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/include/jeffpc/synch.h	Thu Jul 25 11:24:45 2019 -0400
+++ b/include/jeffpc/synch.h	Thu Jul 25 10:55:43 2019 -0400
@@ -64,6 +64,7 @@
 
 struct rwlock {
 	pthread_rwlock_t lock;
+	uintptr_t magic;
 };
 
 struct cond {
--- a/synch.c	Thu Jul 25 11:24:45 2019 -0400
+++ b/synch.c	Thu Jul 25 10:55:43 2019 -0400
@@ -105,6 +105,8 @@
 
 #define GENERATE_LOCK_MASK_ARGS(l)						\
 	((l)->magic != (uintptr_t) (l)) ? 'M' : '.'
+#define GENERATE_RW_MASK_ARGS(l)						\
+	((l)->magic != (uintptr_t) (l)) ? 'M' : '.'
 #define GENERATE_COND_MASK_ARGS(c)						\
 	((c)->magic != (uintptr_t) (c)) ? 'M' : '.'
 
@@ -121,6 +123,14 @@
 		where->file, where->line);
 }
 
+static void print_rw(struct rwlock *lock, const struct lock_context *where)
+{
+	cmn_err(CE_CRIT, "lockdep:     %p <%c> at %s:%d",
+		lock,
+		GENERATE_RW_MASK_ARGS(lock),
+		where->file, where->line);
+}
+
 static void print_cond(struct cond *cond, const struct lock_context *where)
 {
 	cmn_err(CE_CRIT, "lockdep:     %p <%c> at %s:%d",
@@ -389,6 +399,17 @@
 	panic("lockdep: Aborting - bad lock magic");
 }
 
+static void check_rw_magic(struct rwlock *lock, const char *op,
+			   const struct lock_context *where)
+{
+	if (lock->magic == (uintptr_t) lock)
+		return;
+
+	cmn_err(CE_CRIT, "lockdep: thread trying to %s rwlock with bad magic", op);
+	print_rw(lock, where);
+	panic("lockdep: Aborting - bad rwlock magic");
+}
+
 static void check_cond_magic(struct cond *cond, const char *op,
 			     const struct lock_context *where)
 {
@@ -505,6 +526,41 @@
 #endif
 }
 
+static void verify_rw_init(const struct lock_context *where, struct rwlock *l)
+{
+	if (!l)
+		print_invalid_call("RWINIT", where);
+
+	l->magic = (uintptr_t) l;
+}
+
+static void verify_rw_destroy(const struct lock_context *where, struct rwlock *l)
+{
+	if (!l)
+		print_invalid_call("RWDESTROY", where);
+
+	check_rw_magic(l, "destroy", where);
+
+	l->magic = DESTROYED_MAGIC;
+}
+
+static void verify_rw_lock(const struct lock_context *where, struct rwlock *l,
+			   bool wr)
+{
+	if (!l)
+		print_invalid_call("RWLOCK", where);
+
+	check_rw_magic(l, "acquire", where);
+}
+
+static void verify_rw_unlock(const struct lock_context *where, struct rwlock *l)
+{
+	if (!l)
+		print_invalid_call("RWUNLOCK", where);
+
+	check_rw_magic(l, "release", where);
+}
+
 static void verify_cond_init(const struct lock_context *where, struct cond *c)
 {
 	if (!c)
@@ -657,6 +713,8 @@
 {
 	int ret;
 
+	verify_rw_init(where, l);
+
 	ret = pthread_rwlock_init(&l->lock, NULL);
 	if (ret)
 		panic("rwlock init failed @ %s:%d: %s",
@@ -667,6 +725,8 @@
 {
 	int ret;
 
+	verify_rw_destroy(where, l);
+
 	ret = pthread_rwlock_destroy(&l->lock);
 	if (ret)
 		panic("rwlock destroy failed @ %s:%d: %s",
@@ -677,6 +737,8 @@
 {
 	int ret;
 
+	verify_rw_lock(where, l, wr);
+
 	if (wr)
 		ret = pthread_rwlock_wrlock(&l->lock);
 	else
@@ -692,6 +754,8 @@
 {
 	int ret;
 
+	verify_rw_unlock(where, l);
+
 	ret = pthread_rwlock_unlock(&l->lock);
 	if (ret)
 		panic("rwlock unlock failed @ %s:%d: %s",