elf: Initialize tunables_env_alias with loop to avoid memset

Message ID 20240907170454.1660578-1-jesse.huang@sifive.com
State Dropped
Headers
Series elf: Initialize tunables_env_alias with loop to avoid memset |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
redhat-pt-bot/TryBot-32bit success Build for i686
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Test passed

Commit Message

Jesse Huang Sept. 7, 2024, 5:04 p.m. UTC
  In static binaries, __tunables_init is called before the IREL relocation
is performed. This causes a problem where IFUNC for memset is provided,
because the initializer list here is translated to a call to memset,
which gets redirected to the PLT.

At the moment, all of the GOT entries still points to the top of the PLT,
thus the call first jump to the entry of memset in PLT, then jump to the
first entry of PLT, that finally leads to a infinite loop.

Fixed by using a for loop to initialize the array.
---
 elf/dl-tunables.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
  

Comments

H.J. Lu Sept. 7, 2024, 5:33 p.m. UTC | #1
On Sat, Sep 7, 2024 at 10:05 AM Jesse Huang <jesse.huang@sifive.com> wrote:
>
> In static binaries, __tunables_init is called before the IREL relocation
> is performed. This causes a problem where IFUNC for memset is provided,
> because the initializer list here is translated to a call to memset,
> which gets redirected to the PLT.

Why doesn't dl-symbol-redir-ifunc.h work for you?

> At the moment, all of the GOT entries still points to the top of the PLT,
> thus the call first jump to the entry of memset in PLT, then jump to the
> first entry of PLT, that finally leads to a infinite loop.
>
> Fixed by using a for loop to initialize the array.
> ---
>  elf/dl-tunables.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
> index 147cc4cf23..33f88ccf55 100644
> --- a/elf/dl-tunables.c
> +++ b/elf/dl-tunables.c
> @@ -301,7 +301,9 @@ __tunables_init (char **envp)
>      return;
>
>    enum { tunable_num_env_alias = array_length (tunable_env_alias_list) };
> -  struct tunable_toset_t tunables_env_alias[tunable_num_env_alias] = { 0 };
> +  struct tunable_toset_t tunables_env_alias[tunable_num_env_alias];
> +  for (int i = 0; i < tunable_num_env_alias; i++)
> +    tunables_env_alias[i] = (struct tunable_toset_t) { NULL, NULL, 0 };
>
>    while ((envp = get_next_env (envp, &envname, &envval, &prev_envp)) != NULL)
>      {
> --
> 2.46.0
>
  
Jesse Huang Sept. 9, 2024, 9:55 a.m. UTC | #2
I was completely unaware of the file and it indeed solved our problem.
Thank you for pointing it out!


--
Jesse Huang

H.J. Lu <hjl.tools@gmail.com> 於 2024年9月8日 週日 上午1:33寫道:

> On Sat, Sep 7, 2024 at 10:05 AM Jesse Huang <jesse.huang@sifive.com>
> wrote:
> >
> > In static binaries, __tunables_init is called before the IREL relocation
> > is performed. This causes a problem where IFUNC for memset is provided,
> > because the initializer list here is translated to a call to memset,
> > which gets redirected to the PLT.
>
> Why doesn't dl-symbol-redir-ifunc.h work for you?
>
> > At the moment, all of the GOT entries still points to the top of the PLT,
> > thus the call first jump to the entry of memset in PLT, then jump to the
> > first entry of PLT, that finally leads to a infinite loop.
> >
> > Fixed by using a for loop to initialize the array.
> > ---
> >  elf/dl-tunables.c | 4 +++-
> >  1 file changed, 3 insertions(+), 1 deletion(-)
> >
> > diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
> > index 147cc4cf23..33f88ccf55 100644
> > --- a/elf/dl-tunables.c
> > +++ b/elf/dl-tunables.c
> > @@ -301,7 +301,9 @@ __tunables_init (char **envp)
> >      return;
> >
> >    enum { tunable_num_env_alias = array_length (tunable_env_alias_list)
> };
> > -  struct tunable_toset_t tunables_env_alias[tunable_num_env_alias] = {
> 0 };
> > +  struct tunable_toset_t tunables_env_alias[tunable_num_env_alias];
> > +  for (int i = 0; i < tunable_num_env_alias; i++)
> > +    tunables_env_alias[i] = (struct tunable_toset_t) { NULL, NULL, 0 };
> >
> >    while ((envp = get_next_env (envp, &envname, &envval, &prev_envp)) !=
> NULL)
> >      {
> > --
> > 2.46.0
> >
>
>
> --
> H.J.
>
  

Patch

diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
index 147cc4cf23..33f88ccf55 100644
--- a/elf/dl-tunables.c
+++ b/elf/dl-tunables.c
@@ -301,7 +301,9 @@  __tunables_init (char **envp)
     return;
 
   enum { tunable_num_env_alias = array_length (tunable_env_alias_list) };
-  struct tunable_toset_t tunables_env_alias[tunable_num_env_alias] = { 0 };
+  struct tunable_toset_t tunables_env_alias[tunable_num_env_alias];
+  for (int i = 0; i < tunable_num_env_alias; i++)
+    tunables_env_alias[i] = (struct tunable_toset_t) { NULL, NULL, 0 };
 
   while ((envp = get_next_env (envp, &envname, &envval, &prev_envp)) != NULL)
     {