lockdep_reset_lock_reg(lock);
 }
 
-/* Unregister a dynamically allocated key. */
+/*
+ * Unregister a dynamically allocated key.
+ *
+ * Unlike lockdep_register_key(), a search is always done to find a matching
+ * key irrespective of debug_locks to avoid potential invalid access to freed
+ * memory in lock_class entry.
+ */
 void lockdep_unregister_key(struct lock_class_key *key)
 {
        struct hlist_head *hash_head = keyhashentry(key);
                return;
 
        raw_local_irq_save(flags);
-       if (!graph_lock())
-               goto out_irq;
+       lockdep_lock();
 
-       pf = get_pending_free();
        hlist_for_each_entry_rcu(k, hash_head, hash_entry) {
                if (k == key) {
                        hlist_del_rcu(&k->hash_entry);
                        break;
                }
        }
-       WARN_ON_ONCE(!found);
-       __lockdep_free_key_range(pf, key, 1);
-       call_rcu_zapped(pf);
-       graph_unlock();
-out_irq:
+       WARN_ON_ONCE(!found && debug_locks);
+       if (found) {
+               pf = get_pending_free();
+               __lockdep_free_key_range(pf, key, 1);
+               call_rcu_zapped(pf);
+       }
+       lockdep_unlock();
        raw_local_irq_restore(flags);
 
        /* Wait until is_dynamic_key() has finished accessing k->hash_entry. */