From 981de40f5c9d8dc49087c2d351624288ee17b34c Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 24 Sep 2024 03:29:28 +0200 Subject: [PATCH] unix: use vDSO for getrandom() on linux With CL 614835 adding support in the runtime for calling into the getrandom() vDSO function, wire up x/sys/unix's Getrandom() function to it, so that callers can benefit from the increased speed and shared vDSO state with the runtime. Updates golang/go#69577. Change-Id: I17734409982c51bb984a6337f4ffa8f60414ebee Reviewed-on: https://go-review.googlesource.com/c/sys/+/615335 Reviewed-by: Michael Pratt Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI --- unix/syscall_linux.go | 21 ++++++++++++++++++++- unix/vgetrandom_linux.go | 12 ++++++++++++ unix/vgetrandom_unsupported.go | 11 +++++++++++ unix/zsyscall_linux.go | 17 ----------------- 4 files changed, 43 insertions(+), 18 deletions(-) create mode 100644 unix/vgetrandom_linux.go create mode 100644 unix/vgetrandom_unsupported.go diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go index c5bb17ae5..f08abd434 100644 --- a/unix/syscall_linux.go +++ b/unix/syscall_linux.go @@ -2001,7 +2001,26 @@ func Getpgrp() (pid int) { //sysnb Getpid() (pid int) //sysnb Getppid() (ppid int) //sys Getpriority(which int, who int) (prio int, err error) -//sys Getrandom(buf []byte, flags int) (n int, err error) + +func Getrandom(buf []byte, flags int) (n int, err error) { + vdsoRet, supported := vgetrandom(buf, uint32(flags)) + if supported { + if vdsoRet < 0 { + return 0, errnoErr(syscall.Errno(-vdsoRet)) + } + return vdsoRet, nil + } + var p *byte + if len(buf) > 0 { + p = &buf[0] + } + r, _, e := Syscall(SYS_GETRANDOM, uintptr(unsafe.Pointer(p)), uintptr(len(buf)), uintptr(flags)) + if e != 0 { + return 0, errnoErr(e) + } + return int(r), nil +} + //sysnb Getrusage(who int, rusage *Rusage) (err error) //sysnb Getsid(pid int) (sid int, err error) //sysnb Gettid() (tid int) diff --git a/unix/vgetrandom_linux.go b/unix/vgetrandom_linux.go new file mode 100644 index 000000000..47cce9bbd --- /dev/null +++ b/unix/vgetrandom_linux.go @@ -0,0 +1,12 @@ +// 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 && go1.24 + +package unix + +import _ "unsafe" + +//go:linkname vgetrandom runtime.vgetrandom +func vgetrandom(p []byte, flags uint32) (ret int, supported bool) diff --git a/unix/vgetrandom_unsupported.go b/unix/vgetrandom_unsupported.go new file mode 100644 index 000000000..297e97bce --- /dev/null +++ b/unix/vgetrandom_unsupported.go @@ -0,0 +1,11 @@ +// 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 || !go1.24 + +package unix + +func vgetrandom(p []byte, flags uint32) (ret int, supported bool) { + return -1, false +} diff --git a/unix/zsyscall_linux.go b/unix/zsyscall_linux.go index 1bc1a5adb..af30da557 100644 --- a/unix/zsyscall_linux.go +++ b/unix/zsyscall_linux.go @@ -971,23 +971,6 @@ func Getpriority(which int, who int) (prio int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getrandom(buf []byte, flags int) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall(SYS_GETRANDOM, uintptr(_p0), uintptr(len(buf)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Getrusage(who int, rusage *Rusage) (err error) { _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) if e1 != 0 {