systrap: container exits with SIGSEGV after host suspend/resume
- Dominant language
- Go
- Stars
- 19.3k
- Forks
- 2k
- Avg merge
- 3d 5h
- Merged PRs (30d)
- 264
Description
### Description
A long-running container exits unexpectedly after the host (laptop) is suspended and resumed several times. The container is running with gVisor's `systrap` platform. The failure occurs in seccomp user-notification handling and results in runsc exiting with `SIGSEGV`.
### Steps to reproduce
1. build the image `gvisor-resume` with
```Dockerfile
FROM alpine:latest
CMD ["/bin/sh", "-c", "while :; do sleep 86400; done"]
```
2. run the image as a container
```
podman run -d \
--name gvisor-resume-repro \
--runtime=runsc \
--runtime-flag=debug \
--runtime-flag=ignore-cgroups \
gvisor-resume
```
3. suspend and resume the host for several times. I observed the container exit after 3-4 days usually with 4-5 suspend/resumes.
### runsc version
I am using `gvisor` from nixpkgs: `gvisor-20260406.0`
```shell
runsc version VERSION_MISSING
spec: 1.1.0-rc.1
```
### docker version (if using docker)
```shell
Client: Podman Engine
Version: 5.8.4
API Version: 5.8.4
Go Version: go1.26.4
Built: Tue Jan 1 00:00:00 1980
OS/Arch: linux/amd64
```
### uname
Linux tb14 7.1.2 #1-NixOS SMP PREEMPT_DYNAMIC Sat Jun 27 10:08:18 UTC 2026 x86_64 GNU/Linux
### kubectl (if using Kubernetes)
```shell
```
### repo state (if built from source)
_No response_
### runsc debug logs (if available)
Full log available [here](https://gist.github.com/LEXUGE/be7083ce32d51e1bc6fb34c90816c193)
There are errors related to clock discontinuities due to host suspend & resume:
```shell
W0824 19:28:45.003140 1 calibrated_clock.go:135] Clock(Monotonic): error: 10768571943305 ns, adjusted frequency from 3792812755 Hz to 46810093531948735 Hz
W0824 19:28:45.014274 1 calibrated_clock.go:83] CalibratedClock(Monotonic): Extreme clock error. Resetting clock; time may jump.
W0824 19:28:45.017999 1 calibrated_clock.go:135] Clock(Realtime): error: 844457188 ns, adjusted frequency from 3792812496 Hz to 6996228425 Hz
W0824 19:28:45.023263 1 calibrated_clock.go:83] CalibratedClock(Realtime): Extreme clock error. Resetting clock; time may jump.
W0825 08:56:09.223059 1 calibrated_clock.go:135] Clock(Monotonic): error: 19418212189886 ns, adjusted frequency from 3792830044 Hz to 120017238235690773 Hz
W0825 08:56:09.269571 1 calibrated_clock.go:83] CalibratedClock(Monotonic): Extreme clock error. Resetting clock; time may jump.
W0825 09:44:20.072728 1 calibrated_clock.go:135] Clock(Monotonic): error: 2814982889268 ns, adjusted frequency from 3792829716 Hz to 2711886114958695 Hz
W0825 09:44:20.074015 1 calibrated_clock.go:83] CalibratedClock(Monotonic): Extreme clock error. Resetting clock; time may jump.
W0825 14:29:10.976104 1 calibrated_clock.go:135] Clock(Monotonic): error: 2420011679077 ns, adjusted frequency from 3792812771 Hz to 2227782848880453 Hz
W0825 14:29:10.990665 1 calibrated_clock.go:83] CalibratedClock(Monotonic): Extreme clock error. Resetting clock; time may jump.
```
And several hours after the last resume-related clock reset, systrap fails while waiting for a seccomp notification:
```shell
D0825 19:41:31.999093 1 usertrap_amd64.go:225] [ 7: 7] Found the pattern at ip 7ed94dd43924:sysno 3
D0825 19:41:31.999168 1 usertrap_amd64.go:122] [ 7: 7] Allocate a new trap: 0x14453fc3bd10 14
D0825 19:41:31.999421 1 usertrap_amd64.go:238] [ 7: 7] Apply the binary patch addr 7ed94dd43924 trap addr 65460 ([184 3 0 0 0 15 5] -> [255 36 37 96 84 6 0])
W0825 19:41:32.000294 1 syscall_thread.go:222] [ 37: 37] failed waiting for seccomp notify: failed getting response from syscall thread : no such file or directory
W0825 19:41:32.011032 1 subprocess_unsafe.go:130] the subprocess 37 exited (status: 9, err %!s())
W0825 19:41:32.011315 1 task_run.go:365] [ 7: 7] Unexpected SwitchToApp error: systrap corrupted memory: subprocess died
D0825 19:41:32.024047 1 syscall_thread.go:222] [ 49: 49] failed waiting for seccomp notify: failed getting response from syscall thread : no such file or directory
D0825 19:41:32.032854 1 task_run.go:365] [ 2: 2] Unexpected SwitchToApp error: systrap corrupted memory: subprocess died
D0825 19:41:32.047005 1 boot.go:659] application exiting with killed by signal 11
D0825 19:41:32.047353 1 cli.go:310] Exiting with status: 11
```
## From GPT
### Analysis
The `no such file or directory` message is `ENOENT` from gVisor's seccomp notification control path. It does not indicate a missing file in the container. After suspend/resume, a pending seccomp notification can be invalidated or reissued by the kernel. The systrap notification receive path treats this condition as fatal, kills the syscall helper, and returns `subprocess died`.
The subsequent `systrap corrupted memory` message appears to be a generic error used when the shared execution context can no longer be trusted after the helper exits; the logs do not demonstrate actual container memory corruption.
The `usertrap_amd64.go` messages describe gVisor's internal syscall trampoline for guest syscall number 3 (`read`). They are where the failure surfaces, rather than evidence that the container's shell or application caused the crash.
### Related upstream work
- [gVisor PR #12820: systrap: retry seccomp notify send after freezer interruption](https://github.com/google/gvisor/pull/12820)
That change handles the related `ENOENT` case on the notification-send path. The failure above occurs in the notification-receive path (`waitForSeccompNotify`).
Contributor guide
Assessment
This issue has not been assessed yet.