Patch "blk-crypto: use dynamic lock class for blk_crypto_profile::lock" has been added to the 6.1-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    blk-crypto: use dynamic lock class for blk_crypto_profile::lock

to the 6.1-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     blk-crypto-use-dynamic-lock-class-for-blk_crypto_pro.patch
and it can be found in the queue-6.1 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 001e59f3c22f0560e8378bf0c2acca66255f7ff6
Author: Eric Biggers <ebiggers@xxxxxxxxxx>
Date:   Fri Jun 9 23:11:39 2023 -0700

    blk-crypto: use dynamic lock class for blk_crypto_profile::lock
    
    [ Upstream commit 2fb48d88e77f29bf9d278f25bcfe82cf59a0e09b ]
    
    When a device-mapper device is passing through the inline encryption
    support of an underlying device, calls to blk_crypto_evict_key() take
    the blk_crypto_profile::lock of the device-mapper device, then take the
    blk_crypto_profile::lock of the underlying device (nested).  This isn't
    a real deadlock, but it causes a lockdep report because there is only
    one lock class for all instances of this lock.
    
    Lockdep subclasses don't really work here because the hierarchy of block
    devices is dynamic and could have more than 2 levels.
    
    Instead, register a dynamic lock class for each blk_crypto_profile, and
    associate that with the lock.
    
    This avoids false-positive lockdep reports like the following:
    
        ============================================
        WARNING: possible recursive locking detected
        6.4.0-rc5 #2 Not tainted
        --------------------------------------------
        fscryptctl/1421 is trying to acquire lock:
        ffffff80829ca418 (&profile->lock){++++}-{3:3}, at: __blk_crypto_evict_key+0x44/0x1c0
    
                       but task is already holding lock:
        ffffff8086b68ca8 (&profile->lock){++++}-{3:3}, at: __blk_crypto_evict_key+0xc8/0x1c0
    
                       other info that might help us debug this:
         Possible unsafe locking scenario:
    
               CPU0
               ----
          lock(&profile->lock);
          lock(&profile->lock);
    
                        *** DEADLOCK ***
    
         May be due to missing lock nesting notation
    
    Fixes: 1b2628397058 ("block: Keyslot Manager for Inline Encryption")
    Reported-by: Bart Van Assche <bvanassche@xxxxxxx>
    Signed-off-by: Eric Biggers <ebiggers@xxxxxxxxxx>
    Reviewed-by: Bart Van Assche <bvanassche@xxxxxxx>
    Link: https://lore.kernel.org/r/20230610061139.212085-1-ebiggers@xxxxxxxxxx
    Signed-off-by: Jens Axboe <axboe@xxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/block/blk-crypto-profile.c b/block/blk-crypto-profile.c
index 3290c03c9918d..aa7fc1436893c 100644
--- a/block/blk-crypto-profile.c
+++ b/block/blk-crypto-profile.c
@@ -79,7 +79,14 @@ int blk_crypto_profile_init(struct blk_crypto_profile *profile,
 	unsigned int slot_hashtable_size;
 
 	memset(profile, 0, sizeof(*profile));
-	init_rwsem(&profile->lock);
+
+	/*
+	 * profile->lock of an underlying device can nest inside profile->lock
+	 * of a device-mapper device, so use a dynamic lock class to avoid
+	 * false-positive lockdep reports.
+	 */
+	lockdep_register_key(&profile->lockdep_key);
+	__init_rwsem(&profile->lock, "&profile->lock", &profile->lockdep_key);
 
 	if (num_slots == 0)
 		return 0;
@@ -89,7 +96,7 @@ int blk_crypto_profile_init(struct blk_crypto_profile *profile,
 	profile->slots = kvcalloc(num_slots, sizeof(profile->slots[0]),
 				  GFP_KERNEL);
 	if (!profile->slots)
-		return -ENOMEM;
+		goto err_destroy;
 
 	profile->num_slots = num_slots;
 
@@ -441,6 +448,7 @@ void blk_crypto_profile_destroy(struct blk_crypto_profile *profile)
 {
 	if (!profile)
 		return;
+	lockdep_unregister_key(&profile->lockdep_key);
 	kvfree(profile->slot_hashtable);
 	kvfree_sensitive(profile->slots,
 			 sizeof(profile->slots[0]) * profile->num_slots);
diff --git a/include/linux/blk-crypto-profile.h b/include/linux/blk-crypto-profile.h
index e6802b69cdd64..90ab33cb5d0ef 100644
--- a/include/linux/blk-crypto-profile.h
+++ b/include/linux/blk-crypto-profile.h
@@ -111,6 +111,7 @@ struct blk_crypto_profile {
 	 * keyslots while ensuring that they can't be changed concurrently.
 	 */
 	struct rw_semaphore lock;
+	struct lock_class_key lockdep_key;
 
 	/* List of idle slots, with least recently used slot at front */
 	wait_queue_head_t idle_slots_wait_queue;



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux