diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2024-01-04 20:19:39 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2024-01-05 05:49:49 -0800 |
commit | 848746e88ec2aa22e8dea25f2110e2b2c59c712e (patch) | |
tree | 33db2fa3d1b4dc68fec06609cb6bacc4d680a38e /sysdeps/x86 | |
parent | 520b1df08de68a3de328b65a25b86300a7ddf512 (diff) | |
download | glibc-848746e88ec2aa22e8dea25f2110e2b2c59c712e.zip glibc-848746e88ec2aa22e8dea25f2110e2b2c59c712e.tar.gz glibc-848746e88ec2aa22e8dea25f2110e2b2c59c712e.tar.bz2 |
elf: Add ELF_DYNAMIC_AFTER_RELOC to rewrite PLT
Add ELF_DYNAMIC_AFTER_RELOC to allow target specific processing after
relocation.
For x86-64, add
#define DT_X86_64_PLT (DT_LOPROC + 0)
#define DT_X86_64_PLTSZ (DT_LOPROC + 1)
#define DT_X86_64_PLTENT (DT_LOPROC + 3)
1. DT_X86_64_PLT: The address of the procedure linkage table.
2. DT_X86_64_PLTSZ: The total size, in bytes, of the procedure linkage
table.
3. DT_X86_64_PLTENT: The size, in bytes, of a procedure linkage table
entry.
With the r_addend field of the R_X86_64_JUMP_SLOT relocation set to the
memory offset of the indirect branch instruction.
Define ELF_DYNAMIC_AFTER_RELOC for x86-64 to rewrite the PLT section
with direct branch after relocation when the lazy binding is disabled.
PLT rewrite is disabled by default since SELinux may disallow modifying
code pages and ld.so can't detect it in all cases. Use
$ export GLIBC_TUNABLES=glibc.cpu.plt_rewrite=1
to enable PLT rewrite with 32-bit direct jump at run-time or
$ export GLIBC_TUNABLES=glibc.cpu.plt_rewrite=2
to enable PLT rewrite with 32-bit direct jump and on APX processors with
64-bit absolute jump at run-time.
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
Diffstat (limited to 'sysdeps/x86')
-rw-r--r-- | sysdeps/x86/cet-control.h | 12 | ||||
-rw-r--r-- | sysdeps/x86/cpu-features.c | 21 | ||||
-rw-r--r-- | sysdeps/x86/dl-procruntime.c | 1 | ||||
-rw-r--r-- | sysdeps/x86/dl-tunables.list | 5 |
4 files changed, 38 insertions, 1 deletions
diff --git a/sysdeps/x86/cet-control.h b/sysdeps/x86/cet-control.h index a45d59b..f09f193 100644 --- a/sysdeps/x86/cet-control.h +++ b/sysdeps/x86/cet-control.h @@ -32,10 +32,22 @@ enum dl_x86_cet_control cet_permissive }; +/* PLT rewrite control. */ +enum dl_plt_rewrite_control +{ + /* No PLT rewrite. */ + plt_rewrite_none, + /* Rewrite PLT with JMP at run-time. */ + plt_rewrite_jmp, + /* Rewrite PLT with JMP and JMPABS at run-time. */ + plt_rewrite_jmpabs +}; + struct dl_x86_feature_control { enum dl_x86_cet_control ibt : 2; enum dl_x86_cet_control shstk : 2; + enum dl_plt_rewrite_control plt_rewrite : 2; }; #endif /* cet-control.h */ diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c index f193ea7..9ca307f 100644 --- a/sysdeps/x86/cpu-features.c +++ b/sysdeps/x86/cpu-features.c @@ -27,6 +27,22 @@ extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) attribute_hidden; +#ifdef SHARED +static void +TUNABLE_CALLBACK (set_plt_rewrite) (tunable_val_t *valp) +{ + if (valp->numval != 0) + { + /* Use JMPABS only on APX processors. */ + const struct cpu_features *cpu_features = __get_cpu_features (); + GL (dl_x86_feature_control).plt_rewrite + = ((valp->numval > 1 && CPU_FEATURE_PRESENT_P (cpu_features, APX_F)) + ? plt_rewrite_jmpabs + : plt_rewrite_jmp); + } +} +#endif + #ifdef __LP64__ static void TUNABLE_CALLBACK (set_prefer_map_32bit_exec) (tunable_val_t *valp) @@ -1108,7 +1124,10 @@ no_cpuid: TUNABLE_CALLBACK (set_x86_shstk)); #endif -#ifndef SHARED +#ifdef SHARED + TUNABLE_GET (plt_rewrite, tunable_val_t *, + TUNABLE_CALLBACK (set_plt_rewrite)); +#else /* NB: In libc.a, call init_cacheinfo. */ init_cacheinfo (); #endif diff --git a/sysdeps/x86/dl-procruntime.c b/sysdeps/x86/dl-procruntime.c index 4d25d9f..15b3d0d 100644 --- a/sysdeps/x86/dl-procruntime.c +++ b/sysdeps/x86/dl-procruntime.c @@ -67,6 +67,7 @@ PROCINFO_CLASS struct dl_x86_feature_control _dl_x86_feature_control = { .ibt = DEFAULT_DL_X86_CET_CONTROL, .shstk = DEFAULT_DL_X86_CET_CONTROL, + .plt_rewrite = plt_rewrite_none, } # endif # if !defined SHARED || defined PROCINFO_DECL diff --git a/sysdeps/x86/dl-tunables.list b/sysdeps/x86/dl-tunables.list index 147a727..7d82da0 100644 --- a/sysdeps/x86/dl-tunables.list +++ b/sysdeps/x86/dl-tunables.list @@ -66,5 +66,10 @@ glibc { x86_shared_cache_size { type: SIZE_T } + plt_rewrite { + type: INT_32 + minval: 0 + maxval: 2 + } } } |