The sandbox process was executed in the current pid namespace if a target
platform used ptrace. It was the workaround for the kernel issue that was
fixed by 8fb335e07837 ("kernel/exit.c: release ptraced tasks before
zap_pid_ns_processes"). This fix was back-ported to stable branches.
PiperOrigin-RevId: 668121544
This makes the code in controller.go simple, especially
for multi-container restore that requires taking ownership
of files.
PiperOrigin-RevId: 627165958
With the introduction of precompiled seccomp filters, we need three more
concepts that go into building the set of seccomp filters for a `Platform`:
- "Precompiled configurations": A list of platform configurations for which
the seccomp filters get precompiled into the Sentry.
- "Config key": A string that identifies each configuration of the syscall
filters of that platform. This is necessary to identify *which* precompiled
seccomp filter to use at runtime.
- "Variables": A set of named variables that are runtime inputs in syscall
filters. For example, the FD of the KVM device in the KVM platform.
Systrap is the only serious user of this, due to its need for a variable.
The other platforms return a basic struct which simply carries what the
previous two methods did.
I think we should have the KVM VM FD as part of the KVM filters; if we did,
that would be another variable.
This CL is a preamble to actually precompile seccomp filters.
PiperOrigin-RevId: 583482945
This adds a `HottestSyscalls` function to the `Platform` interface, as the
platform determines which syscalls are most often called by the Sentry.
This is used by the Sentry seccomp filter code to build the final list of
hot syscalls.
PiperOrigin-RevId: 582833363
This is just a refactoring, but the intention of this `struct` is to add
other useful options for the program build, such as the list of expected
"hottest" syscalls by frequency.
The interface is a bit awkward, because of the need for two entry points
(one which didn't have any way to set the default actions), and because the
zero value of `linux.BPFAction` is a valid (and common) "default action":
killing the program (`linux.SECCOMP_RET_KILL_THREAD`).
We also can't use `*linux.BPFAction`, as `linux.SECCOMP_RET_*` are constants.
So the struct fields use functions that "resolve" to an action.
This reads fairly well in the call sites (`DefaultAction: Return(action)`),
at the cost of slightly convoluted logic in `seccomp.go`.
PiperOrigin-RevId: 581477348
It is an idea of running codespell as part of our presubmit checks.
Before enabling it for new changes, let's fix what it has found.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This wraps the `map[uintptry]SyscallRule` into an unexported field of a struct
so that it cannot be accessed directly.
This is helpful for the `runsc` and `fsgofer` seccomp filters which are quite
complex and built across multiple files and multiple functions, where it is
not always clear which order they are executed in. By forcing mutations to be
more explicit about their intent (especially "merge with this new rule" vs
"override what happens for this syscall with this new rule"), we can crash if
that intent isn't what's actually happening.
PiperOrigin-RevId: 572361619
This replaces the `seccomp.Rule` type with the `seccomp.SyscallRule`
interface, which is an abstraction that defines how to match a syscall's
arguments and RIP.
This has the following benefits:
- The code can verify that rules are self-contained, as the
`SyscallRule.Render` contract specifies that the rule must jump to
either a "matched" or "not matched" label, and may not fall through.
It uses `ProgramBuilder`'s support for asserting unreachability to
enforce this.
- Rules that match everything are more explicit (no more implicit
"no rules means everything matches" behavior, instead you have to
explicitly specify `seccomp.MatchAll{}`).
- "OR" behavior is explicit (a disjunctive rule is marked as `seccomp.Or`
rather than the current implicit meaning of a list of rules).
- Allows the creation of more sophisticated matching rules that don't work
on a per-argument basis. This change does not do any of that yet, it
simply refactors existing rules without changing the way they work.
- Decouples rule-specific rendering code from the larger program generation
code (BST, architecture check, etc.).
Unfortunately there is no easy way to split this change into multiple
sub-changes without introducing additional complexity to support both forms
of expressing rules, so sorry if this is a large change. But note that it
is actually net-negative in line count.
Despite the size of this change, please review it carefully, as this is a
security-sensitive change.
PiperOrigin-RevId: 571459670
This reduces the diff on an upcoming refactor which modifies all seccomp
rules.
`AnyValue` better reflects the fact that the matcher is about matching a
single syscall argument value, as opposed to e.g. a rule that allows a
syscall through regardless of its argument.
PiperOrigin-RevId: 571110444
`bpf.Instruction` is the same type as `linux.BPFInstruction`, except that it
uses the BPF instruction-to-string decoder to give a nice human-readable
stringification.
PiperOrigin-RevId: 570499020
The --nvproxy flag allows container GPU usage to be specified via device nodes
and mounts provided in the runtime spec, as when using Kubernetes with GKE's
Nvidia GPU device plugin
(https://github.com/GoogleCloudPlatform/container-engine-accelerators/tree/master/cmd/nvidia_gpu).
The --nvproxy-docker flag additionally allows container GPU usage to be
specified via the NVIDIA_VISIBLE_DEVICES container environment variable, as
when using `docker --gpus`. This does not require the Nvidia Container Toolkit
(or the Nvidia Container Runtime [Hook], which are part of the Toolkit), but
does require libnvidia-container, which is typically installed as a dependency
of the Nvidia Container Toolkit.
Updates #14
PiperOrigin-RevId: 535002602
For all trivial and zero frame-sized functions, we now require an explicit
NOFRAME annotation as the heuristic has changed. See go.dev/cl/466316.
Most of these functions do not *require* NOFRAME, but this change encodes
the existing behavior in order to avoid accidental bugs or regressions.
PiperOrigin-RevId: 513946210
"procid" implies "process ID", "processor (CPU?) ID", or "`runtime.p.id`". It
is none of these things. Instead, `procid.Current()` returns the caller's host
thread ID; almost every caller relies on this property. Rename the package
accordingly.
Nit: Replace "system thread identifier" with "host thread ID". "System" is
needlessly vague in a setting where many callers will also have an unrelated
application thread ID, and "identifier" is a guess at what is abbreviated by
"thread ID" - but cf. gettid(2), "NAME: gettid - get thread identification".
PiperOrigin-RevId: 507034135
It is called only when a task switches to the interruptible sleep, because it
is the only state where the task can sleep for a long time.
PiperOrigin-RevId: 485963460
Since `arch.Context64` is the only concrete implementation of
`arch.Context`, this does not functionally change anything.
While `arch.Context64` *can* mean multiple things in the codebase, since
the `arch` module uses conditional compilation to create different builds
for AMD64 vs ARM64, the `Context64` type is still singular within each
possible version this can compile to.
This avoids the overhead involved in calling interface
functions in Go:
https://github.com/teh-cmc/go-internals/blob/master/chapter2_interfaces/README.md#dynamic-dispatch
This overhead is particularly painful for functions like `SyscallSaveOrig`
which is a no-op on AMD64.
On KVM, this reduces syscall latency by 4~5%:
```
name old wall_ns/op new wall_ns/op delta
Getpid 602 ± 4% 579 ± 3% -3.94% (p=0.000 n=66+195)
GetpidOpt 604 ± 3% 573 ± 3% -5.10% (p=0.000 n=71+194)
name old cpu_ns/op new cpu_ns/op delta
Getpid 604 ± 5% 581 ± 0% -3.81% (p=0.000 n=75+130)
GetpidOpt 604 ± 2% 574 ± 3% -4.95% (p=0.000 n=71+196)
```
PiperOrigin-RevId: 461742893