Skip to content

Commit 48a3a1c

Browse files
[libc] implement unistd/getentropy
1 parent acbd822 commit 48a3a1c

File tree

9 files changed

+142
-0
lines changed

9 files changed

+142
-0
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ set(TARGET_LIBC_ENTRYPOINTS
322322
libc.src.unistd.fsync
323323
libc.src.unistd.ftruncate
324324
libc.src.unistd.getcwd
325+
libc.src.unistd.getentropy
325326
libc.src.unistd.geteuid
326327
libc.src.unistd.getpid
327328
libc.src.unistd.getppid

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ set(TARGET_LIBC_ENTRYPOINTS
321321
libc.src.unistd.fsync
322322
libc.src.unistd.ftruncate
323323
libc.src.unistd.getcwd
324+
libc.src.unistd.getentropy
324325
libc.src.unistd.geteuid
325326
libc.src.unistd.getpid
326327
libc.src.unistd.getppid

libc/include/unistd.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,13 @@ functions:
128128
arguments:
129129
- type: char *
130130
- type: size_t
131+
- name: getentropy
132+
standards:
133+
- GNUExtensions
134+
return_type: int
135+
arguments:
136+
- type: void *
137+
- type: size_t
131138
- name: geteuid
132139
standards:
133140
- POSIX

libc/src/unistd/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,3 +350,10 @@ add_entrypoint_object(
350350
DEPENDS
351351
libc.src.__support.threads.identifier
352352
)
353+
354+
add_entrypoint_object(
355+
getentropy
356+
ALIAS
357+
DEPENDS
358+
.${LIBC_TARGET_OS}.getentropy
359+
)

libc/src/unistd/getentropy.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation header for 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 "hdr/types/size_t.h"
10+
#include "src/__support/common.h"
11+
12+
#ifndef LLVM_LIBC_SRC_UNISTD_GETENTROPY_H
13+
#define LLVM_LIBC_SRC_UNISTD_GETENTROPY_H
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
int getentropy(void *buffer, size_t length);
17+
}
18+
19+
#endif // LLVM_LIBC_SRC_UNISTD_GETENTROPY_H

libc/src/unistd/linux/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,3 +570,17 @@ add_entrypoint_object(
570570
libc.src.__support.OSUtil.osutil
571571
libc.src.errno.errno
572572
)
573+
574+
add_entrypoint_object(
575+
getentropy
576+
SRCS
577+
getentropy.cpp
578+
HDRS
579+
../getentropy.h
580+
DEPENDS
581+
libc.hdr.types.size_t
582+
libc.hdr.types.ssize_t
583+
libc.hdr.errno_macros
584+
libc.src.sys.random.getrandom
585+
libc.src.errno.errno
586+
)

libc/src/unistd/linux/getentropy.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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/common.h"
12+
#include "src/errno/libc_errno.h"
13+
#include "src/sys/random/getrandom.h"
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
LLVM_LIBC_FUNCTION(int, getentropy, (void *buffer, size_t length)) {
17+
// check the length limit
18+
if (length > 256) {
19+
libc_errno = EIO;
20+
return -1;
21+
}
22+
23+
char *cursor = static_cast<char *>(buffer);
24+
while (length != 0) {
25+
// 0 flag means urandom and blocking, which meets the assumption of
26+
// getentropy
27+
ssize_t ret = LIBC_NAMESPACE::getrandom(cursor, length, 0);
28+
29+
// on success, advance the buffer pointer
30+
if (ret != -1) {
31+
length -= static_cast<size_t>(ret);
32+
cursor += ret;
33+
continue;
34+
}
35+
36+
// on EINTR, try again
37+
if (libc_errno == EINTR)
38+
continue;
39+
40+
// on ENOSYS, forward errno and exit;
41+
// otherwise, set EIO and exit
42+
if (libc_errno != ENOSYS)
43+
libc_errno = EIO;
44+
return -1;
45+
}
46+
return 0;
47+
}
48+
} // namespace LIBC_NAMESPACE_DECL

libc/test/src/unistd/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,18 @@ add_libc_test(
488488
libc.src.stdio.fflush
489489
)
490490

491+
add_libc_test(
492+
getentropy_test
493+
SUITE
494+
libc_unistd_unittests
495+
SRCS
496+
getentropy_test.cpp
497+
DEPENDS
498+
libc.src.unistd.getentropy
499+
libc.src.errno.errno
500+
libc.test.UnitTest.ErrnoSetterMatcher
501+
)
502+
491503
if(LLVM_LIBC_FULL_BUILD)
492504
add_libc_test(
493505
_exit_test
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===-- Unittests for 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/errno/libc_errno.h"
10+
#include "src/unistd/getentropy.h"
11+
#include "test/UnitTest/ErrnoSetterMatcher.h"
12+
#include "test/UnitTest/Test.h"
13+
14+
using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
15+
16+
TEST(LlvmLibcUnistdGetEntropyTest, LengthTooLong) {
17+
char buf[1024];
18+
ASSERT_THAT(LIBC_NAMESPACE::getentropy(buf, 257), Fails(EIO));
19+
ASSERT_THAT(LIBC_NAMESPACE::getentropy(buf, 1024), Fails(EIO));
20+
}
21+
22+
TEST(LlvmLibcUnistdGetEntropyTest, SmokeTest) {
23+
char buf[256];
24+
ASSERT_THAT(LIBC_NAMESPACE::getentropy(buf, 256), Succeeds());
25+
ASSERT_THAT(LIBC_NAMESPACE::getentropy(buf, 0), Succeeds());
26+
ASSERT_THAT(LIBC_NAMESPACE::getentropy(buf, 1), Succeeds());
27+
ASSERT_THAT(LIBC_NAMESPACE::getentropy(buf, 16), Succeeds());
28+
ASSERT_THAT(LIBC_NAMESPACE::getentropy(buf, 17), Succeeds());
29+
}
30+
31+
TEST(LlvmLibcUnistdGetEntropyTest, OtherError) {
32+
ASSERT_THAT(LIBC_NAMESPACE::getentropy(nullptr, 1), Fails(EIO));
33+
}

0 commit comments

Comments
 (0)