Files
alcove/include
Michael Santos fa07b11b85 Add macros for Linux seccomp mode
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'
```
2014-06-06 14:35:43 -04:00
..