일부 배경:
실시간 선점을 위해 패치가 적용된 임베디드 Linux ARM 4.1.33 시스템이 있습니다. 시스템에는 일부 사용자 정의 수정 커널 코드가 포함되어 있으며 때때로 커널 버그가 발생합니다. 일부 디버깅 후에 개발자 중 한 명이 커널 공간과 사용자 공간의 차이를 이해하지 못하고 uaccess.h에 정의된 함수를 사용하지 않고 사용자 공간 포인터를 역참조하고 있다는 사실이 발견되었습니다.
이후 추가 커널 오류가 발생하는 것을 방지하기 위해 uaccess.h에 정의된 함수를 사용하도록 문제의 함수를 수정했습니다. 이제 수정이 성공했는지 확인하려고 합니다. 그러나 원래 커널 오류는 무작위로 발생하고 때로는 한 번에 며칠 동안 발생하지 않기 때문에 원본 코드에서 안정적으로 다시 생성한 다음 업데이트된 코드에 더 이상 나타나지 않는지 확인하는 방법을 찾고 싶습니다.
문제의 함수는 포인터를 잘못 사용하지만 사용자 공간 값을 올바르게 수정하기 위해 포인터를 사용하는 것으로 보입니다(커널 오류가 발생하는 경우 제외). 이는 포인터의 주소가 사용자 공간과 커널 공간에서 "동일한 것을 의미"한다는 것을 나타냅니다. 이러한 사실을 고려할 때, 그러한 역참조가 커널 오류를 일으킬 수 있다는 것을 내가 아는 유일한 이유는 해당 주소를 포함하는 페이지가 스왑으로 전송되어 페이지 오류를 일으키는 경우입니다. 그러나 플래시 메모리의 제한된 수명으로 인해 시스템에서 스왑이 비활성화되었으므로 이 시나리오는 가능성이 낮아 보입니다.
질문:
커널 공간 내에서 사용자 공간 포인터 역참조와 관련된 Linux 커널 오류의 잠재적인 원인은 무엇입니까? 수정 사항을 적용한 후 더 이상 발생하지 않는지 확인하기 위해 이와 같은 커널 오류가 발생하도록 하려면 어떻게 해야 합니까?
답변1
페이지가 교체될 가능성 외에도 이것이 실패할 수 있는 두 가지 이유가 있습니다.
- 사용자의 주소에서 읽는 경우 페이지를 읽을 수 있어야 합니다. 작성과 실행도 마찬가지입니다.
- 사용자 공간 주소는 이 프로세스에 속하지 않습니다. 커널 주소는 물리적 주소에 일관되게 일대일로 매핑되지만 사용자 공간의 동일한 가상 주소는 현재 프로세스에 따라 다른 물리적 주소를 가리킬 수 있습니다.
답변2
32비트 커널은 프로세스가 4GB의 주소 공간(몇 페이지 제외)을 얻도록 컴파일될 수 있습니다. 이렇게 하면 모든 사용자 공간 포인터가 커널 공간*에서 유효하지 않게 됩니다. 하지만 당신은 지금까지 해냈다는 것을 알게 될 것입니다.
*충돌하지 않을 수도 있습니다. 임의의 커널 메모리를 가리킬 수도 있지만 여기에 쓰면 오류가 발생합니다.
답변3
현재 존재하는지 확인할 수는 없지만 페이지가 현재 "쓰기 시 복사"(아마도 이전 호출을 통해)로 설정되어 있으면 fork()
그럴 것이라고 믿습니다. 커널 페이지는 쓰기 시 복사하면 안 됩니다.