Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions libc/config/windows/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions libc/config/windows/headers.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ set(TARGET_PUBLIC_HEADERS
libc.include.errno
libc.include.fenv
libc.include.math
libc.include.sys_random
)
9 changes: 9 additions & 0 deletions libc/hdr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
22 changes: 22 additions & 0 deletions libc/hdr/sys_random_macros.h
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions libc/hdr/types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
)

Comment on lines +96 to +103
Copy link
Contributor

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.

add_proxy_header_library(
mode_t
HDRS
Expand Down
3 changes: 2 additions & 1 deletion libc/hdr/types/ssize_t.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
6 changes: 6 additions & 0 deletions libc/include/llvm-libc-types/ssize_t.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>)
Copy link
Contributor

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.

#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#else
typedef __INT64_TYPE__ ssize_t;
#endif

#endif // LLVM_LIBC_TYPES_SSIZE_T_H
2 changes: 1 addition & 1 deletion libc/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion libc/src/sys/random/getrandom.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down
4 changes: 2 additions & 2 deletions libc/src/sys/random/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
14 changes: 14 additions & 0 deletions libc/src/sys/random/windows/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
)
67 changes: 67 additions & 0 deletions libc/src/sys/random/windows/getrandom.cpp
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion libc/test/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 15 additions & 3 deletions libc/test/src/sys/random/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
)
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
15 changes: 0 additions & 15 deletions libc/test/src/sys/random/linux/CMakeLists.txt

This file was deleted.

Loading