[libc] Update prctl() declaration to use variadic arguments. (#198654) prctl declaration should typically use variadic arguments (e.g. see https://man7.org/linux/man-pages/man2/prctl.2.html), as the types / quantity of subsequent arguments depends on the `option`. We can't depend on all `<prctl.h>` users to explicitly cast arguments to `unsigned long` and passing all 5 of them every time. * Don't add any option-specific logic, and just consume `arg2`-`arg5` from variadic arguments and pass them to syscall implementation as-is, assuming that they won't be used by the kernel if they are not needed, and consuming these arguments won't lead to crashes. * Updated the test to use `prctl` variants with less than 5 explicit arguments (for PR_SET_NAME and PR_GET_NAME). GitOrigin-RevId: 57d2c4c7889333f8d1ebb77efdb5195c2e4f5e1e
diff --git a/include/sys/prctl.yaml b/include/sys/prctl.yaml index 53f5764..d8f536f 100644 --- a/include/sys/prctl.yaml +++ b/include/sys/prctl.yaml
@@ -11,7 +11,4 @@ return_type: int arguments: - type: int - - type: unsigned long - - type: unsigned long - - type: unsigned long - - type: unsigned long + - type: '...'
diff --git a/src/sys/prctl/linux/prctl.cpp b/src/sys/prctl/linux/prctl.cpp index c726b0a..b2e6765 100644 --- a/src/sys/prctl/linux/prctl.cpp +++ b/src/sys/prctl/linux/prctl.cpp
@@ -12,13 +12,21 @@ #include "src/__support/libc_errno.h" #include "src/__support/macros/config.h" +#include <stdarg.h> #include <sys/syscall.h> // For syscall numbers. namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(int, prctl, - (int option, unsigned long arg2, unsigned long arg3, - unsigned long arg4, unsigned long arg5)) { +LLVM_LIBC_FUNCTION(int, prctl, (int option, ...)) { + va_list vargs; + va_start(vargs, option); + // Try to consume (and pass to syscall_impl) the maximum possible number of + // arguments, even though for some "option" values only few will be provided. + unsigned long arg2 = va_arg(vargs, unsigned long); + unsigned long arg3 = va_arg(vargs, unsigned long); + unsigned long arg4 = va_arg(vargs, unsigned long); + unsigned long arg5 = va_arg(vargs, unsigned long); + va_end(vargs); long ret = LIBC_NAMESPACE::syscall_impl(SYS_prctl, option, arg2, arg3, arg4, arg5); // The manpage states that "... return the nonnegative values described
diff --git a/src/sys/prctl/prctl.h b/src/sys/prctl/prctl.h index c6b5797..b88c6ab 100644 --- a/src/sys/prctl/prctl.h +++ b/src/sys/prctl/prctl.h
@@ -14,8 +14,7 @@ namespace LIBC_NAMESPACE_DECL { -int prctl(int option, unsigned long arg2, unsigned long arg3, - unsigned long arg4, unsigned long arg5); +int prctl(int option, ...); } // namespace LIBC_NAMESPACE_DECL
diff --git a/test/src/sys/prctl/linux/prctl_test.cpp b/test/src/sys/prctl/linux/prctl_test.cpp index 76b829c..0de85b7 100644 --- a/test/src/sys/prctl/linux/prctl_test.cpp +++ b/test/src/sys/prctl/linux/prctl_test.cpp
@@ -9,25 +9,19 @@ #include "src/sys/prctl/prctl.h" #include "test/UnitTest/ErrnoCheckingTest.h" #include "test/UnitTest/ErrnoSetterMatcher.h" -#include <sys/prctl.h> +#include <linux/prctl.h> // Definition of PR_* constants using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; using LlvmLibcSysPrctlTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; TEST_F(LlvmLibcSysPrctlTest, GetSetName) { + ASSERT_THAT(LIBC_NAMESPACE::prctl(PR_GET_NAME, nullptr), Fails(EFAULT, -1)); + + ASSERT_THAT(LIBC_NAMESPACE::prctl(PR_SET_NAME, "libc-test"), Succeeds()); + char name[17]; - unsigned long name_addr = 0; - ASSERT_THAT(LIBC_NAMESPACE::prctl(PR_GET_NAME, name_addr, 0, 0, 0), - Fails(EFAULT, -1)); - - name_addr = reinterpret_cast<unsigned long>("libc-test"); - ASSERT_THAT(LIBC_NAMESPACE::prctl(PR_SET_NAME, name_addr, 0, 0, 0), - Succeeds()); - - name_addr = reinterpret_cast<unsigned long>(name); - ASSERT_THAT(LIBC_NAMESPACE::prctl(PR_GET_NAME, name_addr, 0, 0, 0), - Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::prctl(PR_GET_NAME, name), Succeeds()); ASSERT_STREQ(name, "libc-test"); }