diff --git a/libexec/rtld-elf/aarch64/reloc.c b/libexec/rtld-elf/aarch64/reloc.c --- a/libexec/rtld-elf/aarch64/reloc.c +++ b/libexec/rtld-elf/aarch64/reloc.c @@ -521,7 +521,8 @@ * use. */ tls_static_space = tls_last_offset + tls_last_size + - RTLD_STATIC_TLS_EXTRA; + (ld_optional_static_tls ? ld_optional_static_tls : + RTLD_STATIC_TLS_EXTRA); _tcb_set(allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN)); } diff --git a/libexec/rtld-elf/amd64/reloc.c b/libexec/rtld-elf/amd64/reloc.c --- a/libexec/rtld-elf/amd64/reloc.c +++ b/libexec/rtld-elf/amd64/reloc.c @@ -527,7 +527,9 @@ * offset allocated so far and adding a bit for dynamic * modules to use. */ - tls_static_space = tls_last_offset + RTLD_STATIC_TLS_EXTRA; + tls_static_space = tls_last_offset + + (ld_optional_static_tls ? ld_optional_static_tls : + RTLD_STATIC_TLS_EXTRA); addr = allocate_tls(objs, 0, TLS_TCB_SIZE, TLS_TCB_ALIGN); diff --git a/libexec/rtld-elf/arm/reloc.c b/libexec/rtld-elf/arm/reloc.c --- a/libexec/rtld-elf/arm/reloc.c +++ b/libexec/rtld-elf/arm/reloc.c @@ -454,7 +454,9 @@ * use. */ - tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA; + tls_static_space = tls_last_offset + tls_last_size + + (ld_optional_static_tls ? ld_optional_static_tls : + RTLD_STATIC_TLS_EXTRA); _tcb_set(allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN)); } diff --git a/libexec/rtld-elf/i386/reloc.c b/libexec/rtld-elf/i386/reloc.c --- a/libexec/rtld-elf/i386/reloc.c +++ b/libexec/rtld-elf/i386/reloc.c @@ -510,7 +510,9 @@ * offset allocated so far and adding a bit for dynamic modules to * use. */ - tls_static_space = tls_last_offset + RTLD_STATIC_TLS_EXTRA; + tls_static_space = tls_last_offset + + (ld_optional_static_tls ? ld_optional_static_tls : + RTLD_STATIC_TLS_EXTRA); tls = allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN); _tcb_set(tls); } diff --git a/libexec/rtld-elf/powerpc/reloc.c b/libexec/rtld-elf/powerpc/reloc.c --- a/libexec/rtld-elf/powerpc/reloc.c +++ b/libexec/rtld-elf/powerpc/reloc.c @@ -817,7 +817,9 @@ * use. */ - tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA; + tls_static_space = tls_last_offset + tls_last_size + + (ld_optional_static_tls ? ld_optional_static_tls : + RTLD_STATIC_TLS_EXTRA); _tcb_set(allocate_tls(list, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN)); } diff --git a/libexec/rtld-elf/powerpc64/reloc.c b/libexec/rtld-elf/powerpc64/reloc.c --- a/libexec/rtld-elf/powerpc64/reloc.c +++ b/libexec/rtld-elf/powerpc64/reloc.c @@ -714,7 +714,9 @@ * use. */ - tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA; + tls_static_space = tls_last_offset + tls_last_size + + (ld_optional_static_tls ? ld_optional_static_tls : + RTLD_STATIC_TLS_EXTRA); _tcb_set(allocate_tls(list, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN)); } diff --git a/libexec/rtld-elf/riscv/reloc.c b/libexec/rtld-elf/riscv/reloc.c --- a/libexec/rtld-elf/riscv/reloc.c +++ b/libexec/rtld-elf/riscv/reloc.c @@ -392,7 +392,8 @@ * use. */ tls_static_space = tls_last_offset + tls_last_size + - RTLD_STATIC_TLS_EXTRA; + (ld_optional_static_tls ? ld_optional_static_tls : + RTLD_STATIC_TLS_EXTRA); _tcb_set(allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN)); } diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -50,6 +50,7 @@ extern size_t tls_static_space; extern Elf_Addr tls_dtv_generation; extern int tls_max_index; +extern size_t ld_optional_static_tls; extern int npagesizes; extern size_t *pagesizes; diff --git a/libexec/rtld-elf/rtld.1 b/libexec/rtld-elf/rtld.1 --- a/libexec/rtld-elf/rtld.1 +++ b/libexec/rtld-elf/rtld.1 @@ -26,7 +26,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd November 10, 2022 +.Dd September 29, 2023 .Dt RTLD 1 .Os .Sh NAME @@ -320,6 +320,11 @@ .Nm to dump content of the aux vector to standard output, before passing control to any user code. +.It Ev LD_OPTIONAL_STATIC_TLS +If the variable is specified and has a numeric value, +.Nm +will set the size of the static TLS space to the specified number of +bytes. The minimum value that can be specified is \'128\'. .El .Sh DIRECT EXECUTION MODE .Nm diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -225,6 +225,7 @@ static Obj_Entry obj_rtld; /* The dynamic linker shared object */ static unsigned int obj_count; /* Number of objects in obj_list */ static unsigned int obj_loads; /* Number of loads of objects (gen count) */ +size_t ld_optional_static_tls; /* Optional static TLS space (bytes) */ static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */ STAILQ_HEAD_INITIALIZER(list_global); @@ -365,6 +366,7 @@ LD_TRACE_LOADED_OBJECTS_FMT2, LD_TRACE_LOADED_OBJECTS_ALL, LD_SHOW_AUXV, + LD_OPTIONAL_STATIC_TLS, }; struct ld_env_var_desc { @@ -398,6 +400,7 @@ LD_ENV_DESC(TRACE_LOADED_OBJECTS_FMT2, false), LD_ENV_DESC(TRACE_LOADED_OBJECTS_ALL, false), LD_ENV_DESC(SHOW_AUXV, false), + LD_ENV_DESC(OPTIONAL_STATIC_TLS, false), }; static const char * @@ -515,7 +518,7 @@ struct stat st; Elf_Addr *argcp; char **argv, **env, **envp, *kexecpath; - const char *argv0, *binpath, *library_path_rpath; + const char *argv0, *binpath, *library_path_rpath, *optional_static_tls; struct ld_env_var_desc *lvd; caddr_t imgentry; char buf[MAXPATHLEN]; @@ -738,9 +741,20 @@ else ld_library_path_rpath = false; } + optional_static_tls = ld_get_env_var(LD_OPTIONAL_STATIC_TLS); + if (optional_static_tls != NULL && optional_static_tls[0] != '\0') { + ld_optional_static_tls = parse_integer(optional_static_tls); + if (ld_optional_static_tls < RTLD_STATIC_TLS_EXTRA || + ld_optional_static_tls > SIZE_T_MAX) { + _rtld_error("invalid optional static TLS setting: %s", + optional_static_tls); + rtld_die(); + } + } dangerous_ld_env = libmap_disable || libmap_override != NULL || ld_library_path != NULL || ld_preload != NULL || - ld_elf_hints_path != NULL || ld_loadfltr || !ld_dynamic_weak; + ld_elf_hints_path != NULL || ld_loadfltr || !ld_dynamic_weak || + ld_optional_static_tls; ld_tracing = ld_get_env_var(LD_TRACE_LOADED_OBJECTS); ld_utrace = ld_get_env_var(LD_UTRACE);