[libc-commits] [libc] defd0d9 - [libc] implement unistd/getentropy (#122692)
via libc-commits
libc-commits at lists.llvm.org
Wed Jan 15 02:27:08 PST 2025
Author: Schrodinger ZHU Yifan
Date: 2025-01-15T18:27:05+08:00
New Revision: defd0d966d5ebae37787e76b86f2f2ff2a5cfd59
URL: https://github.com/llvm/llvm-project/commit/defd0d966d5ebae37787e76b86f2f2ff2a5cfd59
DIFF: https://github.com/llvm/llvm-project/commit/defd0d966d5ebae37787e76b86f2f2ff2a5cfd59.diff
LOG: [libc] implement unistd/getentropy (#122692)
Implement GNU extension getentropy. This function is used by many
programs to acquire entropy without handling the loop of getrandom.
Added:
libc/src/unistd/getentropy.h
libc/src/unistd/linux/getentropy.cpp
libc/src/unistd/windows/CMakeLists.txt
libc/src/unistd/windows/getentropy.cpp
libc/test/src/unistd/getentropy_test.cpp
Modified:
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/config/windows/entrypoints.txt
libc/config/windows/headers.txt
libc/include/sys/random.yaml
libc/include/unistd.yaml
libc/src/CMakeLists.txt
libc/src/unistd/CMakeLists.txt
libc/src/unistd/linux/CMakeLists.txt
libc/test/src/CMakeLists.txt
libc/test/src/unistd/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index fc2b0e91c1286d..f5ba3414117682 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -322,6 +322,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.unistd.fsync
libc.src.unistd.ftruncate
libc.src.unistd.getcwd
+ libc.src.unistd.getentropy
libc.src.unistd.geteuid
libc.src.unistd.getpid
libc.src.unistd.getppid
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 723853b2230ae9..0c1ae9561a7e69 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -321,6 +321,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.unistd.fsync
libc.src.unistd.ftruncate
libc.src.unistd.getcwd
+ libc.src.unistd.getentropy
libc.src.unistd.geteuid
libc.src.unistd.getpid
libc.src.unistd.getppid
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 4ecc3ada9c7682..aad320995d339e 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -101,6 +101,9 @@ set(TARGET_LIBC_ENTRYPOINTS
# time.h entrypoints
libc.src.time.time
libc.src.time.clock_getres
+
+ # unistd.h entrypoints
+ libc.src.unistd.getentropy
)
set(TARGET_LIBM_ENTRYPOINTS
diff --git a/libc/config/windows/headers.txt b/libc/config/windows/headers.txt
index bccc04f7697e56..6d9aae92769240 100644
--- a/libc/config/windows/headers.txt
+++ b/libc/config/windows/headers.txt
@@ -6,4 +6,5 @@ set(TARGET_PUBLIC_HEADERS
libc.include.errno
libc.include.fenv
libc.include.math
+ libc.include.unistd
)
diff --git a/libc/include/sys/random.yaml b/libc/include/sys/random.yaml
index 4efb2fbb44733f..a97266a5481dfc 100644
--- a/libc/include/sys/random.yaml
+++ b/libc/include/sys/random.yaml
@@ -15,3 +15,10 @@ functions:
- type: void *
- type: size_t
- type: unsigned int
+ - name: getentropy
+ standards:
+ - GNUExtensions
+ return_type: int
+ arguments:
+ - type: void *
+ - type: size_t
diff --git a/libc/include/unistd.yaml b/libc/include/unistd.yaml
index fada365e0103d0..c1901be446fe5c 100644
--- a/libc/include/unistd.yaml
+++ b/libc/include/unistd.yaml
@@ -128,6 +128,13 @@ functions:
arguments:
- type: char *
- type: size_t
+ - name: getentropy
+ standards:
+ - GNUExtensions
+ return_type: int
+ arguments:
+ - type: void *
+ - type: size_t
- name: geteuid
standards:
- POSIX
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index 32308ba147940c..41183429f67a75 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -15,6 +15,7 @@ add_subdirectory(string)
add_subdirectory(strings)
add_subdirectory(wchar)
add_subdirectory(time)
+add_subdirectory(unistd)
if(${LIBC_TARGET_OS} STREQUAL "linux")
add_subdirectory(dirent)
@@ -23,7 +24,6 @@ if(${LIBC_TARGET_OS} STREQUAL "linux")
add_subdirectory(sched)
add_subdirectory(sys)
add_subdirectory(termios)
- add_subdirectory(unistd)
endif()
if(NOT LLVM_LIBC_FULL_BUILD)
diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt
index 1a0b2e3293d03c..6bdea0c7693bd9 100644
--- a/libc/src/unistd/CMakeLists.txt
+++ b/libc/src/unistd/CMakeLists.txt
@@ -350,3 +350,10 @@ add_entrypoint_object(
DEPENDS
libc.src.__support.threads.identifier
)
+
+add_entrypoint_object(
+ getentropy
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.getentropy
+)
diff --git a/libc/src/unistd/getentropy.h b/libc/src/unistd/getentropy.h
new file mode 100644
index 00000000000000..27e13d2352d817
--- /dev/null
+++ b/libc/src/unistd/getentropy.h
@@ -0,0 +1,19 @@
+//===-- Implementation header for getentropy ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "hdr/types/size_t.h"
+#include "src/__support/common.h"
+
+#ifndef LLVM_LIBC_SRC_UNISTD_GETENTROPY_H
+#define LLVM_LIBC_SRC_UNISTD_GETENTROPY_H
+
+namespace LIBC_NAMESPACE_DECL {
+int getentropy(void *buffer, size_t length);
+}
+
+#endif // LLVM_LIBC_SRC_UNISTD_GETENTROPY_H
diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index ed360c73354ac4..2bb17f56f7b32e 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -570,3 +570,18 @@ add_entrypoint_object(
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
+
+add_entrypoint_object(
+ getentropy
+ SRCS
+ getentropy.cpp
+ HDRS
+ ../getentropy.h
+ DEPENDS
+ libc.hdr.types.size_t
+ libc.hdr.types.ssize_t
+ libc.hdr.errno_macros
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
diff --git a/libc/src/unistd/linux/getentropy.cpp b/libc/src/unistd/linux/getentropy.cpp
new file mode 100644
index 00000000000000..168a1197734ed6
--- /dev/null
+++ b/libc/src/unistd/linux/getentropy.cpp
@@ -0,0 +1,51 @@
+//===-- Linux implementation of getentropy --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/unistd/getentropy.h"
+#include "hdr/errno_macros.h"
+#include "src/__support/OSUtil/syscall.h"
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+LLVM_LIBC_FUNCTION(int, getentropy, (void *buffer, size_t length)) {
+ // check the length limit
+ if (length > 256) {
+ libc_errno = EIO;
+ return -1;
+ }
+
+ char *cursor = static_cast<char *>(buffer);
+ while (length != 0) {
+ // 0 flag means urandom and blocking, which meets the assumption of
+ // getentropy
+ auto ret = syscall_impl<long>(SYS_getrandom, cursor, length, 0);
+
+ // on success, advance the buffer pointer
+ if (ret >= 0) {
+ length -= static_cast<size_t>(ret);
+ cursor += ret;
+ continue;
+ }
+
+ auto error = -static_cast<int>(ret);
+
+ // on EINTR, try again
+ if (error == EINTR)
+ continue;
+
+ // on ENOSYS, forward errno and exit;
+ // otherwise, set EIO and exit
+ libc_errno = (error == ENOSYS) ? ENOSYS : EIO;
+ return -1;
+ }
+ return 0;
+}
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/windows/CMakeLists.txt b/libc/src/unistd/windows/CMakeLists.txt
new file mode 100644
index 00000000000000..195d98cdb51d4c
--- /dev/null
+++ b/libc/src/unistd/windows/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_entrypoint_object(
+ getentropy
+ SRCS
+ getentropy.cpp
+ HDRS
+ ../getentropy.h
+ DEPENDS
+ libc.hdr.types.size_t
+ libc.hdr.errno_macros
+ libc.src.errno.errno
+)
diff --git a/libc/src/unistd/windows/getentropy.cpp b/libc/src/unistd/windows/getentropy.cpp
new file mode 100644
index 00000000000000..bfaec723ac63d1
--- /dev/null
+++ b/libc/src/unistd/windows/getentropy.cpp
@@ -0,0 +1,42 @@
+//===-- Windows implementation of getentropy ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/unistd/getentropy.h"
+#include "hdr/errno_macros.h"
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#include <bcrypt.h>
+#include <ntstatus.h>
+#pragma comment(lib, "bcrypt.lib")
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, getentropy, (void *buffer, size_t length)) {
+ __try {
+ // check the length limit
+ if (length > 256)
+ __leave;
+
+ NTSTATUS result = ::BCryptGenRandom(nullptr, static_cast<PUCHAR>(buffer),
+ static_cast<ULONG>(length),
+ BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+
+ if (result == STATUS_SUCCESS)
+ return 0;
+
+ } __except (EXCEPTION_EXECUTE_HANDLER) {
+ // no need to handle exceptions specially
+ }
+
+ libc_errno = EIO;
+ return -1;
+}
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt
index 31008508d64928..22ec43588f7448 100644
--- a/libc/test/src/CMakeLists.txt
+++ b/libc/test/src/CMakeLists.txt
@@ -61,6 +61,7 @@ add_subdirectory(string)
add_subdirectory(strings)
add_subdirectory(wchar)
add_subdirectory(time)
+add_subdirectory(unistd)
# Depends on utilities in stdlib
add_subdirectory(inttypes)
@@ -70,7 +71,6 @@ if(${LIBC_TARGET_OS} STREQUAL "linux")
add_subdirectory(sched)
add_subdirectory(sys)
add_subdirectory(termios)
- add_subdirectory(unistd)
endif()
if(NOT LLVM_LIBC_FULL_BUILD)
diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt
index e036e09cde702e..c3eebdf2a877d3 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -488,6 +488,18 @@ add_libc_test(
libc.src.stdio.fflush
)
+add_libc_test(
+ getentropy_test
+ SUITE
+ libc_unistd_unittests
+ SRCS
+ getentropy_test.cpp
+ DEPENDS
+ libc.src.unistd.getentropy
+ libc.src.errno.errno
+ libc.test.UnitTest.ErrnoSetterMatcher
+)
+
if(LLVM_LIBC_FULL_BUILD)
add_libc_test(
_exit_test
diff --git a/libc/test/src/unistd/getentropy_test.cpp b/libc/test/src/unistd/getentropy_test.cpp
new file mode 100644
index 00000000000000..f7329ae4193275
--- /dev/null
+++ b/libc/test/src/unistd/getentropy_test.cpp
@@ -0,0 +1,28 @@
+//===-- Unittests for getentropy ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "src/unistd/getentropy.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+
+TEST(LlvmLibcUnistdGetEntropyTest, LengthTooLong) {
+ char buf[1024];
+ ASSERT_THAT(LIBC_NAMESPACE::getentropy(buf, 257), Fails(EIO));
+}
+
+TEST(LlvmLibcUnistdGetEntropyTest, SmokeTest) {
+ char buf[256];
+ ASSERT_THAT(LIBC_NAMESPACE::getentropy(buf, 256), Succeeds());
+}
+
+TEST(LlvmLibcUnistdGetEntropyTest, OtherError) {
+ ASSERT_THAT(LIBC_NAMESPACE::getentropy(nullptr, 1), Fails(EIO));
+}
More information about the libc-commits
mailing list