В ядре Linux устранена следующая уязвимость:
NFSD: запретить использование владельцем блокировки после освобождения во время отключения клиента.
__destroy_client() освобождает открытых владельцев клиента, но владельца блокировки
единственной ссылкой которого является заблокированный замок (nbl), он остается включенным
cl_ownerstr_hashtbl. client_has_state() не учитывает голого владельца,
поэтому DESTROY_CLIENTID может связаться с __destroy_client() с такими владельцами
присутствует.
__destroy_client() затем обходит таблицу, вызывая remove_blocked_locks().
на каждого владельца без справки. При освобождении заблокированного замка
ссылка на владельца хранится через flc_owner. Сетевая прачечная пожинает плоды
заблокированные блокировки из nn->blocked_locks_lru независимо от состояния клиента.
Эти два пути используют блокировку_locks_lock только для сращивания списка, а не
срок жизни владельца. Таким образом, прачечная освобождает владельца как
__destroy_client() разыменовывает его, разыменование NULL в
Remove_blocked_locks().
nfsd4_release_lockowner() хранит ссылку на один и тот же вызов;
__destroy_client() этого не делает. Удерживайте cl_lock на другой стороне дорожки, взяв
ссылку и разхеширование каждого владельца, а затем отбросьте его перед
Remove_blocked_locks() и nfs4_put_stateowner(), которые принимают
заблокированные_locks_lock и cl_lock.
Показать оригинальное описание (EN)
In the Linux kernel, the following vulnerability has been resolved: NFSD: Prevent lock owner use-after-free during client teardown __destroy_client() releases a client's open owners, but a lock owner whose only reference is a blocked lock (nbl) stays on cl_ownerstr_hashtbl. client_has_state() does not count a bare owner, so DESTROY_CLIENTID can reach __destroy_client() with such owners present. __destroy_client() then walks the table, calling remove_blocked_locks() on each owner without a reference. Freeing a blocked lock drops the owner reference held via flc_owner. The per-net laundromat reaps blocked locks from nn->blocked_locks_lru independently of client state. The two paths share blocked_locks_lock only for the list splice, not the owner's lifetime. The laundromat therefore frees the owner as __destroy_client() dereferences it, a NULL dereference in remove_blocked_locks(). nfsd4_release_lockowner() holds a reference across the same call; __destroy_client() does not. Hold cl_lock across the walk, taking a reference and unhashing each owner, then drop it before remove_blocked_locks() and nfs4_put_stateowner(), which take blocked_locks_lock and cl_lock.
Характеристики атаки
Последствия
Строка CVSS v3.1