Skip to content

Commit

Permalink
sys: mask SIGPROF during BPF_PROG_LOAD to prevent livelocks
Browse files Browse the repository at this point in the history
If a thread receives a signal while blocked in BPF_PROG_LOAD, the verifier
can cooperatively interrupt itself by checking pending signals for the thread
and return -EAGAIN from the syscall to request userspace to retry.

When a Go program is built and run with pprof enabled, threads are routinely
sent a SIGPROF to make them dump profiling information, which can lead to a
runaway reaction if the program takes longer to verify than the interrupt
frequency. To prevent this, mask SIGPROF before calling BPF_PROG_LOAD and
remove it when done.

Signed-off-by: Timo Beckers <timo@isovalent.com>
  • Loading branch information
ti-mo committed Sep 28, 2022
1 parent 1bdff75 commit 1caaad1
Showing 1 changed file with 7 additions and 0 deletions.
7 changes: 7 additions & 0 deletions internal/sys/syscall.go
Expand Up @@ -17,6 +17,13 @@ var ENOTSUPP = syscall.Errno(524)
//
// Any pointers contained in attr must use the Pointer type from this package.
func BPF(cmd Cmd, attr unsafe.Pointer, size uintptr) (uintptr, error) {
// Prevent the Go profiler from repeatedly interrupting the verifier,
// which could otherwise lead to a livelock due to receiving EAGAIN.
if cmd == BPF_PROG_LOAD {
maskProfilerSignal()
defer unmaskProfilerSignal()
}

for {
r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size)
runtime.KeepAlive(attr)
Expand Down

0 comments on commit 1caaad1

Please sign in to comment.