1 //===-- Linux implementation of getentropy --------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "src/unistd/getentropy.h" 10 #include "hdr/errno_macros.h" 11 #include "src/__support/OSUtil/syscall.h" 12 #include "src/__support/common.h" 13 #include "src/errno/libc_errno.h" 14 15 #include <sys/syscall.h> // For syscall numbers. 16 17 namespace LIBC_NAMESPACE_DECL { 18 LLVM_LIBC_FUNCTION(int, getentropy, (void *buffer, size_t length)) { 19 // check the length limit 20 if (length > 256) { 21 libc_errno = EIO; 22 return -1; 23 } 24 25 char *cursor = static_cast<char *>(buffer); 26 while (length != 0) { 27 // 0 flag means urandom and blocking, which meets the assumption of 28 // getentropy 29 auto ret = syscall_impl<long>(SYS_getrandom, cursor, length, 0); 30 31 // on success, advance the buffer pointer 32 if (ret >= 0) { 33 length -= static_cast<size_t>(ret); 34 cursor += ret; 35 continue; 36 } 37 38 auto error = -static_cast<int>(ret); 39 40 // on EINTR, try again 41 if (error == EINTR) 42 continue; 43 44 // on ENOSYS, forward errno and exit; 45 // otherwise, set EIO and exit 46 libc_errno = (error == ENOSYS) ? ENOSYS : EIO; 47 return -1; 48 } 49 return 0; 50 } 51 } // namespace LIBC_NAMESPACE_DECL 52