summaryrefslogtreecommitdiffhomepage
path: root/pkg/rand/rand_linux.go
diff options
context:
space:
mode:
authorJonathan Giannuzzi <jonathan@giannuzzi.be>2018-10-10 14:17:27 -0700
committerShentubot <shentubot@google.com>2018-10-10 14:18:47 -0700
commit8388a505e735045f31c6f7180711ef57148dc517 (patch)
tree8f5e5a7ed88d47f52f309e732871f7d622d02a01 /pkg/rand/rand_linux.go
parentddb34b3690c07f6c8efe2b96f89166145c4a7d3c (diff)
Support for older Linux kernels without getrandom
Change-Id: I1fb9f5b47a264a7617912f6f56f995f3c4c5e578 PiperOrigin-RevId: 216591484
Diffstat (limited to 'pkg/rand/rand_linux.go')
-rw-r--r--pkg/rand/rand_linux.go31
1 files changed, 27 insertions, 4 deletions
diff --git a/pkg/rand/rand_linux.go b/pkg/rand/rand_linux.go
index 37ac07620..a2be66b3b 100644
--- a/pkg/rand/rand_linux.go
+++ b/pkg/rand/rand_linux.go
@@ -17,23 +17,46 @@
package rand
import (
+ "crypto/rand"
"io"
+ "sync"
"golang.org/x/sys/unix"
)
// reader implements an io.Reader that returns pseudorandom bytes.
-type reader struct{}
+type reader struct {
+ once sync.Once
+ useGetrandom bool
+}
// Read implements io.Reader.Read.
-func (reader) Read(p []byte) (int, error) {
- return unix.Getrandom(p, 0)
+func (r *reader) Read(p []byte) (int, error) {
+ r.once.Do(func() {
+ _, err := unix.Getrandom(p, 0)
+ if err != unix.ENOSYS {
+ r.useGetrandom = true
+ }
+ })
+
+ if r.useGetrandom {
+ return unix.Getrandom(p, 0)
+ }
+ return rand.Read(p)
}
// Reader is the default reader.
-var Reader io.Reader = reader{}
+var Reader io.Reader = &reader{}
// Read reads from the default reader.
func Read(b []byte) (int, error) {
return io.ReadFull(Reader, b)
}
+
+// Init can be called to make sure /dev/urandom is pre-opened on kernels that
+// do not support getrandom(2).
+func Init() error {
+ p := make([]byte, 1)
+ _, err := Read(p)
+ return err
+}