what is vdso & vsyscall

pwnable 문제를 풀다가

C
root@b734c24aca1e:/home/rtld# ldd rtld 
	linux-vdso.so.1 =>  (0x00007ffdfa390000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000732628c41000)
	/lib64/ld-linux-x86-64.so.2 (0x000073262920e000)
root@b734c24aca1e:/home/rtld# mkdir backup 

다음과 같이 어떤 라이브러리를 쓰나 확인하고 있었는데 문득 의문이 들었다.

linux-vdso.so.1 => (0x00007ffdfa390000) 얘는 뭐지?

vdso는 Virtual Dynamically-linked Shared Object 라는 뜻으로 딱봐도 라이브러리 같이 보인다. 하지만 이는 커널에서 제공하는 가짜 라이브러리이다. 커널의 하는 일중 하나는 프로세스 관리이다. 아마 커널이 이 프로세스를 관리하기 위해 주는 대표적인 환상에 대해 알 것이다. 대표적으로 가상메모리를 통해 프로세스가 자신만의 메모리가 있는 것처럼 착각하게 하며 context switch를 통해 프로그램이 자신만 cpu를 쓰는 것처럼 착각하게 한다.

이 vdso 도 이것의 일종이라고 할 수 있다. 기존의 라이브러리는 실제로 존재하며 여러 프로세스들이 공유를 하고 있는게 맞다. 하지만 얘는 가상의 라이브러리를 제공한다.

vdso 의 역할은 시스템 콜을 하지않고 자주 쓰이는 커널의 기능을 유저레벨에서 끝내기 위해 있다. 즉, 커널이 시스템콜에 대한 몇가지 기능들을 때어서 가상 라이브러리로 프로그램에 붙여준다고 생각하면 된다. 그러면, 굳이 커널 레벨 까지 안내려가도 되니깐 시스템콜로 인한 오버헤드를 줄일 수 있다.

C
pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
    0x555555400000     0x555555401000 r-xp     1000 0      /home/rtld/rtld
    0x555555601000     0x555555602000 r--p     1000 1000   /home/rtld/rtld
    0x555555602000     0x555555603000 rw-p     1000 2000   /home/rtld/rtld
    0x7ffff7a0d000     0x7ffff7bcd000 r-xp   1c0000 0      /lib/x86_64-linux-gnu/libc-2.23.so
    0x7ffff7bcd000     0x7ffff7dcd000 ---p   200000 1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
    0x7ffff7dcd000     0x7ffff7dd1000 r--p     4000 1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
    0x7ffff7dd1000     0x7ffff7dd3000 rw-p     2000 1c4000 /lib/x86_64-linux-gnu/libc-2.23.so
    0x7ffff7dd3000     0x7ffff7dd7000 rw-p     4000 0      
    0x7ffff7dd7000     0x7ffff7dfd000 r-xp    26000 0      /lib/x86_64-linux-gnu/ld-2.23.so
    0x7ffff7fed000     0x7ffff7ff0000 rw-p     3000 0      
    0x7ffff7ff6000     0x7ffff7ffa000 r--p     4000 0      [vvar]
    0x7ffff7ffa000     0x7ffff7ffc000 r-xp     2000 0      [vdso]
    0x7ffff7ffc000     0x7ffff7ffd000 r--p     1000 25000  /lib/x86_64-linux-gnu/ld-2.23.so
    0x7ffff7ffd000     0x7ffff7ffe000 rw-p     1000 26000  /lib/x86_64-linux-gnu/ld-2.23.so
    0x7ffff7ffe000     0x7ffff7fff000 rw-p     1000 0      
    0x7ffffffde000     0x7ffffffff000 rw-p    21000 0      [stack]
0xffffffffff600000 0xffffffffff601000 --xp     1000 0      [vsyscall]

따라서 실제로 프로그램에서 보면

C
    0x7ffff7ff6000     0x7ffff7ffa000 r--p     4000 0      [vvar]
    0x7ffff7ffa000     0x7ffff7ffc000 r-xp     2000 0      [vdso]

이 부분이 vdso 가 존재하는 부분이며 그 위에 vvar은 vdso 에서 사용하는 변수들이 있는 곳이다.

그리고

C
0xffffffffff600000 0xffffffffff601000 --xp     1000 0      [vsyscall]

맨아래 다음과 같은 부분이 있는데 이 부분은 예전 vdso 를 사용하기 전에 사용하던 기능이다. 따라서 지금은 사장되었지만 호환성으로 남아있다.