diff --git a/sysdeps/unix/sysv/linux/x86_64/dl-plt-rewrite.h b/sysdeps/unix/sysv/linux/x86_64/dl-plt-rewrite.h new file mode 100644 index 00000000000..ad637df9302 --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86_64/dl-plt-rewrite.h @@ -0,0 +1,43 @@ +/* PLT rewrite helper function. Linux/x86-64 version. + Copyright (C) 2024 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +static __always_inline bool +dl_plt_rewrite_supported (void) +{ + /* PLT rewrite is enabled. Check if mprotect works. */ + void *plt = (void *) INTERNAL_SYSCALL_CALL (mmap, NULL, 4096, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + if (__glibc_unlikely (plt == MAP_FAILED)) + return false; + + /* Touch the PROT_READ | PROT_WRITE page. */ + *(int32_t *) plt = 1; + + /* If the updated PROT_READ | PROT_WRITE page can be changed to + PROT_EXEC | PROT_READ, rewrite PLT. */ + bool status = (INTERNAL_SYSCALL_CALL (mprotect, plt, 4096, + PROT_EXEC | PROT_READ) == 0); + + INTERNAL_SYSCALL_CALL (munmap, plt, 4096); + + return status; +} diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c index 46bdaffbc26..25e6622a79b 100644 --- a/sysdeps/x86/cpu-features.c +++ b/sysdeps/x86/cpu-features.c @@ -28,10 +28,16 @@ extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) attribute_hidden; #if defined SHARED && defined __x86_64__ +# include + static void TUNABLE_CALLBACK (set_plt_rewrite) (tunable_val_t *valp) { - if (valp->numval != 0) + /* We must be careful about where we put the call to + dl_plt_rewrite_supported() since it may generate + spurious SELinux log entries. It should only be + attempted if the user requested a PLT rewrite. */ + if (valp->numval != 0 && dl_plt_rewrite_supported ()) { /* Use JMPABS only on APX processors. */ const struct cpu_features *cpu_features = __get_cpu_features (); diff --git a/sysdeps/x86_64/dl-plt-rewrite.h b/sysdeps/x86_64/dl-plt-rewrite.h new file mode 100644 index 00000000000..cab6fe75eaa --- /dev/null +++ b/sysdeps/x86_64/dl-plt-rewrite.h @@ -0,0 +1,25 @@ +/* PLT rewrite helper function. x86-64 version. + Copyright (C) 2024 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +static __always_inline bool +dl_plt_rewrite_supported (void) +{ + return true; +}