Message ID | 20240307144425.2075652-1-josimmon@redhat.com |
---|---|
State | New |
Headers | show |
Series | elf/rtld: Count skipped environment variables for enable_secure | expand |
On 3/7/24 09:44, Joe Simmons-Talbott wrote: > When using the glibc.rtld.enable_secure tunable we need to keep track of > the count of environment variables we skip due to __libc_enable_secure > being set and adjust the auxv section of the stack. This fixes an > assertion when running ld.so directly with glibc.rtld.enable_secure set. > > elf/rtld.c:1324 assert (auxv == sp + 1); > --- > elf/rtld.c | 26 ++++++++++++++++++-------- > 1 file changed, 18 insertions(+), 8 deletions(-) > > diff --git a/elf/rtld.c b/elf/rtld.c > index ac4bb23652..089863a8fa 100644 > --- a/elf/rtld.c > +++ b/elf/rtld.c > @@ -155,7 +155,7 @@ static void dl_main_state_init (struct dl_main_state *state); > Since all of them start with `LD_' we are a bit smarter while finding > all the entries. */ > extern char **_environ attribute_hidden; > -static void process_envvars (struct dl_main_state *state); > +static int process_envvars (struct dl_main_state *state); > > int _dl_argc attribute_relro attribute_hidden; > char **_dl_argv attribute_relro = NULL; > @@ -1287,7 +1287,7 @@ rtld_setup_main_map (struct link_map *main_map) > _dl_argv and _dl_argc accordingly. Those arguments are removed from > argv here. */ > static void > -_dl_start_args_adjust (int skip_args) > +_dl_start_args_adjust (int skip_args, int skip_env) > { > void **sp = (void **) (_dl_argv - skip_args - 1); > void **p = sp + skip_args; > @@ -1319,7 +1319,7 @@ _dl_start_args_adjust (int skip_args) > while (*p != NULL); > > #ifdef HAVE_AUX_VECTOR > - void **auxv = (void **) GLRO(dl_auxv) - skip_args; > + void **auxv = (void **) GLRO(dl_auxv) - skip_args - skip_env; > GLRO(dl_auxv) = (ElfW(auxv_t) *) auxv; /* Aliasing violation. */ > assert (auxv == sp + 1); > > @@ -1350,6 +1350,7 @@ dl_main (const ElfW(Phdr) *phdr, > unsigned int i; > bool rtld_is_main = false; > void *tcbp = NULL; > + int skip_env = 0; > > struct dl_main_state state; > dl_main_state_init (&state); > @@ -1363,7 +1364,7 @@ dl_main (const ElfW(Phdr) *phdr, > #endif > > /* Process the environment variable which control the behaviour. */ > - process_envvars (&state); > + skip_env = process_envvars (&state); > > #ifndef HAVE_INLINED_SYSCALLS > /* Set up a flag which tells we are just starting. */ > @@ -1628,7 +1629,7 @@ dl_main (const ElfW(Phdr) *phdr, > _dl_argv[0] = argv0; > > /* Adjust arguments for the application entry point. */ > - _dl_start_args_adjust (_dl_argv - orig_argv); > + _dl_start_args_adjust (_dl_argv - orig_argv, skip_env); > } > else > { > @@ -2532,11 +2533,12 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n"); > } > } > > -static void > +static int > process_envvars_secure (struct dl_main_state *state) > { > char **runp = _environ; > char *envline; > + int skip_env = 0; > > while ((envline = _dl_next_ld_env_entry (&runp)) != NULL) > { > @@ -2578,6 +2580,9 @@ process_envvars_secure (struct dl_main_state *state) > const char *nextp = UNSECURE_ENVVARS; > do > { > + if (getenv (nextp) != NULL) > + skip_env++; Please add a detailed comment here about why the skip count is adjusted based on the validity of the *next* pointer being non-NULL. > + > unsetenv (nextp); > nextp = strchr (nextp, '\0') + 1; > } > @@ -2590,6 +2595,8 @@ process_envvars_secure (struct dl_main_state *state) > || state->mode != rtld_mode_normal > || state->version_info) > _exit (5); > + > + return skip_env; > } > > static void > @@ -2743,13 +2750,16 @@ process_envvars_default (struct dl_main_state *state) > } > } > > -static void > +static int > process_envvars (struct dl_main_state *state) > { > + int skip_env = 0; > if (__glibc_unlikely (__libc_enable_secure)) > - process_envvars_secure (state); > + skip_env += process_envvars_secure (state); > else > process_envvars_default (state); > + > + return skip_env; > } > > #if HP_TIMING_INLINE
On Thu, Mar 7, 2024 at 3:41 PM Carlos O'Donell <carlos@redhat.com> wrote: > > On 3/7/24 09:44, Joe Simmons-Talbott wrote: > > When using the glibc.rtld.enable_secure tunable we need to keep track of > > the count of environment variables we skip due to __libc_enable_secure > > being set and adjust the auxv section of the stack. This fixes an > > assertion when running ld.so directly with glibc.rtld.enable_secure set. > > > > elf/rtld.c:1324 assert (auxv == sp + 1); > > --- > > elf/rtld.c | 26 ++++++++++++++++++-------- > > 1 file changed, 18 insertions(+), 8 deletions(-) > > > > diff --git a/elf/rtld.c b/elf/rtld.c > > index ac4bb23652..089863a8fa 100644 > > --- a/elf/rtld.c > > +++ b/elf/rtld.c > > @@ -155,7 +155,7 @@ static void dl_main_state_init (struct dl_main_state *state); > > Since all of them start with `LD_' we are a bit smarter while finding > > all the entries. */ > > extern char **_environ attribute_hidden; > > -static void process_envvars (struct dl_main_state *state); > > +static int process_envvars (struct dl_main_state *state); > > > > int _dl_argc attribute_relro attribute_hidden; > > char **_dl_argv attribute_relro = NULL; > > @@ -1287,7 +1287,7 @@ rtld_setup_main_map (struct link_map *main_map) > > _dl_argv and _dl_argc accordingly. Those arguments are removed from > > argv here. */ > > static void > > -_dl_start_args_adjust (int skip_args) > > +_dl_start_args_adjust (int skip_args, int skip_env) > > { > > void **sp = (void **) (_dl_argv - skip_args - 1); > > void **p = sp + skip_args; > > @@ -1319,7 +1319,7 @@ _dl_start_args_adjust (int skip_args) > > while (*p != NULL); > > > > #ifdef HAVE_AUX_VECTOR > > - void **auxv = (void **) GLRO(dl_auxv) - skip_args; > > + void **auxv = (void **) GLRO(dl_auxv) - skip_args - skip_env; > > GLRO(dl_auxv) = (ElfW(auxv_t) *) auxv; /* Aliasing violation. */ > > assert (auxv == sp + 1); > > > > @@ -1350,6 +1350,7 @@ dl_main (const ElfW(Phdr) *phdr, > > unsigned int i; > > bool rtld_is_main = false; > > void *tcbp = NULL; > > + int skip_env = 0; > > > > struct dl_main_state state; > > dl_main_state_init (&state); > > @@ -1363,7 +1364,7 @@ dl_main (const ElfW(Phdr) *phdr, > > #endif > > > > /* Process the environment variable which control the behaviour. */ > > - process_envvars (&state); > > + skip_env = process_envvars (&state); > > > > #ifndef HAVE_INLINED_SYSCALLS > > /* Set up a flag which tells we are just starting. */ > > @@ -1628,7 +1629,7 @@ dl_main (const ElfW(Phdr) *phdr, > > _dl_argv[0] = argv0; > > > > /* Adjust arguments for the application entry point. */ > > - _dl_start_args_adjust (_dl_argv - orig_argv); > > + _dl_start_args_adjust (_dl_argv - orig_argv, skip_env); > > } > > else > > { > > @@ -2532,11 +2533,12 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n"); > > } > > } > > > > -static void > > +static int > > process_envvars_secure (struct dl_main_state *state) > > { > > char **runp = _environ; > > char *envline; > > + int skip_env = 0; > > > > while ((envline = _dl_next_ld_env_entry (&runp)) != NULL) > > { > > @@ -2578,6 +2580,9 @@ process_envvars_secure (struct dl_main_state *state) > > const char *nextp = UNSECURE_ENVVARS; > > do > > { > > + if (getenv (nextp) != NULL) > > + skip_env++; > > > Please add a detailed comment here about why the skip count is adjusted > based on the validity of the *next* pointer being non-NULL. > I added a comment and posted a v2. Thanks, Joe > > + > > unsetenv (nextp); > > nextp = strchr (nextp, '\0') + 1; > > } > > @@ -2590,6 +2595,8 @@ process_envvars_secure (struct dl_main_state *state) > > || state->mode != rtld_mode_normal > > || state->version_info) > > _exit (5); > > + > > + return skip_env; > > } > > > > static void > > @@ -2743,13 +2750,16 @@ process_envvars_default (struct dl_main_state *state) > > } > > } > > > > -static void > > +static int > > process_envvars (struct dl_main_state *state) > > { > > + int skip_env = 0; > > if (__glibc_unlikely (__libc_enable_secure)) > > - process_envvars_secure (state); > > + skip_env += process_envvars_secure (state); > > else > > process_envvars_default (state); > > + > > + return skip_env; > > } > > > > #if HP_TIMING_INLINE > > -- > Cheers, > Carlos. >
diff --git a/elf/rtld.c b/elf/rtld.c index ac4bb23652..089863a8fa 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -155,7 +155,7 @@ static void dl_main_state_init (struct dl_main_state *state); Since all of them start with `LD_' we are a bit smarter while finding all the entries. */ extern char **_environ attribute_hidden; -static void process_envvars (struct dl_main_state *state); +static int process_envvars (struct dl_main_state *state); int _dl_argc attribute_relro attribute_hidden; char **_dl_argv attribute_relro = NULL; @@ -1287,7 +1287,7 @@ rtld_setup_main_map (struct link_map *main_map) _dl_argv and _dl_argc accordingly. Those arguments are removed from argv here. */ static void -_dl_start_args_adjust (int skip_args) +_dl_start_args_adjust (int skip_args, int skip_env) { void **sp = (void **) (_dl_argv - skip_args - 1); void **p = sp + skip_args; @@ -1319,7 +1319,7 @@ _dl_start_args_adjust (int skip_args) while (*p != NULL); #ifdef HAVE_AUX_VECTOR - void **auxv = (void **) GLRO(dl_auxv) - skip_args; + void **auxv = (void **) GLRO(dl_auxv) - skip_args - skip_env; GLRO(dl_auxv) = (ElfW(auxv_t) *) auxv; /* Aliasing violation. */ assert (auxv == sp + 1); @@ -1350,6 +1350,7 @@ dl_main (const ElfW(Phdr) *phdr, unsigned int i; bool rtld_is_main = false; void *tcbp = NULL; + int skip_env = 0; struct dl_main_state state; dl_main_state_init (&state); @@ -1363,7 +1364,7 @@ dl_main (const ElfW(Phdr) *phdr, #endif /* Process the environment variable which control the behaviour. */ - process_envvars (&state); + skip_env = process_envvars (&state); #ifndef HAVE_INLINED_SYSCALLS /* Set up a flag which tells we are just starting. */ @@ -1628,7 +1629,7 @@ dl_main (const ElfW(Phdr) *phdr, _dl_argv[0] = argv0; /* Adjust arguments for the application entry point. */ - _dl_start_args_adjust (_dl_argv - orig_argv); + _dl_start_args_adjust (_dl_argv - orig_argv, skip_env); } else { @@ -2532,11 +2533,12 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n"); } } -static void +static int process_envvars_secure (struct dl_main_state *state) { char **runp = _environ; char *envline; + int skip_env = 0; while ((envline = _dl_next_ld_env_entry (&runp)) != NULL) { @@ -2578,6 +2580,9 @@ process_envvars_secure (struct dl_main_state *state) const char *nextp = UNSECURE_ENVVARS; do { + if (getenv (nextp) != NULL) + skip_env++; + unsetenv (nextp); nextp = strchr (nextp, '\0') + 1; } @@ -2590,6 +2595,8 @@ process_envvars_secure (struct dl_main_state *state) || state->mode != rtld_mode_normal || state->version_info) _exit (5); + + return skip_env; } static void @@ -2743,13 +2750,16 @@ process_envvars_default (struct dl_main_state *state) } } -static void +static int process_envvars (struct dl_main_state *state) { + int skip_env = 0; if (__glibc_unlikely (__libc_enable_secure)) - process_envvars_secure (state); + skip_env += process_envvars_secure (state); else process_envvars_default (state); + + return skip_env; } #if HP_TIMING_INLINE