getrandom.mx raw

   1  // Copyright 2021 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  //go:build dragonfly || freebsd || linux
   6  
   7  package unix
   8  
   9  import (
  10  	"sync/atomic"
  11  	"syscall"
  12  	"unsafe"
  13  )
  14  
  15  //go:linkname vgetrandom runtime.vgetrandom
  16  //go:noescape
  17  func vgetrandom(p []byte, flags uint32) (ret int, supported bool)
  18  
  19  var getrandomUnsupported atomic.Bool
  20  
  21  // GetRandomFlag is a flag supported by the getrandom system call.
  22  type GetRandomFlag uintptr
  23  
  24  // GetRandom calls the getrandom system call.
  25  func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
  26  	ret, supported := vgetrandom(p, uint32(flags))
  27  	if supported {
  28  		if ret < 0 {
  29  			return 0, syscall.Errno(-ret)
  30  		}
  31  		return ret, nil
  32  	}
  33  	if getrandomUnsupported.Load() {
  34  		return 0, syscall.ENOSYS
  35  	}
  36  	r1, _, errno := syscall.Syscall(getrandomTrap,
  37  		uintptr(unsafe.Pointer(unsafe.SliceData(p))),
  38  		uintptr(len(p)),
  39  		uintptr(flags))
  40  	if errno != 0 {
  41  		if errno == syscall.ENOSYS {
  42  			getrandomUnsupported.Store(true)
  43  		}
  44  		return 0, errno
  45  	}
  46  	return int(r1), nil
  47  }
  48