Linux를 실행하는 임베디드 시스템에는 UIO의 커널 드라이버를 활용하는 사용자 공간에 PCI 드라이버가 있습니다. 애플리케이션은 __uio_register_device()
커널에서 호출된 장치 등록을 트리거할 수 있습니다 uio.c
. 그런 다음 응용프로그램은 장치 파일( /dev/uio0
)을 엽니다. 그런 다음 장치 정보를 보유하고 있는 일부 커널 메모리를 확보하기 위해 장치 등록을 취소( )함으로써 uio_unregister_device()
올바르지 않게 동작합니다 . 그런 다음 응용 프로그램은 파일을 닫고 해제된 포인터에 액세스 중이므로 커널이 패닉 상태가 됩니다.
애플리케이션을 수정하는 것 외에도 어떻게 Linux 커널을 이에 대해 견고하게 만들 수 있습니까?
uio_open()
uio_release()
키 할당 메모리(in)에 대한 파일 포인터를 가져 옵니다 private_data
. 그런데 uio_unregister_device()
이런 정보가 없어서 어떻게 해야할지 모르겠습니다. 아니면 앱에서 파일을 강제로 닫는 방법이 있나요? 무슨 일이 일어나고 있는지에 대한 다른 제안이나 다른 설명이 있습니까?
편집: 아래와 같이 쉽게 재현할 수 있으며 사용자 공간 관점을 보여줍니다.
# 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...
충돌의 원인은 Unable to handle kernel paging request at virtual address
세 가지 다른 스타일입니다. idev
또는 유효하지 않은 포인터(반드시 NULL일 필요는 없으며 임의의 데이터임) idev->info
.idev->owner