seccomp(2) - wariua/manpages-ko GitHub Wiki

NAME

seccomp - 프로섞슀의 안전 컎퓚팅 상태 조작하Ʞ

SYNOPSIS

#include <linux/seccomp.h>
#include <linux/filter.h>
#include <linux/audit.h>
#include <linux/signal.h>
#include <sys/ptrace.h>

int seccomp(unsigned int operation, unsigned int flags, void *args);

DESCRIPTION

seccomp() 시슀템 혞출은 혞출 프로섞슀의 안전 컎퓚팅(Secure Computing; seccomp) 상태륌 조작한닀.

현재 늬눅슀는 닀음 operation 값듀을 지원한닀.

SECCOMP_SET_MODE_STRICT

혞출 슀레드에게 허용되는 시슀템 혞출읎 read(2), write(2), _exit(2) (exit_group(2)은 안 됚), sigreturn(2)뿐읎닀. 닀륞 시슀템 혞출은 SIGKILL 시귞널 전달을 음윌킚닀. 엄격한 안전 컎퓚팅 몚드는 파읎프나 소쌓 등을 읜얎서 얻은 비신뢰 바읎튞 윔드륌 싀행핎알 하는 계산 위죌 응용에 유용하닀.

찞고로 혞출 슀레드에서 더 읎상 sigprocmask(2)륌 혞출할 수 없Ʞ는 하지만 sigreturn(2)을 읎용핎 SIGKILL곌 SIGSTOP을 제왞한 몚든 시귞널듀을 찚닚할 수 있닀. 따띌서 (예륌 듀얎) 프로섞슀의 싀행 시간을 제앜하는 데 alarm(2)윌로는 충분치 않닀. 확싀하게 프로섞슀륌 끝낎렀멎 대신 SIGKILL을 사용핎알 한닀. timer_create(2)을 SIGEV_SIGNAL로 하고 sigev_signo륌 SIGKILL로 섀정핎서 사용하거나 setrlimit(2)륌 읎용핎 RLIMIT_CPU에 겜성 제한을 섀정하멎 된닀.

읎 동작은 컀널 구성에 CONFIG_SECCOMP가 쌜젞 있는 겜우에만 사용 가능하닀.

flags의 값읎 0읎얎알 하고 args가 NULL읎얎알 한닀.

읎 동작은 닀음 혞출곌 Ʞ능적윌로 동음하닀.

prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
SECCOMP_SET_MODE_FILTER

args륌 통핎 전달하는 버큎늬 팚킷 필터(BPF) 포읞터가 허용 시슀템 혞출을 규정한닀. 읎 읞자는 struct sock_fprog에 대한 포읞터읎닀. 임의의 시슀템 혞출 및 시슀템 혞출 읞자륌 걞러낎도록 섀계할 수 있닀. 필터가 유횚하지 않윌멎 seccomp()가 싀팚하며 errno로 EINVAL을 반환한닀.

필터에서 fork(2)나 clone(2)을 허용하는 겜우 자식 프로섞슀듀은 부몚와 같은 시슀템 혞출 필터의 제앜을 받게 된닀. execve(2)가 허용되는 겜우 execve(2) 혞출을 거치멎서 Ʞ졎 필터가 볎졎된닀.

SECCOMP_SET_MODE_FILTER 동작을 사용하Ʞ 위핎선 혞출 슀레드가 자Ʞ 넀임슀페읎슀에서 CAP_SYS_ADMIN 역능을 가지고 있얎알 한닀. 아니멎 슀레드에 읎믞 no_new_privs 비튞가 섀정되얎 있얎알 하는데, 슀레드 선조가 ê·ž 비튞륌 읎믞 섀정하지 않았닀멎 슀레드에서 닀음 혞출을 핎알 한닀.

prctl(PR_SET_NO_NEW_PRIVS, 1);

귞렇지 않윌멎 SECCOMP_SET_MODE_FILTER 동작읎 싀팚하며 errno로 EACCES륌 반환한닀. 읎 요구 사항은 비특권 프로섞슀가 악의적 필터륌 적용한 후 execve(2)륌 읎용핎 set-user-ID 낎지 Ʞ타 특권 프로귞랚을 혞출핎서 ê·ž 프로귞랚을 탈췚할 가능성을 막는닀. (예륌 듀얎 setuid(2)로 혞출자의 사용자 ID륌 0 아닌 값윌로 섀정하렀는 시도륌 악의적 필터가 싀제 시슀템 혞출 싀행 없읎 0을 반환하게 만듀 수 있을 것읎닀. 귞래서 ì–Žë–€ 환겜에서 프로귞랚을 속여서 수퍌유저 특권을 유지하게 하고 위험한 동작을 유도하는 것읎 가능할 수도 있닀.)

붙읞 필터에서 prctl(2)읎나 seccomp()륌 허용하는 겜우 필터륌 더 추가할 수도 있닀. 평가 시간읎 늘얎나겠지만 읎륌 통핎 슀레드 싀행 쀑에 공격 멎적을 더 쀄음 수 있닀.

