Re: [PATCH] lockdep: Speed up lockdep_unregister_key() with expedited RCU synchronization

From: Waiman Long
Date: Tue Mar 25 2025 - 10:57:51 EST


On 3/25/25 10:52 AM, Waiman Long wrote:
I agree that the commit that I mentioned is not relevant to the current case. You are right that is_dynamic_key() is the only function that is problematic, the other two are protected by the lockdep_lock. So they are safe. Anyway, I believe that the actual race happens in the iteration of the hashed list in is_dynamic_key(). The key that you save in the lockdep_key_hazptr in your proposed patch should never be the key (dead_key) that is passed to lockdep_unregister_key(). In is_dynamic_key():

    hlist_for_each_entry_rcu(k, hash_head, hash_entry) {
                if (k == key) {
                        found = true;
                        break;
                }
        }

key != k (dead_key), but before accessing its content to get to hash_entry, an interrupt/NMI can happen. In the mean time, the structure holding the key is freed and its content can be overwritten with some garbage. When interrupt/NMI returns, hash_entry can point to anything leading to crash or an infinite loop.  Perhaps we can use some kind of synchronization mechanism between is_dynamic_key() and lockdep_unregister_key() to prevent this kind of racing. For example, we can have an atomic counter associated with each head of the hashed table. is_dynamic_key() can increment the counter if it is not zero to proceed and lockdep_unregister_key() have to make sure it can safely decrement the counter to 0 before going ahead. Just a thought!

Well, that is essentially an arch_rwlock_t for each list head.

Cheers,
Longman