В ядре Linux устранена следующая уязвимость:
ieee802154: ca8210: исправлена утечка cas_ctl при сбое spi_async
ca8210_spi_transfer() выделяет cas_ctl с помощью kzalloc_obj(GFP_ATOMIC)
и полностью полагается на обратный вызов завершения SPI
ca8210_spi_transfer_complete(), чтобы освободить его. API spi_async() вызывает обратный вызов завершения только в случае успешного завершения.
подача. В случае сбоя он возвращает отрицательный код ошибки, даже не
постановка обратного вызова в очередь, в результате чего остается cas_ctl и встроенный в него spi_message
и spi_transfer осиротел.
Каждый kfree(cas_ctl) в драйвере
внутри обратного вызова завершения, поэтому другого пути восстановления нет.
ca8210_spi_transfer() вызывается из ca8210_spi_exchange(),
обработчик прерывания ca8210_interrupt_handler() и путь повтора
внутри самого обратного вызова завершения. Обмен и прерывание
пути обработчика зацикливаются на -EBUSY, поэтому при постоянном конфликте по шине SPI
каждая повторная итерация пропускает новый cas_ctl (~ 600 байт на
возникновение). Исправьте это, освободив cas_ctl на пути ошибки spi_async().
Пока здесь,
исправьте вводящую в заблуждение строку ошибки: функция вызывает spi_async(),
не spi_sync().
Показать оригинальное описание (EN)
In the Linux kernel, the following vulnerability has been resolved: ieee802154: ca8210: fix cas_ctl leak on spi_async failure ca8210_spi_transfer() allocates cas_ctl with kzalloc_obj(GFP_ATOMIC) and relies entirely on the SPI completion callback ca8210_spi_transfer_complete() to free it. The spi_async() API only invokes the completion callback on successful submission. On failure it returns a negative error code without ever queuing the callback, which leaves cas_ctl and its embedded spi_message and spi_transfer orphaned. Every kfree(cas_ctl) in the driver is inside the completion callback, so there is no other reclamation path. ca8210_spi_transfer() is called from ca8210_spi_exchange(), the interrupt handler ca8210_interrupt_handler(), and from the retry path inside the completion callback itself. The exchange and interrupt handler paths loop on -EBUSY, so under sustained SPI bus contention every retry iteration leaks a fresh cas_ctl (~600 bytes per occurrence). Fix it by freeing cas_ctl on the spi_async() error path. While here, correct the misleading error string: the function calls spi_async(), not spi_sync().