Em um sistema embarcado rodando Linux, temos um driver PCI no espaço do usuário fazendo uso do driver do kernel para o UIO. O aplicativo pode acionar o registro do dispositivo que chama __uio_register_device()
no uio.c
do kernel. Em seguida, o aplicativo abre o arquivo do dispositivo ( /dev/uio0
). E então ele se comporta mal ao cancelar o registro do dispositivo ( uio_unregister_device()
), o que libera algumas informações do dispositivo de armazenamento de memória do kernel. Em seguida, o aplicativo fecha o arquivo - e o kernel entra em pane porque os ponteiros que foram liberados estão sendo acessados.
Além de consertar o aplicativo, como posso tornar o kernel do Linux robusto contra isso?
uio_open()
e uio_release()
obtêm ponteiros de arquivos que apontam para a memória alocada crítica (em private_data
). Mas uio_unregister_device()
não tem essa informação, então não sei o que fazer. Ou há uma maneira de forçar o fechamento do arquivo no aplicativo? Alguma outra sugestão ou uma interpretação diferente do que está acontecendo?
Editar: pode ser facilmente reproduzido da seguinte forma - e mostra a perspectiva do espaço do usuário:
# replace '1234 abcd' by vendor id and device id
echo '1234 abcd' > /sys/bus/pci/drivers/uio_pci_generic/new_id
echo '0000:00:01.0' > /sys/bus/pci/drivers/uio_pci_generic/bind
# 'bind' may not even be needed. /dev/uio0 is created
cat /dev/uio0 &
# now be bad
echo '0000:00:01.0' > /sys/bus/pci/drivers/uio_pci_generic/unbind
kill <cat process ID>
# kernel panic...
Provoca uma falha devido a Unable to handle kernel paging request at virtual address
- com três diferentes sabores. O idev
, idev->info
ou idev->owner
é um ponteiro inválido (não é necessário NULL, apenas dados aleatórios).