В ядре Linux устранена следующая уязвимость:
btrfs: исправлено недопустимое разыменование указателя в __btrfs_run_delayed_refs(). В начале цикла мы пытаемся получить заблокированную опорную точку с задержкой.
если 'locked_ref' в настоящее время имеет значение NULL, вызвав btrfs_select_ref_head(),
который может возвращать указатель ошибки. Если указатель ошибки равен -EAGAIN, мы делаем
продолжить и вернуться к началу цикла, который не будет пытаться
снова вызвать btrfs_select_ref_head(), поскольку 'locked_ref' больше не является
NULL, но это ERR_PTR(-EAGAIN), и тогда мы делаем:
spin_lock(&locked_ref->lock);
против значения ERR_PTR(-EAGAIN), генерируя недопустимый указатель
разыменование.
Исправьте это, гарантируя, что для параметра locked_ref установлено значение NULL, когда
btrfs_select_ref_head() возвращает ERR_PTR(-EAGAIN) и увеличивает счетчик.
а также, чтобы предотвратить бесконечный цикл. Мы делаем это, выполнив переход к
нижней части цикла, который уже устанавливает для 'locked_ref' значение NULL и выполняет
cond_resched() с приращением к count прямо перед переходом. Эти меры были приняты до рефакторинга в коммите 0110a4c43451.
(«btrfs: рефакторинг цикла __btrfs_run_delayed_refs»), но были непреднамеренно
потерялся потом.
Показать оригинальное описание (EN)
In the Linux kernel, the following vulnerability has been resolved: btrfs: fix invalid pointer dereference in __btrfs_run_delayed_refs() In the beginning of the loop, we try to obtain a locked delayed ref head, if 'locked_ref' is currently NULL, by calling btrfs_select_ref_head(), which can return an error pointer. If the error pointer is -EAGAIN we do a continue and go back to the beginning of the loop, which will not try again to call btrfs_select_ref_head() since 'locked_ref' is no longer NULL but it's ERR_PTR(-EAGAIN), and then we do: spin_lock(&locked_ref->lock); against a ERR_PTR(-EAGAIN) value, generating an invalid pointer dereference. Fix this by ensuring that 'locked_ref' is set to NULL when btrfs_select_ref_head() returns ERR_PTR(-EAGAIN) and incrementing 'count' as well, to prevent infinite looping. We do this by doing a goto to the bottom of the loop that already sets 'locked_ref' to NULL and does a cond_resched(), with an increment to 'count' right before the goto. These measures were in place before the refactoring in commit 0110a4c43451 ("btrfs: refactor __btrfs_run_delayed_refs loop") but were unintentionally lost afterwards.
Характеристики атаки
Последствия
Строка CVSS v3.1