개요
시스템콜은 Userprocess가 Kernel process에서만 다룰 수 있는 민감한 Resource에 접근하기 위한 방법이다. Userporcess는 프로그램 작동중 파일의 읽기와 쓰기 같은 커널 영역에서만 처리되어야 하는 작업에 당면하면 시스템콜을 부르게 된다. 시스템콜은 그에 따른 시스템콜을 호출하게 된다. 이러한 시스템콜에대한 Abstraction은 라이브러리의 형태로 언어마다 주어지게 된다 (C언어와 같은 경우는 Libc에 저장).
후에 라이브러리에서는 Kernel영역에 접근하기 위해서 syscall(sysenter)이나 int0x80을 호출하게 되고, User program이 제시한 인자를 커널영역에 카피한후, 인자를 체크한후 시스템콜을 수행하게 된다. 이때 인자를 커널영역에 카핑하는 이유는, argument checking과정에서 일어날 수도 있는 혹시모르는 보안상의 허점을 막기 위함이다.
기능
시스템 호출이란 프로그래밍 언어에서 지원하지 않는 기능에 대하여 운영 체제의 루틴을 호출하여 이용하는 것을 말한다. 시스템 호출의 세 가지 기능은 다음과 같다.
- 사용자 모드에 있는 응용 프로그램이 커널의 기능을 사용할 수 있도록 한다.
- 시스템 호출을 하면 사용자 모드에서 커널 모드로 바뀐다.
- 커널에서 시스템 호출을 처리하면 커널 모드에서 사용자 모드로 돌아가 작업을 계속한다.
- 프로세스 제어(process Control)
- 파일 조작(file manipulation)
- 장치 관리(Device Management)
- 정보 유지(Information maintenance)
- 통신(Communication)
SYSCALL/SYSENTER
SYSCALL/SYSENTER 은 interrupt없이 시스템콜을 처리할 수 있게 해주는 x86의 기능이다. 기존의 INT80을 이용한 시스템콜과 비교하여, 이 시스템 콜은 MSR 레지스터에 숨겨져 있던 CS, SS세그먼트 레지스터를 로딩하고 기타 여하의 레지스터를 로딩하는 것으로 구현된다. 또한 불필요한 check를 줄여서 불과 몇 사이클로 system call entry에 CPU가 들어갈 수 있도록 도와준다.
MSR Register
- STAR(0xC0000081): Ring0와 Ring3의 Segment base와 SYSCALL EIP(RIP)를 설정할 수 있게 해준다.
하위 32비트 (SYSCALL EIP) 상위 32-47 (Kernel segment base) 상위 48-63 (User segment base)
- LSTAR (0xC0000082): 64비트 모드에서 사용할 커널의 RIP
- SFMASK (0xC0000084): SYSCALL의 플래그 마스크를 설정한다.
하위 32비트 SYSCALL falg mask, 이 비트가 설정되면 기존의 rFALGS(ELFAGS)는 clear된다.
작동 방식
- SYSCALL: CS를 STAR의 47:32를 로딩하고, SFMASK로 EFLAGS를 마스킹한다. 그 다음 현재 RIP를 RCX에 저장하고, RIP를 (EIP를 STAR) LSTAR에서 로딩하고 SS를 STAR 47:32 + 16(32비트에서는 8)로 로딩하고 execute시킨다.
- SYSRET: CS를 STAR 48:63부터 로딩하고, RCX에서 RIP를 가져오고, STAR로부터 SS를 설정한다.
여기서 64비트 모드에서는 RFLAGS가 R11레지스터에 로딩되고 가져오게 된다. (즉 USER모드에서의 RFLAGS) 또한 Stack switching을 구현하는 것은 자동으로 이루어지는 것이 아니라 커널이 처리해 주어야 한다.