CVE-2024-56592 in Linux
Zusammenfassung
von VulDB • 11.05.2026
Im Linux-Kernel wurde folgende Schwachstelle behoben:
bpf: Aufruf von free_htab_elem() nach htab_unlock_bucket()
Für htab von Maps (Karten) kann es vorkommen, dass beim Entfernen der Map aus der htab noch die letzte Referenz auf die Map gehalten wird. bpf_map_fd_put_ptr() ruft bpf_map_free_id() auf, um die ID des entfernten Map-Elements freizugeben. Allerdings wird bpf_map_fd_put_ptr() aufgerufen, während ein Bucket-Lock (raw_spin_lock_t) gehalten wird, und bpf_map_free_id() versucht, map_idr_lock (spinlock_t) zu erwerben, was folgende lockdep-Warnung auslöst:
============================= [ BUG: Invalid wait context ]
6.11.0-rc4+ #49 Not tainted ----------------------------- test_maps/4881 versucht zu sperren: ffffffff84884578 (map_idr_lock){+...}-{3:3}, at: bpf_map_free_id.part.0+0x21/0x70
Weitere Informationen, die bei der Fehlersuche helfen könnten: context-{5:5}
2 Locks gehalten von test_maps/4881: #0: ffffffff846caf60 (rcu_read_lock){....}-{1:3}, at: bpf_fd_htab_map_update_elem+0xf9/0x270
#1: ffff888149ced148 (&htab->lockdep_key#2){....}-{2:2}, at: htab_map_update_elem+0x178/0xa80
Stack-Backtrace: dump_stack_lvl+0x1e5/0x2e0 check_noncircular_enqueued_wait+0x130/0x150 __lock_acquire+0x1338/0x23f0 lock_acquire+0x165/0x440 _raw_spin_lock+0x45/0x60 x64_sys_call+0x1b2a/0x20d0 do_syscall_64+0x5d/0x100 entry_SYSCALL_64_after_hwframe+0x76/0x7e
Eine Möglichkeit, die lockdep-Warnung zu beheben, besteht darin, raw_spinlock_t auch für map_idr_lock zu verwenden. Allerdings löst bpf_map_alloc_id(), das idr_alloc_cyclic() nach dem Erwerben von map_idr_lock aufruft, eine ähnliche lockdep-Warnung aus, da der Lock des Slabs (s->cpu_slab->lock) weiterhin ein spinlock_t ist.
Anstatt den Typ von map_idr_lock zu ändern, wird das Problem dadurch behoben, dass htab_put_fd_value() nach htab_unlock_bucket() aufgerufen wird. Allerdings reicht es nicht aus, den Aufruf von htab_put_fd_value() nur zu verschieben, da die alten Map-Zeiger in der htab von Maps während des batchweisen Löschens nicht gespeichert werden können. Daher wird auch der Aufruf von free_htab_elem() verschoben, sodass diese freizugebenden Elemente ähnlich wie bei der LRU-Map verkettet werden können.
Es gibt vier Aufrufer für ->map_fd_put_ptr:
(1) alloc_htab_elem() (über htab_put_fd_value()) Es ruft ->map_fd_put_ptr() unter einem raw_spinlock_t auf. Der Aufruf von htab_put_fd_value() kann nicht einfach nach htab_unlock_bucket() verschoben werden, da das alte Element bereits in htab->extra_elems gespeichert wurde. Es kann unmittelbar nach htab_unlock_bucket() wieder verwendet werden, und der Aufruf von htab_put_fd_value() nach htab_unlock_bucket() könnte das neu hinzugefügte Element falsch freigeben. Daher wird der Map-Zeiger des alten Elements für die htab von Maps vor dem Entsperren des Buckets gespeichert und der map_ptr nach dem Entsperren freigegeben. Neben dem Map-Zeiger im alten Element sollten auch die speziellen Felder im alten Element auf die gleiche Weise behandelt werden.
(2) free_htab_elem() (über htab_put_fd_value()) Sein Aufrufer umfasst __htab_map_lookup_and_delete_elem(), htab_map_delete_elem() und __htab_map_lookup_and_delete_batch().
Für htab_map_delete_elem() wird free_htab_elem() einfach nach htab_unlock_bucket() aufgerufen. Für __htab_map_lookup_and_delete_batch() wird, ähnlich wie bei der LRU-Map, das freizugebende Element in die Liste node_to_free verkettet und free_htab_elem() für diese Elemente nach dem Entsperren aufgerufen. Es ist sicher, batch_flink als Link für node_to_free zu verwenden, da diese Elemente bereits aus der Hash-llist entfernt wurden.
Da htab von Maps keine lookup_and_delete-Operation unterstützt, hat __htab_map_lookup_and_delete_elem() das Problem nicht, daher bleibt es unverändert.
If you want to get best quality of vulnerability data, you may have to visit VulDB.