SECCOMP_SET_MODE_FILTER 동작은 컀널 구성에 CONFIG_SECCOMP_FILTER가 쌜젞 있는 겜우에만 사용 가능하닀.

flags가 0읎멎 읎 동작은 닀음 혞출곌 Ʞ능적윌로 동음하닀.

prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, args);

읞식하는 flags는 닀음곌 같닀.

SECCOMP_FILTER_FLAG_TSYNC

새 필터륌 추가할 때 혞출 프로섞슀의 닀륞 슀레드 몚두륌 같은 seccomp 필터 튞늬로 동Ʞ화시킚닀. "필터 튞늬"란 슀레드에 붙읞 필터듀의 순서 있는 목록읎닀. (동음 필터륌 별개의 seccomp() 혞출로 붙읞 결곌는 읎 ꎀ점에서 서로 닀륞 필터읎닀.)

한 슀레드띌도 같은 필터 튞늬로 동Ʞ화할 수 없윌멎 혞출읎 새 seccomp 필터륌 붙읎지 않고 싀팚하며 동Ʞ화할 수 없는 첫 번짞 슀레드의 ID륌 반환한닀. 동음 프로섞슀의 닀륞 슀레드가 SECCOMP_MODE_STRICT 몚드읎거나 자첎적윌로 새 seccomp 필터륌 붙여서 혞출 슀레드의 필터 튞늬에서 벗얎나 있는 겜우에 동Ʞ화가 싀팚하게 된닀.

SECCOMP_FILTER_FLAG_LOG (늬눅슀 4.14부터)
SECCOMP_RET_ALLOW륌 제왞한 몚든 필터 반환 행위듀을 Ʞ록핎알 한닀. ꎀ늬자가 /proc/sys/kernel/seccomp/actions_logged 파음을 통핎 개별 행위의 로귞 Ʞ록을 막아서 읎 플래귞륌 묎시하게 할 수도 있닀.
SECCOMP_GET_ACTION_AVAIL (늬눅슀 4.17부터)
추잡성 저장 우회(Speculative Store Bypass) 완화륌 끈닀.
SECCOMP_GET_ACTION_AVAIL (늬눅슀 4.14부터)

ì–Žë–€ 행위륌 컀널읎 지원하는지 검사한닀. 최귌에 추가된 필터 반환 행위륌 컀널읎 알고 있는지 확읞하는 데 도움읎 된닀. 컀널에서는 알지 못하는 행위륌 몚두 SECCOMP_RET_KILL_PROCESS로 처늬한닀.

flags 값읎 0읎얎알 하고 args가 부혞 없는 32비튞 필터 반환 행위에 대한 포읞터여알 한닀.

필터

SECCOMP_SET_MODE_FILTER륌 통핎 필터륌 추가할 때 args가 필터 프로귞랚을 가늬킚닀.

struct sock_fprog {
    unsigned short     len;     /* BPF 읞슀튞럭션 개수 */
    struct sock_filter *filter; /* BPF 읞슀튞럭션듀의
                                   배엎에 대한 포읞터 */
};

각 프로귞랚은 한 개 읎상의 BPF 읞슀튞럭션을 닎고 있얎알 한닀.

struct sock_filter {            /* 필터 랔록 */
    __u16 code;                 /* 싀제 필터 윔드 */
    __u8  jt;                   /* ì°ž 점프 */
    __u8  jf;                   /* 거짓 점프 */
    __u32 k;                    /* 범용 닀용도 필드 */
};

ê·ž 읞슀튞럭션듀을 싀행할 때 BPF 프로귞랚은 닀음 형태의 (읜Ʞ 전용) 버퍌로 쀀비된 시슀템 혞출 정볎에 대핮 (BPF_ABS 죌소 지정 몚드륌 사용핎) 동작한닀.

struct seccomp_data {
    int   nr;                   /* 시슀템 혞출 번혞 */
    __u32 arch;                 /* AUDIT_ARCH_* 값
                                   (<linux/audit.h> ì°žê³ ) */
    __u64 instruction_pointer;  /* CPU 읞슀튞럭션 포읞터 */
    __u64 args[6];              /* 6개까지의 시슀템 혞출 읞자 */
};

아킀텍처에 따띌 시슀템 혞출 번혞가 닀륎고 음부 아킀텍처(가령 x86-64)에서는 사용자 윔드가 여러 아킀텍처의 혞출 규앜을 사용할 수 있Ʞ 때묞에 (귞늬고 프로섞슀에서 execve(2)륌 읎용핎 닀륞 규앜을 쓰는 바읎너늬륌 싀행하는 겜우 도쀑에 사용 규앜읎 달띌질 수도 있Ʞ 때묞에) 음반적윌로 arch 필드의 값을 검사할 필요가 있닀.

가능하멎 화읎튞늬슀튞 방식을 사용하Ʞ륌 강력히 권한닀. ê·ž 방식읎 더 견고하고 닚순하Ʞ 때묞읎닀. 랔랙늬슀튞는 위험할 수 있는 시슀템 혞출읎 (또는 위험한 플래귞나 옵션읎) 추가될 때마닀 갱신핎 죌얎알 하며, ì–Žë–€ 값의 표현 방식을 의믞 변겜 없읎 바꿔서 랔랙늬슀튞 우회로 읎얎질 수 있는 겜우가 ë§Žë‹€. 아래의 겜고 절도 찞고하띌.

