Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Fix interactions of initial-exec TLS model and dlopen



details:   https://anonhg.NetBSD.org/src/rev/56ca9e0e8534
branches:  trunk
changeset: 376190:56ca9e0e8534
user:      joerg <joerg%NetBSD.org@localhost>
date:      Sun Jun 04 01:24:56 2023 +0000

description:
Fix interactions of initial-exec TLS model and dlopen

(1) If an initial-exec relocation was used for a non-local symbol
(i.e. the definition of the symbol is in a different DSO), the
computation of the static TLS offset used the wrong DSO.
This would effectively mean the wrong address was computed
(PR toolchain/50277, PR pkg/57445).

Fix this by forcing the computation of the correct DSO (the one defining
the symbol).

This code uses __UNCONST to avoid the vast interface changes for this
special case.

(2) If symbols from a DSO loaded via dlopen are used with both
global-dynamic/local-dynamic and initial-exec relocations AND
a initial-exec relocation was resolved first in a thread, a split brain
situation could exist where the dynamic relocations would use one memory
block (separate allocation) and the initial-exec relocations the static
per-thread TLS space.

(3) If the initial-exec relocation in (2) is seen after any thread has
already used a GD/LD allocation, bail out. Since IE relocations are used
only in the GOT, this will prevent the dlopen. This is a bit more
aggressive than necessary, but a full blown reference counting doesn't
seem to be justified.

diffstat:

 libexec/ld.elf_so/README.TLS               |   5 +-
 libexec/ld.elf_so/arch/aarch64/mdreloc.c   |  10 +++---
 libexec/ld.elf_so/arch/alpha/alpha_reloc.c |   8 ++--
 libexec/ld.elf_so/arch/arm/mdreloc.c       |   8 ++--
 libexec/ld.elf_so/arch/hppa/hppa_reloc.c   |   7 ++-
 libexec/ld.elf_so/arch/i386/mdreloc.c      |  12 +++---
 libexec/ld.elf_so/arch/m68k/mdreloc.c      |  10 ++---
 libexec/ld.elf_so/arch/mips/mips_reloc.c   |  10 ++---
 libexec/ld.elf_so/arch/or1k/mdreloc.c      |  10 ++---
 libexec/ld.elf_so/arch/powerpc/ppc_reloc.c |   7 ++-
 libexec/ld.elf_so/arch/riscv/mdreloc.c     |   8 ++--
 libexec/ld.elf_so/arch/sh3/mdreloc.c       |   8 ++--
 libexec/ld.elf_so/arch/sparc/mdreloc.c     |  10 +++---
 libexec/ld.elf_so/arch/sparc64/mdreloc.c   |  10 +++---
 libexec/ld.elf_so/arch/x86_64/mdreloc.c    |   8 ++--
 libexec/ld.elf_so/map_object.c             |   6 +-
 libexec/ld.elf_so/rtld.h                   |   7 ++-
 libexec/ld.elf_so/tls.c                    |  34 ++++++++++++++------
 tests/libexec/ld.elf_so/t_tls_extern.c     |  50 ++++++++++-------------------
 19 files changed, 112 insertions(+), 116 deletions(-)

diffs (truncated from 840 to 300 lines):

diff -r 1cea1107a5b9 -r 56ca9e0e8534 libexec/ld.elf_so/README.TLS
--- a/libexec/ld.elf_so/README.TLS      Sat Jun 03 21:44:08 2023 +0000
+++ b/libexec/ld.elf_so/README.TLS      Sun Jun 04 01:24:56 2023 +0000
@@ -43,9 +43,10 @@ This is normally def->st_value + rela->r
 
 (c) R_TYPE(TLS_TPOFF): Static TLS offset.  The code has to check whether
 the static TLS offset for this module has been allocated
-(defobj->tls_done) and otherwise call _rtld_tls_offset_allocate().  This
+(defobj->tls_static) and otherwise call _rtld_tls_offset_allocate().  This
 may fail if no static space is available and the object has been pulled
-in via dlopen(3).
+in via dlopen(3). It can also fail if the TLS area has already been used
+via a global-dynamic allocation.
 
 For TLS Variant I, this is typically:
 
