Home | History | Annotate | Download | only in unix
      1 // Copyright 2014 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 package unix
      6 
      7 import (
      8 	"runtime"
      9 	"sync/atomic"
     10 	"syscall"
     11 	"unsafe"
     12 )
     13 
     14 var randomTrap = map[string]uintptr{
     15 	"386":     355,
     16 	"amd64":   318,
     17 	"arm":     384,
     18 	"ppc64":   359,
     19 	"ppc64le": 359,
     20 }[runtime.GOARCH]
     21 
     22 var randomUnsupported int32 // atomic
     23 
     24 // GetRandomFlag is a flag supported by the getrandom system call.
     25 type GetRandomFlag uintptr
     26 
     27 const (
     28 	// GRND_NONBLOCK means return EAGAIN rather than blocking.
     29 	GRND_NONBLOCK GetRandomFlag = 0x0001
     30 
     31 	// GRND_RANDOM means use the /dev/random pool instead of /dev/urandom.
     32 	GRND_RANDOM GetRandomFlag = 0x0002
     33 )
     34 
     35 // GetRandom calls the Linux getrandom system call.
     36 // See https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c6e9d6f38894798696f23c8084ca7edbf16ee895
     37 func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
     38 	if randomTrap == 0 {
     39 		return 0, syscall.ENOSYS
     40 	}
     41 	if len(p) == 0 {
     42 		return 0, nil
     43 	}
     44 	if atomic.LoadInt32(&randomUnsupported) != 0 {
     45 		return 0, syscall.ENOSYS
     46 	}
     47 	r1, _, errno := syscall.Syscall(randomTrap,
     48 		uintptr(unsafe.Pointer(&p[0])),
     49 		uintptr(len(p)),
     50 		uintptr(flags))
     51 	if errno != 0 {
     52 		if errno == syscall.ENOSYS {
     53 			atomic.StoreInt32(&randomUnsupported, 1)
     54 		}
     55 		return 0, errno
     56 	}
     57 	return int(r1), nil
     58 }
     59