]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
rtld/arm: fix initial-exec (IE) thread-local storage relocation
authorR. Christian McDonald <rcm@rcm.sh>
Fri, 3 Nov 2023 12:56:58 +0000 (13:56 +0100)
committerKristof Provost <kp@FreeBSD.org>
Fri, 3 Nov 2023 21:43:40 +0000 (22:43 +0100)
commit98fd69f0090da73d9d0451bd769d7752468284c6
tree6b2fdb20e3d9d5766cd4ce0e52803a6382660b19
parent6c3ae01cc75afdd575f54289b2879a7c98d55bf6
rtld/arm: fix initial-exec (IE) thread-local storage relocation

net/frr[89] revealed an interesting edge-case on arm when dynamically
linking a shared library that declares more than one static TLS variable
with at least one  using the "initial-exec" TLS model. In the case
of frr[89], this library was libfrr.so which essentially does the
following:

#include <stdio.h>

#include "lib.h"

static __thread int *a
__attribute__((tls_model("initial-exec")));

void lib_test()
{
static __thread int b = -1;

printf("&a = %p\n", &a);
printf(" a = %p\n", a);

printf("\n");

printf("&b = %p\n", &b);
printf(" b = %d\n", b);
}

Allocates a file scoped `static __thread` pointer with
tls_model("initial-exec") and later a block scoped TLS int. Notice in
the above minimal reproducer, `b == -1`. The relocation process does
the wrong thing and ends up pointing both `a` and `b` at the same place
in memory.

The output of the above in the broken state is:

&a = 0x4009c018
 a = 0xffffffff

&b = 0x4009c018
 b = -1

With the patch applied, the output becomes:

&a = 0x4009c01c
 a = 0x0

&b = 0x4009c018
 b = -1

Reviewed by: kib
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D42415/
libexec/rtld-elf/arm/reloc.c