Support for older Linux kernels without getrandom

Change-Id: I1fb9f5b47a264a7617912f6f56f995f3c4c5e578
PiperOrigin-RevId: 216591484
This commit is contained in:
Jonathan Giannuzzi 2018-10-10 14:17:27 -07:00 committed by Shentubot
parent ddb34b3690
commit 8388a505e7
3 changed files with 38 additions and 6 deletions

View File

@ -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) {
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
}

View File

@ -25,6 +25,7 @@ go_library(
"//pkg/control/server",
"//pkg/cpuid",
"//pkg/log",
"//pkg/rand",
"//pkg/sentry/arch",
"//pkg/sentry/context",
"//pkg/sentry/control",

View File

@ -17,7 +17,7 @@ package boot
import (
"fmt"
"math/rand"
mrand "math/rand"
"os"
"os/signal"
"runtime"
@ -30,6 +30,7 @@ import (
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
"gvisor.googlesource.com/gvisor/pkg/cpuid"
"gvisor.googlesource.com/gvisor/pkg/log"
"gvisor.googlesource.com/gvisor/pkg/rand"
"gvisor.googlesource.com/gvisor/pkg/sentry/arch"
"gvisor.googlesource.com/gvisor/pkg/sentry/control"
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/host"
@ -133,7 +134,7 @@ type execProcess struct {
func init() {
// Initialize the random number generator.
rand.Seed(gtime.Now().UnixNano())
mrand.Seed(gtime.Now().UnixNano())
// Register the global syscall table.
kernel.RegisterSyscallTable(slinux.AMD64)
@ -167,9 +168,16 @@ type Args struct {
// New initializes a new kernel loader configured by spec.
// New also handles setting up a kernel for restoring a container.
func New(args Args) (*Loader, error) {
// We initialize the rand package now to make sure /dev/urandom is pre-opened
// on kernels that do not support getrandom(2).
if err := rand.Init(); err != nil {
return nil, fmt.Errorf("error setting up rand: %v", err)
}
if err := usage.Init(); err != nil {
return nil, fmt.Errorf("error setting up memory usage: %v", err)
}
// Create kernel and platform.
p, err := createPlatform(args.Conf, args.DeviceFD)
if err != nil {