Allow Sentry to kill itself even when it is the init process

PiperOrigin-RevId: 733399678
This commit is contained in:
Andrei Vagin
2025-03-04 11:25:32 -08:00
committed by gVisor bot
parent 1f79e1b26f
commit d844c7bbb7
7 changed files with 48 additions and 6 deletions
+1
View File
@@ -41,6 +41,7 @@ go_library(
"//pkg/sentry/memmap",
"//pkg/sentry/platform",
"//pkg/sentry/platform/interrupt",
"//pkg/sighandling",
"//pkg/sync",
"@org_golang_x_sys//unix:go_default_library",
],
+7
View File
@@ -15,6 +15,8 @@
package ptrace
import (
"os"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/seccomp"
"gvisor.dev/gvisor/pkg/sentry/platform"
@@ -26,6 +28,11 @@ func (*PTrace) SeccompInfo() platform.SeccompInfo {
PlatformName: "ptrace",
Filters: seccomp.MakeSyscallRules(map[uintptr]seccomp.SyscallRule{
unix.SYS_PTRACE: seccomp.MatchAll{},
unix.SYS_RT_TGSIGQUEUEINFO: seccomp.PerArg{
seccomp.EqualTo(os.Getpid()),
seccomp.AnyValue{}, // tid
seccomp.EqualTo(unix.SIGKILL),
},
unix.SYS_TGKILL: seccomp.MatchAll{},
unix.SYS_WAIT4: seccomp.MatchAll{},
}),
+2 -2
View File
@@ -27,6 +27,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/platform"
"gvisor.dev/gvisor/pkg/sighandling"
"gvisor.dev/gvisor/pkg/sync"
)
@@ -357,8 +358,7 @@ func (t *thread) unexpectedStubExit() {
// these cases, we don't need to panic. There is no reasons to
// think that something wrong in gVisor.
log.Warningf("The ptrace stub process %v has been killed by SIGKILL.", t.tgid)
pid := os.Getpid()
unix.Tgkill(pid, pid, unix.Signal(unix.SIGKILL))
sighandling.KillItself()
}
t.dumpAndPanic(fmt.Sprintf("wait failed: the process %d:%d exited: %x (err %v)", t.tgid, t.tid, msg, err))
}
+1
View File
@@ -99,6 +99,7 @@ go_library(
"//pkg/sentry/platform/systrap/sysmsg",
"//pkg/sentry/platform/systrap/usertrap",
"//pkg/sentry/usage",
"//pkg/sighandling",
"//pkg/sync",
"//pkg/syncevent",
"@org_golang_x_sys//unix:go_default_library",
+8 -1
View File
@@ -15,6 +15,8 @@
package systrap
import (
"os"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/seccomp"
@@ -93,7 +95,12 @@ func (systrapSeccomp) SyscallFilters(vars precompiledseccomp.Values) seccomp.Sys
},
},
unix.SYS_TGKILL: seccomp.MatchAll{},
unix.SYS_WAIT4: seccomp.MatchAll{},
unix.SYS_RT_TGSIGQUEUEINFO: seccomp.PerArg{
seccomp.EqualTo(os.Getpid()),
seccomp.AnyValue{}, // tid
seccomp.EqualTo(unix.SIGKILL),
},
unix.SYS_WAIT4: seccomp.MatchAll{},
unix.SYS_IOCTL: seccomp.Or{
seccomp.PerArg{
seccomp.NonNegativeFD{},
+2 -3
View File
@@ -16,7 +16,6 @@ package systrap
import (
"fmt"
"os"
"runtime"
"sync"
"sync/atomic"
@@ -36,6 +35,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/platform/systrap/sysmsg"
"gvisor.dev/gvisor/pkg/sentry/platform/systrap/usertrap"
"gvisor.dev/gvisor/pkg/sentry/usage"
"gvisor.dev/gvisor/pkg/sighandling"
)
var (
@@ -609,8 +609,7 @@ func (t *thread) unexpectedStubExit() {
// these cases, we don't need to panic. There is no reasons to
// think that something wrong in gVisor.
log.Warningf("The ptrace stub process %v has been killed by SIGKILL.", t.tgid)
pid := os.Getpid()
unix.Tgkill(pid, pid, unix.Signal(unix.SIGKILL))
sighandling.KillItself()
}
t.dumpAndPanic(fmt.Sprintf("wait failed: the process %d:%d exited: %x (err %v)", t.tgid, t.tid, msg, err))
}
@@ -19,6 +19,7 @@ package sighandling
import (
"fmt"
"os"
"unsafe"
"golang.org/x/sys/unix"
@@ -74,3 +75,29 @@ func ReplaceSignalHandler(sig unix.Signal, handler uintptr, previous *uintptr) e
return nil
}
// KillItself sends SIGKILL to the current process, bypassing the init process
// restriction.
//
// The standard `kill(getpid(), SIGKILL)` syscall doesn't work when the current
// process is the init process within its PID namespace. This is a "known"
// Linux feature.
//
// This function uses the rt_tgqueueinfo syscall to send a "kernel-generated"
// SIGKILL.
func KillItself() error {
pid := os.Getpid()
tid, _, _ := unix.RawSyscall(unix.SYS_GETTID, 0, 0, 0)
info := linux.SignalInfo{Code: linux.SI_KERNEL}
// The current thread can send a fake kernel siginfo to itself.
if _, _, e := unix.RawSyscall6(
unix.SYS_RT_TGSIGQUEUEINFO,
uintptr(pid), uintptr(tid),
uintptr(linux.SIGKILL),
uintptr(unsafe.Pointer(&info)),
0, 0,
); e != 0 {
return e
}
panic("unreachable")
}