Commit 5308c6d9 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

crypto/rand: handle EAGAIN reads from /dev/urandom

Fixes #9205

Change-Id: Iacd608ba43332008984aa8ece17dcb5757f27b3f
Reviewed-on: https://go-review.googlesource.com/1611Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent 8655f04d
// 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.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package rand
import (
"os"
"syscall"
)
func init() {
isEAGAIN = unixIsEAGAIN
}
// unixIsEAGAIN reports whether err is a syscall.EAGAIN wrapped in a PathError.
// See golang.org/issue/9205
func unixIsEAGAIN(err error) bool {
if pe, ok := err.(*os.PathError); ok {
if errno, ok := pe.Err.(syscall.Errno); ok && errno == syscall.EAGAIN {
return true
}
}
return false
}
......@@ -58,12 +58,28 @@ func (r *devReader) Read(b []byte) (n int, err error) {
if runtime.GOOS == "plan9" {
r.f = f
} else {
r.f = bufio.NewReader(f)
r.f = bufio.NewReader(hideAgainReader{f})
}
}
return r.f.Read(b)
}
var isEAGAIN func(error) bool // set by eagain.go on unix systems
// hideAgainReader masks EAGAIN reads from /dev/urandom.
// See golang.org/issue/9205
type hideAgainReader struct {
r io.Reader
}
func (hr hideAgainReader) Read(p []byte) (n int, err error) {
n, err = hr.r.Read(p)
if err != nil && isEAGAIN != nil && isEAGAIN(err) {
err = nil
}
return
}
// Alternate pseudo-random implementation for use on
// systems without a reliable /dev/urandom.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment