[libc-commits] [libc] [libc] implement getrandom for windows (PR #119438)
via libc-commits
libc-commits at lists.llvm.org
Tue Dec 10 11:28:08 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Schrodinger ZHU Yifan (SchrodingerZhu)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/119438.diff
16 Files Affected:
- (modified) libc/config/windows/entrypoints.txt (+3)
- (modified) libc/config/windows/headers.txt (+1)
- (modified) libc/hdr/CMakeLists.txt (+9)
- (added) libc/hdr/sys_random_macros.h (+22)
- (modified) libc/hdr/types/CMakeLists.txt (+8)
- (modified) libc/hdr/types/ssize_t.h (+2-1)
- (modified) libc/include/llvm-libc-types/ssize_t.h (+6)
- (modified) libc/src/CMakeLists.txt (+1-1)
- (modified) libc/src/sys/random/getrandom.h (+2-1)
- (modified) libc/src/sys/random/linux/CMakeLists.txt (+2-2)
- (added) libc/src/sys/random/windows/CMakeLists.txt (+14)
- (added) libc/src/sys/random/windows/getrandom.cpp (+67)
- (modified) libc/test/src/CMakeLists.txt (+1-1)
- (modified) libc/test/src/sys/random/CMakeLists.txt (+15-3)
- (renamed) libc/test/src/sys/random/getrandom_test.cpp (+2)
- (removed) libc/test/src/sys/random/linux/CMakeLists.txt (-15)
``````````diff
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 4ecc3ada9c7682..e615c5fc284f82 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
+
+ # sys/random.h entrypoints
+ libc.src.sys.random.getrandom
)
set(TARGET_LIBM_ENTRYPOINTS
diff --git a/libc/config/windows/headers.txt b/libc/config/windows/headers.txt
index bccc04f7697e56..8670dede45df26 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.sys_random
)
diff --git a/libc/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt
index 5eb311f4bb2298..f2396575b06d58 100644
--- a/libc/hdr/CMakeLists.txt
+++ b/libc/hdr/CMakeLists.txt
@@ -189,6 +189,15 @@ add_proxy_header_library(
libc.include.sys_auxv
)
+add_proxy_header_library(
+ sys_random_macros
+ HDRS
+ sys_random_macros.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-macros.sys_random_macros
+ libc.include.sys_random
+)
+
add_header_library(wchar_overlay HDRS wchar_overlay.h)
add_proxy_header_library(
diff --git a/libc/hdr/sys_random_macros.h b/libc/hdr/sys_random_macros.h
new file mode 100644
index 00000000000000..3c1fce2ca5cc42
--- /dev/null
+++ b/libc/hdr/sys_random_macros.h
@@ -0,0 +1,22 @@
+//===-- Definition of macros from sys/auxv.h ------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_SYS_RANDOM_MACROS_H
+#define LLVM_LIBC_HDR_SYS_RANDOM_MACROS_H
+
+#if defined(LIBC_FULL_BUILD) || defined(_WIN32)
+
+#include "include/llvm-libc-macros/sys-random-macros.h"
+
+#else // Overlay mode
+
+#include <sys/random.h>
+
+#endif // LLVM_LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_SYS_RANDOM_MACROS_H
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index 68a0e9603f9752..fcc1776f1e7eda 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -93,6 +93,14 @@ add_proxy_header_library(
libc.include.llvm-libc-types.size_t
)
+add_proxy_header_library(
+ ssize_t
+ HDRS
+ ssize_t.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.ssize_t
+)
+
add_proxy_header_library(
mode_t
HDRS
diff --git a/libc/hdr/types/ssize_t.h b/libc/hdr/types/ssize_t.h
index 4d2000780ee11f..9ebc822434b914 100644
--- a/libc/hdr/types/ssize_t.h
+++ b/libc/hdr/types/ssize_t.h
@@ -8,7 +8,8 @@
#ifndef LLVM_LIBC_HDR_TYPES_SSIZE_T_H
#define LLVM_LIBC_HDR_TYPES_SSIZE_T_H
-#ifdef LIBC_FULL_BUILD
+// stddef does not provide ssize_t on windows.
+#if defined(LIBC_FULL_BUILD) || defined(_WIN32)
#include "include/llvm-libc-types/ssize_t.h"
diff --git a/libc/include/llvm-libc-types/ssize_t.h b/libc/include/llvm-libc-types/ssize_t.h
index 41e4b6d2c500ad..5f2f325753166f 100644
--- a/libc/include/llvm-libc-types/ssize_t.h
+++ b/libc/include/llvm-libc-types/ssize_t.h
@@ -9,6 +9,12 @@
#ifndef LLVM_LIBC_TYPES_SSIZE_T_H
#define LLVM_LIBC_TYPES_SSIZE_T_H
+// https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types
+#if __has_include(<BaseTsd.h>)
+#include <BaseTsd.h>
+typedef SSIZE_T ssize_t;
+#else
typedef __INT64_TYPE__ ssize_t;
+#endif
#endif // LLVM_LIBC_TYPES_SSIZE_T_H
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index 9fc331ad18a391..e6ac299f7346e5 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -16,7 +16,7 @@ add_subdirectory(strings)
add_subdirectory(wchar)
add_subdirectory(time)
-if(${LIBC_TARGET_OS} STREQUAL "linux")
+if(${LIBC_TARGET_OS} STREQUAL "linux" OR ${LIBC_TARGET_OS} STREQUAL "windows")
add_subdirectory(dirent)
add_subdirectory(fcntl)
add_subdirectory(pthread)
diff --git a/libc/src/sys/random/getrandom.h b/libc/src/sys/random/getrandom.h
index 134bd0cd9468d8..376ec389e582fb 100644
--- a/libc/src/sys/random/getrandom.h
+++ b/libc/src/sys/random/getrandom.h
@@ -9,8 +9,9 @@
#ifndef LLVM_LIBC_SRC_SYS_RANDOM_GETRANDOM_H
#define LLVM_LIBC_SRC_SYS_RANDOM_GETRANDOM_H
+#include "hdr/sys_random_macros.h"
+#include "hdr/types/ssize_t.h"
#include "src/__support/macros/config.h"
-#include <sys/random.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/random/linux/CMakeLists.txt b/libc/src/sys/random/linux/CMakeLists.txt
index 474e275ee597a8..dc6506adfc5cd1 100644
--- a/libc/src/sys/random/linux/CMakeLists.txt
+++ b/libc/src/sys/random/linux/CMakeLists.txt
@@ -5,8 +5,8 @@ add_entrypoint_object(
HDRS
../getrandom.h
DEPENDS
- libc.include.sys_random
- libc.include.sys_syscall
+ libc.hdr.sys_random_macros
+ libc.hdr.types.ssize_t
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
diff --git a/libc/src/sys/random/windows/CMakeLists.txt b/libc/src/sys/random/windows/CMakeLists.txt
new file mode 100644
index 00000000000000..948b343bb69e88
--- /dev/null
+++ b/libc/src/sys/random/windows/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_entrypoint_object(
+ getrandom
+ SRCS
+ getrandom.cpp
+ HDRS
+ ../getrandom.h
+ DEPENDS
+ # Maybe we should include the following
+ # but we don't really care the flags on Windows
+ # libc.hdr.sys_random_macros
+ libc.hdr.types.ssize_t
+ libc.src.errno.errno
+ libc.src.__support.CPP.limits
+)
diff --git a/libc/src/sys/random/windows/getrandom.cpp b/libc/src/sys/random/windows/getrandom.cpp
new file mode 100644
index 00000000000000..af5cc2e05edc99
--- /dev/null
+++ b/libc/src/sys/random/windows/getrandom.cpp
@@ -0,0 +1,67 @@
+//===-- Windows implementation of getrandom -------------------------------===//
+//
+// 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/sys/random/getrandom.h"
+#include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/limits.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+#include "src/errno/libc_errno.h"
+
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+#include <Windows.h>
+#include <bcrypt.h>
+#include <ntstatus.h>
+#pragma comment(lib, "bcrypt.lib")
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(ssize_t, getrandom,
+ (void *buf, size_t buflen,
+ [[maybe_unused]] unsigned int flags)) {
+ // https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
+ // BCRYPT_USE_SYSTEM_PREFERRED_RNG
+ // Use the system-preferred random number generator algorithm. The hAlgorithm
+ // parameter must be NULL.
+
+ // flags are ignored as Windows does not distinguish between urandom/random.
+ // size_t is larger than ULONG. Linux API allows getrandom to return fewer
+ // bytes than required. Hence, we trancate the size_t to ULONG. If user really
+ // needs huge amount of bytes (which is highly unlikely), they can call
+ // getrandom multiple times in a loop. This is also the common pattern in
+ // Linux.
+
+ // https://learn.microsoft.com/en-us/windows-hardware/drivers/gettingstarted/virtual-address-spaces
+ // A 64-bit process on 64-bit Windows has a virtual address space within the
+ // 128-terabyte range 0x000'00000000 through 0x7FFF'FFFFFFFF.
+ if (buf == nullptr || cpp::bit_cast<INT_PTR>(buf) < 0) {
+ libc_errno = EFAULT;
+ return -1;
+ }
+
+ constexpr size_t PARAM_LIMIT =
+ static_cast<size_t>(cpp::numeric_limits<ULONG>::max());
+ constexpr size_t RETURN_LIMIT =
+ static_cast<size_t>(cpp::numeric_limits<ssize_t>::max());
+ buflen = buflen > PARAM_LIMIT ? PARAM_LIMIT : buflen;
+ buflen = buflen > RETURN_LIMIT ? RETURN_LIMIT : buflen;
+ NTSTATUS result = ::BCryptGenRandom(nullptr, static_cast<PUCHAR>(buf),
+ static_cast<ULONG>(buflen),
+ BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+
+ // not possible to overflow as we have truncated the limit.
+ if (LIBC_LIKELY(result == STATUS_SUCCESS))
+ return static_cast<ssize_t>(buflen);
+
+ libc_errno = EINVAL;
+ return -1;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt
index 31008508d64928..ee393ed76969a3 100644
--- a/libc/test/src/CMakeLists.txt
+++ b/libc/test/src/CMakeLists.txt
@@ -65,7 +65,7 @@ add_subdirectory(time)
# Depends on utilities in stdlib
add_subdirectory(inttypes)
-if(${LIBC_TARGET_OS} STREQUAL "linux")
+if(${LIBC_TARGET_OS} STREQUAL "linux" OR ${LIBC_TARGET_OS} STREQUAL "windows")
add_subdirectory(fcntl)
add_subdirectory(sched)
add_subdirectory(sys)
diff --git a/libc/test/src/sys/random/CMakeLists.txt b/libc/test/src/sys/random/CMakeLists.txt
index b4bbe81c92ff2e..c7146c2d478622 100644
--- a/libc/test/src/sys/random/CMakeLists.txt
+++ b/libc/test/src/sys/random/CMakeLists.txt
@@ -1,3 +1,15 @@
-if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
- add_subdirectory(${LIBC_TARGET_OS})
-endif()
+add_custom_target(libc_sys_random_unittests)
+
+add_libc_unittest(
+ getrandom_test
+ SUITE
+ libc_sys_random_unittests
+ SRCS
+ getrandom_test.cpp
+ DEPENDS
+ libc.hdr.sys_random_macros
+ libc.src.errno.errno
+ libc.src.math.fabs
+ libc.src.sys.random.getrandom
+ libc.test.UnitTest.ErrnoSetterMatcher
+)
diff --git a/libc/test/src/sys/random/linux/getrandom_test.cpp b/libc/test/src/sys/random/getrandom_test.cpp
similarity index 98%
rename from libc/test/src/sys/random/linux/getrandom_test.cpp
rename to libc/test/src/sys/random/getrandom_test.cpp
index e3481b73ca0027..10d0577d05c62e 100644
--- a/libc/test/src/sys/random/linux/getrandom_test.cpp
+++ b/libc/test/src/sys/random/getrandom_test.cpp
@@ -13,12 +13,14 @@
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"
+#ifndef _WIN32
TEST(LlvmLibcGetRandomTest, InvalidFlag) {
LIBC_NAMESPACE::cpp::array<char, 10> buffer;
LIBC_NAMESPACE::libc_errno = 0;
ASSERT_THAT(LIBC_NAMESPACE::getrandom(buffer.data(), buffer.size(), -1),
LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails(EINVAL));
}
+#endif
TEST(LlvmLibcGetRandomTest, InvalidBuffer) {
LIBC_NAMESPACE::libc_errno = 0;
diff --git a/libc/test/src/sys/random/linux/CMakeLists.txt b/libc/test/src/sys/random/linux/CMakeLists.txt
deleted file mode 100644
index 737326cb158ce5..00000000000000
--- a/libc/test/src/sys/random/linux/CMakeLists.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-add_custom_target(libc_sys_random_unittests)
-
-add_libc_unittest(
- getrandom_test
- SUITE
- libc_sys_random_unittests
- SRCS
- getrandom_test.cpp
- DEPENDS
- libc.include.sys_random
- libc.src.errno.errno
- libc.src.math.fabs
- libc.src.sys.random.getrandom
- libc.test.UnitTest.ErrnoSetterMatcher
-)
``````````
</details>
https://github.com/llvm/llvm-project/pull/119438
More information about the libc-commits
mailing list