Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save dsseng/5b3db47436a4c360986def9302f97548 to your computer and use it in GitHub Desktop.
Save dsseng/5b3db47436a4c360986def9302f97548 to your computer and use it in GitHub Desktop.
From ca3036f6a5f834ea5502689cb9b10c5c38a3b657 Mon Sep 17 00:00:00 2001
From: Dmitrii Sharshakov <[email protected]>
Date: Fri, 2 May 2025 15:10:32 +0200
Subject: [PATCH] Revert "runtime: use vDSO for getrandom() on linux"
eb6f2c24cd17c0ca1df7e343f8d9187eef7d6e13
---
src/crypto/rand/rand_test.go | 3 -
src/internal/syscall/unix/getrandom.go | 11 ---
src/runtime/os_linux.go | 9 --
src/runtime/sys_linux_amd64.s | 33 --------
src/runtime/sys_linux_arm64.s | 45 ----------
src/runtime/sys_linux_loong64.s | 43 ----------
src/runtime/sys_linux_ppc64x.s | 50 -----------
src/runtime/sys_linux_s390x.s | 50 -----------
src/runtime/vdso_linux_amd64.go | 2 -
src/runtime/vdso_linux_arm64.go | 7 +-
src/runtime/vdso_linux_loong64.go | 5 +-
src/runtime/vdso_linux_ppc64x.go | 5 +-
src/runtime/vdso_linux_s390x.go | 5 +-
src/runtime/vgetrandom_linux.go | 112 -------------------------
src/runtime/vgetrandom_unsupported.go | 2 -
15 files changed, 8 insertions(+), 374 deletions(-)
delete mode 100644 src/runtime/vgetrandom_linux.go
diff --git a/src/crypto/rand/rand_test.go b/src/crypto/rand/rand_test.go
index 2590dc3e37..dd28d76602 100644
--- a/src/crypto/rand/rand_test.go
+++ b/src/crypto/rand/rand_test.go
@@ -194,9 +194,6 @@ func TestReadError(t *testing.T) {
}
func BenchmarkRead(b *testing.B) {
- b.Run("4", func(b *testing.B) {
- benchmarkRead(b, 4)
- })
b.Run("32", func(b *testing.B) {
benchmarkRead(b, 32)
})
diff --git a/src/internal/syscall/unix/getrandom.go b/src/internal/syscall/unix/getrandom.go
index db3e7ac0f0..4270898b7e 100644
--- a/src/internal/syscall/unix/getrandom.go
+++ b/src/internal/syscall/unix/getrandom.go
@@ -12,10 +12,6 @@ import (
"unsafe"
)
-//go:linkname vgetrandom runtime.vgetrandom
-//go:noescape
-func vgetrandom(p []byte, flags uint32) (ret int, supported bool)
-
var getrandomUnsupported atomic.Bool
// GetRandomFlag is a flag supported by the getrandom system call.
@@ -23,13 +19,6 @@ type GetRandomFlag uintptr
// GetRandom calls the getrandom system call.
func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
- ret, supported := vgetrandom(p, uint32(flags))
- if supported {
- if ret < 0 {
- return 0, syscall.Errno(-ret)
- }
- return ret, nil
- }
if getrandomUnsupported.Load() {
return 0, syscall.ENOSYS
}
diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go
index 8b3c4d0ecc..b0298857f0 100644
--- a/src/runtime/os_linux.go
+++ b/src/runtime/os_linux.go
@@ -32,10 +32,6 @@ type mOS struct {
// for doAllThreadsSyscall.
needPerThreadSyscall atomic.Uint8
- // This is a pointer to a chunk of memory allocated with a special
- // mmap invocation in vgetrandomGetState().
- vgetrandomState uintptr
-
waitsema uint32 // semaphore for parking on locks
}
@@ -356,7 +352,6 @@ func osinit() {
ncpu = getproccount()
physHugePageSize = getHugePageSize()
osArchInit()
- vgetrandomInit()
}
var urandom_dev = []byte("/dev/urandom\x00")
@@ -415,10 +410,6 @@ func unminit() {
// Called from exitm, but not from drop, to undo the effect of thread-owned
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
func mdestroy(mp *m) {
- if mp.vgetrandomState != 0 {
- vgetrandomPutState(mp.vgetrandomState)
- mp.vgetrandomState = 0
- }
}
// #ifdef GOARCH_386
diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s
index 941f70b0e8..b6c64dc095 100644
--- a/src/runtime/sys_linux_amd64.s
+++ b/src/runtime/sys_linux_amd64.s
@@ -704,36 +704,3 @@ TEXT runtime·sbrk0(SB),NOSPLIT,$0-8
SYSCALL
MOVQ AX, ret+0(FP)
RET
-
-// func vgetrandom1(buf *byte, length uintptr, flags uint32, state uintptr, stateSize uintptr) int
-TEXT runtime·vgetrandom1<ABIInternal>(SB),NOSPLIT,$16-48
- MOVQ SI, R8 // stateSize
- MOVL CX, DX // flags
- MOVQ DI, CX // state
- MOVQ BX, SI // length
- MOVQ AX, DI // buf
-
- MOVQ SP, R12
-
- MOVQ runtime·vdsoGetrandomSym(SB), AX
- MOVQ g_m(R14), BX
-
- MOVQ m_vdsoPC(BX), R9
- MOVQ R9, 0(SP)
- MOVQ m_vdsoSP(BX), R9
- MOVQ R9, 8(SP)
- LEAQ buf+0(FP), R9
- MOVQ R9, m_vdsoSP(BX)
- MOVQ -8(R9), R9
- MOVQ R9, m_vdsoPC(BX)
-
- ANDQ $~15, SP
-
- CALL AX
-
- MOVQ R12, SP
- MOVQ 8(SP), R9
- MOVQ R9, m_vdsoSP(BX)
- MOVQ 0(SP), R9
- MOVQ R9, m_vdsoPC(BX)
- RET
diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s
index 7a81d5479e..51c87bea05 100644
--- a/src/runtime/sys_linux_arm64.s
+++ b/src/runtime/sys_linux_arm64.s
@@ -785,48 +785,3 @@ TEXT runtime·sbrk0(SB),NOSPLIT,$0-8
SVC
MOVD R0, ret+0(FP)
RET
-
-// func vgetrandom1(buf *byte, length uintptr, flags uint32, state uintptr, stateSize uintptr) int
-TEXT runtime·vgetrandom1<ABIInternal>(SB),NOSPLIT,$16-48
- MOVD RSP, R20
-
- MOVD runtime·vdsoGetrandomSym(SB), R8
- MOVD g_m(g), R21
-
- MOVD m_vdsoPC(R21), R9
- MOVD R9, 8(RSP)
- MOVD m_vdsoSP(R21), R9
- MOVD R9, 16(RSP)
- MOVD LR, m_vdsoPC(R21)
- MOVD $buf-8(FP), R9
- MOVD R9, m_vdsoSP(R21)
-
- MOVD RSP, R9
- BIC $15, R9
- MOVD R9, RSP
-
- MOVBU runtime·iscgo(SB), R9
- CBNZ R9, nosaveg
- MOVD m_gsignal(R21), R9
- CBZ R9, nosaveg
- CMP g, R9
- BEQ nosaveg
- MOVD (g_stack+stack_lo)(R9), R22
- MOVD g, (R22)
-
- BL (R8)
-
- MOVD ZR, (R22)
- B restore
-
-nosaveg:
- BL (R8)
-
-restore:
- MOVD R20, RSP
- MOVD 16(RSP), R1
- MOVD R1, m_vdsoSP(R21)
- MOVD 8(RSP), R1
- MOVD R1, m_vdsoPC(R21)
- NOP R0 // Satisfy go vet, since the return value comes from the vDSO function.
- RET
diff --git a/src/runtime/sys_linux_loong64.s b/src/runtime/sys_linux_loong64.s
index 57cee99da7..b4a6da93c3 100644
--- a/src/runtime/sys_linux_loong64.s
+++ b/src/runtime/sys_linux_loong64.s
@@ -655,46 +655,3 @@ TEXT runtime·socket(SB),$0-20
MOVV R0, 2(R0) // unimplemented, only needed for android; declared in stubs_linux.go
MOVW R0, ret+16(FP) // for vet
RET
-
-// func vgetrandom1(buf *byte, length uintptr, flags uint32, state uintptr, stateSize uintptr) int
-TEXT runtime·vgetrandom1<ABIInternal>(SB),NOSPLIT,$16-48
- MOVV R3, R23
-
- MOVV runtime·vdsoGetrandomSym(SB), R12
-
- MOVV g_m(g), R24
-
- MOVV m_vdsoPC(R24), R13
- MOVV R13, 8(R3)
- MOVV m_vdsoSP(R24), R13
- MOVV R13, 16(R3)
- MOVV R1, m_vdsoPC(R24)
- MOVV $buf-8(FP), R13
- MOVV R13, m_vdsoSP(R24)
-
- AND $~15, R3
-
- MOVBU runtime·iscgo(SB), R13
- BNE R13, nosaveg
- MOVV m_gsignal(R24), R13
- BEQ R13, nosaveg
- BEQ g, R13, nosaveg
- MOVV (g_stack+stack_lo)(R13), R25
- MOVV g, (R25)
-
- JAL (R12)
-
- MOVV R0, (R25)
- JMP restore
-
-nosaveg:
- JAL (R12)
-
-restore:
- MOVV R23, R3
- MOVV 16(R3), R25
- MOVV R25, m_vdsoSP(R24)
- MOVV 8(R3), R25
- MOVV R25, m_vdsoPC(R24)
- NOP R4 // Satisfy go vet, since the return value comes from the vDSO function.
- RET
diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s
index 8735b932ed..ba4988b723 100644
--- a/src/runtime/sys_linux_ppc64x.s
+++ b/src/runtime/sys_linux_ppc64x.s
@@ -757,53 +757,3 @@ TEXT runtime·socket(SB),$0-20
MOVD R0, 0(R0) // unimplemented, only needed for android; declared in stubs_linux.go
MOVW R0, ret+16(FP) // for vet
RET
-
-// func vgetrandom1(buf *byte, length uintptr, flags uint32, state uintptr, stateSize uintptr) int
-TEXT runtime·vgetrandom1<ABIInternal>(SB),NOSPLIT,$16-48
- MOVD R1, R15
-
- MOVD runtime·vdsoGetrandomSym(SB), R12
- MOVD R12, CTR
- MOVD g_m(g), R21
-
- MOVD m_vdsoPC(R21), R22
- MOVD R22, 32(R1)
- MOVD m_vdsoSP(R21), R22
- MOVD R22, 40(R1)
- MOVD LR, m_vdsoPC(R21)
- MOVD $buf-FIXED_FRAME(FP), R22
- MOVD R22, m_vdsoSP(R21)
-
- RLDICR $0, R1, $59, R1
-
- MOVBZ runtime·iscgo(SB), R22
- CMP R22, $0
- BNE nosaveg
- MOVD m_gsignal(R21), R22
- CMP R22, $0
- BEQ nosaveg
- CMP R22, g
- BEQ nosaveg
- MOVD (g_stack+stack_lo)(R22), R22
- MOVD g, (R22)
-
- BL (CTR)
-
- MOVD $0, (R22)
- JMP restore
-
-nosaveg:
- BL (CTR)
-
-restore:
- MOVD $0, R0
- MOVD R15, R1
- MOVD 40(R1), R22
- MOVD R22, m_vdsoSP(R21)
- MOVD 32(R1), R22
- MOVD R22, m_vdsoPC(R21)
-
- BVC out
- NEG R3, R3
-out:
- RET
diff --git a/src/runtime/sys_linux_s390x.s b/src/runtime/sys_linux_s390x.s
index 2f9d4beda8..59e2f2ab31 100644
--- a/src/runtime/sys_linux_s390x.s
+++ b/src/runtime/sys_linux_s390x.s
@@ -605,53 +605,3 @@ TEXT runtime·socket(SB),$0-20
MOVD $0, 2(R0) // unimplemented, only needed for android; declared in stubs_linux.go
MOVW R0, ret+16(FP)
RET
-
-// func vgetrandom1(buf *byte, length uintptr, flags uint32, state uintptr, stateSize uintptr) int
-TEXT runtime·vgetrandom1(SB),NOSPLIT,$16-48
- MOVD buf+0(FP), R2
- MOVD length+8(FP), R3
- MOVW flags+16(FP), R4
- MOVD state+24(FP), R5
- MOVD stateSize+32(FP), R6
-
- MOVD R15, R7
-
- MOVD runtime·vdsoGetrandomSym(SB), R1
- MOVD g_m(g), R9
-
- MOVD m_vdsoPC(R9), R12
- MOVD R12, 8(R15)
- MOVD m_vdsoSP(R9), R12
- MOVD R12, 16(R15)
- MOVD R14, m_vdsoPC(R9)
- MOVD $buf+0(FP), R12
- MOVD R12, m_vdsoSP(R9)
-
- SUB $160, R15
- MOVD $~7, R12
- AND R12, R15
-
- MOVB runtime·iscgo(SB), R12
- CMPBNE R12, $0, nosaveg
- MOVD m_gsignal(R9), R12
- CMPBEQ R12, $0, nosaveg
- CMPBEQ g, R12, nosaveg
- MOVD (g_stack+stack_lo)(R12), R12
- MOVD g, (R12)
-
- BL R1
-
- MOVD $0, (R12)
- JMP restore
-
-nosaveg:
- BL R1
-
-restore:
- MOVD R7, R15
- MOVD 16(R15), R12
- MOVD R12, m_vdsoSP(R9)
- MOVD 8(R15), R12
- MOVD R12, m_vdsoPC(R9)
- MOVD R2, ret+40(FP)
- RET
diff --git a/src/runtime/vdso_linux_amd64.go b/src/runtime/vdso_linux_amd64.go
index 8a89771ca4..9c56409137 100644
--- a/src/runtime/vdso_linux_amd64.go
+++ b/src/runtime/vdso_linux_amd64.go
@@ -17,13 +17,11 @@ var vdsoLinuxVersion = vdsoVersionKey{"LINUX_2.6", 0x3ae75f6}
var vdsoSymbolKeys = []vdsoSymbolKey{
{"__vdso_gettimeofday", 0x315ca59, 0xb01bca00, &vdsoGettimeofdaySym},
{"__vdso_clock_gettime", 0xd35ec75, 0x6e43a318, &vdsoClockgettimeSym},
- {"__vdso_getrandom", 0x25425d, 0x84a559bf, &vdsoGetrandomSym},
}
var (
vdsoGettimeofdaySym uintptr
vdsoClockgettimeSym uintptr
- vdsoGetrandomSym uintptr
)
// vdsoGettimeofdaySym is accessed from the syscall package.
diff --git a/src/runtime/vdso_linux_arm64.go b/src/runtime/vdso_linux_arm64.go
index 21f875d0df..f5959525af 100644
--- a/src/runtime/vdso_linux_arm64.go
+++ b/src/runtime/vdso_linux_arm64.go
@@ -15,10 +15,7 @@ var vdsoLinuxVersion = vdsoVersionKey{"LINUX_2.6.39", 0x75fcb89}
var vdsoSymbolKeys = []vdsoSymbolKey{
{"__kernel_clock_gettime", 0xb0cd725, 0xdfa941fd, &vdsoClockgettimeSym},
- {"__kernel_getrandom", 0x9800c0d, 0x540d4e24, &vdsoGetrandomSym},
}
-var (
- vdsoClockgettimeSym uintptr
- vdsoGetrandomSym uintptr
-)
+// initialize to fall back to syscall
+var vdsoClockgettimeSym uintptr = 0
diff --git a/src/runtime/vdso_linux_loong64.go b/src/runtime/vdso_linux_loong64.go
index 37ee02dcb0..e00ef952b3 100644
--- a/src/runtime/vdso_linux_loong64.go
+++ b/src/runtime/vdso_linux_loong64.go
@@ -19,10 +19,9 @@ var vdsoLinuxVersion = vdsoVersionKey{"LINUX_5.10", 0xae78f70}
var vdsoSymbolKeys = []vdsoSymbolKey{
{"__vdso_clock_gettime", 0xd35ec75, 0x6e43a318, &vdsoClockgettimeSym},
- {"__vdso_getrandom", 0x25425d, 0x84a559bf, &vdsoGetrandomSym},
}
+// initialize to fall back to syscall
var (
- vdsoClockgettimeSym uintptr
- vdsoGetrandomSym uintptr
+ vdsoClockgettimeSym uintptr = 0
)
diff --git a/src/runtime/vdso_linux_ppc64x.go b/src/runtime/vdso_linux_ppc64x.go
index 939da7b54c..09c8d9d20e 100644
--- a/src/runtime/vdso_linux_ppc64x.go
+++ b/src/runtime/vdso_linux_ppc64x.go
@@ -16,10 +16,9 @@ var vdsoLinuxVersion = vdsoVersionKey{"LINUX_2.6.15", 0x75fcba5}
var vdsoSymbolKeys = []vdsoSymbolKey{
{"__kernel_clock_gettime", 0xb0cd725, 0xdfa941fd, &vdsoClockgettimeSym},
- {"__kernel_getrandom", 0x9800c0d, 0x540d4e24, &vdsoGetrandomSym},
}
+// initialize with vsyscall fallbacks
var (
- vdsoClockgettimeSym uintptr
- vdsoGetrandomSym uintptr
+ vdsoClockgettimeSym uintptr = 0
)
diff --git a/src/runtime/vdso_linux_s390x.go b/src/runtime/vdso_linux_s390x.go
index 113152ff0a..970ecd3ce6 100644
--- a/src/runtime/vdso_linux_s390x.go
+++ b/src/runtime/vdso_linux_s390x.go
@@ -16,10 +16,9 @@ var vdsoLinuxVersion = vdsoVersionKey{"LINUX_2.6.29", 0x75fcbb9}
var vdsoSymbolKeys = []vdsoSymbolKey{
{"__kernel_clock_gettime", 0xb0cd725, 0xdfa941fd, &vdsoClockgettimeSym},
- {"__kernel_getrandom", 0x9800c0d, 0x540d4e24, &vdsoGetrandomSym},
}
+// initialize with vsyscall fallbacks
var (
- vdsoClockgettimeSym uintptr
- vdsoGetrandomSym uintptr
+ vdsoClockgettimeSym uintptr = 0
)
diff --git a/src/runtime/vgetrandom_linux.go b/src/runtime/vgetrandom_linux.go
deleted file mode 100644
index a6ec4b701c..0000000000
--- a/src/runtime/vgetrandom_linux.go
+++ /dev/null
@@ -1,112 +0,0 @@
-// 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 linux && (amd64 || arm64 || arm64be || ppc64 || ppc64le || loong64 || s390x)
-
-package runtime
-
-import (
- "internal/cpu"
- "unsafe"
-)
-
-//go:noescape
-func vgetrandom1(buf *byte, length uintptr, flags uint32, state uintptr, stateSize uintptr) int
-
-var vgetrandomAlloc struct {
- states []uintptr
- statesLock mutex
- stateSize uintptr
- mmapProt int32
- mmapFlags int32
-}
-
-func vgetrandomInit() {
- if vdsoGetrandomSym == 0 {
- return
- }
-
- var params struct {
- SizeOfOpaqueState uint32
- MmapProt uint32
- MmapFlags uint32
- reserved [13]uint32
- }
- if vgetrandom1(nil, 0, 0, uintptr(unsafe.Pointer(&params)), ^uintptr(0)) != 0 {
- return
- }
- vgetrandomAlloc.stateSize = uintptr(params.SizeOfOpaqueState)
- vgetrandomAlloc.mmapProt = int32(params.MmapProt)
- vgetrandomAlloc.mmapFlags = int32(params.MmapFlags)
-
- lockInit(&vgetrandomAlloc.statesLock, lockRankLeafRank)
-}
-
-func vgetrandomGetState() uintptr {
- lock(&vgetrandomAlloc.statesLock)
- if len(vgetrandomAlloc.states) == 0 {
- num := uintptr(ncpu) // Just a reasonable size hint to start.
- stateSizeCacheAligned := (vgetrandomAlloc.stateSize + cpu.CacheLineSize - 1) &^ (cpu.CacheLineSize - 1)
- allocSize := (num*stateSizeCacheAligned + physPageSize - 1) &^ (physPageSize - 1)
- num = (physPageSize / stateSizeCacheAligned) * (allocSize / physPageSize)
- p, err := mmap(nil, allocSize, vgetrandomAlloc.mmapProt, vgetrandomAlloc.mmapFlags, -1, 0)
- if err != 0 {
- unlock(&vgetrandomAlloc.statesLock)
- return 0
- }
- newBlock := uintptr(p)
- if vgetrandomAlloc.states == nil {
- vgetrandomAlloc.states = make([]uintptr, 0, num)
- }
- for i := uintptr(0); i < num; i++ {
- if (newBlock&(physPageSize-1))+vgetrandomAlloc.stateSize > physPageSize {
- newBlock = (newBlock + physPageSize - 1) &^ (physPageSize - 1)
- }
- vgetrandomAlloc.states = append(vgetrandomAlloc.states, newBlock)
- newBlock += stateSizeCacheAligned
- }
- }
- state := vgetrandomAlloc.states[len(vgetrandomAlloc.states)-1]
- vgetrandomAlloc.states = vgetrandomAlloc.states[:len(vgetrandomAlloc.states)-1]
- unlock(&vgetrandomAlloc.statesLock)
- return state
-}
-
-func vgetrandomPutState(state uintptr) {
- lock(&vgetrandomAlloc.statesLock)
- vgetrandomAlloc.states = append(vgetrandomAlloc.states, state)
- unlock(&vgetrandomAlloc.statesLock)
-}
-
-// This is exported for use in internal/syscall/unix as well as x/sys/unix.
-//
-//go:linkname vgetrandom
-func vgetrandom(p []byte, flags uint32) (ret int, supported bool) {
- if vgetrandomAlloc.stateSize == 0 {
- return -1, false
- }
-
- // We use getg().m instead of acquirem() here, because always taking
- // the lock is slightly more expensive than not always taking the lock.
- // However, we *do* require that m doesn't migrate elsewhere during the
- // execution of the vDSO. So, we exploit two details:
- // 1) Asynchronous preemption is aborted when PC is in the runtime.
- // 2) Most of the time, this function only calls vgetrandom1(), which
- // does not have a preamble that synchronously preempts.
- // We do need to take the lock when getting a new state for m, but this
- // is very much the slow path, in the sense that it only ever happens
- // once over the entire lifetime of an m. So, a simple getg().m suffices.
- mp := getg().m
-
- if mp.vgetrandomState == 0 {
- mp.locks++
- state := vgetrandomGetState()
- mp.locks--
- if state == 0 {
- return -1, false
- }
- mp.vgetrandomState = state
- }
- return vgetrandom1(unsafe.SliceData(p), uintptr(len(p)), flags, mp.vgetrandomState, vgetrandomAlloc.stateSize), true
-}
diff --git a/src/runtime/vgetrandom_unsupported.go b/src/runtime/vgetrandom_unsupported.go
index 070392cfaa..a0c627d6e5 100644
--- a/src/runtime/vgetrandom_unsupported.go
+++ b/src/runtime/vgetrandom_unsupported.go
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !(linux && (amd64 || arm64 || arm64be || ppc64 || ppc64le || loong64 || s390x))
-
package runtime
import _ "unsafe"
--
2.49.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment