1*4b9c6d91SCole Faust# Minijail tools 2*4b9c6d91SCole Faust 3*4b9c6d91SCole Faust## generate_seccomp_policy.py 4*4b9c6d91SCole Faust 5*4b9c6d91SCole FaustThis script lets you build a Minijail seccomp-bpf filter from strace output. 6*4b9c6d91SCole FaustThis is very useful if the process that is traced has a fairly tight working 7*4b9c6d91SCole Faustdomain, and it can be traced in a few scenarios that will exercise all of the 8*4b9c6d91SCole Faustneeded syscalls. In particular, you should always make sure that failure cases 9*4b9c6d91SCole Faustare also exercised to account for calls to `abort(2)`. 10*4b9c6d91SCole Faust 11*4b9c6d91SCole FaustIf `libminijail` or `minijail0` are used with preloading (the default with 12*4b9c6d91SCole Faustdynamically-linked executables), the first few system calls after the first call 13*4b9c6d91SCole Faustto `execve(2)` might not be needed, since the seccomp-bpf filter is installed 14*4b9c6d91SCole Faustafter that point in a sandboxed process. 15*4b9c6d91SCole Faust 16*4b9c6d91SCole Faust### Sample usage 17*4b9c6d91SCole Faust 18*4b9c6d91SCole Faust```shell 19*4b9c6d91SCole Fauststrace -f -e raw=all -o strace.txt -- <program> 20*4b9c6d91SCole Faust./tools/generate_seccomp_policy.py strace.txt > <program>.policy 21*4b9c6d91SCole Faust``` 22*4b9c6d91SCole Faust 23*4b9c6d91SCole Faust### Using linux audit logs to generate policy 24*4b9c6d91SCole Faust 25*4b9c6d91SCole Faust*** note 26*4b9c6d91SCole Faust**NOTE**: Certain syscalls made by `minijail0` may be misattributed to the 27*4b9c6d91SCole Faustsandboxed binary and may result in a policy that is overly-permissive. 28*4b9c6d91SCole FaustPlease pay some extra attention when manually reviewing the allowable args for 29*4b9c6d91SCole Faustthese syscalls: `ioctl`, `socket`, `prctl`, `mmap`, `mprotect`, and `mmap2`. 30*4b9c6d91SCole Faust*** 31*4b9c6d91SCole Faust 32*4b9c6d91SCole FaustLinux kernel v4.14+ support `SECCOMP_RET_LOG`. This allows minijail to log 33*4b9c6d91SCole Faustsyscalls via the [audit subsystem][1] (Redhat has a nice overview [here][2]) 34*4b9c6d91SCole Faustinstead of blocking them. One caveat of this approach is that `SECCOMP_RET_LOG` 35*4b9c6d91SCole Faustdoes not log syscall arguments for finer grained filtering. 36*4b9c6d91SCole FaustThe audit subsystem itself has a mechanism to log all syscalls. Though a 37*4b9c6d91SCole Faust`SYSCALL` event is more voluminous than a corresponding `SECCOMP` event. 38*4b9c6d91SCole FaustWe employ here a combination of both techniques. We rely on `SECCOMP` for all 39*4b9c6d91SCole Faustexcept the syscalls for which we want finer grained filtering. 40*4b9c6d91SCole Faust 41*4b9c6d91SCole FaustNote that this requires python3 bindings for `auparse` which are generally 42*4b9c6d91SCole Faustavailable in distro packages named `python3-audit` or `python-audit`. 43*4b9c6d91SCole Faust 44*4b9c6d91SCole Faust#### Per-boot setup of audit rules on DUT 45*4b9c6d91SCole Faust 46*4b9c6d91SCole FaustSet up `audit` rules and an empty seccomp policy for later use. This can be 47*4b9c6d91SCole Faustdone in the `pre-start` section of your upstart conf. 48*4b9c6d91SCole Faust 49*4b9c6d91SCole Faust`$UID` is the uid for your process. Using root will lead to logspam. 50*4b9c6d91SCole Faust 51*4b9c6d91SCole FaustAs mentioned above, these extra audit rules enable `SYSCALL` auditing which 52*4b9c6d91SCole Faustin turn lets the tool inspect arguments for a pre-selected subset of syscalls. 53*4b9c6d91SCole FaustThe list of syscalls here matches the list of keys in `arg_inspection`. 54*4b9c6d91SCole Faust 55*4b9c6d91SCole Faust```shell 56*4b9c6d91SCole Faustfor arch in b32 b64; do 57*4b9c6d91SCole Faust auditctl -a exit,always -F uid=$UID -F arch=$arch -S ioctl -S socket \ 58*4b9c6d91SCole Faust -S prctl -S mmap -S mprotect \ 59*4b9c6d91SCole Faust $([ "$arch" = "b32" ] && echo "-S mmap2") -c 60*4b9c6d91SCole Faustdone 61*4b9c6d91SCole Fausttouch /tmp/empty.policy 62*4b9c6d91SCole Faust``` 63*4b9c6d91SCole Faust 64*4b9c6d91SCole Faust#### Run your program under minijail with an empty policy 65*4b9c6d91SCole Faust 66*4b9c6d91SCole FaustAgain, this can be done via your upstart conf. Just be sure to stimulate all 67*4b9c6d91SCole Faustcorner cases, error conditions, etc for comprehensive coverage. 68*4b9c6d91SCole Faust 69*4b9c6d91SCole Faust```shell 70*4b9c6d91SCole Faustminijail0 -u $UID -g $GID -L -S /tmp/empty.policy -- <program> 71*4b9c6d91SCole Faust``` 72*4b9c6d91SCole Faust 73*4b9c6d91SCole Faust#### Generate policy using the audit.log 74*4b9c6d91SCole Faust 75*4b9c6d91SCole Faust```shell 76*4b9c6d91SCole Faust./tools/generate_seccomp_policy.py --audit-comm $PROGRAM_NAME audit.log \ 77*4b9c6d91SCole Faust > $PROGRAM_NAME.policy 78*4b9c6d91SCole Faust``` 79*4b9c6d91SCole Faust 80*4b9c6d91SCole FaustNote that the tool can also consume multiple audit logs and/or strace traces to 81*4b9c6d91SCole Faustproduce one unified policy. 82*4b9c6d91SCole Faust 83*4b9c6d91SCole Faust## compile_seccomp_policy.py 84*4b9c6d91SCole Faust 85*4b9c6d91SCole FaustAn external seccomp-bpf compiler that is documented [here][3]. This uses a 86*4b9c6d91SCole Faustslightly different syntax and generates highly-optimized BPF binaries that can 87*4b9c6d91SCole Faustbe provided to `minijail0`'s `--seccomp-bpf-binary` or `libminijail`'s 88*4b9c6d91SCole Faust`minijail_set_secomp_filters()`. This requires the existence of an 89*4b9c6d91SCole Faustarchitecture-specific `constants.json` file that contains the mapping of syscall 90*4b9c6d91SCole Faustnames to numbers, the values of any compile-time constants that could be used to 91*4b9c6d91SCole Faustsimplify the parameter declaration for filters (like `O_RDONLY` and any other 92*4b9c6d91SCole Faustconstant defined in typical headers in `/usr/include`). 93*4b9c6d91SCole Faust 94*4b9c6d91SCole FaustPolicy files can also include references to frequency files, which enable 95*4b9c6d91SCole Faustprofile-guided optimization of the generated BPF code. 96*4b9c6d91SCole Faust 97*4b9c6d91SCole FaustThe generated BPF code can be analyzed using 98*4b9c6d91SCole Faust[libseccomp](https://github.com/seccomp/libseccomp)'s `tools/scmp_bpf_disasm`. 99*4b9c6d91SCole Faust 100*4b9c6d91SCole Faust### Sample usage 101*4b9c6d91SCole Faust 102*4b9c6d91SCole Faust```shell 103*4b9c6d91SCole Faustmake minijail0 constants.json 104*4b9c6d91SCole Faust 105*4b9c6d91SCole Faust# Create the .policy file using the syntax described in the documentation. 106*4b9c6d91SCole Faustcat > test/seccomp.policy <<EOF 107*4b9c6d91SCole Faustread: allow 108*4b9c6d91SCole Faustwrite: allow 109*4b9c6d91SCole Faustrt_sigreturn: allow 110*4b9c6d91SCole Faustexit: allow 111*4b9c6d91SCole FaustEOF 112*4b9c6d91SCole Faust 113*4b9c6d91SCole Faust# Compile the .policy file into a .bpf filter 114*4b9c6d91SCole Faust./tools/compile_seccomp_policy.py test/seccomp.policy test/seccomp.bpf 115*4b9c6d91SCole Faust 116*4b9c6d91SCole Faust# Load the filter to sandbox your program. 117*4b9c6d91SCole Faust./minijail0 --seccomp-bpf-binary=test/seccomp.bpf -- <program> 118*4b9c6d91SCole Faust``` 119*4b9c6d91SCole Faust 120*4b9c6d91SCole Faust## generate_constants_json.py 121*4b9c6d91SCole Faust 122*4b9c6d91SCole FaustThis script generates the `constants.json` file from LLVM IR assembly files. 123*4b9c6d91SCole FaustThis makes it easier to generate architecture-specific `constants.json` files at 124*4b9c6d91SCole Faustbuild-time. 125*4b9c6d91SCole Faust 126*4b9c6d91SCole Faust[1]: https://people.redhat.com/sgrubb/audit/ 127*4b9c6d91SCole Faust[2]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/chap-system_auditing 128*4b9c6d91SCole Faust[3]: https://docs.google.com/document/d/e/2PACX-1vQOeYLWmJJrRWvglnMo5cynkUe0gZ9wVsndLLePkJg6dfUXSOUWoveBBeY3u5nQMlEU4dt_vRgj0ifR/pub 129