API로 날아오는 “임의의” 코드를 안전하게 실행하기 위해 개발 § 1차 방어막 ‒ Linux container via Docker • 파일시스템, 프로세스/IPC/네트워크 네임스페이스 분리 • 메모리 및 CPU 사용률 제어 § 2차 방어막 ‒ Sorna Jail • Docker나 Linux container가 지원하지 않는 세밀한 정책 구현 • 예 : 프로세스/쓰레드 개수 제한, execve 시스템콜의 대상 제한, 관리 프로 세스에 대한 SIGKILL 제한, 네트워크 접근 제어 등 § 코드 : https://github.com/lablup/sorna-repl/tree/master/jail
2016년 1월 프로덕션 적용 § Docker seccomp profile • https://docs.docker.com/engine/security/seccomp/ • Docker v1.10부터 적용 (2016년 2월 릴리즈) • 이전까지는 apparmor 이용 § 결과 • docker run --security-opt seccomp:unconfined ...
/path/to/runtime /path/to/REPLscript Runtime Process (Python, Julia, R, bash, NodeJS, etc.) User code PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 work 20 0 8628 784 688 S 0.0 0.0 0:00.01 sh 7 work 20 0 188664 3628 2992 S 0.0 0.2 0:00.39 jail 94 work 20 0 179552 14396 7516 S 0.0 0.7 0:00.10 python
개발 시 C/C++을 대체하기 위한 목적 § 주요 특징 • 간단하고 배우기 쉬운 문법 (C/Java 유경험자는 1~2일이면 대충 사용) • 메모리 관리는 garbage collection • goroutine + channel을 이용한 멀티태스킹 • 패키지 시스템 제공 (go get) • fast & static build ‒ 바이너리 배포가 매우 편리함 • 아직은 generic을 잘 지원하지 않음 • 표준화된 코딩스타일 (gofmt 도구 제공, $GOPATH) CC BY 3.0 Renee French
당장 리눅스에서 strace python helloworld.py 라도 해보세요! § gdb는 어떻게 만들었을까요? • 한번쯤 궁금하지 않았나요? § ptrace system call • 다른 프로세스의 모든 시스템콜 호출 모니터링 • 다른 프로세스의 레지스터를 보거나 메모리를 읽고 쓸 수 있음 • 대부분의 Unix/Linux/BSD 계열 운영체제에서 제공 • man ptrace
kill(getpid(), SIGSTOP) ptrace(PTRACE_ATTACH, …) kill(pid, SIGCONT) (blocked) (blocked) (other initialization) Linux 3.4부터 PTRACE_ATTACH 대신 PTRACE_SEIZE 이용 가능 (차이점은 뒤에서 설명!) tracer tracee
PTRACE_O_TRACESYSGOOD § signal-delivery-stop • tracee가 운영체제, 자신, 또는 다른 프로세스가 발생시킨 signal 받은 경우 § group-stop • tracee가 받은 signal이 “stopping”인 경우 signal-delivery-stop 이후에 추가로 발생. tracee가 정지 상태임을 알려준다. § ptrace-event-stop • tracee가 지정된 이벤트를 발생시키는 경우 (execve, fork, clone 등) • PTRACE_O_TRACECLONE, PTRACE_O_TRACEEXEC, PTRACE_O_TRACEFORK, PTRACE_O_TRACESECCOMP, ... SIGSTOP, SIGTSP, SIGTTIN, SIGTTOU
jail 안에서 도는 shell이 job control을 하지 못한다. • Ctrl+Z가 작동하지 않는다. § Linux 3.4 이전까지 문제점 • group-stop인지 signal-delivery-stop인지 구분하려면 원래는 PTRACE_GETSIGINFO 불러서 EINVAL 리턴 확인해야 함 • tracee가 stop 상태를 유지해야 하는데 PTRACE_CONT 해버리면 stop 상태 가 풀려버림 § Linxu 3.4 이후 • PTRACE_ATTACH 대신 PTRACE_SEIZE 사용하면 group-stop 여부를 (status>>16) == PTRACE_EVENT_STOP 조건으로 정확히 검출 가능 • group-stop인 경우 PTRACE_CONT 대신 PTRACE_LISTEN 사용
file descriptor에 대한 read(), write() 만 가능하도록 프로세스 샌드박싱 • 이외의 시스템콜을 부르면 커널이 SIGKILL § seccomp-bpf 확장 • BPF (Berkeley Packet Filter) 기반으로 allow, block, trace할 시스템콜들 을 인자에 대한 조건식과 함께 지정 가능 • block하는 경우 오류 리턴값 지정 가능 (예: EPERM) • trace하는 경우 ptrace-event-stop을 통해 보다 직접 구현한 필터링 조건 적용이나 인자·리턴값 조작 가능 • libseccomp2 라이브러리를 통해 사용