go icon indicating copy to clipboard operation
go copied to clipboard

runtime/secret: aggregated heap allocations can keep secret values alive longer than expected

Open DanielMorsing opened this issue 3 weeks ago • 3 comments

$ go version
go version go1.26-devel_0d0d5c9a82 Fri Dec 5 17:31:30 2025 -0800 linux/amd64
$ cat secret.go
package main

import (
	"fmt"
	"math"
	"runtime"
	"runtime/secret"
	"unsafe"
)

var (
	xa *int
	xb *int
)

var addr uintptr

func main() {
	secret.Do(func() {
		a := math.MaxInt
		b := math.MaxInt
		xa = &a
		xb = &b
		addr = uintptr(unsafe.Pointer(&a))
	})
	xa = nil
	runtime.GC()
	x := *(*int)(unsafe.Pointer(addr))
	fmt.Printf("xa value after gc: %x\n", x)
	xb = nil
	runtime.GC()
	x = *(*int)(unsafe.Pointer(addr))
	fmt.Printf("xa value after xb unreachable: %x\n", x)
}
$ GOEXPERIMENT=runtimesecret go run secret.go
xa value after gc: 7fffffffffffffff
xa value after xb unreachable: 0

In this case, a secret value that should have been zeroed is kept "alive" by an adjacent value whos storage is aggregated together with it by the compiler (see cmd/compile/internal/ssagen/ssa.go:/newHeapaddr/)

I'm not sure what the right answer is here. This is a contrived example, but it does break the guarantees set out by the secret package. I think we can either:

  1. ignore it and document that secret is best effort only and hope that users don't write code like this
  2. make a new allocator function that knows about the structure of these aggregated values that will de-aggregate when running in secret mode.
  3. disable this optimization. This would have to be globally since functions cannot know when they are running in secret mode.

DanielMorsing avatar Dec 09 '25 12:12 DanielMorsing

Is this just #76356 as it applies to runtime/secret, or is there more here?

cc @golang/runtime

prattmic avatar Dec 09 '25 16:12 prattmic

In this case, a secret value that should have been zeroed is kept "alive" by an adjacent value whos storage is aggregated together with it by the compiler (see cmd/compile/internal/ssagen/ssa.go:/newHeapaddr/)

Ah, I see, this is about aggregated heap allocations.

Though I imagine tiny allocations affect secret mode as well?

prattmic avatar Dec 09 '25 16:12 prattmic

Tiny allocations are handled specially when we are in secret mode https://cs.opensource.google/go/go/+/master:src/runtime/malloc_stubs.go;l=61

DanielMorsing avatar Dec 09 '25 16:12 DanielMorsing

Change https://go.dev/cl/728921 mentions this issue: runtime/secret: warn users about allocations, loosen gurantees.

gopherbot avatar Dec 10 '25 11:12 gopherbot