xref: /aosp_15_r20/external/crosvm/third_party/minijail/tools/README.md (revision 4b9c6d91573e8b3a96609339b46361b5476dd0f9)
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