-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[libc] implement getrandom for windows #119438
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-libc Author: Schrodinger ZHU Yifan (SchrodingerZhu) ChangesFull diff: https://github.com/llvm/llvm-project/pull/119438.diff 16 Files Affected:
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
-)
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this necessary? getrandom
is a linux specific function.
add_proxy_header_library( | ||
ssize_t | ||
HDRS | ||
ssize_t.h | ||
FULL_BUILD_DEPENDS | ||
libc.include.llvm-libc-types.ssize_t | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is important, but should probably be in a separate patch.
#define LLVM_LIBC_TYPES_SSIZE_T_H | ||
|
||
// https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types | ||
#if __has_include(<BaseTsd.h>) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__has_include
isn't the appropriate way to check if this is a windows target. I'd recommend doing #ifdef WIN32
instead.
Good point. I made this as there are other parts of code that assumes getrandom on default. Maybe I should chane them instead. Closing this now. I will separate out the ssize_t changes. |
This PR implements the
getrandom
emulation usingBCryptGenRandom
.