Source File
secret.go
Belonging Package
runtime
// Copyright 2024 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 (amd64 || arm64) && linuxpackage runtimeimport ()//go:linkname secret_count runtime/secret.countfunc secret_count() int32 {return getg().secret}//go:linkname secret_inc runtime/secret.incfunc secret_inc() {:= getg().secret++}//go:linkname secret_dec runtime/secret.decfunc secret_dec() {:= getg().secret--}//go:linkname secret_eraseSecrets runtime/secret.eraseSecretsfunc secret_eraseSecrets() {// zero all the stack memory that might be dirtied with// secrets. We do this from the systemstack so that we// don't have to figure out which holes we have to keep// to ensure that we can return from memclr. gp.sched will// act as a pigeonhole for our actual return.:= getg().stack.losystemstack(func() {// Note, this systemstack call happens within the secret mode,// so we don't have to call out to erase our registers, the systemstack// code will do that.:= acquirem():= .curg.sched.sp// we need to keep systemstack return on top of the stack being cleared// for traceback-= goarch.PtrSize// TODO: keep some sort of low water mark so that we don't have// to zero a potentially large stack if we used just a little// bit of it. That will allow us to use a higher value for// lo than gp.stack.lo.memclrNoHeapPointers(unsafe.Pointer(), -)releasem()})// Don't put any code here: the stack frame's contents are gone!}// specialSecret tracks whether we need to zero an object immediately// upon freeing.type specialSecret struct {special special}// addSecret records the fact that we need to zero p immediately// when it is freed.func addSecret( unsafe.Pointer) {// TODO(dmo): figure out the cost of these. These are mostly// intended to catch allocations that happen via the runtime// that the user has no control over and not big buffers that user// code is allocating. The cost should be relatively low,// but we have run into a wall with other special allocations before.lock(&mheap_.speciallock):= (*specialSecret)(mheap_.specialSecretAlloc.alloc()).special.kind = _KindSpecialSecretunlock(&mheap_.speciallock)addspecial(, &.special, false)}// send a no-op signal to an M for the purposes of// clobbering the signal stack//// Use sigpreempt. If we don't have a preemption queued, this just// turns into a no-opfunc noopSignal( *m) {signalM(, sigPreempt)}// secret_getStack returns the memory range of the// current goroutine's stack.// For testing only.// Note that this is kind of tricky, as the goroutine can// be copied and/or exit before the result is used, at which// point it may no longer be valid.////go:linkname secret_getStack runtime/secret.getStackfunc secret_getStack() (uintptr, uintptr) {:= getg()return .stack.lo, .stack.hi}// return a slice of all Ms signal stacks// For testing only.////go:linkname secret_appendSignalStacks runtime/secret.appendSignalStacksfunc secret_appendSignalStacks( []stack) []stack {// This is probably overkill, but it's what// doAllThreadsSyscall does:= stopTheWorld(stwAllThreadsSyscall)allocmLock.lock()acquirem()for := allm; != nil; = .alllink {= append(, .gsignal.stack)}releasem(getg().m)allocmLock.unlock()startTheWorld()return}
![]() |
The pages are generated with Golds v0.8.3-preview. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |