[PATCH v2 1/1] Add system-wide tunables: implement overridability

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Mon Jul 6 21:06:14 GMT 2026



On 02/07/26 12:19, DJ Delorie wrote:
> 
> Andreas Schwab <schwab@suse.de> writes:
>> That proves to be pretty fragile.
> 
> How about this?
> 
>     Add system-wide tunables: implement overridability
>     
>     Implement the overridability/nonoverridability flags
>     for tunables.
> 
> diff --git a/elf/Makefile b/elf/Makefile
> index 789c504da9..7b00a0b931 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -347,7 +347,11 @@ tests-static += \
>    tst-tls9-static \
>    # tests-static
>  
> -tst-tunconf1-TUNABLES-only = glibc.malloc.tcache_count=5
> +tst-tunconf1-TUNABLES-only = \
> +   glibc.malloc.tcache_count=5 \
> +  :glibc.malloc.perturb=41 \
> +  :glibc.malloc.mmap_threshold=10002 \
> +  :glibc.malloc.trim_threshold=10002

No need to add ':' for each tunable, the TUNABLES rule already handles it.

The rest looks ok.

>  
>  static-dlopen-environment = \
>    LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx)dlfcn
> diff --git a/elf/dl-tunable-types.h b/elf/dl-tunable-types.h
> index f421c01c26..3506eee512 100644
> --- a/elf/dl-tunable-types.h
> +++ b/elf/dl-tunable-types.h
> @@ -65,6 +65,8 @@ struct _tunable
>    tunable_val_t val;			/* The value.  */
>    bool initialized;			/* Flag to indicate that the tunable is
>  					   initialized.  */
> +  bool locked;				/* If set, modifications are not
> +					   allowed.  */
>    /* Compatibility elements.  */
>    const char env_alias[TUNABLE_ALIAS_MAX]; /* The compatibility environment
>  					   variable name.  */
> diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
> index 197d940d38..d19c2358c1 100644
> --- a/elf/dl-tunables.c
> +++ b/elf/dl-tunables.c
> @@ -72,6 +72,9 @@ do_tunable_update_val (tunable_t *cur, const tunable_val_t *valp,
>  {
>    tunable_num_t val, min, max;
>  
> +  if (cur->locked)
> +    return;
> +
>    switch (cur->type.type_code)
>      {
>      case TUNABLE_TYPE_STRING:
> @@ -409,6 +412,12 @@ __tunables_init (char **envp, char **argv)
>  	    goto skip_due_to_filter;
>  	  }
>  
> +	  /* If the tunable is set here, any previously set
> +	     overridability flag is discarded.  We need to reset the
> +	     overridability flag here so we can change the tunable,
> +	     and may set it later if this tunable also locks it.  */
> +	  tunable_list[tid].locked = false;
> +
>  	  /* See if the parsed type matches the desired type.  */
>  	  if (tunable_list[tid].type.type_code == TUNABLE_TYPE_STRING)
>  	    {
> @@ -435,6 +444,12 @@ __tunables_init (char **envp, char **argv)
>  		}
>  	    }
>  
> +	  /* The overriability flag only applies to tunables
> +	     which aren't filtered out.  */
> +	  if ((tec->flags & TUNCONF_FLAG_OVERRIDABLE)
> +	      == TUNCONF_OVERRIDE_DENY)
> +	    tunable_list[tid].locked = true;
> +
>  	skip_due_to_filter:;
>  	}
>      }
> diff --git a/elf/tst-tunconf1.c b/elf/tst-tunconf1.c
> index c95a7cb8ba..74f596d913 100644
> --- a/elf/tst-tunconf1.c
> +++ b/elf/tst-tunconf1.c
> @@ -26,10 +26,30 @@ do_test (void)
>  {
>    size_t tcache_count = TUNABLE_GET_FULL (glibc, malloc, tcache_count, size_t, NULL);
>    size_t tcache_max = TUNABLE_GET_FULL (glibc, malloc, tcache_max, size_t, NULL);
> +  size_t perturb = TUNABLE_GET_FULL (glibc, malloc, perturb, size_t, NULL);
> +  size_t mmap_threshold = TUNABLE_GET_FULL (glibc, malloc, mmap_threshold, size_t, NULL);
> +  size_t trim_threshold = TUNABLE_GET_FULL (glibc, malloc, trim_threshold, size_t, NULL);
> +
>    printf("tcache count is %ld (should be 5, from env)\n", (long)tcache_count);
>    TEST_COMPARE ((long)tcache_count, 5);
>    printf("tcache max is %ld (should be 4, from /etc)\n", (long)tcache_max);
>    TEST_COMPARE ((long)tcache_max, 4);
> +
> +  /* This is set by the environment but blocked by the config.  */
> +  printf("perturb is %ld (should be 42, from /etc)\n",
> +	 (long)perturb);
> +  TEST_COMPARE ((long)perturb, 42);
> +
> +  /* This is blocked by the general config, enabled by filter, set in env.  */
> +  printf("mmap_threshold is %ld (should be 10002, from env)\n",
> +	 (long)mmap_threshold);
> +  TEST_COMPARE ((long)mmap_threshold, 10002);
> +
> +  /* This is allowed by the general config, blocked by filter, set in env.  */
> +  printf("trim_threshold is %ld (should be 10001, from filter)\n",
> +	 (long)trim_threshold);
> +  TEST_COMPARE ((long)trim_threshold, 10001);
> +
>    return 0;
>  }
>  
> diff --git a/elf/tst-tunconf1.root/etc/tunables.conf b/elf/tst-tunconf1.root/etc/tunables.conf
> index f373a67902..f708a8fce4 100644
> --- a/elf/tst-tunconf1.root/etc/tunables.conf
> +++ b/elf/tst-tunconf1.root/etc/tunables.conf
> @@ -8,7 +8,15 @@ $glibc.test_unsecure=1
>  # These are checked inside the test case
>  glibc.malloc.tcache_max=6
>  $glibc.malloc.tcache_count=3
> +
> +-glibc.malloc.perturb=42
> +-glibc.malloc.mmap_threshold=10000
> +overridable glibc.malloc.trim_threshold=10000
> +
>  [proc:/bin/ls]
>  glibc.malloc.tcache_max=7
> +
>  [proc:tst-tunconf1]
>  glibc.malloc.tcache_max=4
> ++glibc.malloc.mmap_threshold=10001
> +nonoverridable glibc.malloc.trim_threshold=10001
> diff --git a/elf/tunconf.c b/elf/tunconf.c
> index a5ca755abd..c27b50b1de 100644
> --- a/elf/tunconf.c
> +++ b/elf/tunconf.c
> @@ -194,34 +194,40 @@ add_tunable (char *line, const char *filename, int lineno)
>    /* Parse modifiers.  */
>    while (*line)
>      {
> -      if (strncmp (line, "overridable ", 13) == 0)
> +      int prefix_len;
> +
> +#define TUN_PREFIX(s)				\
> +      prefix_len = sizeof(s) - 1,			\
> +	strncmp (line, s " ", prefix_len + 1) == 0
> +
> +      if (TUN_PREFIX("overridable"))
>  	{
>  	  top = TOP_ALLOW;
>  	  /* The line++ below skips the space.  */
> -	  line += 12;
> +	  line += prefix_len;
>  	}
> -      else if (strncmp (line, "nonoverridable ", 16) == 0)
> +      else if (TUN_PREFIX ("nonoverridable"))
>  	{
>  	  top = TOP_DENY;
> -	  line += 15;
> +	  line += prefix_len;
>  	}
> -      else if (strncmp (line, "onlysecure ", 11) == 0)
> +      else if (TUN_PREFIX ("onlysecure"))
>  	{
>  	  exclude_nonsecure = 1;
>  	  exclude_secure = 0;
> -	  line += 10;
> +	  line += prefix_len;
>  	}
> -      else if (strncmp (line, "nonsecure ", 10) == 0)
> +      else if (TUN_PREFIX ("nonsecure"))
>  	{
>  	  exclude_secure = 1;
>  	  exclude_nonsecure = 0;
> -	  line += 9;
> +	  line += prefix_len;
>  	}
> -      else if (strncmp (line, "anysecure ", 10) == 0)
> +      else if (TUN_PREFIX ("anysecure"))
>  	{
>  	  exclude_secure = 0;
>  	  exclude_nonsecure = 0;
> -	  line += 9;
> +	  line += prefix_len;
>  	}
>        else switch (*line)
>  	{
> diff --git a/scripts/gen-tunables.awk b/scripts/gen-tunables.awk
> index 5d34075c16..7c832303db 100644
> --- a/scripts/gen-tunables.awk
> +++ b/scripts/gen-tunables.awk
> @@ -169,7 +169,7 @@ END {
>      n = indices[2];
>      m = indices[3];
>      printf ("  {TUNABLE_NAME_S(%s, %s, %s)", t, n, m)
> -    printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, {%s}, false, %s},\n",
> +    printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, {%s}, false, false, %s},\n",
>  	    types[t,n,m], minvals[t,n,m], maxvals[t,n,m], default_val[t,n,m],
>  	    default_val[t,n,m], env_alias[t,n,m]);
>    }
> 



More information about the Libc-alpha mailing list