#include <stdio.h>
int main() {
printf("hello world\n");
}
$ gcc -o no-pie test.c -no-pie
$ gcc -o default test.c
$
$ readelf -a ./no-pie | grep "NOW"
$
$ readelf -a ./default | grep "NOW"
0x000000000000001e (FLAGS) BIND_NOW
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
$
$
no-pie 옵션과 바인딩의 연관성을 검색하던 중에
$ strings `which gcc` | grep "\-z now"
... %{static|shared|r:;!no-pie:-pie -z now} ...
위와 같은 옵션을 발견했습니다. no-pie 옵션이 없을 때 "-pie -z now" 옵션을 추가해주는데 -pie는 그렇다 쳐도 -z now를 추가해주는 이유를 모르겠습니다
pie를 사용하지 않을 때 lazy-binding을 사용하면 성능상, 보안상의 이점이 따로 있을까요?
두개가 연관성이 있나요...? 잘 모르겠네요... 제가 볼땐 별개인 것 같은데...
now bind는 바이너리가 실행될때 libc 내 주소를 got에 가져오고
lazy bind는 함수가 실행될때 가져오는 차이가 있고
pie는 쉽게 말해서 코드 영역의 aslr인데
둘의 연관성이 있는지 잘 모르겠습니다.
다만, 아래 링크와 같이 우분투에서는 디폴트 옵션으로 된 부분이 있다고 하네요.
https://stackoverflow.com/questions/62527697/why-does-gcc-link-with-z-now-by-default-although-lazy-binding-is-the-default
그러므로 마지막에 질문하신 부분은 연계해서 고려해야하는 것이 아니라 별개로 봐야될 것 같습니다.
제가 질문의 의도를 파악하지 못하고 있었네요.
말씀하신 것과 같이 데비안에서 '권장하는' 컴파일 옵션이 설명해주신 부분인 것 같습니다.
권장한다는 것은 곧 보안이나 속도를 위한 최소한의 요건들을 경험적으로 판단하여 설정해둔 것이라 생각합니다.
저기서 조금 빠진 부분이 있는데 바로 relro 입니다.
링크해주신 부분 이외에 다른 곳에서 설정되는 것 같네요.
즉, now와 함께 relro가 기본 옵션으로 들어갑니다.
기본 옵션의 경우 아무 소스코드나 만드신 이후에
gcc --verbose 파일명
과 같이 실행해보시면 확인하실 수 있습니다.
relro가 들어가면서 왜 now가 pie와 함께 쓰였는지 이해되실거라 생각합니다.
다소 어렵게 생각하시는 것 같은데, 조금은 쉽게 생각해보시는 것도 좋을 것 같습니다 ㅎ
말 그대로 별도 옵션을 지정하지 않은 경우에 대한 기본 '권장' 옵션이고, 유저의 판단하에 옵션을 지정할 경우 다른 권장 옵션은 지정되지 않아야 정상인거 아닐까요 ㅎㅎ
아무 옵션 없이 컴파일 했을때 모든 보호기법이 들어가는 것처럼요