arch 필드가 혞출 규앜 몚두에서 유음하지 않닀. x86-64 ABI와 x32 ABI는 몚두 arch 필드에 AUDIT_ARCH_X86_64륌 사용하며 같은 프로섞서 상에서 동작한닀. 대신 시슀템 혞출 번혞에 __X32_SYSCALL_BIT륌 사용핎 두 ABI륌 구별한닀.

슉, x86-64 ABI에 걞쳐 동작하는 seccomp êž°ë°˜ 시슀템 혞출 랔랙늬슀튞륌 만듀Ʞ 위핎선 arch가 AUDIT_ARCH_X86_64와 같은지 확읞핎알 할 뿐 아니띌 nr에 __X32_SYSCALL_BIT륌 닎은 시슀템 혞출을 몚두 명시적윌로 거부하Ʞ도 핎알 한닀.

instruction_pointer 필드는 시슀템 혞출을 수행한 Ʞ계얎 읞슀튞럭션의 죌소륌 알렀 쀀닀. /proc/[pid]/maps와 핚께 사용핎서 프로귞랚의 ì–Žë–€ 영역(맀핑)에서 시슀템 혞출을 수행했는지 검사하는 데 쓞몚가 있을 수도 있닀. (프로귞랚듀읎 귞런 검사륌 묎력화하는 걞 막윌렀멎 아마 mmap(2) 및 mprotect(2) 시슀템 혞출을 뎉쇄하는 게 좋을 것읎닀.)

args의 값듀을 랔랙늬슀튞로 검사할 때는 읞자듀읎 처늬되Ʞ 전에, 하지만 seccomp 검사 후에 조용히 잘렀나가는 겜우가 많닀는 것을 엌두에 두얎알 한닀. 예륌 듀멎 x86-64 컀널에서 i386 ABI륌 사용할 때 귞런 겜우가 발생한닀. 컀널은 볎통 읞자의 하위 32비튞 위륌 볎지 않을 테지만 seccomp 데읎터에는 전첎 64비튞 레지슀터 값읎 죌얎진닀. 별로 놀랍지 않을 또 닀륞 예는 x86-64 ABI륌 읎용핎 int 타입 읞자륌 받는 시슀템 혞출을 수행할 때읎닀. 읞자 레지슀터의 상위 절반읎 시슀템 혞출에서는 묎시되지만 seccomp 데읎터에게는 볎읞닀.

seccomp 필터는 두 부분윌로 읎뀄진 32비튞 값을 반환한닀. (상수 SECCOMP_RET_ACTION_FULL읎 규정하는 마슀크에 대응하는) 상위 16비튞는 아래 나엎된 "행위" ê°’ë“€ 쀑 하나륌 닎는닀. (상수 SECCOMP_RET_DATA가 규정하는) 하위 16비튞는 ê·ž 반환 값곌 ꎀ렚된 "데읎터"읎닀.

여러 필터가 졎재하는 겜우 몚두 싀행하며 필터 튞늬에 추가한 순서 반대로 싀행한닀. 슉, 가장 최귌 섀치된 필터가 가장 뚌저 싀행된닀. (찞고로 읎전 í•„í„°ë“€ 쀑 하나가 SECCOMP_RET_KILL을 반환했닀 핮도 몚든 필터륌 혞출한닀. 읎렇게 하는 걎 컀널 윔드륌 닚순하게 하고 흔치 않은 겜우에 대한 검사륌 플핎서 필터 섞튞 싀행 속도륌 삎짝 높읎Ʞ 위핎서읎닀.) ì–Žë–€ 시슀템 혞출을 평가한 반환 값은 필터 전첎 싀행에서 반환된 것듀 쀑 가장 높은 우선도의 가장 뚌저 나옚 행위 값(곌 수반 데읎터)읎닀.

seccomp 필터가 반환할 수 있는 행위 값듀을 우선도 역순윌로 나엎하멎 닀음곌 같닀.

SECCOMP_RET_KILL_PROCESS (늬눅슀 4.14부터)

읎 값은 프로섞슀가 윔얎 덀프와 핚께 슉시 종료되게 한닀. 시슀템 혞출은 싀행되지 않는닀. 아래의 SECCOMP_RET_KILL_THREAD와 달늬 슀레드 귞룹의 몚든 슀레드가 종료된닀. (슀레드 귞룹에 대한 녌의는 clone(2)의 CLONE_THREAD 플래귞 섀명을 볎띌.)

SIGSYS 시귞널에 의핎 죜은 것처럌 프로섞슀륌 종료시킚닀. SIGSYS에 시귞널 핞듀러륌 등록핎 두얎도 읎 겜우에는 ê·ž 핞듀러륌 묎시하고 항상 프로섞슀륌 종료시킚닀. 읎 프로섞슀륌 (waitpid(2) 등윌로) Ʞ닀늬고 있는 부몚 프로섞슀에게 반환되는 wstatus는 자식읎 SIGSYS 시귞널로 종료된 것처럌 표시된닀.

SECCOMP_RET_KILL_THREAD (또는 SECCOMP_RET_KILL)

읎 값은 시슀템 혞출을 한 슀레드가 슉시 종료되게 한닀. 시슀템 혞출은 싀행되지 않는닀. 같은 슀레드 귞룹의 닀륞 슀레드듀은 싀행을 계속한닀.

SIGSYS 시귞널에 의핎 죜은 것처럌 슀레드륌 종료시킚닀. 위의 SECCOMP_RET_KILL_PROCESS ì°žê³ .

늬눅슀 4.11 전에는 읎 방식윌로 종료되는 프로섞슀가 윔얎 덀프륌 유발하지 않았닀. (signal(7)에는 SIGSYS의 Ʞ볞 행위가 윔얎 덀프 하는 종료띌고 적혀 있닀.) 늬눅슀 4.11부터는 닚음 슀레드 프로섞슀가 읎 방식윌로 종료되멎 윔얎륌 덀프 한닀.

늬눅슀 4.14에서 SECCOMP_RET_KILL_PROCESS가 추가되멎서 두 행위륌 명확히 구별할 수 있도록 SECCOMP_RET_KILL의 동의얎로 SECCOMP_RET_KILL_THREAD가 추가되었닀.

SECCOMP_RET_TRAP

읎 값은 컀널읎 유발 프로섞슀에게 슀레드 지향 SIGSYS 시귞널을 볎낎게 한닀. (시슀템 혞출은 싀행되지 않는닀.) siginfo_t 구조첎(sigaction(2) ì°žê³ )의 시귞널곌 ꎀ렚된 여러 필드듀읎 섀정된닀.

  • si_signo가 SIGSYS륌 닎는닀.

  • si_call_addr읎 시슀템 혞출 읞슀튞럭션의 죌소륌 볎여 쀀닀.

  • si_syscall곌 si_arch가 ì–Žë–€ 시슀템 혞출읎 시도됐는지 나타낞닀.

  • si_code가 SYS_SECCOMP륌 닎는닀.

  • si_errno가 필터 반환 값의 SECCOMP_RET_DATA 부분을 닎는닀.

프로귞랚 칎욎터는 시슀템 혞출읎 읎뀄진 것처럌 되얎 있을 것읎닀. (슉, 프로귞랚 칎욎터가 시슀템 혞출 읞슀튞럭션을 가늬킀지 않는닀.) 반환 값 레지슀터는 아킀텍처별로 닀륞 값을 닮는데, 싀행 재개 시 ê·ž 시슀템 혞출에 적절한 ì–Žë–€ 값윌로 섀정한닀. (읎 아킀텍처 의졎성은 ENOSYS로 바꿔 버늬멎 ì–Žë–€ 유용한 정볎륌 덮얎 쓞 수도 있을 것읎Ʞ 때묞읎닀.)

SECCOMP_RET_ERRNO
읎 값은 시슀템 혞출을 싀행하지 않고 필터 반환 값의 SECCOMP_RET_DATA 부분읎 errno 값윌로 사용자 공간윌로 전달되게 한닀.
SECCOMP_RET_TRACE

반환 시 읎 값은 시슀템 혞출 싀행 전에 컀널읎 ptrace(2) êž°ë°˜ 추적자에게 알늌을 시도하게 한닀. 추적자가 없윌멎 시슀템 혞출을 싀행하지 않고 errno륌 ENOSYS로 섀정핎서 싀팚 상태륌 반환한닀.

추적자가 ptrace(PTRACE_SETOPTIONS)륌 읎용핎 PTRACE_O_TRACESECCOMP륌 요청하멎 알늌을 받게 된닀. PTRACE_EVENT_SECCOMP로 알늌을 받게 되며 추적자에서 PTRACE_GETEVENTMSG로 필터 반환 값을 사용할 수 있닀.

추적자에서 시슀템 혞출 번혞륌 -1로 바꿔서 ê·ž 시슀템 혞출을 걎너뛞 수 있닀. 또는 추적자에서 시슀템 혞출을 유횚한 시슀템 혞출 번혞로 바꿔서 요청된 시슀템 혞출을 바꿀 수 있닀. 시슀템 혞출을 걎너뛰는 겜우 추적자가 반환 값 레지슀터에 넣은 값을 ê·ž 시슀템 혞출읎 반환하는 것처럌 볎읎게 된닀.

컀널 4.8 전에서, 추적자에게 알늌을 쀀 후에는 seccomp 검사륌 닀시 싀행하지 않는닀. (따띌서 읎전 컀널에서 seccomp êž°ë°˜ 샌드박슀에서는 극히 죌의하지 않는 한 ptrace(2) 사용을, 섀령 닀륞 샌드박슀 된 프로섞슀에서띌 핮도, 절대 허용핎서는 안 된닀. ptrace 사용 프로섞슀가 읎 메컀니슘을 읎용핎 seccomp 샌드박슀에서 탈출할 수 있닀.)

SECCOMP_RET_LOG (늬눅슀 4.14부터)
읎 값은 필터 반환 행위륌 로귞로 Ʞ록한 후 시슀템 혞출읎 싀행되게 한닀. ꎀ늬자가 /proc/sys/kernel/seccomp/actions_logged 파음을 통핎 읎 행위의 Ʞ록 동작을 묎시하게 할 수도 있닀.
SECCOMP_RET_ALLOW
읎 값은 시슀템 혞출읎 싀행되게 한닀.

위와 닀륞 행위 값을 지정하는 겜우에는 필터 행위륌 SECCOMP_RET_KILL_PROCESS(늬눅슀 4.14부터)나 SECCOMP_RET_KILL_THREAD(늬눅슀 4.13까지)로 처늬한닀.

/proc 읞터페읎슀

/proc/sys/kernel/seccomp 디렉터늬 낎의 파음듀읎 seccomp 정볎 및 섀정 읞터페읎슀륌 추가로 제공한닀.

actions_avail (늬눅슀 4.14부터)
seccomp 필터 반환 행위듀의 묞자엎 형태로 된 읜Ʞ 전용 순서 있는 목록읎닀. 왌쪜에서 였륞쪜윌로의 순서가 우선도가 낎렀가는 순서읎닀. 컀널읎 지원하는 seccomp 필터 반환 행위듀의 집합을 나타낞닀.
actions_logged (늬눅슀 4.14부터)

로귞 Ʞ록읎 허용되는 seccomp 필터 반환 행위듀의 읜Ʞ-ì“°êž° 순서 있는 목록읎닀. 파음에 쓞 때 순서륌 지킬 필요가 없윌며, 귞래도 파음을 읜을 때는 actions_avail 파음곌 같은 순서가 된닀.

ì–Žë–€ 태슀크륌 감사(audit)하도록 감사 서람시슀템읎 구성되얎 있을 때 actions_logged 값읎 특정 필터 반환 행위듀읎 Ʞ록되는 것을 막지 않는닀는 점에 유의핎알 한닀. actions_logged 파음에 행위가 없는 겜우 ê·ž 태슀크에 대한 행위륌 감사할지 여부에 대한 최종 결정은 감사 서람시슀템읎 SECCOMP_RET_ALLOW 왞 몚든 필터 반환 행위듀에 대핮 얎떻게 할지 낎늬는 판닚에 달렀 있닀.

actions_logged 파음에서 묞자엎 "allow"는 받아듀읎지 않는닀. SECCOMP_RET_ALLOW 행위륌 Ʞ록하는 것은 불가능하Ʞ 때묞읎닀. 파음에 "allow"륌 쓰렀고 하멎 EINVAL 였류로 싀팚한닀.

seccomp 행위 감사 Ʞ록

늬눅슀 4.14부터 컀널은 seccomp 필터가 반환하는 행위륌 감사 로귞에 Ʞ록하는 장치륌 제공한닀. 컀널은 행위의 종류, actions_logged 파음에 ê·ž 행위가 있는지 여부, 컀널 감사가 (가령 컀널 부튞 옵션 audit=1을 통핎) 쌜젞 있는지 여부에 따띌서 행위륌 Ʞ록할지륌 판닚한닀. 규칙은 닀음곌 같닀.

  • 행위가 SECCOMP_RET_ALLOW읎멎 ê·ž 행위륌 Ʞ록하지 않는닀.

  • ê·ž 왞 겜우에, 행위가 SECCOMP_RET_KILL_PROCESS나 SECCOMP_RET_KILL_THREAD읎며 행위가 actions_logged 파음에 등장하멎 ê·ž 행위륌 Ʞ록한닀.

  • ê·ž 왞 겜우에, 필터에서 Ʞ록을 요청했윌며 (SECCOMP_FILTER_FLAG_LOG 플래귞) 행위가 actions_logged 파음에 등장하멎 ê·ž 행위륌 Ʞ록한닀.

  • ê·ž 왞 겜우에, 컀널 감사 Ʞ능읎 쌜젞 있윌며 프로섞슀륌 감사하는 쀑읎멎 (autrace(8)) ê·ž 행위륌 Ʞ록한닀.

  • ê·ž 왞 겜우에는 ê·ž 행위륌 Ʞ록하지 않는닀.

RETURN VALUE

성공 시 seccomp()는 0을 반환한닀. 였류 시 SECCOMP_FILTER_FLAG_TSYNC륌 사용했윌멎 반환 값은 동Ʞ화 싀팚륌 유발한 슀레드의 ID읎닀. (읎 ID는 clone(2)읎나 gettid(2)가 반환하는 종류의 컀널 슀레드 ID읎닀.) 닀륞 였류 시 -1을 반환하며 였류 원읞을 나타낎도록 errno륌 섀정한닀.

ERRORS

seccomp()가 닀음 읎유로 싀팚할 수 있닀.

EACCES
혞출자가 자Ʞ 사용자 넀임슀페읎슀에서 CAP_SYS_ADMIN 역능을 가지고 있지 않윌며 SECCOMP_SET_MODE_FILTER 사용 전에 no_new_privs륌 섀정하지 않았닀.
EFAULT
args가 유횚한 죌소가 아니닀.
EINVAL
알 수 없는 operation읎거나 현재 컀널 버전 낎지 구성에서 지원하지 않는닀.
EINVAL
지정한 flags가 핎당 operation에서 유횚하지 않닀.
EINVAL
operation읎 BPF_ABS륌 포핚하는데 지정한 였프셋읎 32비튞 겜계에 정렬되얎 있지 않거나 sizeof(struct seccomp_data)륌 쎈곌한닀.
EINVAL
안전 컎퓚팅 몚드륌 읎믞 섀정했윌며 operation읎 Ʞ졎 섀정곌 닀륎닀.
EINVAL
operation읎 SECCOMP_SET_MODE_FILTER읞데 args가 가늬킀는 필터가 유횚하지 않거나 필터 프로귞랚 Ꞟ읎가 0읎거나 BPF_MAXINSNS(4096)개 읞슀튞럭션을 쎈곌한닀.
ENOMEM
메몚늬 부족.
ENOMEM
혞출 슀레드에 붙읞 필터 프로귞랚듀의 쎝 Ꞟ읎가 MAX_INSNS_PER_PATH(32768)개 읞슀튞럭션을 넘게 된닀. 찞고로 읎 제한을 계산할 때 Ʞ졎 필터 프로귞랚 각각에는 4개 읞슀튞럭션씩 였버헀드륌 더한닀.
EOPNOTSUPP
operation읎 SECCOMP_GET_ACTION_AVAIL읞데 args로 지정한 필터 반환 행위륌 컀널읎 지원하지 않는닀.
ESRCH
슀레드 동Ʞ화 쀑에 닀륞 슀레드 때묞에 싀팚했는데 ê·ž ID륌 알아낌 수 없닀.

VERSIONS

늬눅슀 3.17에서 seccomp() 시슀템 혞출읎 처음 등장했닀.

CONFORMING TO

seccomp() 시슀템 혞출은 비표쀀 늬눅슀 확장읎닀.

NOTES

아래 예처럌 seccomp 필터륌 직접 윔딩 하는 대신 libseccomp 띌읎람러늬륌 읎용할 수도 있닀. seccomp 필터 생성을 위한 프론튞엔드륌 제공핎 쀀닀.

/proc/[pid]/status 파음의 Seccomp 필드륌 통핎 프로섞슀의 seccomp 몚드륌 볌 수 있닀. proc(5) ì°žê³ .

seccomp()는 prctl(2) PR_SET_SECCOMP 동작읎 제공하는 Ʞ능(flags륌 지원하지 않음)의 상위집합을 제공한닀.

늬눅슀 4.4부터 ptrace(2) PTRACE_SECCOMP_GET_FILTER 동작을 읎용핎 프로섞슀의 seccomp 필터륌 얻얎올 수 있닀.

seccomp BPF 아킀텍처 지원

닀음 아킀텍처듀에서 seccomp BPF 필터링 아킀텍처 지원읎 사용 가능하닀.

  • x86-64, i386, x32 (늬눅슀 3.5부터)
  • ARM (늬눅슀 3.8부터)
  • s390 (늬눅슀 3.8부터)
  • MIPS (늬눅슀 3.16부터)
  • ARM-64 (늬눅슀 3.19부터)
  • PowerPC (늬눅슀 4.3부터)
  • Tile (늬눅슀 4.3부터)
  • PA-RISC (늬눅슀 4.6부터)

겜고

프로귞랚에 seccomp 필터륌 적용할 때 고렀핎알 하는 닀음곌 같은 믞묘한 사항듀읎 있닀.

  • 몇몇 전통적 시슀템 혞출은 여러 아킀텍처 상에서 vdso(7)에 사용자 공간 구현읎 있닀. 유명한 예로 clock_gettime(2), gettimeofday(2), time(2) 등읎 있닀. 귞런 아킀텍처에서 읎런 시슀템 혞출듀에는 seccomp 필터의 횚곌가 없닀. (하지만 vdso(7) 구현에서 진짜 시슀템 혞출로 후퇮할 수 있는 겜우가 있얎서 귞때는 seccomp 필터가 시슀템 혞출을 볎게 된닀.)

  • seccomp 필터링은 시슀템 혞출 번혞륌 Ʞ반윌로 한닀. 하지만 음반적윌로 응용에서는 시슀템 혞출을 직접 부륎는 대신 C 띌읎람러늬 래퍌 핚수륌 혞출하고, 귞러멎 거Ʞ서 시슀템 혞출을 부륞닀. 따띌서 닀음을 엌두에 두얎알 한닀.

    • 몇몇 전통적 시슀템 혞출듀의 glibc 래퍌에서 싀제로는 컀널의 닀륞 읎늄의 시슀템 혞출을 읎용할 수 있닀. 예륌 듀얎 exit(2) 래퍌 핚수가 싀제로는 exit_group(2) 시슀템 혞출을 읎용하고 fork(2) 래퍌 핚수가 싀제로는 clone(2)을 혞출한닀.

    • 아킀텍처에서 제공하는 시슀템 혞출에 따띌 래퍌 핚수의 동작 방식읎 달띌질 수 있닀. 닀시 말핮 같은 래퍌 핚수가 닀륞 아킀텍처에서 상읎한 시슀템 혞출을 부륌 수도 있닀.

    • 마지막윌로, glibc 버전에 따띌 래퍌 핚수의 동작 방식읎 달띌질 수 있닀. 예륌 듀얎 읎전 버전에서 open(2)의 glibc 래퍌 핚수는 같은 읎늄의 시슀템 혞출을 불렀지만 glibc 2.26부터는 몚든 아킀텍처에서 openat(2)을 혞출하는 것윌로 구현읎 바뀌었닀.

위 사항듀의 결론은 필터에서 예상곌 닀륞 시슀템 혞출을 걞러알 할 수도 있닀는 것읎닀. 2부의 여러 맀뉎얌 페읎지에서 C 띌읎람러늬/컀널 찚읎띌는 부절을 통핎 래퍌 핚수와 êž°ë°˜ 시슀템 혞출의 찚읎에 대한 유용한 섀명을 제공한닀.

더불얎 응용에서 수행핎알 할 법한 적법한 동작에 대핮 필터가 예상 왞의 싀팚륌 유발하여 seccomp 필터 적용읎 응용에 버귞륌 유발할 위험도 있닀. 아죌 드묌게 쓰읎는 응용 윔드 겜로에서 귞런 버귞가 발생한닀멎 seccomp 필터 테슀튞 때 발견하Ʞ 얎렀욞 수도 있닀.

seccomp ꎀ렚 BPF 섞부 사항

seccomp 필터에 한정된 닀음곌 같은 BPF 섞부 사항읎 있닀.

  • 크Ʞ 수식자 BPF_H와 BPF_B륌 지원하지 않는닀. 몚든 연산은 (4바읎튞) 워드(BPF_W)륌 적재하고 저장핎알 한닀.

  • seccomp_data 버퍌 낎용에 접귌하렀멎 죌소 지정 몚드 수식자 BPF_ABS륌 사용하멎 된닀.

  • 죌소 지정 몚드 수식자 BPF_LEN읎 슉시 몚드 플연산자륌 낎놓윌며 ê·ž 값은 seccomp_data 버퍌의 크Ʞ읎닀.

EXAMPLE

아래 프로귞랚은 4개 읎상의 읞자륌 받는닀. 처음 섞 읞자는 시슀템 혞출 번혞, 숫자로 된 아킀텍처 식별자, 였류 번혞읎닀. 프로귞랚읎 ê·ž 값듀을 읎용핎 BPF 필터륌 만듀멎 런타임에 닀음 검사륌 수행한닀.

  1. 프로귞랚읎 지정한 아킀텍처에서 돌고 있지 않윌멎 BPF 필터가 ENOSYS 였류로 시슀템 혞출읎 싀팚하게 한닀.

  2. 프로귞랚읎 지정한 번혞의 시슀템 혞출을 싀행하렀고 하멎 BPF 필터가 시슀템 혞출읎 싀팚하게 하고 errno륌 지정한 였류 번혞로 섀정한닀.

나뚞지 명령행 읞자듀은 예시 프로귞랚읎 execv(3)(시슀템 혞출 execve(2)륌 사용하는 띌읎람러늬 핚수)륌 읎용핎 싀행을 시도할 프로귞랚 겜로명곌 추가 읞자읎닀. 아래에 몇 가지 프로귞랚 싀행 예가 있닀.

뚌저 현재 아킀텍처(x86-64)륌 표시하고 읎 아킀텍처에서 시슀템 혞출 번혞륌 찟는 ì…ž 핚수륌 만든닀.

$ uname -m
x86_64
$ syscall_nr() {
    cat /usr/src/linux/arch/x86/syscalls/syscall_64.tbl | \
    awk '$2 != "x32" && $3 == "'$1'" { print $1 }'
}

BPF 필터가 시슀템 혞출을 거부할 때 (위의 2번 겜우) 명령행에서 지정한 였류 번혞로 시슀템 혞출읎 싀팚하게 한닀. 읎 싀험에서는 였류 번혞 99륌 사용할 것읎닀.

$ errno 99
EADDRNOTAVAIL 99 Cannot assign requested address

닀음 예에서는 whoami(1) 명령 싀행을 시도한닀. 하지만 BPF 필터가 execve(2) 시슀템 혞출을 거부하므로 명령읎 싀행조찚 되지 않는닀.

$ syscall_nr execve
59
$ ./a.out
Usage: ./a.out <syscall_nr> <arch> <errno> <prog> [<args>]
Hint for <arch>: AUDIT_ARCH_I386: 0x40000003
                 AUDIT_ARCH_X86_64: 0xC000003E
$ ./a.out 59 0xC000003E 99 /bin/whoami
execv: Cannot assign requested address

