summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2019-04-25 10:19:52 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2021-01-31 22:21:03 +0000
commit81bdd897aed026a470620cfa5c7241ee1d30ca24 (patch)
tree820b84bae00ab4579f320e8cada740f57719f608
parentdb8c5efa5c9e7994ee17df614ac6e0a027b4c50a (diff)
lockdep: Swap storage for pin_count and references
As a lockmap takes a reference for every ww_mutex used together, this can be an arbitrarily large number and under control of userspace -- easily overflowing the arbitrary limit of 4096. However, the pin_count (used for detecting unexpected lock dropping) is a full 32b despite nesting being extremely rare (see lockdep_pin_lock). Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20190425092004.9995-33-chris@chris-wilson.co.uk
-rw-r--r--include/linux/lockdep.h4
-rw-r--r--kernel/locking/lockdep.c11
2 files changed, 9 insertions, 6 deletions
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index b9e9adec73e8..93c530aec462 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -138,8 +138,8 @@ struct held_lock {
unsigned int read:2; /* see lock_acquire() comment */
unsigned int check:1; /* see lock_acquire() comment */
unsigned int hardirqs_off:1;
- unsigned int references:12; /* 32 bits */
- unsigned int pin_count;
+ unsigned int pin_count:12; /* 32 bits */
+ unsigned int references;
};
/*
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index bdaf4829098c..b49290d7aeba 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -5207,11 +5207,14 @@ static struct pin_cookie __lock_pin_lock(struct lockdep_map *lock)
if (match_held_lock(hlock, lock)) {
/*
- * Grab 16bits of randomness; this is sufficient to not
- * be guessable and still allows some pin nesting in
- * our u32 pin_count.
+ * Grab 6bits of randomness; this is barely sufficient
+ * to not be guessable and still allows some 32 levels
+ * of pin nesting in our u12 pin_count.
*/
- cookie.val = 1 + (prandom_u32() >> 16);
+ cookie.val = 1 + (prandom_u32() >> 26);
+ if (DEBUG_LOCKS_WARN_ON(hlock->pin_count + cookie.val >= 1 << 12))
+ return NIL_COOKIE;
+
hlock->pin_count += cookie.val;
return cookie;
}