Skip to content

runtime: provide a way to opt in to stack trace printing for process-terminating signals in secure-mode binaries on Unix OSes #69868

@cespare

Description

@cespare

Go version

go version go1.23.1 linux/amd64

Output of go env in your module/workspace:

n/a

What did you do?

Consider two trivial go programs. First, sleep.go:

//go:build ignore

package main

import "time"

func main() {
	time.Sleep(time.Hour)
}

Second, panic.go:

//go:build ignore

package main

func main() {
	panic("asdf")
}

First, run sleep.go and then interrupt it by hitting C-\ (SIGQUIT):

$ rm -f sleep && go build -o sleep sleep.go && ./sleep
^\SIGQUIT: quit
PC=0x46c46e m=0 sigcode=128

goroutine 0 gp=0x50da00 m=0 mp=0x50e660 [idle]:
... lots of stack trace elided...
rflags 0x246
cs     0x33

Next, run panic.go in the same way:

$ rm -f panic && go build -o panic panic.go && ./panic
panic: asdf

goroutine 1 [running]:
main.main()
        /home/caleb/w/_scratch/x/panic.go:6 +0x25

All normal stuff. Now let's do the same thing but with a binary that has CAP_SYS_ADMIN:

$ rm -f sleep && go build -o sleep sleep.go && sudo setcap 'cap_sys_admin+ep' ./sleep && ./sleep
^\SIGQUIT: quit
$ rm -f panic && go build -o panic panic.go && sudo setcap 'cap_sys_admin+ep' ./panic && ./panic
panic: asdf

In both cases (SIGQUIT and a normal panic), printing stack traces is suppressed by the Go runtime. This is a security measure implemented last year in #60272.

If I want to bypass this stack trace suppression anyway, I can do so for panics by calling runtime/debug.SetTraceback. For example, If I add the line

debug.SetTraceback("single")

to panic.go, then it restores the normal unprivileged panic stack trace printing behavior:

$ rm -f panic && go build -o panic panic.go && sudo setcap 'cap_sys_admin+ep' ./panic && ./panic
panic: asdf

goroutine 1 [running]:
main.main()
        /home/caleb/w/_scratch/x/panic.go:9 +0x32

However, as far as I know, there is no equivalent way to opt in to the default signal-handling stack trace printing behavior. If I want to print stack traces on SIGQUIT, I'd have to listen for the signal and do it myself.

What did you see happen?

No way to turn on stack trace printing for process-terminating signals for this CAP_SYS_ADMIN binary.

What did you expect to see?

I believe there should be a way to ask the runtime to print stack traces on SIGQUIT when running in secure mode. One way to to this would be to piggyback on debug.SetTraceback and restore the signal stack trace printing behavior when SetTraceback is called with some value other than "none" (or perhaps only when called with "all" or "single", or perhaps only when called with "all").

Alternatively, we can provide a new API such as runtime/debug.SetSignalTraceback(bool).

cc:

Metadata

Metadata

Assignees

No one assigned

    Labels

    FeatureRequestIssues asking for a new feature that does not need a proposal.NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.compiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    Status

    Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions