mirror of
https://github.com/uselessd/alcove.git
synced 2026-04-24 13:46:02 +00:00
Macros to create bpf instructions, taken from procket.
A minimal example (set up for little endian ARM):
-module(filt).
-export([enforce/2,enforce/3]).
-include_lib("alcove/include/alcove.hrl").
-include_lib("alcove/include/alcove_seccomp.hrl").
-define(EM_ARM, 40).
-define(__AUDIT_ARCH_LE, 16#40000000).
-define(AUDIT_ARCH_ARM, ?EM_ARM bxor ?__AUDIT_ARCH_LE).
-define(OFFSET_SYSCALL_NR, 0).
-define(OFFSET_ARCH_NR, 4).
-define(VALIDATE_ARCHITECTURE(Offset_arch_nr, Arch_nr), [
?BPF_STMT(?BPF_LD+?BPF_W+?BPF_ABS, Offset_arch_nr),
?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, Arch_nr, 1, 0),
?BPF_STMT(?BPF_RET+?BPF_K, ?SECCOMP_RET_KILL)
]).
-define(EXAMINE_SYSCALL(Offset_syscall_nr),
?BPF_STMT(?BPF_LD+?BPF_W+?BPF_ABS, Offset_syscall_nr)).
-define(ALLOW_SYSCALL(Syscall_nr), [
?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, Syscall_nr, 0, 1),
?BPF_STMT(?BPF_RET+?BPF_K, ?SECCOMP_RET_ALLOW)
]).
-define(NR_exit, 1).
-define(NR_read, 3).
-define(NR_write, 4).
-define(NR_setrlimit, 75).
-define(NR_getrlimit, 76).
-define(NR_sigreturn, 119).
-define(NR_poll, 168).
-define(NR_rt_sigreturn, 173).
-define(NR_ugetrlimit, 191).
-define(NR_exit_group, 248).
filter() ->
[
?VALIDATE_ARCHITECTURE(?OFFSET_ARCH_NR, ?AUDIT_ARCH_ARM),
?EXAMINE_SYSCALL(?OFFSET_SYSCALL_NR),
?ALLOW_SYSCALL(?NR_rt_sigreturn),
?ALLOW_SYSCALL(?NR_sigreturn),
?ALLOW_SYSCALL(?NR_exit_group),
?ALLOW_SYSCALL(?NR_exit),
?ALLOW_SYSCALL(?NR_read),
?ALLOW_SYSCALL(?NR_write),
?ALLOW_SYSCALL(?NR_setrlimit),
?ALLOW_SYSCALL(?NR_getrlimit),
?ALLOW_SYSCALL(?NR_ugetrlimit),
?ALLOW_SYSCALL(?NR_poll),
?BPF_STMT(?BPF_RET+?BPF_K, ?SECCOMP_RET_KILL)
].
enforce(Drv, Pids) ->
enforce(Drv, Pids, filter()).
enforce(Drv, Pids, Filter) ->
PR_SET_NO_NEW_PRIVS = alcove:define(Drv, 'PR_SET_NO_NEW_PRIVS'),
PR_SET_SECCOMP = alcove:define(Drv, 'PR_SET_SECCOMP'),
SECCOMP_MODE_FILTER = alcove:define(Drv, 'SECCOMP_MODE_FILTER'),
{ok,_,_,_,_,_} = alcove:prctl(Drv, Pids, PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0),
Prog = [
<<(iolist_size(Filter) div 8):2/native-unsigned-integer-unit:8>>,
<<0:16>>,
{ptr, list_to_binary(Filter)}
],
{ok,_,_,_,_,_} = alcove:prctl(Drv, Pids,
PR_SET_SECCOMP, SECCOMP_MODE_FILTER, Prog, 0, 0),
ok.
```
And running it:
```
1> {ok,Drv} = alcove_drv:start([termsig]).
{ok,<0.44.0>}
2> {ok,Fork} = alcove:fork(Drv).
{ok,19125}
3> filt:enforce(Drv, [Fork]).
ok
4> alcove:version(Drv, [Fork]).
<<"0.5.0">>
5> alcove:getpid(Drv, [Fork]).
19125
6> alcove:fork(Drv, [Fork]).
ok
7> alcove:event(Drv, [Fork]).
{termsig,31}
8> alcove:signal_constant(Drv, 31).
'SIGSYS'
```