From 516699848b7c19b2b7f80de82c66012719f6835b Mon Sep 17 00:00:00 2001 From: Daniel Morsing Date: Wed, 10 Dec 2025 10:13:05 +0000 Subject: [PATCH] runtime/secret: warn users about allocations, loosen guarantees The discussion at #76477 warranted some stronger documentation about what is expected from users of the secret package. In addition, #76764 presented a problem about when a user can expect their secrets to be deleted. Fix by loosening the guarantee to when all allocations from within a secret function have been deemed unreachable. Provide some guidance for users to steer them away from situations where allocations live on for long after the secret function has finished executing Fixes #76764. Updates #76477. Change-Id: I0cef3e7275737f32ec48f71355e588b3be26ea32 Reviewed-on: https://go-review.googlesource.com/c/go/+/728921 LUCI-TryBot-Result: Go LUCI Reviewed-by: David Chase Reviewed-by: Michael Knyszek --- src/runtime/secret/doc.go | 15 +++++++++++++++ src/runtime/secret/secret.go | 15 +++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/runtime/secret/doc.go diff --git a/src/runtime/secret/doc.go b/src/runtime/secret/doc.go new file mode 100644 index 0000000000..c0dd4f95a6 --- /dev/null +++ b/src/runtime/secret/doc.go @@ -0,0 +1,15 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build goexperiment.runtimesecret + +// Package secret contains helper functions for zeroing out memory +// that is otherwise invisible to a user program in the service of +// forward secrecy. See https://en.wikipedia.org/wiki/Forward_secrecy for +// more information. +// +// This package (runtime/secret) is experimental, +// and not subject to the Go 1 compatibility promise. +// It only exists when building with the GOEXPERIMENT=runtimesecret environment variable set. +package secret diff --git a/src/runtime/secret/secret.go b/src/runtime/secret/secret.go index 9eae22605f..00a03b2d50 100644 --- a/src/runtime/secret/secret.go +++ b/src/runtime/secret/secret.go @@ -18,12 +18,23 @@ import ( // entire call tree initiated by f.) // - Any registers used by f are erased before Do returns. // - Any stack used by f is erased before Do returns. -// - Any heap allocation done by f is erased as soon as the garbage -// collector realizes that it is no longer reachable. +// - Heap allocations done by f are erased as soon as the garbage +// collector realizes that all allocated values are no longer reachable. // - Do works even if f panics or calls runtime.Goexit. As part of // that, any panic raised by f will appear as if it originates from // Do itself. // +// Users should be cautious of allocating inside Do. +// Erasing heap memory after Do returns may increase garbage collector sweep times and +// requires additional memory to keep track of allocations until they are to be erased. +// These costs can compound when an allocation is done in the service of growing a value, +// like appending to a slice or inserting into a map. In these cases, the entire new allocation is erased rather +// than just the secret parts of it. +// +// To reduce lifetimes of allocations and avoid unexpected performance issues, +// if a function invoked by Do needs to yield a result that shouldn't be erased, +// it should do so by copying the result into an allocation created by the caller. +// // Limitations: // - Currently only supported on linux/amd64 and linux/arm64. On unsupported // platforms, Do will invoke f directly.