diff -r 1cea1107a5b9 -r 56ca9e0e8534 libexec/ld.elf_so/arch/aarch64/mdreloc.c
--- a/libexec/ld.elf_so/arch/aarch64/mdreloc.c  Sat Jun 03 21:44:08 2023 +0000
+++ b/libexec/ld.elf_so/arch/aarch64/mdreloc.c  Sun Jun 04 01:24:56 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.17 2022/12/03 09:10:40 skrll Exp $ */
+/* $NetBSD: mdreloc.c,v 1.18 2023/06/04 01:24:56 joerg Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.17 2022/12/03 09:10:40 skrll Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.18 2023/06/04 01:24:56 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -157,7 +157,7 @@ static void
        }
        offs += rela->r_addend;
 
-       if (defobj->tls_done) {
+       if (defobj->tls_static) {
                /* Variable is in initially allocated TLS segment */
                where[0] = (Elf_Addr)_rtld_tlsdesc_static;
                where[1] = defobj->tlsoffset + offs +
@@ -299,8 +299,8 @@ int
                        break;
 
                case R_TLS_TYPE(TLS_TPREL):
-                       if (!defobj->tls_done &&
-                           _rtld_tls_offset_allocate(obj))
+                       if (!defobj->tls_static &&
+                           _rtld_tls_offset_allocate(__UNCONST(defobj)))
                                return -1;
 
                        *where = (Elf_Addr)(def->st_value + defobj->tlsoffset +
diff -r 1cea1107a5b9 -r 56ca9e0e8534 libexec/ld.elf_so/arch/alpha/alpha_reloc.c
--- a/libexec/ld.elf_so/arch/alpha/alpha_reloc.c        Sat Jun 03 21:44:08 2023 +0000
+++ b/libexec/ld.elf_so/arch/alpha/alpha_reloc.c        Sun Jun 04 01:24:56 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: alpha_reloc.c,v 1.43 2017/08/10 19:03:26 joerg Exp $   */
+/*     $NetBSD: alpha_reloc.c,v 1.44 2023/06/04 01:24:57 joerg Exp $   */
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -62,7 +62,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: alpha_reloc.c,v 1.43 2017/08/10 19:03:26 joerg Exp $");
+__RCSID("$NetBSD: alpha_reloc.c,v 1.44 2023/06/04 01:24:57 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -280,8 +280,8 @@ int
                        break;
 
                case R_TYPE(TPREL64):
-                       if (!defobj->tls_done &&
-                           _rtld_tls_offset_allocate(obj))
+                       if (!defobj->tls_static &&
+                           _rtld_tls_offset_allocate(__UNCONST(defobj)))
                                return -1;
 
                        tmp = (Elf64_Addr)(def->st_value +
diff -r 1cea1107a5b9 -r 56ca9e0e8534 libexec/ld.elf_so/arch/arm/mdreloc.c
--- a/libexec/ld.elf_so/arch/arm/mdreloc.c      Sat Jun 03 21:44:08 2023 +0000
+++ b/libexec/ld.elf_so/arch/arm/mdreloc.c      Sun Jun 04 01:24:56 2023 +0000
@@ -1,8 +1,8 @@
-/*     $NetBSD: mdreloc.c,v 1.45 2020/06/16 21:02:20 joerg Exp $       */
+/*     $NetBSD: mdreloc.c,v 1.46 2023/06/04 01:24:57 joerg Exp $       */
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.45 2020/06/16 21:02:20 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.46 2023/06/04 01:24:57 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -228,8 +228,8 @@ int
                        break;
 
                case R_TYPE(TLS_TPOFF32):
-                       if (!defobj->tls_done &&
-                           _rtld_tls_offset_allocate(obj))
+                       if (!defobj->tls_static &&
+                           _rtld_tls_offset_allocate(__UNCONST(defobj)))
                                return -1;
 
                        if (__predict_true(RELOC_ALIGNED_P(where)))
diff -r 1cea1107a5b9 -r 56ca9e0e8534 libexec/ld.elf_so/arch/hppa/hppa_reloc.c
--- a/libexec/ld.elf_so/arch/hppa/hppa_reloc.c  Sat Jun 03 21:44:08 2023 +0000
+++ b/libexec/ld.elf_so/arch/hppa/hppa_reloc.c  Sun Jun 04 01:24:56 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: hppa_reloc.c,v 1.49 2022/05/30 17:06:34 skrll Exp $    */
+/*     $NetBSD: hppa_reloc.c,v 1.50 2023/06/04 01:24:57 joerg Exp $    */
 
 /*-
  * Copyright (c) 2002, 2004 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: hppa_reloc.c,v 1.49 2022/05/30 17:06:34 skrll Exp $");
+__RCSID("$NetBSD: hppa_reloc.c,v 1.50 2023/06/04 01:24:57 joerg Exp $");
 #endif /* not lint */
 
 #include <stdlib.h>
@@ -553,7 +553,8 @@ int
                        break;
 
                case R_TYPE(TLS_TPREL32):
-                       if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
+                       if (!defobj->tls_static &&
+                           _rtld_tls_offset_allocate(__UNCONST(defobj)))
                                return -1;
 
                        *where = (Elf_Addr)(defobj->tlsoffset + def->st_value +
diff -r 1cea1107a5b9 -r 56ca9e0e8534 libexec/ld.elf_so/arch/i386/mdreloc.c
--- a/libexec/ld.elf_so/arch/i386/mdreloc.c     Sat Jun 03 21:44:08 2023 +0000
+++ b/libexec/ld.elf_so/arch/i386/mdreloc.c     Sun Jun 04 01:24:56 2023 +0000
@@ -1,8 +1,8 @@
-/*     $NetBSD: mdreloc.c,v 1.41 2018/04/03 21:10:27 joerg Exp $       */
+/*     $NetBSD: mdreloc.c,v 1.42 2023/06/04 01:24:57 joerg Exp $       */
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.41 2018/04/03 21:10:27 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.42 2023/06/04 01:24:57 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -147,8 +147,8 @@ int
                        break;
 
                case R_TYPE(TLS_TPOFF):
-                       if (!defobj->tls_done &&
-                           _rtld_tls_offset_allocate(obj))
+                       if (!defobj->tls_static &&
+                           _rtld_tls_offset_allocate(__UNCONST(defobj)))
                                return -1;
 
                        *where += (Elf_Addr)(def->st_value - defobj->tlsoffset);
@@ -159,8 +159,8 @@ int
                        break;
 
                case R_TYPE(TLS_TPOFF32):
-                       if (!defobj->tls_done &&
-                           _rtld_tls_offset_allocate(obj))
+                       if (!defobj->tls_static &&
+                           _rtld_tls_offset_allocate(__UNCONST(defobj)))
                                return -1;
 
                        *where += (Elf_Addr)(defobj->tlsoffset - def->st_value);
diff -r 1cea1107a5b9 -r 56ca9e0e8534 libexec/ld.elf_so/arch/m68k/mdreloc.c
--- a/libexec/ld.elf_so/arch/m68k/mdreloc.c     Sat Jun 03 21:44:08 2023 +0000
+++ b/libexec/ld.elf_so/arch/m68k/mdreloc.c     Sun Jun 04 01:24:56 2023 +0000
@@ -1,8 +1,8 @@
-/*     $NetBSD: mdreloc.c,v 1.33 2017/08/10 19:03:26 joerg Exp $       */
+/*     $NetBSD: mdreloc.c,v 1.34 2023/06/04 01:24:57 joerg Exp $       */
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.33 2017/08/10 19:03:26 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.34 2023/06/04 01:24:57 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -142,9 +142,6 @@ int
                        break;
 
                case R_TYPE(TLS_DTPREL32):
-                       if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
-                               return -1;
-
                        *where = (Elf_Addr)(def->st_value + rela->r_addend
                            - TLS_DTV_OFFSET);
                        rdbg(("DTPREL32 %s in %s --> %p in %s",
@@ -153,7 +150,8 @@ int
                        break;
 
                case R_TYPE(TLS_TPREL32):
-                       if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
+                       if (!defobj->tls_static &&
+                           _rtld_tls_offset_allocate(__UNCONST(defobj)))
                                return -1;
 
                        *where = (Elf_Addr)(def->st_value + rela->r_addend
diff -r 1cea1107a5b9 -r 56ca9e0e8534 libexec/ld.elf_so/arch/mips/mips_reloc.c
--- a/libexec/ld.elf_so/arch/mips/mips_reloc.c  Sat Jun 03 21:44:08 2023 +0000
+++ b/libexec/ld.elf_so/arch/mips/mips_reloc.c  Sun Jun 04 01:24:56 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mips_reloc.c,v 1.74 2021/03/06 20:11:08 christos Exp $ */
+/*     $NetBSD: mips_reloc.c,v 1.75 2023/06/04 01:24:57 joerg Exp $    */
 
 /*
  * Copyright 1997 Michael L. Hitch <mhitch%montana.edu@localhost>
@@ -30,7 +30,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mips_reloc.c,v 1.74 2021/03/06 20:11:08 christos Exp $");
+__RCSID("$NetBSD: mips_reloc.c,v 1.75 2023/06/04 01:24:57 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -429,9 +429,6 @@ int
                        Elf_Addr old = load_ptr(where, ELFSIZE / 8);
                        Elf_Addr val = old;
 
-                       if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
-                               return -1;
-
                        val += (Elf_Addr)def->st_value - TLS_DTV_OFFSET;
                        store_ptr(where, val, ELFSIZE / 8);
 
@@ -450,7 +447,8 @@ int
                        Elf_Addr old = load_ptr(where, ELFSIZE / 8);
                        Elf_Addr val = old;
 
-                       if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
+                       if (!defobj->tls_static &&
+                           _rtld_tls_offset_allocate(__UNCONST(defobj)))
                                return -1;
 
                        val += (Elf_Addr)(def->st_value + defobj->tlsoffset
diff -r 1cea1107a5b9 -r 56ca9e0e8534 libexec/ld.elf_so/arch/or1k/mdreloc.c
--- a/libexec/ld.elf_so/arch/or1k/mdreloc.c     Sat Jun 03 21:44:08 2023 +0000
+++ b/libexec/ld.elf_so/arch/or1k/mdreloc.c     Sun Jun 04 01:24:56 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mdreloc.c,v 1.3 2017/08/10 19:03:26 joerg Exp $        */
+/*     $NetBSD: mdreloc.c,v 1.4 2023/06/04 01:24:57 joerg Exp $        */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.3 2017/08/10 19:03:26 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.4 2023/06/04 01:24:57 joerg Exp $");
 #endif /* not lint */
 
 #include <stdarg.h>
@@ -171,9 +171,6 @@ int
                        break;
 
                case R_TYPE(TLS_DTPOFF):
-                       if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
-                               return -1;
-
                        *where = (Elf_Addr)(def->st_value + rela->r_addend
                            - TLS_DTV_OFFSET);
                        rdbg(("DTPOFF %s in %s --> %p in %s",
@@ -182,7 +179,8 @@ int
                        break;
 
                case R_TYPE(TLS_TPOFF):
-                       if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
+                       if (!defobj->tls_static &&
+                           _rtld_tls_offset_allocate(__UNCONST(defobj)))
                                return -1;
 
                        *where = (Elf_Addr)(def->st_value + rela->r_addend
diff -r 1cea1107a5b9 -r 56ca9e0e8534 libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
--- a/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c        Sat Jun 03 21:44:08 2023 +0000
+++ b/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c        Sun Jun 04 01:24:56 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ppc_reloc.c,v 1.62 2022/07/06 17:35:20 martin Exp $    */
+/*     $NetBSD: ppc_reloc.c,v 1.63 2023/06/04 01:24:57 joerg Exp $     */
 
 /*-
  * Copyright (C) 1998  Tsubai Masanari
@@ -30,7 +30,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: ppc_reloc.c,v 1.62 2022/07/06 17:35:20 martin Exp $");
+__RCSID("$NetBSD: ppc_reloc.c,v 1.63 2023/06/04 01:24:57 joerg Exp $");
 #endif /* not lint */
 
 #include <stdarg.h>



Home | Main Index | Thread Index | Old Index