diff options
| author | Daniel Morsing <daniel.morsing@gmail.com> | 2025-09-25 17:26:03 +0100 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2025-11-26 15:42:52 -0800 |
| commit | a3fb92a7100f3f2824d483ee0cbcf1264584b3e4 (patch) | |
| tree | 9c01886504bdfa077c25b6bef804e95b86d1e474 /src/runtime/proc.go | |
| parent | 0c747b7aa757da0a0a0ac7b2b5834dca84c7c019 (diff) | |
| download | go-a3fb92a7100f3f2824d483ee0cbcf1264584b3e4.tar.xz | |
runtime/secret: implement new secret package
Implement secret.Do.
- When secret.Do returns:
- Clear stack that is used by the argument function.
- Clear all the registers that might contain secrets.
- On stack growth in secret mode, clear the old stack.
- When objects are allocated in secret mode, mark them and then zero
the marked objects immediately when they are freed.
- If the argument function panics, raise that panic as if it originated
from secret.Do. This removes anything about the secret function
from tracebacks.
For now, this is only implemented on linux for arm64 and amd64.
This is a rebased version of Keith Randalls initial implementation at
CL 600635. I have added arm64 support, signal handling, preemption
handling and dealt with vDSOs spilling into system stacks.
Fixes #21865
Change-Id: I6fbd5a233beeaceb160785e0c0199a5c94d8e520
Co-authored-by: Keith Randall <khr@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/704615
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/runtime/proc.go')
| -rw-r--r-- | src/runtime/proc.go | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 3b98be1074..16538098cf 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -8,6 +8,7 @@ import ( "internal/abi" "internal/cpu" "internal/goarch" + "internal/goexperiment" "internal/goos" "internal/runtime/atomic" "internal/runtime/exithook" @@ -4454,6 +4455,13 @@ func goexit1() { // goexit continuation on g0. func goexit0(gp *g) { + if goexperiment.RuntimeSecret && gp.secret > 0 { + // Erase the whole stack. This path only occurs when + // runtime.Goexit is called from within a runtime/secret.Do call. + memclrNoHeapPointers(unsafe.Pointer(gp.stack.lo), gp.stack.hi-gp.stack.lo) + // Since this is running on g0, our registers are already zeroed from going through + // mcall in secret mode. + } gdestroy(gp) schedule() } @@ -4482,6 +4490,7 @@ func gdestroy(gp *g) { gp.timer = nil gp.bubble = nil gp.fipsOnlyBypass = false + gp.secret = 0 if gcBlackenEnabled != 0 && gp.gcAssistBytes > 0 { // Flush assist credit to the global pool. This gives @@ -5216,6 +5225,10 @@ func malg(stacksize int32) *g { // The compiler turns a go statement into a call to this. func newproc(fn *funcval) { gp := getg() + if goexperiment.RuntimeSecret && gp.secret > 0 { + panic("goroutine spawned while running in secret mode") + } + pc := sys.GetCallerPC() systemstack(func() { newg := newproc1(fn, gp, pc, false, waitReasonZero) |
