rtld: introduce STATIC_TLS_EXTRA

The new STATIC_TLS_EXTRA variable provides a means for applications
to increases the size of the extra static TLS space allocated by
rtld beyond the default of '128'. This extra static TLS space is used
for objects loaded with dlopen.

The value specified in the variable must be no less than the default
value and no greater than the maximum allowed value for size_t type.

If an invalid value is specified, rtld will ignore it and just use
the default value.

The rtld(1) man page is updated to document this new option.

Obtained from:  Juniper Networks, Inc.
Differential Revision:  https://reviews.freebsd.org/D42025
This commit is contained in:
Stephen J. Kiernan 2023-10-29 17:13:10 -04:00
parent f969fb53d8
commit 95335dd3c1
10 changed files with 35 additions and 12 deletions

View file

@ -521,7 +521,7 @@ allocate_initial_tls(Obj_Entry *objs)
* use.
*/
tls_static_space = tls_last_offset + tls_last_size +
RTLD_STATIC_TLS_EXTRA;
ld_static_tls_extra;
_tcb_set(allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN));
}

View file

@ -527,7 +527,7 @@ allocate_initial_tls(Obj_Entry *objs)
* 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_static_tls_extra;
addr = allocate_tls(objs, 0, TLS_TCB_SIZE, TLS_TCB_ALIGN);

View file

@ -454,7 +454,8 @@ allocate_initial_tls(Obj_Entry *objs)
* use.
*/
tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
tls_static_space = tls_last_offset + tls_last_size +
ld_static_tls_extra;
_tcb_set(allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN));
}

View file

@ -510,7 +510,7 @@ allocate_initial_tls(Obj_Entry *objs)
* 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_static_tls_extra;
tls = allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN);
_tcb_set(tls);
}

View file

@ -817,7 +817,8 @@ allocate_initial_tls(Obj_Entry *list)
* use.
*/
tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
tls_static_space = tls_last_offset + tls_last_size +
ld_static_tls_extra;
_tcb_set(allocate_tls(list, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN));
}

View file

@ -714,7 +714,8 @@ allocate_initial_tls(Obj_Entry *list)
* use.
*/
tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
tls_static_space = tls_last_offset + tls_last_size +
ld_static_tls_extra;
_tcb_set(allocate_tls(list, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN));
}

View file

@ -392,7 +392,7 @@ allocate_initial_tls(Obj_Entry *objs)
* use.
*/
tls_static_space = tls_last_offset + tls_last_size +
RTLD_STATIC_TLS_EXTRA;
ld_static_tls_extra;
_tcb_set(allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN));
}

View file

@ -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 October 29, 2023
.Dt RTLD 1
.Os
.Sh NAME
@ -320,6 +320,12 @@ If set, causes
.Nm
to dump content of the aux vector to standard output, before passing
control to any user code.
.It Ev LD_STATIC_TLS_EXTRA
If the variable is specified and has a numeric value,
.Nm
will set the size of the static TLS extra space to the specified number
of bytes. The static TLS extra space is used when loading objects with
dlopen. The minimum value that can be specified is \'128\'.
.El
.Sh DIRECT EXECUTION MODE
.Nm

View file

@ -225,6 +225,8 @@ static Obj_Entry *obj_main; /* The main program shared object */
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_static_tls_extra = /* Static TLS extra space (bytes) */
RTLD_STATIC_TLS_EXTRA;
static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */
STAILQ_HEAD_INITIALIZER(list_global);
@ -365,6 +367,7 @@ enum {
LD_TRACE_LOADED_OBJECTS_FMT2,
LD_TRACE_LOADED_OBJECTS_ALL,
LD_SHOW_AUXV,
LD_STATIC_TLS_EXTRA,
};
struct ld_env_var_desc {
@ -398,6 +401,7 @@ static struct ld_env_var_desc ld_env_vars[] = {
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(STATIC_TLS_EXTRA, false),
};
static const char *
@ -515,7 +519,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
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, *static_tls_extra;
struct ld_env_var_desc *lvd;
caddr_t imgentry;
char buf[MAXPATHLEN];
@ -738,9 +742,16 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
else
ld_library_path_rpath = false;
}
static_tls_extra = ld_get_env_var(LD_STATIC_TLS_EXTRA);
if (static_tls_extra != NULL && static_tls_extra[0] != '\0') {
sz = parse_integer(static_tls_extra);
if (sz >= RTLD_STATIC_TLS_EXTRA && sz <= SIZE_T_MAX)
ld_static_tls_extra = sz;
}
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 ||
static_tls_extra != NULL;
ld_tracing = ld_get_env_var(LD_TRACE_LOADED_OBJECTS);
ld_utrace = ld_get_env_var(LD_UTRACE);
@ -6105,13 +6116,15 @@ parse_args(char* argv[], int argc, bool *use_pathp, int *fdp,
"Env prefix %s\n"
"Default hint file %s\n"
"Hint file %s\n"
"libmap file %s\n",
"libmap file %s\n"
"Optional static TLS size %zd bytes\n",
machine,
__FreeBSD_version, ld_standard_library_path,
gethints(false),
ld_env_prefix, ld_elf_hints_default,
ld_elf_hints_path,
ld_path_libmap_conf);
ld_path_libmap_conf,
ld_static_tls_extra);
_exit(0);
} else {
_rtld_error("Invalid argument: '%s'", arg);

View file

@ -50,6 +50,7 @@ extern size_t tls_last_size;
extern size_t tls_static_space;
extern Elf_Addr tls_dtv_generation;
extern int tls_max_index;
extern size_t ld_static_tls_extra;
extern int npagesizes;
extern size_t *pagesizes;