
시스템 호출 필터링 정책을 지정하기 위한 언어 및 라이브러리입니다.
Kafel은 시스템 호출 필터링 정책을 지정하기 위한 언어 및 라이브러리입니다. 정책은 seccomp-filter와 함께 사용할 수 있는 BPF 코드로 컴파일됩니다.
이것은 공식 Google 제품이 아닙니다.
struct sock_fprog prog;
kafel_ctxt_t ctxt = kafel_ctxt_create();
kafel_set_input_string(ctxt, seccomp_policy);
if (kafel_compile(ctxt, &prog)) {
fprintf(stderr, "policy compilation failed: %s", kafel_error_msg(ctxt));
kafel_ctxt_destroy(&ctxt);
exit(-1);
}
kafel_ctxt_destroy(&ctxt);
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
free(prog.filter);
struct sock_fprog prog;
if (kafel_compile_string(seccomp_policy, &prog)) {
fputs("policy compilation failed", stderr);
exit(-1);
}
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
free(prog.filter);
정책을 정의하는 데 간단한 언어가 사용됩니다.
정책 파일은 문장(statement)들로 구성됩니다.
문장은 다음 중 하나일 수 있습니다:
파일 범위에 배치된 정책 정의 문장은 암시적인 최상위 정책에 추가됩니다. 이 최상위 정책이 컴파일됩니다.
DEFAULT the_action
일치하는 규칙이 없을 때 the_action 동작을 취해야 함을 지정합니다.
기본 동작은 한 번만 지정해야 합니다.
정책 파일에 기본 동작이 지정되지 않으면 기본 동작은 KILL입니다.
Kafel은 다음 숫자 표기법을 지원합니다:
420xfa107770b10101정책을 더 읽기 쉽게 만들기 위해 숫자 상수를 정의할 수 있습니다. 상수 정의는 정책 파일의 거의 모든 곳에 배치될 수 있습니다. 상수 정의는 정책 정의 내부에 배치될 수 없습니다. 정의된 상수는 숫자가 필요한 모든 곳에서 사용할 수 있습니다.
#define MYCONST 123
정책 정의는 쉼표로 구분된 동작 블록과 사용 문장의 목록입니다.
samples/ 디렉토리에는 지원되는 기능을 보여주는 몇 가지 예제 정책이 포함되어 있습니다.
USE someOtherPolicy는 마치 someOtherPolicy 본문이 그 자리에 붙여넣어진 것처럼 동작합니다. 사용 문장 앞에 정의된 정책만 사용할 수 있습니다.
사용 문장을 사용하면 더 큰 정책의 구성 요소가 되는 의미 있는 필터링 규칙 그룹을 만들 수 있습니다.
동작 블록은 대상과 쉼표로 구분된 시스템 호출 일치 규칙 목록으로 구성됩니다.
일치하는 첫 번째 규칙의 대상이 정책 결정입니다.
다음 표는 Kafel 대상과 해당 seccomp-filter 반환 값을 나열합니다.
규칙은 시스템 호출 이름과 선택적 부울 표현식 목록으로 구성됩니다.
부울 표현식 목록은 쉼표로 구분됩니다.
쉼표는 의미상 ||와 동일하지만 우선순위가 가장 낮으므로 읽기 더 쉬울 수 있습니다.
일반적으로 시스템 호출은 Linux 커널에 정의된 이름으로 지정됩니다.
그러나 표준 시스템 호출 목록에 없는 __사용자 정의 시스템 호출__을 필터링할 수도 있습니다.
상수를 정의하여 시스템 호출 이름 대신 사용하거나 SYSCALL 키워드를 활용할 수 있습니다.
#define mysyscall -1
POLICY my_const {
ALLOW {
mysyscall
}
}
POLICY my_literal {
ALLOW {
SYSCALL[-1]
}
}
ON 가드를 사용하여 시스템 호출 규칙을 아키텍처 하위 집합으로 제한할 수 있습니다. 가드는 단일 아키텍처 이름 또는 중괄호로 묶인 쉼표로 구분된 목록을 허용합니다. 이름은 kafel_set_target_archs가 인식하는 대상에 해당합니다(예: x86_64, x86, arm, aarch64, mips64, riscv64, m68k).
ALLOW {
io_uring_setup ON x86_64,
arm_fadvise64_64 ON arm
}
가드 외부의 아키텍처에 대해 컴파일할 때 해당 시스템 호출 규칙은 무시되므로, 더 이상 시스템 호출 가용성 차이를 처리하기 위해 전체 정책을 중복할 필요가 없습니다.
부울 표현식은 인수를 기반으로 시스템 호출을 필터링하는 데 사용됩니다. 표현식은 C 언어 구문과 유사하지만 산술 연산자가 없습니다.
some_syscall(first_arg, my_arg_name) { first_arg == 42 && my_arg_name != 42 }
비트 AND(&) 및 OR(|) 연산자를 사용하여 플래그를 테스트할 수 있습니다.
mmap { (prot & PROT_EXEC) == 0 },
open { flags == O_RDONLY|O_CLOEXEC }
잘 알려진 시스템 호출의 인수를 선언할 필요 없이 Linux 커널 및 man 페이지에 지정된 일반 이름을 사용할 수 있습니다.
write { fd == 1 }
정책의 재사용과 구성을 간소화하기 위해 kafel은 포함 지원을 제공합니다.
#include "some_other_file.policy"
Kafel은 검색 경로에 명시적으로 추가된 디렉터리에서만 포함된 파일을 찾습니다.
kafel_add_include_search_path(ctxt, "includes/path");
includes/path를 검색 경로에 추가합니다. 위 예제 포함 지시문은 includes/path/some_other_file.policy를 참조합니다.
포함 지시문은 개행 또는 세미콜론으로 종료됩니다. 하나의 지시문에 공백으로 구분된 여러 파일을 지정할 수 있습니다.
#include "first.policy" "second.policy"; #include "third.policy"
nsjail과 함께 사용하면 다음 명령으로 셸에 상당히 제한된 환경을 만들 수 있습니다.
$ ./nsjail --chroot / --seccomp_string 'POLICY a { ALLOW { write, execve, brk, access, mmap, open, newfstat, close, read, mprotect, arch_prctl, munmap, getuid, getgid, getpid, rt_sigaction, geteuid, getppid, getcwd, getegid, ioctl, fcntl, newstat, clone, wait4, rt_sigreturn, exit_group } } USE a DEFAULT KILL' -- /bin/sh -i
[2017-01-15T21:53:08+0100] Mode: STANDALONE_ONCE
[2017-01-15T21:53:08+0100] Jail parameters: hostname:'NSJAIL', chroot:'/', process:'/bin/sh', bind:[::]:0, max_conns_per_ip:0, uid:(ns:1000, global:1000), gid:(ns:1000, global:1000), time_limit:0, personality:0, daemonize:false, clone_newnet:true, clone_newuser:true, clone_newns:true, clone_newpid:true, clone_newipc:true, clonew_newuts:true, clone_newcgroup:false, keep_caps:false, tmpfs_size:4194304, disable_no_new_privs:false, pivot_root_only:false
[2017-01-15T21:53:08+0100] Mount point: src:'/' dst:'/' type:'' flags:0x5001 options:''
[2017-01-15T21:53:08+0100] Mount point: src:'(null)' dst:'/proc' type:'proc' flags:0x0 options:''
[2017-01-15T21:53:08+0100] PID: 18873 about to execute '/bin/sh' for [STANDALONE_MODE]
/bin/sh: 0: can't access tty; job control turned off
$ set
IFS='
'
OPTIND='1'
PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
PPID='0'
PS1='$ '
PS2='> '
PS4='+ '
PWD='/'
$ id
Bad system call
$ exit
[2017-01-15T21:53:17+0100] PID: 18873 exited with status: 159, (PIDs left: 0)
| Kafel | seccomp-filter |
|---|
ALLOW | SECCOMP_RET_ALLOW |
LOG | SECCOMP_RET_LOG |
KILL, KILL_THREAD, DENY | SECCOMP_RET_KILL |
KILL_PROCESS | SECCOMP_RET_KILL_PROCESS |
USER_NOTIF | SECCOMP_RET_USER_NOTIF |
ERRNO(number) | SECCOMP_RET_ERRNO+number |
TRAP(number) | SECCOMP_RET_TRAP+number |
TRACE(number) | SECCOMP_RET_TRACE+number |