This subdivides all `RuleSet`s into single-syscall rulesets, and then
classifies them depending on:
- Whether they are "trivial" or not, where "trivial" means that the syscall
rules do not perform any verification of the syscall arguments or RIP.
- Whether they are marked "hot" or not, where "hot" means "expected to be
frequently called".
It then orders the program as follows:
- All hot non-trivial rules go first. This makes it so that the host kernel
can clear the syscall faster for frequently-called syscalls. These are
checked linearly, as they tend to follow a Pareto distribution in terms of
frequency. If they need a vsyscall check, that check is added individually.
- All cold rules go next, and form a BST. This mimics the structure of the BST
construction that existed prior to this change.
- Lastly, all the trivial syscalls are added as a last BST.
This speeds up rule evaluation because it maximizes the use of Linux's
seccomp cache for trivial syscalls. These are therefore only ever checked
once, so they can stay at the "bottom" of the program.
All remaining (non-trivial) syscalls are ordered such that hot syscalls
are checked first, and then cold syscalls are checked with a BST.
This is a complex and security-sensitive change, but fuzz testing with full
branch coverage has shown that this has the exact same behavior as a BPF
program taken from before any of my recent seccomp/BPF changes (other than
the one adding non-negative FD checks to all `ioctl(2)` system calls).
Some benchmark results ("orig" is the state before this change):
```
│ orig │ reordered │
│ sec/op │ sec/op vs base │
SentrySystrap/futex 79.44n ± 2% 73.93n ± 2% -6.93% (n=729+722)
SentrySystrap/nanosleep 112.3n ± 12% 107.2n ± 12% ~ (p=0.505 n=482+477)
SentrySystrap/sendmmsg 88.50n ± 1% 81.62n ± 1% -7.78% (n=729+722)
SentrySystrap/fstat 30.80n ± 2% 30.63n ± 3% ~ (p=0.903 n=722+712)
[...]
SentrySystrap/Postgres-48 64.30n ± 5% 61.74n ± 6% -3.97% (p=0.039 n=376+377)
```
PiperOrigin-RevId: 582808055
This adds a method called `InterestingValues` to `ValueMatcher` and
`halfValueMatcher` that lists the values worth testing for this argument.
Then, the new `SyscallRules.UsefulTestCases` function aggregates all of
this into a set of useful test cases that can be used to seed the corpus
of a seccomp fuzz test.
PiperOrigin-RevId: 581148821
This doesn't introduce new optimizations, but creates a framework for
optimizations to be expressed over a `SyscallRule`. Such rules are
recursively applied across the tree of `SyscallRule`s in a similar manner
as the BPF optimizer is applied across BPF bytecode.
This also removes the need for a `merge` function that is aware of `Or` rule
semantics, as the current set of basic optimizers will achieve the same
result.
PiperOrigin-RevId: 578347984
This removes the interface indirection from BPF evaluation, which is
a very hot path (runs for every application syscall for seccomp'd containers)
and simplifies the code in general.
```
│ initial │ hey_look_no_interfaces │
│ sec/op │ sec/op vs base │
Interpreter 26.31n ± 0% 21.12n ± 0% -19.73% (p=0.000 n=21+20)
```
PiperOrigin-RevId: 576375947
Split usermem package to help remove syserror dependency in go_marshal.
New hostarch package contains code not dependent on syserror.
PiperOrigin-RevId: 365651233
The syscall package has been deprecated in favor of golang.org/x/sys.
Note that syscall is still used in the following places:
- pkg/sentry/socket/hostinet/stack.go: some netlink related functionalities
are not yet available in golang.org/x/sys.
- syscall.Stat_t is still used in some places because os.FileInfo.Sys() still
returns it and not unix.Stat_t.
Updates #214
PiperOrigin-RevId: 360701387
syscalls in ARM64 is different from that in X86_64, use
differen syscallrules for each arch.
The auditnumber are also different for different arch.
Use LINUX_AUDIT_ARCH to get correct auditnumber.
Signed-off-by: Howard Zhang <howard.zhang@arm.com>
Nothing reads them and they can simply get stale.
Generated with:
$ sed -i "s/licenses(\(.*\)).*/licenses(\1)/" **/BUILD
PiperOrigin-RevId: 231818945
Change-Id: Ibc3f9838546b7e94f13f217060d31f4ada9d4bf0
This change also adds extensive testing to the p9 package via mocks. The sanity
checks and type checks are moved from the gofer into the core package, where
they can be more easily validated.
PiperOrigin-RevId: 218296768
Change-Id: I4fc3c326e7bf1e0e140a454cbacbcc6fd617ab55
This is a defense-in-depth measure. If the sentry is compromised, this prevents
system call injection to the stubs. There is some complexity with respect to
ptrace and seccomp interactions, so this protection is not really available
for kernel versions < 4.8; this is detected dynamically.
Note that this also solves the vsyscall emulation issue by adding in
appropriate trapping for those system calls. It does mean that a compromised
sentry could theoretically inject these into the stub (ignoring the trap and
resume, thereby allowing execution), but they are harmless.
PiperOrigin-RevId: 216647581
Change-Id: Id06c232cbac1f9489b1803ec97f83097fcba8eb8
We have been unnecessarily creating too many savable types implicitly.
PiperOrigin-RevId: 206334201
Change-Id: Idc5a3a14bfb7ee125c4f2bb2b1c53164e46f29a8