[PATCH v2 0/1] Call prctl(2) with signed long integers, and avoid casts
Alejandro Colomar
alx@kernel.org
Wed Dec 3 22:45:06 GMT 2025
Hi!
We were discussing some patch for fixing some less-than-ideal calls to
prctl(2) in util-linux. I've found similar calls elsewhere too. In the
end, prctl(2) is easy to get wrong (or at least not right), because it's
not type-safe, by being a variadic function.
We were wondering if libc could do something to fix this in every
project at the same time, by providing some type-safe wrappers.
How about providing a header file like the one below in glibc?
Have a lovely night!
Alex
---
// Copyright 2025, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: LGPL-3.0-or-later WITH LGPL-3.0-linking-exception
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/prctl.h>
#include <sys/types.h>
#if !defined(__has_c_attribute)
# define __has_c_attribute(x) 0
#endif
#if __has_attribute(__null_terminated_string_arg__)
# define LIBPRCTL_ATTR_STRING(i) __attribute__((__null_terminated_string_arg__(i)))
#else
# define LIBPRCTL_ATTR_STRING(i)
#endif
#if __has_attribute(__deprecated__)
# define LIBPRCTL_ATTR_DEPRECATED __attribute__((__deprecated__))
#else
# define LIBPRCTL_ATTR_DEPRECATED
#endif
_Static_assert(sizeof(long) == sizeof(void *), "");
_Static_assert(sizeof(long) == sizeof(size_t), "");
static inline int pr_cap_ambient_raise(int64_t cap) {
return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (long){cap}, 0L, 0L);
}
static inline int pr_cap_ambient_lower(int64_t cap) {
return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, (long){cap}, 0L, 0L);
}
static inline int pr_cap_ambient_is_set(int64_t cap) {
return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, (long){cap}, 0L,0L);
}
static inline int pr_cap_ambient_clear_all(void) {
return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0L, 0L, 0L);
}
static inline int pr_capbset_read(int64_t cap) {
return prctl(PR_CAPBSET_READ, (long){cap});
}
static inline int pr_capbset_drop(int64_t cap) {
return prctl(PR_CAPBSET_DROP, (long){cap});
}
static inline int pr_set_child_subreaper(bool set) {
return prctl(PR_SET_CHILD_SUBREAPER, (long){set});
}
static inline int pr_get_child_subreaper(bool *isset)
{
int ret, x;
ret = prctl(PR_GET_CHILD_SUBREAPER, &x);
*isset = x;
return ret;
}
static inline int pr_set_dumpable(bool set) {
return prctl(PR_SET_DUMPABLE, (long){set});
}
static inline int pr_get_dumpable(void) {
return prctl(PR_GET_DUMPABLE);
}
static inline int pr_set_endian(int endianness) {
return prctl(PR_SET_ENDIAN, (long){endianness});
}
static inline int pr_get_endian(int *endianness) {
return prctl(PR_GET_ENDIAN, endianness);
}
static inline int pr_set_fp_mode(unsigned int mode) {
return prctl(PR_SET_FP_MODE, (unsigned long){mode});
}
static inline int pr_get_fp_mode(void) {
return prctl(PR_GET_FP_MODE);
}
static inline int pr_set_fpemu(int fpemu) {
return prctl(PR_SET_FPEMU, (long){fpemu});
}
static inline int pr_get_fpemu(int *fpemu) {
return prctl(PR_GET_FPEMU, fpemu);
}
static inline int pr_set_fpexec(int mode) {
return prctl(PR_SET_FPEXC, (long){mode});
}
static inline int pr_get_fpexec(int *mode) {
return prctl(PR_GET_FPEXC, mode);
}
static inline int pr_set_io_flusher(bool set) {
return prctl(PR_SET_IO_FLUSHER, (long){set}, 0L, 0L, 0L);
}
static inline int pr_get_io_flusher(void) {
return prctl(PR_GET_IO_FLUSHER, 0L, 0L, 0L, 0L);
}
static inline int pr_set_keepcaps(bool set) {
return prctl(PR_SET_KEEPCAPS, (long){set});
}
static inline int pr_get_keepcaps(void) {
return prctl(PR_GET_KEEPCAPS);
}
static inline int pr_mce_kill_clear(void) {
return prctl(PR_MCE_KILL, PR_MCE_KILL_CLEAR, 0L, 0L, 0L);
}
static inline int pr_mce_kill_set(int policy) {
return prctl(PR_MCE_KILL, PR_MCE_KILL_SET, (long){policy}, 0L, 0L);
}
static inline int pr_mce_kill_get(void) {
return prctl(PR_MCE_KILL_GET, 0L, 0L, 0L, 0L);
}
static inline int pr_set_mm_start_code(const void *addr) {
return prctl(PR_SET_MM, PR_SET_MM_START_CODE, addr, 0L, 0L);
}
static inline int pr_set_mm_end_code(const void *addr) {
return prctl(PR_SET_MM, PR_SET_MM_END_CODE, addr, 0L, 0L);
}
static inline int pr_set_mm_start_data(const void *addr) {
return prctl(PR_SET_MM, PR_SET_MM_START_DATA, addr, 0L, 0L);
}
static inline int pr_set_mm_end_data(const void *addr) {
return prctl(PR_SET_MM, PR_SET_MM_END_DATA, addr, 0L, 0L);
}
static inline int pr_set_mm_start_stack(const void *addr) {
return prctl(PR_SET_MM, PR_SET_MM_START_STACK, addr, 0L, 0L);
}
static inline int pr_set_mm_start_brk(const void *addr) {
return prctl(PR_SET_MM, PR_SET_MM_START_BRK, addr, 0L, 0L);
}
static inline int pr_set_mm_brk(const void *addr) {
return prctl(PR_SET_MM, PR_SET_MM_BRK, addr, 0L, 0L);
}
static inline int pr_set_mm_arg_start(const void *addr) {
return prctl(PR_SET_MM, PR_SET_MM_ARG_START, addr, 0L, 0L);
}
static inline int pr_set_mm_arg_end(const void *addr) {
return prctl(PR_SET_MM, PR_SET_MM_ARG_END, addr, 0L, 0L);
}
static inline int pr_set_mm_env_start(const void *addr) {
return prctl(PR_SET_MM, PR_SET_MM_ENV_START, addr, 0L, 0L);
}
static inline int pr_set_mm_env_end(const void *addr) {
return prctl(PR_SET_MM, PR_SET_MM_ENV_END, addr, 0L, 0L);
}
static inline int pr_set_mm_auxv(const void *addr, size_t size) {
return prctl(PR_SET_MM, PR_SET_MM_AUXV, addr, size, 0L);
}
static inline int pr_set_mm_exe_file(int fd) {
return prctl(PR_SET_MM, PR_SET_MM_EXE_FILE, (long){fd}, 0L, 0L);
}
static inline int pr_set_mm_map(struct prctl_mm_map *map)
{
return prctl(PR_SET_MM, PR_SET_MM_MAP, map,
sizeof(struct prctl_mm_map), 0L);
}
static inline int pr_set_mm_map_size(size_t *size)
{
int ret;
unsigned int x;
ret = prctl(PR_SET_MM, PR_SET_MM_MAP_SIZE, &x, 0L, 0L);
*size = x;
return ret;
}
LIBPRCTL_ATTR_STRING(3)
static inline int
pr_set_vma_anon_name(const void *addr, size_t size, const char *name)
{
return prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, addr, size, name);
}
LIBPRCTL_ATTR_DEPRECATED
static inline int pr_mpx_enable_management(void) {
return prctl(PR_MPX_ENABLE_MANAGEMENT, 0L, 0L, 0L, 0L);
}
LIBPRCTL_ATTR_DEPRECATED
static inline int pr_mpx_disable_management(void) {
return prctl(PR_MPX_DISABLE_MANAGEMENT, 0L, 0L, 0L, 0L);
}
LIBPRCTL_ATTR_STRING(1)
static inline int pr_set_name(const char *name) {
return prctl(PR_SET_NAME, name);
}
LIBPRCTL_ATTR_STRING(1)
static inline int pr_get_name(char name[16]) {
return prctl(PR_GET_NAME, name);
}
static inline int pr_set_no_new_privs(void) {
return prctl(PR_SET_NO_NEW_PRIVS, 1L, 0L, 0L, 0L);
}
static inline int pr_get_no_new_privs(void) {
return prctl(PR_GET_NO_NEW_PRIVS, 0L, 0L, 0L, 0L);
}
static inline int pr_pac_reset_keys(unsigned long keys) {
return prctl(PR_PAC_RESET_KEYS, keys, 0L, 0L, 0L);
}
static inline int pr_set_pdeathsig(int sig) {
return prctl(PR_SET_PDEATHSIG, (long){sig});
}
static inline int pr_get_pdeathsig(int *sig) {
return prctl(PR_GET_PDEATHSIG, sig);
}
static inline int pr_set_ptracer(pid_t pid) {
return prctl(PR_SET_PTRACER, (long){pid});
}
LIBPRCTL_ATTR_DEPRECATED
static inline int pr_set_seccomp_mode_strict(void) {
return prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
}
LIBPRCTL_ATTR_DEPRECATED
static inline int pr_set_seccomp_mode_filter(const struct sock_fprog *filter) {
return prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, filter);
}
static inline int pr_get_seccomp(void) {
return prctl(PR_GET_SECCOMP);
}
static inline int pr_set_securebits(unsigned int securebits) {
return prctl(PR_SET_SECUREBITS, (unsigned long){securebits});
}
static inline int pr_get_securebits(void) {
return prctl(PR_GET_SECUREBITS);
}
static inline int pr_get_speculation_ctrl(long misfeature) {
return prctl(PR_GET_SPECULATION_CTRL, misfeature, 0L, 0L, 0L);
}
static inline int pr_set_speculation_ctrl(long misfeature, int ctrl) {
return prctl(PR_SET_SPECULATION_CTRL, misfeature, (long){ctrl}, 0L, 0L);
}
static inline int pr_sve_set_vl(unsigned long val) {
return prctl(PR_SVE_SET_VL, val);
}
static inline int pr_sve_get_vl(void) {
return prctl(PR_SVE_GET_VL);
}
static inline int pr_sys_dispatch_on(size_t off, size_t size, int8_t *sw)
{
return prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON,
off, size, sw);
}
static inline int pr_sys_dispatch_off(void) {
return prctl(PR_SET_SYSCALL_USER_DISPATCH,PR_SYS_DISPATCH_OFF,0L,0L,0L);
}
static inline int pr_set_tagged_addr_ctrl(int mode) {
return prctl(PR_SET_TAGGED_ADDR_CTRL, (long){mode}, 0L, 0L, 0L);
}
static inline int pr_get_tagged_addr_ctrl(void) {
return prctl(PR_GET_TAGGED_ADDR_CTRL, 0L, 0L, 0L, 0L);
}
static inline int pr_task_perf_events_enable(void) {
return prctl(PR_TASK_PERF_EVENTS_ENABLE);
}
static inline int pr_task_perf_events_disable(void) {
return prctl(PR_TASK_PERF_EVENTS_DISABLE);
}
static inline int pr_set_thp_disable(bool set, unsigned int flags)
{
return prctl(PR_SET_THP_DISABLE, (long){set},
(unsigned long){flags}, 0L, 0L);
}
static inline int pr_get_thp_disable(void) {
return prctl(PR_GET_THP_DISABLE, 0L, 0L, 0L, 0L);
}
static inline int pr_get_tid_address(int **addrp) {
return prctl(PR_GET_TID_ADDRESS, addrp);
}
static inline int pr_set_timerslack(unsigned int slack) {
return prctl(PR_SET_TIMERSLACK, (unsigned long){slack});
}
static inline int pr_get_timerslack(void) {
return prctl(PR_GET_TIMERSLACK);
}
static inline int pr_set_timing(int mode) {
return prctl(PR_SET_TIMING, (long){mode});
}
static inline int pr_get_timing(void) {
return prctl(PR_GET_TIMING);
}
static inline int pr_set_tsc(int mode) {
return prctl(PR_SET_TSC, (long){mode});
}
static inline int pr_get_tsc(int *mode) {
return prctl(PR_GET_TSC, mode);
}
static inline int pr_set_unalign(unsigned int bits) {
return prctl(PR_SET_UNALIGN, (long){bits});
}
static inline int pr_get_unalign(unsigned int *bits) {
return prctl(PR_GET_UNALIGN, bits);
}
static inline int pr_get_auxv(void *auxv, size_t size) {
return prctl(PR_GET_AUXV, auxv, size, 0L, 0L);
}
static inline int pr_set_mdwe(unsigned int mask) {
return prctl(PR_SET_MDWE, mask, 0L, 0L, 0L);
}
static inline int pr_get_mdwe(void) {
return prctl(PR_GET_MDWE, 0L, 0L, 0L, 0L);
}
static inline int pr_riscv_set_icache_flush_ctx(int ctx, int scope) {
return prctl(PR_RISCV_SET_ICACHE_FLUSH_CTX, (long){ctx}, (long){scope});
}
static inline int pr_futex_hash_get_slots(void) {
return prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_GET_SLOTS);
}
static inline int pr_futex_hash_set_slots(size_t size) {
return prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_SET_SLOTS, size, 0L);
}
--
<https://www.alejandro-colomar.es>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20251203/d86d1044/attachment-0001.sig>
More information about the Libc-alpha
mailing list