// Copyright 2014 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. package syscall import ( "runtime" "sync/atomic" stdsyscall "syscall" "unsafe" ) var randomTrap = map[string]uintptr{ "386": 355, "amd64": 318, "arm": 384, }[runtime.GOARCH] var randomUnsupported int32 // atomic // GetRandomFlag is a flag supported by the getrandom system call. type GetRandomFlag uintptr const ( // GRND_NONBLOCK means return EAGAIN rather than blocking. GRND_NONBLOCK GetRandomFlag = 0x0001 // GRND_RANDOM means use the /dev/random pool instead of /dev/urandom. GRND_RANDOM GetRandomFlag = 0x0002 ) // GetRandom calls the Linux getrandom system call. // See https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c6e9d6f38894798696f23c8084ca7edbf16ee895 func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) { if randomTrap == 0 { return 0, stdsyscall.ENOSYS } if len(p) == 0 { return 0, nil } if atomic.LoadInt32(&randomUnsupported) != 0 { return 0, stdsyscall.ENOSYS } r1, _, errno := stdsyscall.Syscall(randomTrap, uintptr(unsafe.Pointer(&p[0])), uintptr(len(p)), uintptr(flags)) if errno != 0 { if errno == stdsyscall.ENOSYS { atomic.StoreInt32(&randomUnsupported, 1) } return 0, errno } return int(r1), nil }