Skip to content

Commit 86bde5a

Browse files
[libc] implement prctl (#74386)
Implement `prctl` as specified in https://man7.org/linux/man-pages/man2/prctl.2.html. This patch also includes test cases covering two simple use cases: 1. `PR_GET_NAME/PR_SET_NAME`: where userspace data is passed via arg2. 2. `PR_GET_THP_DISABLE`: where return value is passed via syscal retval.
1 parent 901bc51 commit 86bde5a

File tree

14 files changed

+155
-2
lines changed

14 files changed

+155
-2
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ set(TARGET_LIBC_ENTRYPOINTS
165165
libc.src.sys.wait.wait4
166166
libc.src.sys.wait.waitpid
167167

168+
# sys/prctl.h entrypoints
169+
libc.src.sys.prctl.prctl
170+
168171
# termios.h entrypoints
169172
libc.src.termios.cfgetispeed
170173
libc.src.termios.cfgetospeed

libc/config/linux/arm/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ set(TARGET_LIBC_ENTRYPOINTS
9292
# sys/mman.h entrypoints
9393
libc.src.sys.mman.mmap
9494
libc.src.sys.mman.munmap
95+
96+
# sys/prctl.h entrypoints
97+
libc.src.sys.prctl.prctl
9598
)
9699

97100
set(TARGET_LIBM_ENTRYPOINTS

libc/config/linux/riscv/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ set(TARGET_LIBC_ENTRYPOINTS
171171
libc.src.sys.wait.wait4
172172
libc.src.sys.wait.waitpid
173173

174+
# sys/prctl.h entrypoints
175+
libc.src.sys.prctl.prctl
176+
174177
# termios.h entrypoints
175178
libc.src.termios.cfgetispeed
176179
libc.src.termios.cfgetospeed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ set(TARGET_LIBC_ENTRYPOINTS
174174
libc.src.sys.wait.wait4
175175
libc.src.sys.wait.waitpid
176176

177+
# sys/prctl.h entrypoints
178+
libc.src.sys.prctl.prctl
179+
177180
# termios.h entrypoints
178181
libc.src.termios.cfgetispeed
179182
libc.src.termios.cfgetospeed

libc/include/sys/prctl.h.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
// the macros itself.
1616
#include <linux/prctl.h>
1717

18-
// TODO: Define the prctl macros.
19-
2018
%%public_api()
2119

2220
#endif // LLVM_LIBC_SYS_PRCTL_H

libc/src/sys/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ add_subdirectory(sendfile)
77
add_subdirectory(stat)
88
add_subdirectory(utsname)
99
add_subdirectory(wait)
10+
add_subdirectory(prctl)

libc/src/sys/prctl/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
2+
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
3+
endif()
4+
5+
add_entrypoint_object(
6+
prctl
7+
ALIAS
8+
DEPENDS
9+
.${LIBC_TARGET_OS}.prctl
10+
)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
add_entrypoint_object(
2+
prctl
3+
SRCS
4+
prctl.cpp
5+
HDRS
6+
../prctl.h
7+
DEPENDS
8+
libc.include.sys_prctl
9+
libc.include.sys_syscall
10+
libc.src.__support.OSUtil.osutil
11+
libc.src.errno.errno
12+
)

libc/src/sys/prctl/linux/prctl.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===---------- Linux implementation of the prctl function ----------------===//
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/sys/prctl/prctl.h"
10+
11+
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
12+
13+
#include "src/errno/libc_errno.h"
14+
#include <sys/syscall.h> // For syscall numbers.
15+
16+
namespace LIBC_NAMESPACE {
17+
18+
LLVM_LIBC_FUNCTION(int, prctl,
19+
(int option, unsigned long arg2, unsigned long arg3,
20+
unsigned long arg4, unsigned long arg5)) {
21+
long ret =
22+
LIBC_NAMESPACE::syscall_impl(SYS_prctl, option, arg2, arg3, arg4, arg5);
23+
// The manpage states that "... return the nonnegative values described
24+
// above. All other option values return 0 on success. On error,
25+
// -1 is returned, and errno is set to indicate the error."
26+
// According to the kernel implementation
27+
// (https://github.com/torvalds/linux/blob/bee0e7762ad2c6025b9f5245c040fcc36ef2bde8/kernel/sys.c#L2442),
28+
// return value from the syscall is set to 0 on default so we do not need to
29+
// set the value on success manually.
30+
if (ret < 0) {
31+
libc_errno = static_cast<int>(-ret);
32+
return -1;
33+
}
34+
return static_cast<int>(ret);
35+
}
36+
37+
} // namespace LIBC_NAMESPACE

libc/src/sys/prctl/prctl.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation header for prctl ---------------------------*-C++-*-===//
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+
#ifndef LLVM_LIBC_SRC_SYS_PRCTL_PRCTL_H
10+
#define LLVM_LIBC_SRC_SYS_PRCTL_PRCTL_H
11+
12+
#include <sys/prctl.h>
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
int prctl(int option, unsigned long arg2, unsigned long arg3,
17+
unsigned long arg4, unsigned long arg5);
18+
19+
} // namespace LIBC_NAMESPACE
20+
21+
#endif // LLVM_LIBC_SRC_SYS_PRCTL_PRCTL_H

libc/test/src/sys/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ add_subdirectory(socket)
77
add_subdirectory(stat)
88
add_subdirectory(utsname)
99
add_subdirectory(wait)
10+
add_subdirectory(prctl)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
2+
add_subdirectory(${LIBC_TARGET_OS})
3+
endif()
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
add_custom_target(libc_sys_prctl_unittests)
2+
3+
add_libc_unittest(
4+
prctl_test
5+
SUITE
6+
libc_sys_prctl_unittests
7+
SRCS
8+
prctl_test.cpp
9+
DEPENDS
10+
libc.include.sys_prctl
11+
libc.include.errno
12+
libc.src.sys.prctl.prctl
13+
libc.src.errno.errno
14+
)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//===-- Unittests for prctl -----------------------------------------------===//
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/sys/prctl/prctl.h"
11+
#include "test/UnitTest/ErrnoSetterMatcher.h"
12+
#include <errno.h>
13+
#include <sys/prctl.h>
14+
15+
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
16+
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
17+
18+
TEST(LlvmLibcSysPrctlTest, GetSetName) {
19+
char name[17];
20+
unsigned long name_addr = 0;
21+
ASSERT_THAT(LIBC_NAMESPACE::prctl(PR_GET_NAME, name_addr, 0, 0, 0),
22+
Fails(EFAULT, -1));
23+
24+
name_addr = reinterpret_cast<unsigned long>("libc-test");
25+
ASSERT_THAT(LIBC_NAMESPACE::prctl(PR_SET_NAME, name_addr, 0, 0, 0),
26+
Succeeds());
27+
28+
name_addr = reinterpret_cast<unsigned long>(name);
29+
ASSERT_THAT(LIBC_NAMESPACE::prctl(PR_GET_NAME, name_addr, 0, 0, 0),
30+
Succeeds());
31+
ASSERT_STREQ(name, "libc-test");
32+
}
33+
34+
TEST(LlvmLibcSysPrctlTest, GetTHPDisable) {
35+
// Manually check errno since the return value logic here is not
36+
// covered in ErrnoSetterMatcher.
37+
libc_errno = 0;
38+
int ret = LIBC_NAMESPACE::prctl(PR_GET_THP_DISABLE, 0, 0, 0, 0);
39+
ASSERT_EQ(libc_errno, 0);
40+
// PR_GET_THP_DISABLE return (as the function result) the current
41+
// setting of the "THP disable" flag for the calling thread, which
42+
// is either 1, if the flag is set; or 0, if it is not.
43+
ASSERT_TRUE(ret == 0 || ret == 1);
44+
}

0 commit comments

Comments
 (0)