[PATCH v7 3/4] Add system-wide tunables: Apply tunables part

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Thu May 28 16:16:32 GMT 2026



On 21/02/24 20:49, DJ Delorie wrote:
> Load ld.so.cache and fetch the tunables extension.  Apply
> those tunables to the current program.  We do not yet apply
> security policies.
> ---
>  elf/dl-cache.c    | 38 ++++++++++++++++++++++++++++
>  elf/dl-tunables.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++
>  elf/tunconf.h     |  3 +++
>  3 files changed, 104 insertions(+)
> 
> diff --git a/elf/dl-cache.c b/elf/dl-cache.c
> index 9d5fc05cd6..1aa64e4102 100644
> --- a/elf/dl-cache.c
> +++ b/elf/dl-cache.c
> @@ -27,6 +27,7 @@
>  #include <dl-isa-level.h>
>  #include <fcntl.h>
>  #include <sys/stat.h>
> +#include "tunconf.h"
>  
>  /* This is the starting address and the size of the mmap()ed file.  */
>  static struct cache_file *cache;
> @@ -606,3 +607,40 @@ _dl_unload_cache (void)
>       now.  */
>  }
>  #endif
> +
> +const struct tunable_header_cached *
> +_dl_load_cache_tunables (const char **data)
> +{
> +  struct cache_extension_all_loaded ext;
> +  struct tunable_header_cached *thc;
> +  struct tunable_entry_cached *tec;
> +  int count;
> +
> +  if (_dl_check_ldsocache_needs_loading ())
> +    _dl_maybe_load_ldsocache ();
> +
> +  if (cache_new)
> +    *data = (const char *) cache_new;
> +  else
> +    return NULL;
> +
> +  if (!cache_extension_load (cache_new, cache, cachesize, &ext))
> +    return NULL;
> +
> +  /* Validate length/contents here. */
> +  if (ext.sections[cache_extension_tag_tunables].size
> +      < sizeof(struct tunable_header_cached))
> +    return NULL;
> +
> +  thc = (struct tunable_header_cached *)
> +    ext.sections[cache_extension_tag_tunables].base;
> +  tec = thc->tunables;
> +  count = thc->num_tunables;
> +
> +  if (ext.sections[cache_extension_tag_tunables].base
> +      + ext.sections[cache_extension_tag_tunables].size
> +      < (void *) & tec[count])
> +    return NULL;
> +
> +  return thc;

Should we validate that all '*data + thc->tunables[t].{name,value}_offset' are
valid string here? It should avoid loading invalid/corrupted files.

> +}
> diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
> index 5c65e8b458..20e4056d74 100644
> --- a/elf/dl-tunables.c
> +++ b/elf/dl-tunables.c
> @@ -37,6 +37,7 @@
>  
>  #define TUNABLES_INTERNAL 1
>  #include "dl-tunables.h"
> +#include "tunconf.h"
>  
>  static char **
>  get_next_env (char **envp, char **name, char **val, char ***prev_envp)
> @@ -302,6 +303,68 @@ __tunables_init (char **envp)
>    if (MALLOC_DEFAULT_THP_PAGESIZE > 0)
>      TUNABLE_SET (glibc, malloc, hugetlb, 1);
>  
> +#if defined(SHARED) && defined (USE_LDCONFIG)
> +  const struct tunable_header_cached *thc;
> +  const char *td;
> +
> +  thc = _dl_load_cache_tunables (&td);
> +  if (thc != NULL)
> +    {
> +      for (int t = 0; t < thc->num_tunables; ++ t)
> +	{
> +	  const struct tunable_entry_cached *tec = &( thc->tunables[t] );
> +	  int tid = tec->tunable_id;
> +	  const char *name = td + tec->name_offset;
> +	  const char *value = td + tec->value_offset;
> +
> +	  /* Check that we have the correct tunable, and search by
> +	     name if needed.  We rely on order of operations here to
> +	     avoid mis-indexing tunables[].  */
> +	  if (tid < 0 || tid >= tunables_list_size
> +	      || strcmp (name, tunable_list[tid].name) != 0)
> +	    {
> +	      /* It does not, search by name instead.  */
> +	      tid = -1;
> +	      for (int i = 0; i < tunables_list_size; i++)
> +		{
> +		  if (strcmp (name, tunable_list[i].name) == 0)
> +		    {
> +		      tid = i;
> +		      break;
> +		    }
> +		}
> +	      if (tid == -1)
> +		continue;
> +	    }
> +	  /* At this point, TID is valid for the tunable we want.  See
> +	     if the parsed type matches the desired type.  */
> +
> +	  if (tunable_list[tid].type.type_code == TUNABLE_TYPE_STRING)
> +	    {
> +	      /* This is a memory leak but there's no easy way around
> +		 it, as the mapping will go away.  */
> +	      tunable_list[tid].val.strval.str = __strdup (value);
> +	      tunable_list[tid].val.strval.len = strlen (value);
> +	    }
> +	  else
> +	    {
> +	      tunable_val_t tval;
> +	      if (tec->flags & TUNCONF_FLAG_PARSED)
> +		{
> +		  tval.numval = tec->parsed_value;
> +		  do_tunable_update_val (& tunable_list[tid],
> +					 &tval, NULL, NULL);
> +		}
> +	      else
> +		{
> +		  tunable_initialize (& tunable_list[tid],
> +				      value, strlen (value));
> +		}
> +	    }
> +	}
> +    }
> +#endif /* defined(SHARED) && defined (USE_LDCONFIG) */
> +
>    /* Ignore tunables for AT_SECURE programs.  */
>    if (__libc_enable_secure)
>      return;
> diff --git a/elf/tunconf.h b/elf/tunconf.h
> index 7578605c5a..9551119167 100644
> --- a/elf/tunconf.h
> +++ b/elf/tunconf.h
> @@ -38,3 +38,6 @@ void parse_tunconf (const char *filename, char *opt_chroot);
>  struct tunable_header_cached * get_tunconf_ext (uint32_t str_offset);
>  #define TUNCONF_SIZE(thc_p) (sizeof(struct tunable_header_cached)		\
>  		     + thc_p->num_tunables * sizeof (struct tunable_entry_cached))
> +
> +extern const struct tunable_header_cached *
> +_dl_load_cache_tunables (const char **data);



More information about the Libc-alpha mailing list