github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/pkg/sentry/syscalls/linux/sys_random.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package linux 16 17 import ( 18 "math" 19 20 "github.com/metacubex/gvisor/pkg/errors/linuxerr" 21 "github.com/metacubex/gvisor/pkg/hostarch" 22 "github.com/metacubex/gvisor/pkg/rand" 23 "github.com/metacubex/gvisor/pkg/safemem" 24 "github.com/metacubex/gvisor/pkg/sentry/arch" 25 "github.com/metacubex/gvisor/pkg/sentry/kernel" 26 "github.com/metacubex/gvisor/pkg/usermem" 27 ) 28 29 const ( 30 _GRND_NONBLOCK = 0x1 31 _GRND_RANDOM = 0x2 32 ) 33 34 // GetRandom implements the linux syscall getrandom(2). 35 // 36 // In a multi-tenant/shared environment, the only valid implementation is to 37 // fetch data from the urandom pool, otherwise starvation attacks become 38 // possible. The urandom pool is also expected to have plenty of entropy, thus 39 // the GRND_RANDOM flag is ignored. The GRND_NONBLOCK flag does not apply, as 40 // the pool will already be initialized. 41 func GetRandom(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 42 addr := args[0].Pointer() 43 length := args[1].SizeT() 44 flags := args[2].Int() 45 46 // Flags are checked for validity but otherwise ignored. See above. 47 if flags & ^(_GRND_NONBLOCK|_GRND_RANDOM) != 0 { 48 return 0, nil, linuxerr.EINVAL 49 } 50 51 if length > math.MaxInt32 { 52 length = math.MaxInt32 53 } 54 ar, ok := addr.ToRange(uint64(length)) 55 if !ok { 56 return 0, nil, linuxerr.EFAULT 57 } 58 59 n, err := t.MemoryManager().CopyOutFrom(t, hostarch.AddrRangeSeqOf(ar), safemem.FromIOReader{rand.Reader}, usermem.IOOpts{ 60 AddressSpaceActive: true, 61 }) 62 if n > 0 { 63 return uintptr(n), nil, nil 64 } 65 return 0, nil, err 66 }