* [RFC PATCH] locking/ww_mutex: Adjust to lockdep nest_lock requirements
@ 2023-09-11 8:40 Thomas Hellström
0 siblings, 0 replies; 2+ messages in thread
From: Thomas Hellström @ 2023-09-11 8:40 UTC (permalink / raw)
To: linux-kernel
Cc: Thomas Hellström, Peter Zijlstra, Ingo Molnar, Will Deacon,
Waiman Long, Boqun Feng, Daniel Vetter, Maarten Lankhorst,
Christian König, intel-xe, intel-gfx, dri-devel
When using mutex_acquire_nest() with a nest_lock, lockdep refcounts the
number of acquired lockdep_maps of mutexes of the same class, and also
keeps a pointer to the first acquired lockdep_map of a class. That pointer
is then used for various comparison-, printing- and checking purposes,
but there is no mechanism to actively ensure that lockdep_map stays in
memory. Instead, a warning is printed if the lockdep_map is freed and
there are still held locks of the same lock class, even if the lockdep_map
itself has been released.
In the context of WW/WD transactions that means that if a user unlocks
and frees a ww_mutex from within an ongoing ww transaction, and that
mutex happens to be the first ww_mutex grabbed in the transaction,
such a warning is printed and there might be a risk of a UAF.
Note that this is only problem when lockdep is enabled and affects only
dereferences of struct lockdep_map.
Adjust to this by adding a fake lockdep_map to the acquired context and
make sure it is the first acquired lockdep map of the associated
ww_mutex class. Then hold it for the duration of the WW/WD transaction.
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Will Deacon <will@kernel.org>
Cc: Waiman Long <longman@redhat.com>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: intel-xe@lists.freedesktop.org
Cc: intel-gfx@lists.freedesktop.org
Cc: dri-devel@lists.freedestkop.org
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
include/linux/ww_mutex.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/include/linux/ww_mutex.h b/include/linux/ww_mutex.h
index bb763085479a..a401a2f31a77 100644
--- a/include/linux/ww_mutex.h
+++ b/include/linux/ww_mutex.h
@@ -65,6 +65,16 @@ struct ww_acquire_ctx {
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
+ /**
+ * @first_lock_dep_map: fake lockdep_map for first locked ww_mutex.
+ *
+ * lockdep requires the lockdep_map for the first locked ww_mutex
+ * in a ww transaction to remain in memory until all ww_mutexes of
+ * the transaction have been unlocked. Ensure this by keeping a
+ * fake locked ww_mutex lockdep map between ww_acquire_init() and
+ * ww_acquire_fini().
+ */
+ struct lockdep_map first_lock_dep_map;
#endif
#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
unsigned int deadlock_inject_interval;
@@ -146,7 +156,10 @@ static inline void ww_acquire_init(struct ww_acquire_ctx *ctx,
debug_check_no_locks_freed((void *)ctx, sizeof(*ctx));
lockdep_init_map(&ctx->dep_map, ww_class->acquire_name,
&ww_class->acquire_key, 0);
+ lockdep_init_map(&ctx->first_lock_dep_map, ww_class->mutex_name,
+ &ww_class->mutex_key, 0);
mutex_acquire(&ctx->dep_map, 0, 0, _RET_IP_);
+ mutex_acquire_nest(&ctx->first_lock_dep_map, 0, 0, &ctx->dep_map, _RET_IP_);
#endif
#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
ctx->deadlock_inject_interval = 1;
@@ -185,6 +198,7 @@ static inline void ww_acquire_done(struct ww_acquire_ctx *ctx)
static inline void ww_acquire_fini(struct ww_acquire_ctx *ctx)
{
#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ mutex_release(&ctx->first_lock_dep_map, _THIS_IP_);
mutex_release(&ctx->dep_map, _THIS_IP_);
#endif
#ifdef DEBUG_WW_MUTEXES
--
2.41.0
^ permalink raw reply related [flat|nested] 2+ messages in thread[parent not found: <20230911090729.5287-1-thomas.hellstrom@linux.intel.com>]
* Re: [RFC PATCH] locking/ww_mutex: Adjust to lockdep nest_lock requirements
[not found] <20230911090729.5287-1-thomas.hellstrom@linux.intel.com>
@ 2023-09-12 5:32 ` kernel test robot
0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2023-09-12 5:32 UTC (permalink / raw)
To: Thomas Hellström
Cc: oe-lkp, lkp, Peter Zijlstra, Ingo Molnar, Will Deacon,
Waiman Long, Boqun Feng, Daniel Vetter, Maarten Lankhorst,
Christian König, linux-kernel, dri-devel, oliver.sang
Hello,
kernel test robot noticed "WARNING:possible_recursive_locking_detected" on:
commit: bb043828b2d487832c946751ffcc4ebd80d2a624 ("[RFC PATCH] locking/ww_mutex: Adjust to lockdep nest_lock requirements")
url: https://github.com/intel-lab-lkp/linux/commits/Thomas-Hellstr-m/locking-ww_mutex-Adjust-to-lockdep-nest_lock-requirements/20230911-170838
base: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next
patch link: https://lore.kernel.org/all/20230911090729.5287-1-thomas.hellstrom@linux.intel.com/
patch subject: [RFC PATCH] locking/ww_mutex: Adjust to lockdep nest_lock requirements
in testcase: boot
compiler: clang-16
test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G
(please refer to attached dmesg/kmsg for entire log/backtrace)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <oliver.sang@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202309121305.81d349e5-oliver.sang@intel.com
[ 252.054712][ T1] WARNING: possible recursive locking detected
[ 252.055056][ T1] 6.5.0-rc2-00590-gbb043828b2d4 #5 Not tainted
[ 252.055056][ T1] --------------------------------------------
[ 252.055056][ T1] swapper/1 is trying to acquire lock:
[ 252.055056][ T1] ffffc9000001f990 (ww_class_mutex){+.+.}-{0:0}, at: test_ww_mutex_init (kbuild/src/rand/kernel/locking/test-ww_mutex.c:77 kbuild/src/rand/kernel/locking/test-ww_mutex.c:632)
[ 252.055056][ T1]
[ 252.055056][ T1] but task is already holding lock:
[ 252.055056][ T1] ffffc9000001f800 (ww_class_mutex){+.+.}-{0:0}, at: do_one_initcall (kbuild/src/rand/init/main.c:1232)
[ 252.055056][ T1]
[ 252.055056][ T1] other info that might help us debug this:
[ 252.055056][ T1] Possible unsafe locking scenario:
[ 252.055056][ T1]
[ 252.055056][ T1] CPU0
[ 252.055056][ T1] ----
[ 252.055056][ T1] lock(ww_class_mutex);
[ 252.055056][ T1]
[ 252.055056][ T1] *** DEADLOCK ***
[ 252.055056][ T1]
[ 252.055056][ T1] May be due to missing lock nesting notation
[ 252.055056][ T1]
[ 252.055056][ T1] 2 locks held by swapper/1:
[ 252.055056][ T1] #0: ffffc9000001f7d8 (ww_class_acquire){+.+.}-{0:0}, at: do_one_initcall (kbuild/src/rand/init/main.c:1232)
[ 252.055056][ T1] #1: ffffc9000001f800 (ww_class_mutex){+.+.}-{0:0}, at: do_one_initcall (kbuild/src/rand/init/main.c:1232)
[ 252.055056][ T1]
[ 252.055056][ T1] stack backtrace:
[ 252.055056][ T1] CPU: 0 PID: 1 Comm: swapper Not tainted 6.5.0-rc2-00590-gbb043828b2d4 #5 9492b9dd86bdf82b2f3deb22196638d07aad10f2
[ 252.055056][ T1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[ 252.055056][ T1] Call Trace:
[ 252.055056][ T1] <TASK>
[ 252.055056][ T1] dump_stack_lvl (kbuild/src/rand/lib/dump_stack.c:?)
[ 252.055056][ T1] __lock_acquire (kbuild/src/rand/kernel/locking/lockdep.c:?)
[ 252.055056][ T1] ? finish_lock_switch (kbuild/src/rand/arch/x86/include/asm/irqflags.h:42 kbuild/src/rand/arch/x86/include/asm/irqflags.h:77 kbuild/src/rand/kernel/sched/sched.h:1378 kbuild/src/rand/kernel/sched/core.c:5133)
[ 252.055056][ T1] ? __schedule (kbuild/src/rand/kernel/sched/core.c:6718)
[ 252.055056][ T1] lock_acquire (kbuild/src/rand/kernel/locking/lockdep.c:5761)
[ 252.055056][ T1] ? test_ww_mutex_init (kbuild/src/rand/kernel/locking/test-ww_mutex.c:77 kbuild/src/rand/kernel/locking/test-ww_mutex.c:632)
[ 252.055056][ T1] __mutex_lock_common (kbuild/src/rand/kernel/locking/mutex.c:603)
[ 252.055056][ T1] ? test_ww_mutex_init (kbuild/src/rand/kernel/locking/test-ww_mutex.c:77 kbuild/src/rand/kernel/locking/test-ww_mutex.c:632)
[ 252.055056][ T1] ? mark_lock (kbuild/src/rand/arch/x86/include/asm/bitops.h:228 kbuild/src/rand/arch/x86/include/asm/bitops.h:240 kbuild/src/rand/include/asm-generic/bitops/instrumented-non-atomic.h:142 kbuild/src/rand/kernel/locking/lockdep.c:228 kbuild/src/rand/kernel/locking/lockdep.c:4663)
[ 252.055056][ T1] ? test_ww_mutex_init (kbuild/src/rand/kernel/locking/test-ww_mutex.c:77 kbuild/src/rand/kernel/locking/test-ww_mutex.c:632)
[ 252.055056][ T1] ww_mutex_lock (kbuild/src/rand/kernel/locking/mutex.c:754 kbuild/src/rand/kernel/locking/mutex.c:871)
[ 252.055056][ T1] test_ww_mutex_init (kbuild/src/rand/kernel/locking/test-ww_mutex.c:77 kbuild/src/rand/kernel/locking/test-ww_mutex.c:632)
[ 252.055056][ T1] ? __asan_memcpy (kbuild/src/rand/mm/kasan/shadow.c:105)
[ 252.055056][ T1] ? do_one_initcall (kbuild/src/rand/init/main.c:1232)
[ 252.055056][ T1] ? __pfx_test_mutex_work (kbuild/src/rand/kernel/locking/test-ww_mutex.c:41)
[ 252.055056][ T1] ? __pfx_test_ww_mutex_init (kbuild/src/rand/kernel/locking/test-ww_mutex.c:622)
[ 252.055056][ T1] do_one_initcall (kbuild/src/rand/init/main.c:1232)
[ 252.055056][ T1] ? __pfx_test_ww_mutex_init (kbuild/src/rand/kernel/locking/test-ww_mutex.c:622)
[ 252.055056][ T1] do_initcall_level (kbuild/src/rand/init/main.c:1293)
[ 252.055056][ T1] do_initcalls (kbuild/src/rand/init/main.c:1307)
[ 252.055056][ T1] kernel_init_freeable (kbuild/src/rand/init/main.c:1550)
[ 252.055056][ T1] ? __pfx_kernel_init (kbuild/src/rand/init/main.c:1429)
[ 252.055056][ T1] kernel_init (kbuild/src/rand/init/main.c:1439)
[ 252.055056][ T1] ? __pfx_kernel_init (kbuild/src/rand/init/main.c:1429)
[ 252.055056][ T1] ret_from_fork (kbuild/src/rand/arch/x86/kernel/process.c:151)
[ 252.055056][ T1] ? __pfx_kernel_init (kbuild/src/rand/init/main.c:1429)
[ 252.055056][ T1] ret_from_fork_asm (kbuild/src/rand/arch/x86/entry/entry_64.S:298)
[ 252.055056][ T1] RIP: 0000:0x0
[ 252.055056][ T1] Code: Unable to access opcode bytes at 0xffffffffffffffd6.
Code starting with the faulting instruction
===========================================
[ 252.055056][ T1] RSP: 0000:0000000000000000 EFLAGS: 00000000 ORIG_RAX: 0000000000000000
[ 252.055056][ T1] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 252.055056][ T1] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[ 252.055056][ T1] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
[ 252.055056][ T1] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
[ 252.055056][ T1] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[ 252.055056][ T1] </TASK>
[ 258.685819][ T1] All ww mutex selftests passed
The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20230912/202309121305.81d349e5-oliver.sang@intel.com
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2023-09-12 5:33 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-11 8:40 [RFC PATCH] locking/ww_mutex: Adjust to lockdep nest_lock requirements Thomas Hellström
[not found] <20230911090729.5287-1-thomas.hellstrom@linux.intel.com>
2023-09-12 5:32 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox