
Uma linguagem e biblioteca para especificar políticas de filtragem de chamadas de sistema.
Kafel é uma linguagem e biblioteca para especificar políticas de filtragem de syscalls. As políticas são compiladas em código BPF que pode ser usado com o seccomp-filter.
Este NÃO é um produto oficial do 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);
Uma linguagem simples é usada para definir políticas.
O arquivo de política consiste em declarações.
Uma declaração pode ser:
Declarações de definição de política colocadas no escopo do arquivo serão adicionadas à política implícita de nível superior. Esta política de nível superior será compilada.
DEFAULT the_action
Especifica que a ação the_action deve ser tomada quando nenhuma regra corresponder.
A ação padrão deve ser especificada apenas uma vez.
Se o arquivo de política não especificar ações padrão, a ação padrão será KILL
Kafel suporta as seguintes notações numéricas:
420xfa107770b10101Você pode definir constantes numéricas para tornar suas políticas mais legíveis. Definições de constantes podem ser colocadas em quase qualquer lugar no arquivo de política. Uma definição de constante não pode ser colocada dentro de uma definição de política. As constantes definidas podem então ser usadas em qualquer lugar onde um número é esperado.
#define MYCONST 123
A definição de política é uma lista de blocos de ação e declarações de uso separadas por vírgulas.
samples/ contém alguns exemplos de políticas que demonstram funcionalidades suportadas.
Uma USE someOtherPolicy se comporta como se o corpo de someOtherPolicy fosse colado em seu
lugar. Você só pode usar políticas definidas antes da declaração de uso.
Com declarações de uso, você pode criar grupos significativos de regras de filtragem que são blocos de construção de políticas maiores.
Um bloco de ação consiste em um alvo e uma lista de regras de correspondência de syscalls separadas com vírgulas.
O alvo da primeira regra correspondida é a decisão da política.
A tabela a seguir lista os alvos do Kafel e seus valores de retorno correspondentes do seccomp-filter.
Uma regra consiste em um nome de syscall e uma lista opcional de expressões booleanas.
Lista de expressões booleanas separadas por vírgulas.
Uma vírgula é semanticamente equivalente a || mas tem a precedência mais baixa,
portanto pode ser mais fácil de ler.
Normalmente, as syscalls são especificadas por seus nomes, conforme definidos no kernel Linux.
No entanto, você também pode filtrar syscalls personalizadas que não estão na lista padrão
de syscalls.
Você pode definir uma constante e usá-la no lugar do nome da syscall ou
utilizar a palavra-chave SYSCALL.
#define mysyscall -1
POLICY my_const {
ALLOW {
mysyscall
}
}
POLICY my_literal {
ALLOW {
SYSCALL[-1]
}
}
Você pode restringir uma regra de syscall a um subconjunto de arquiteturas usando o guarda
ON. O guarda aceita um único nome de arquitetura ou uma lista separada por vírgulas
entre chaves. Os nomes correspondem aos alvos reconhecidos por
kafel_set_target_archs (por exemplo x86_64, x86, arm, aarch64,
mips64, riscv64, m68k).
ALLOW {
io_uring_setup ON x86_64,
arm_fadvise64_64 ON arm
}
Ao compilar para uma arquitetura fora do guarda, a regra de syscall é ignorada, portanto, políticas entre arquiteturas não precisam mais duplicar políticas inteiras apenas para contabilizar diferenças de disponibilidade de syscalls.
Expressões booleanas são usadas para filtrar syscalls com base em seus argumentos. Uma expressão se assemelha à sintaxe da linguagem C, exceto que não há operadores aritméticos.
some_syscall(first_arg, my_arg_name) { first_arg == 42 && my_arg_name != 42 }
Os operadores bitwise and (&) e or ('|') podem ser usados para testar flags.
mmap { (prot & PROT_EXEC) == 0 },
open { flags == O_RDONLY|O_CLOEXEC }
Você não precisa declarar argumentos para syscalls conhecidas, mas pode apenas usar
seus nomes regulares conforme especificado no kernel Linux e nas páginas man.
write { fd == 1 }
Para simplificar a reutilização e composição de políticas, o kafel oferece suporte a inclusão.
#include "some_other_file.policy"
O Kafel procura por arquivos incluídos apenas em diretórios explicitamente adicionados aos caminhos de pesquisa.
kafel_add_include_search_path(ctxt, "includes/path");
Adiciona includes/path aos caminhos de pesquisa - o exemplo de diretiva de inclusão
se referirá então a includes/path/some_other_file.policy.
A diretiva de inclusão é terminada por uma nova linha ou um ponto e vírgula. Vários arquivos, separados por espaços em branco, podem ser especificados em uma diretiva.
#include "first.policy" "second.policy"; #include "third.policy"
Quando usado com nsjail, o seguinte comando permite criar um ambiente razoavelmente restrito para seu shell
$ ./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 |