https://marc.info/?l=openbsd-tech&m=152035796722258&w=2
OpenBSD는 스택 레지스터 검사를 도입합니다
"커널에 의해 기회주의적으로 시행됩니다."-> 선택사항이라는 뜻인가요?
"시스템 호출이 발생하면 스택 포인터 레지스터가 해당 페이지를 가리키는지 확인합니다. 그렇지 않으면 프로그램이 종료됩니다."- 프로그래머가 아닌 사람에게 스택 레지스터에 대해 더 자세히 설명할 수 있는 사람이 있습니까? 선택 사항이라면 왜 그것이 없는 모든 프로그램을 종료합니까?
답변1
스택 포인터 레지스터는 하드웨어 레지스터입니다. 스택에 사용되는 영역의 메모리 위치*를 가리킵니다. 스택 포인터 레지스터는 일반적으로 메모리 액세스 전후에 포인터 값을 증가시키거나 감소시켜 스택의 데이터 주소를 지정할 때 사용됩니다. 이 검사는 시스템 호출이 발생할 때 수행되며 레지스터가 유효한 스택 주소를 가리키는지 여부를 확인합니다. "기회주의"는 "선택적"을 의미하지 않습니다.
[*]: 일부 아키텍처에서는 유효 주소가 스택 페이지의 마지막 주소 뒤의 주소일 수도 있습니다.
답변2
모든 스레드에는 스택이 있습니다. 스택은 스레드가 지역 변수, 함수 반환 주소 등을 저장하는 데 사용하는 특수 메모리 영역입니다. CPU가 스레드를 실행할 때 해당 스레드의 레지스터(SP)는 스택의 메모리 주소를 가리켜야 합니다.
대부분의 경우 커널은 스레드 스택을 할당하지만 애플리케이션이 스택을 생성하는 경우도 있습니다. 애플리케이션은 신호 처리기(커널이 프로세스에 신호를 보낼 때 실행되는 코드)에 대한 사용자 정의 스택을 생성하거나 이를 구현하기 위해 수행할 수 있습니다. 스레드 라이브러리.
이를 위해 애플리케이션은 커널에 메모리 영역을 요청한 다음 이를 스택으로 표시하여 커널이 해당 영역이 스택임을 알 수 있도록 합니다. 그러나 개발자 오류로 인해 애플리케이션은 스택에 등록되지 않은 일부 메모리를 사용하도록 커널에 요청할 수 있습니다. 이 경우 뭔가 나쁜 일이 발생할 수 있습니다. 커널은 유용한 데이터가 스택에 기록되었다고 생각하지만 스택이 아니기 때문에 덮어쓸 수 있습니다! 해커는 이를 사용하여 프로그램을 손상시킬 수 있습니다.
OpenBSD에서 메모리를 예약할 때(예: mmap 사용) 다음을 명시적으로 명시해야 합니다.
맑은 장면:
- 응용 프로그램: 커널, 스택으로 사용할 메모리를 좀 가질 수 있나요?
- 커널: 물론, 이것은 당신의 메모리입니다
- 응용 프로그램: 좋습니다. 이것을 신호 스택으로 사용하십시오.
- 커널: ok(신호 처리 시 CPU SP 레지스터가 이 메모리를 가리키도록 내부 구조를 구성)
비오는 날 장면:
- 응용 프로그램: 커널, 메모리를 좀 가질 수 있나요?
- 커널: 물론, 이것은 당신의 메모리입니다
- 응용 프로그램: 좋습니다. 이것을 신호 스택으로 사용하십시오.
- 커널: 하지만 이 메모리는 스택용이 아닙니다! 당신은 나를 속이고 싶어!
- (커널이 애플리케이션을 종료함)
다음은 이러한 플래그의 추가 예입니다.
PROT_EXEC: 코드(CPU가 실행할 수 있는 것)를 저장하기 위해 메모리를 예약하도록 커널에 요청 PROT_WRITE: 쓰기 가능한 데이터를 저장할 메모리를 예약하도록 커널에 요청
따라서 데이터를 실행하거나 코드를 작성할 수 없습니다(이를 W^X라고 하며 OpenBSD 사람들은 이를 자랑스럽게 생각합니다).
더 많은 예시를 읽고 배울 man mmap
수 있습니다.map sigaltstack