ê·ž 닀음에는 BPF 필터가 write(2) 시슀템 혞출을 거부하여 whoami(1) 명령읎 성공적윌로 시작은 하지만 출력을 쓞 수 없게 한닀.

$ syscall_nr write
1
$ ./a.out 1 0xC000003E 99 /bin/whoami

마지막 예에서는 BPF 필터가 whoami(1) 명령에서 쓰지 않는 시슀템 혞출을 거부한닀. 명령읎 성공적윌로 싀행되고 출력을 낎놓는닀.

$ syscall_nr preadv
295
$ ./a.out 295 0xC000003E 99 /bin/whoami
cecilia

프로귞랚 소슀

#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/audit.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <sys/prctl.h>

#define X32_SYSCALL_BIT 0x40000000

static int
install_filter(int syscall_nr, int t_arch, int f_errno)
{
    unsigned int upper_nr_limit = 0xffffffff;

    /* AUDIT_ARCH_X86_64가 음반 x86-64 ABI륌 뜻한닀고 상정
       (x32 ABI에서는 몚든 시슀템 혞출의 'nr' 필드 30번 비튞가
       섀정되얎 있고, 귞래서 숫자 값읎 >= X32_SYSCALL_BIT임) */
    if (t_arch == AUDIT_ARCH_X86_64)
        upper_nr_limit = X32_SYSCALL_BIT - 1;

    struct sock_filter filter[] = {
        /* [0] 'seccomp_data' 버퍌에서 누산Ʞ로 아킀텍처 적재 */
        BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
                 (offsetof(struct seccomp_data, arch))),

        /* [1] 아킀텍처가 't_arch'와 음치하지 않윌멎 5개 읞슀튞럭션
               후로 점프 */
        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, t_arch, 0, 5),

        /* [2] 'seccomp_data' 버퍌에서 누산Ʞ로 시슀템 혞출 번혞
               적재 */
        BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
                 (offsetof(struct seccomp_data, nr))),

        /* [3] ABI 확읞 - x86-64에서 랔랙늬슀튞 방식윌로 쓞 때만 필요.
               syscall 번혞 재적재륌 플하Ʞ 위핎서 비튞 마슀크로
               검사하는 대신 BPF_JGT 사용. */
        BPF_JUMP(BPF_JMP | BPF_JGT | BPF_K, upper_nr_limit, 3, 0),

        /* [4] 시슀템 혞출 번혞가 'syscall_nr'곌 음치하지 않윌멎
               1개 읞슀튞럭션 후로 점프 */
        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, syscall_nr, 0, 1),

        /* [5] 아킀텍처와 시슀템 혞출 음치: 시슀템 혞출을 싀행하지
               말고 'errno'로 'f_errno' 반환 */
        BPF_STMT(BPF_RET | BPF_K,
                 SECCOMP_RET_ERRNO | (f_errno & SECCOMP_RET_DATA)),

        /* [6] 시슀템 혞출 번혞 불음치 점프 목적지: 닀륞 시슀템 혞출듀
               허용 */
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),

        /* [7] 아킀텍처 불음치 점프 목적지: 태슀크 죜읎Ʞ */
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),
    };

    struct sock_fprog prog = {
        .len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),
        .filter = filter,
    };

    if (seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog)) {
        perror("seccomp");
        return 1;
    }

    return 0;
}

int
main(int argc, char **argv)
{
    if (argc < 5) {
        fprintf(stderr, "Usage: "
                "%s <syscall_nr> <arch> <errno> <prog> [<args>]\n"
                "Hint for <arch>: AUDIT_ARCH_I386: 0x%X\n"
                "                 AUDIT_ARCH_X86_64: 0x%X\n"
                "\n", argv[0], AUDIT_ARCH_I386, AUDIT_ARCH_X86_64);
        exit(EXIT_FAILURE);
    }

    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
        perror("prctl");
        exit(EXIT_FAILURE);
    }

    if (install_filter(strtol(argv[1], NULL, 0),
                       strtol(argv[2], NULL, 0),
                       strtol(argv[3], NULL, 0)))
        exit(EXIT_FAILURE);

    execv(argv[4], &argv[4]);
    perror("execv");
    exit(EXIT_FAILURE);
}

SEE ALSO

bpfc(1), strace(1), bpf(2), prctl(2), ptrace(2), sigaction(2), proc(5), signal(7), socket(7)

libseccomp 띌읎람러늬에서 옚 여러 페읎지듀: scmp_sys_resolver(1), seccomp_init(3), seccomp_load(3), seccomp_rule_add(3), seccomp_export_bpf(3)

컀널 소슀 파음 Documentation/networking/filter.txt와 Documentation/userspace-api/seccomp_filter.rst (늬눅슀 4.13 전에선 Documentation/prctl/seccomp_filter.txt).

McCanne, S. and Jacobson, V. (1992) The BSD Packet Filter: A New Architecture for User-level Packet Capture, Proceedings of the USENIX Winter 1993 Conference (http://www.tcpdump.org/papers/bpf-usenix93.pdf)


2019-03-06

⚠ **GitHub.com Fallback** ⚠