Kafel Documentation

repository·master·Indexed 18 days ago

https://github.com/google/kafel

A language and library for specifying syscall filtering policies that compile into BPF code for use with seccomp-filter. It features a high-level syntax for defining security policies, including architecture guards, argument filtering, and include directives. The library provides C APIs for compilation, such as kafel_compile and kafel_compile_string, and includes the dump_policy_bpf CLI tool for inspecting compiled BPF policies.

Tokens
1.6K
Snippets
6
Records
8
Agent score
13%

What's inside Kafel

  1. Kafel Policy Language Overview

    master

    Kafel uses a simple domain-specific language to define syscall filtering policies. A policy file consists of statements that can be:

    • Constant definitions: Using #define NAME value.
    • Policy definitions: Named blocks of rules.
    • Policy definition statements: Using USE name to compose policies.
    • Default action statements: Using DEFAULT action to specify what happens when no rules match.

    Policy definition statements placed at the file scope are added to an implicit top-level policy which is compiled by default.

  2. Define syscall matching rules and argument filters

    master

    An action block contains a target and a list of syscall matching rules. The first rule matched determines the policy decision.

    Syscall Naming

    • Use standard Linux kernel syscall names.
    • For custom syscalls, use a constant or the SYSCALL[number] syntax.

    Architecture Guards

    Use the ON guard to restrict rules to specific architectures (e.g., x86_64, arm, aarch64). Rules are ignored if the architecture does not match.

    Argument Filtering

    Filter syscalls based on arguments using boolean expressions. Supports ==, !=, &&, ||, and bitwise operators & and | for testing flags.

    // Architecture guard example
    ALLOW {
      io_uring_setup ON x86_64,
      arm_fadvise64_64 ON arm
    }
    
    // Argument filtering example
    some_syscall(first_arg, my_arg_name) { first_arg == 42 && my_arg_name != 42 }
    
    // Bitwise flag testing
    open { flags == O_RDONLY|O_CLOEXEC }
  3. Compile Kafel policies in C

    master

    Kafel provides two ways to compile a syscall filtering policy string into a sock_fprog structure for use with seccomp-filter via prctl.

    With verbose error reporting

    Use kafel_ctxt_create and kafel_compile to get detailed error messages if compilation fails.

    Without verbose error reporting

    Use kafel_compile_string for a simpler, single-step compilation when detailed error messages are not required.

    // With verbose error reporting
    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);
    
    // Without verbose error reporting
    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);
  4. Use dump_policy_bpf to inspect compiled BPF policies

    master

    The dump_policy_bpf CLI tool allows you to inspect compiled BPF policies by dumping them in either a human-readable disassembly format or as a C source file. It takes a policy file as input and uses the Kafel library to compile and then display the resulting BPF instructions.

    Usage

    Basic usage (Human-readable disassembly): By default, the tool outputs a human-readable disassembly of the BPF program.

    ./dump_policy_bpf <INPUT_FILE>

    Output as C source code: Use the -c flag to output the BPF program as a C source file (using pretty_print).

    ./dump_policy_bpf -c <INPUT_FILE>

    Input via stdin: If no file is provided, the tool reads from standard input.

    cat policy.kafel | ./dump_policy_bpf
    # Example: Dump policy as C source
    ./dump_policy_bpf -c my_policy.kafel
  5. Use include directives to compose policies

    master

    Kafel supports #include to reuse policy files.

    • Syntax: #include "file.policy" or #include "file1.policy" "file2.policy";
    • The directive can be terminated by a newline or a semicolon.
    • To use included files, you must add the directory to the search path using kafel_add_include_search_path(ctxt, "path") in your C code.
    kafel_add_include_search_path(ctxt, "includes/path");
    #include "some_other_file.policy"
  6. Configure the default action in Kafel

    master

    The DEFAULT statement specifies the action taken when no rules in the policy match.

    • Syntax: DEFAULT the_action
    • The default action must be specified exactly once.
    • If no default action is specified in the policy file, the default action is KILL.
    DEFAULT the_action
  7. Map Kafel actions to seccomp-filter return values

    master

    Kafel actions map directly to Linux kernel seccomp return values. Use these keywords in your action blocks.

    | 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` |
  8. dump_policy_bpf CLI flags

    master

    The dump_policy_bpf tool supports the following command-line options:

    FlagDescription
    -hSets the output mode to HUMAN_READABLE (default).
    -cSets the output mode to C_SOURCE_FILE.

    Arguments:

    • INPUT: The path to the policy file to be compiled and dumped. If omitted, the tool reads from stdin.