Message ID | xna5lq2er9.fsf@greed.delorie.com |
---|---|
State | New |
Headers | show |
Series | [1/3] Add system-wide tunables: ldconfig part | expand |
On 19/04/24 00: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. So the idea is to have GLIBC_TUNABLES to override system-wide tunables and later handle if the tunable can be override or not? > --- > elf/dl-cache.c | 24 +++++++++++++ > elf/dl-tunables.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++ > elf/tunconf.h | 3 ++ > 3 files changed, 112 insertions(+) > > diff --git a/elf/dl-cache.c b/elf/dl-cache.c > index d90278889d..7ccb96d1ca 100644 > --- a/elf/dl-cache.c > +++ b/elf/dl-cache.c > @@ -28,6 +28,7 @@ > #include <dl-isa-level.h> > #include <sys/types.h> > #include <sys/stat.h> > +#include "tunconf.h" > > #ifndef _DL_PLATFORMS_COUNT > # define _DL_PLATFORMS_COUNT 0 > @@ -616,3 +617,26 @@ _dl_unload_cache (void) > now. */ > } > #endif > + > +const struct tunable_header_cached * > +_dl_load_cache_tunables (const char **data) > +{ > + struct cache_extension_all_loaded ext; > + > + /* This loads the cache (temporary). */ > + if (_dl_check_ldsocache_needs_loading ()) > + _dl_maybe_load_ldsocache (); > + > + if (cache_new && cache_new != (void *) -1) > + *data = (const char *) cache_new; > + else > + *data = (const char *) &cache->libs[cache->nlibs]; > + > + 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; > + return ext.sections[cache_extension_tag_tunables].base; > +} > diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c > index d3ccd2ecd4..5ecddccff6 100644 > --- a/elf/dl-tunables.c > +++ b/elf/dl-tunables.c > @@ -35,6 +35,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) > @@ -264,6 +265,31 @@ parse_tunables (const char *valstring) > tunables[i].t->name); > } > > +/* We need this functionality before we load the real strcmp function. */ > +static int > +dl_strcmp(const char *s1, const char *s2) > +{ > + while (*s1 && *s2) > + { > + if (*s1 != *s2) > + return *s1 - *s2; > + ++s1; > + ++s2; > + } > + return *s1 - *s2; > +} > +static int > +dl_strlen(const char *s) > +{ > + int len = 0; > + while (*s) > + { > + ++s; > + ++len; > + } > + return len; > +} > + > /* Initialize the tunables list from the environment. For now we only use the > ENV_ALIAS to find values. Later we will also use the tunable names to find > values. */ > @@ -273,6 +299,65 @@ __tunables_init (char **envp) > char *envname = NULL; > char *envval = NULL; > char **prev_envp = envp; > + 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 > + || dl_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 (dl_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. */ > + 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, dl_strlen(value)); > + } > + } > + } > + } > > /* Ignore tunables for AT_SECURE programs. */ > if (__libc_enable_secure) > diff --git a/elf/tunconf.h b/elf/tunconf.h > index a6c5f0dd9a..623fb7546d 100644 > --- a/elf/tunconf.h > +++ b/elf/tunconf.h > @@ -38,3 +38,6 @@ void parse_tunconf (const char *filename, int do_chroot, 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);
diff --git a/elf/dl-cache.c b/elf/dl-cache.c index d90278889d..7ccb96d1ca 100644 --- a/elf/dl-cache.c +++ b/elf/dl-cache.c @@ -28,6 +28,7 @@ #include <dl-isa-level.h> #include <sys/types.h> #include <sys/stat.h> +#include "tunconf.h" #ifndef _DL_PLATFORMS_COUNT # define _DL_PLATFORMS_COUNT 0 @@ -616,3 +617,26 @@ _dl_unload_cache (void) now. */ } #endif + +const struct tunable_header_cached * +_dl_load_cache_tunables (const char **data) +{ + struct cache_extension_all_loaded ext; + + /* This loads the cache (temporary). */ + if (_dl_check_ldsocache_needs_loading ()) + _dl_maybe_load_ldsocache (); + + if (cache_new && cache_new != (void *) -1) + *data = (const char *) cache_new; + else + *data = (const char *) &cache->libs[cache->nlibs]; + + 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; + return ext.sections[cache_extension_tag_tunables].base; +} diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c index d3ccd2ecd4..5ecddccff6 100644 --- a/elf/dl-tunables.c +++ b/elf/dl-tunables.c @@ -35,6 +35,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) @@ -264,6 +265,31 @@ parse_tunables (const char *valstring) tunables[i].t->name); } +/* We need this functionality before we load the real strcmp function. */ +static int +dl_strcmp(const char *s1, const char *s2) +{ + while (*s1 && *s2) + { + if (*s1 != *s2) + return *s1 - *s2; + ++s1; + ++s2; + } + return *s1 - *s2; +} +static int +dl_strlen(const char *s) +{ + int len = 0; + while (*s) + { + ++s; + ++len; + } + return len; +} + /* Initialize the tunables list from the environment. For now we only use the ENV_ALIAS to find values. Later we will also use the tunable names to find values. */ @@ -273,6 +299,65 @@ __tunables_init (char **envp) char *envname = NULL; char *envval = NULL; char **prev_envp = envp; + 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 + || dl_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 (dl_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. */ + 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, dl_strlen(value)); + } + } + } + } /* Ignore tunables for AT_SECURE programs. */ if (__libc_enable_secure) diff --git a/elf/tunconf.h b/elf/tunconf.h index a6c5f0dd9a..623fb7546d 100644 --- a/elf/tunconf.h +++ b/elf/tunconf.h @@ -38,3 +38,6 @@ void parse_tunconf (const char *filename, int do_chroot, 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);