В ядре Linux устранена следующая уязвимость:
scsi: target: core: исправить использование iSCSI ISID после освобождения в REGISTER AND MOVE.
core_scsi3_emulate_pro_register_and_move() отображает ПОСТОЯННЫЙ РЕЗЕРВ OUT
список параметров с помощью Transport_kmap_data_sg() и анализирует пункт назначения
TransportID с помощью target_parse_pr_out_transport_id(). Для iSCSI
TransportID (КОД ФОРМАТА 01b), iscsi_parse_pr_out_transport_id() возвращает
ISID в iport_ptr как необработанный указатель на этот сопоставленный буфер. Затем функция отменяет отображение буфера с помощью Transport_kunmap_data_sg() перед
разыменование iport_ptr в strcmp(), __core_scsi3_locate_pr_reg() и
core_scsi3_alloc_registration().
Если список параметров охватывает более
одна страница (ДЛИНА СПИСКА ПАРАМЕТРОВ > 4096), Transport_kmap_data_sg() использует
vmap() и Transport_kunmap_data_sg() выполняют vunmap(), поэтому ядро виртуальное. Поддержка адреса iport_ptr удаляется, и каждое последующее разыменование
чтение неотображенного региона с возможностью использования после освобождения. Сохраняйте сопоставленный список параметров до тех пор, пока iport_ptr больше не понадобится: drop
ранний Transport_kunmap_data_sg() и один раз отмените сопоставление на пути к успеху,
прямо перед возвращением.
Пути ошибок уже не сопоставлены с существующими
«if (buf) Transport_kunmap_data_sg(cmd)» на метке out:, которая теперь запускается
при каждой ошибке после отображения карты происходит выход, поскольку buf больше не очищается раньше времени. Только
чтение сопоставления происходит во время удержания спин-блокировок; карту и отключить карту
вызовы остаются вне любой блокировки. Звонящий брат/сестра
core_scsi3_decode_spec_i_port() уже использует буфер перед его отменой
и остается неизменным.
Показать оригинальное описание (EN)
In the Linux kernel, the following vulnerability has been resolved: scsi: target: core: Fix iSCSI ISID use-after-free in REGISTER AND MOVE core_scsi3_emulate_pro_register_and_move() maps the PERSISTENT RESERVE OUT parameter list with transport_kmap_data_sg() and parses the destination TransportID with target_parse_pr_out_transport_id(). For an iSCSI TransportID (FORMAT CODE 01b), iscsi_parse_pr_out_transport_id() returns the ISID in iport_ptr as a raw pointer into that mapped buffer. The function then unmaps the buffer with transport_kunmap_data_sg() before dereferencing iport_ptr in strcmp(), __core_scsi3_locate_pr_reg() and core_scsi3_alloc_registration(). When the parameter list spans more than one page (PARAMETER LIST LENGTH > 4096), transport_kmap_data_sg() uses vmap() and transport_kunmap_data_sg() does vunmap(), so the kernel virtual address backing iport_ptr is torn down and every subsequent dereference is a use-after-free read of the unmapped region. Keep the parameter list mapped until iport_ptr is no longer needed: drop the early transport_kunmap_data_sg() and unmap once on the success path, right before returning. The error paths already unmap through the existing "if (buf) transport_kunmap_data_sg(cmd)" at the out: label, which now runs on every post-map error exit because buf is no longer cleared early. Only reads of the mapping happen while spinlocks are held; the map and unmap calls remain outside any lock. The sibling caller core_scsi3_decode_spec_i_port() already uses the buffer before unmapping it and is left unchanged.
Характеристики атаки
Последствия
Строка CVSS v3.1