Home | History | Annotate | Line # | Download | only in ld.elf_so
t_tls_extern.c revision 1.10
      1 /*	$NetBSD: t_tls_extern.c,v 1.10 2023/06/02 19:08:48 riastradh Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2023 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/types.h>
     30 
     31 #include <atf-c.h>
     32 #include <dlfcn.h>
     33 
     34 #define	ATF_REQUIRE_DL(x)	ATF_REQUIRE_MSG(x, "%s: %s", #x, dlerror())
     35 
     36 enum order {
     37 	DEF_USE_EAGER,
     38 	DEF_USE_LAZY,
     39 	USE_DEF,
     40 	USE_DEF_NOLOAD,
     41 };
     42 
     43 static void
     44 tls_extern(const char *libdef, const char *libuse, enum order order,
     45     bool xfail)
     46 {
     47 	void *def, *use;
     48 	int *(*fdef)(void), *(*fuse)(void);
     49 	int *pdef, *puse;
     50 
     51 	(void)dlerror();
     52 
     53 	switch (order) {
     54 	case DEF_USE_EAGER:
     55 		ATF_REQUIRE_DL(def = dlopen(libdef, 0));
     56 		ATF_REQUIRE_DL(fdef = dlsym(def, "fdef"));
     57 		pdef = (*fdef)();
     58 		ATF_REQUIRE_DL(use = dlopen(libuse, 0));
     59 		ATF_REQUIRE_DL(fuse = dlsym(use, "fuse"));
     60 		puse = (*fuse)();
     61 		break;
     62 	case DEF_USE_LAZY:
     63 		ATF_REQUIRE_DL(def = dlopen(libdef, 0));
     64 		ATF_REQUIRE_DL(use = dlopen(libuse, 0));
     65 		goto lazy;
     66 	case USE_DEF:
     67 		ATF_REQUIRE_DL(use = dlopen(libuse, 0));
     68 		ATF_REQUIRE_DL(def = dlopen(libdef, 0));
     69 		goto lazy;
     70 	case USE_DEF_NOLOAD:
     71 		ATF_REQUIRE_DL(use = dlopen(libuse, 0));
     72 		ATF_REQUIRE_DL(def = dlopen(libdef, RTLD_NOLOAD));
     73 lazy:		ATF_REQUIRE_DL(fdef = dlsym(def, "fdef"));
     74 		ATF_REQUIRE_DL(fuse = dlsym(use, "fuse"));
     75 		pdef = (*fdef)();
     76 		puse = (*fuse)();
     77 		break;
     78 	}
     79 
     80 	if (xfail) {
     81 		atf_tc_expect_fail("PR toolchain/50277:"
     82 		    " rtld relocation bug with thread local storage");
     83 	}
     84 	ATF_CHECK_EQ_MSG(pdef, puse,
     85 	    "%p in defining library != %p in using library",
     86 	    pdef, puse);
     87 }
     88 
     89 ATF_TC(dynamic_abusedef);
     90 ATF_TC_HEAD(dynamic_abusedef, tc)
     91 {
     92 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
     93 	    " loading static use than dynamic def");
     94 }
     95 ATF_TC_BODY(dynamic_abusedef, tc)
     96 {
     97 	tls_extern("libh_def_dynamic.so", "libh_abuse_dynamic.so",
     98 	    USE_DEF, /*xfail*/true);
     99 }
    100 
    101 ATF_TC(dynamic_abusedefnoload);
    102 ATF_TC_HEAD(dynamic_abusedefnoload, tc)
    103 {
    104 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
    105 	    " loading static use then dynamic def with RTLD_NOLOAD");
    106 }
    107 ATF_TC_BODY(dynamic_abusedefnoload, tc)
    108 {
    109 	tls_extern("libh_def_dynamic.so", "libh_abuse_dynamic.so",
    110 	    USE_DEF_NOLOAD, /*xfail*/true);
    111 }
    112 
    113 ATF_TC(dynamic_defabuse_eager);
    114 ATF_TC_HEAD(dynamic_defabuse_eager, tc)
    115 {
    116 	atf_tc_set_md_var(tc, "descr", "dlopen refuses extern __thread for TLS,"
    117 	    " loading dynamic def then static use eagerly");
    118 }
    119 ATF_TC_BODY(dynamic_defabuse_eager, tc)
    120 {
    121 	void *def;
    122 	int *(*fdef)(void);
    123 
    124 	ATF_REQUIRE_DL(def = dlopen("libh_def_dynamic.so", 0));
    125 	ATF_REQUIRE_DL(fdef = dlsym(def, "fdef"));
    126 	(void)(*fdef)();
    127 	atf_tc_expect_fail("rtld fails to detect dynamic-then-static abuse");
    128 	ATF_CHECK_EQ_MSG(NULL, dlopen("libh_abuse_dynamic.so", 0),
    129 	    "dlopen failed to detect static-then-dynamic abuse");
    130 }
    131 
    132 ATF_TC(dynamic_defabuse_lazy);
    133 ATF_TC_HEAD(dynamic_defabuse_lazy, tc)
    134 {
    135 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
    136 	    " loading dynamic def then static use lazily");
    137 }
    138 ATF_TC_BODY(dynamic_defabuse_lazy, tc)
    139 {
    140 	tls_extern("libh_def_dynamic.so", "libh_abuse_dynamic.so",
    141 	    DEF_USE_LAZY, /*xfail*/true);
    142 }
    143 
    144 ATF_TC(dynamic_defuse_eager);
    145 ATF_TC_HEAD(dynamic_defuse_eager, tc)
    146 {
    147 	atf_tc_set_md_var(tc, "descr", "extern __thread for dynamic TLS works,"
    148 	    " loading def then use eagerly");
    149 }
    150 ATF_TC_BODY(dynamic_defuse_eager, tc)
    151 {
    152 	tls_extern("libh_def_dynamic.so", "libh_use_dynamic.so",
    153 	    DEF_USE_EAGER, /*xfail*/false);
    154 }
    155 
    156 ATF_TC(dynamic_defuse_lazy);
    157 ATF_TC_HEAD(dynamic_defuse_lazy, tc)
    158 {
    159 	atf_tc_set_md_var(tc, "descr", "extern __thread for dynamic TLS works,"
    160 	    " loading def then use lazyly");
    161 }
    162 ATF_TC_BODY(dynamic_defuse_lazy, tc)
    163 {
    164 	tls_extern("libh_def_dynamic.so", "libh_use_dynamic.so",
    165 	    DEF_USE_LAZY, /*xfail*/false);
    166 }
    167 
    168 ATF_TC(dynamic_usedef);
    169 ATF_TC_HEAD(dynamic_usedef, tc)
    170 {
    171 	atf_tc_set_md_var(tc, "descr", "extern __thread for dynamic TLS works,"
    172 	    " loading use then def");
    173 }
    174 ATF_TC_BODY(dynamic_usedef, tc)
    175 {
    176 	tls_extern("libh_def_dynamic.so", "libh_use_dynamic.so",
    177 	    USE_DEF, /*xfail*/false);
    178 }
    179 
    180 ATF_TC(dynamic_usedefnoload);
    181 ATF_TC_HEAD(dynamic_usedefnoload, tc)
    182 {
    183 	atf_tc_set_md_var(tc, "descr", "extern __thread for dynamic TLS works,"
    184 	    " loading use then def with RTLD_NOLOAD");
    185 }
    186 ATF_TC_BODY(dynamic_usedefnoload, tc)
    187 {
    188 	tls_extern("libh_def_dynamic.so", "libh_use_dynamic.so",
    189 	    USE_DEF_NOLOAD, /*xfail*/false);
    190 }
    191 
    192 ATF_TC(static_abusedef);
    193 ATF_TC_HEAD(static_abusedef, tc)
    194 {
    195 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
    196 	    " loading dynamic use then static def");
    197 }
    198 ATF_TC_BODY(static_abusedef, tc)
    199 {
    200 	tls_extern("libh_def_static.so", "libh_abuse_static.so",
    201 	    USE_DEF, /*xfail*/true);
    202 }
    203 
    204 ATF_TC(static_abusedefnoload);
    205 ATF_TC_HEAD(static_abusedefnoload, tc)
    206 {
    207 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
    208 	    " loading dynamic use then static def with RTLD_NOLOAD");
    209 }
    210 ATF_TC_BODY(static_abusedefnoload, tc)
    211 {
    212 	tls_extern("libh_def_static.so", "libh_abuse_static.so",
    213 	    USE_DEF_NOLOAD, /*xfail*/true);
    214 }
    215 
    216 ATF_TC(static_defabuse_eager);
    217 ATF_TC_HEAD(static_defabuse_eager, tc)
    218 {
    219 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
    220 	    " loading static def then dynamic use eagerly");
    221 }
    222 ATF_TC_BODY(static_defabuse_eager, tc)
    223 {
    224 	tls_extern("libh_def_static.so", "libh_abuse_static.so",
    225 	    DEF_USE_EAGER, /*xfail*/true);
    226 }
    227 
    228 ATF_TC(static_defabuse_lazy);
    229 ATF_TC_HEAD(static_defabuse_lazy, tc)
    230 {
    231 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
    232 	    " loading static def then dynamic use lazyly");
    233 }
    234 ATF_TC_BODY(static_defabuse_lazy, tc)
    235 {
    236 	tls_extern("libh_def_static.so", "libh_abuse_static.so",
    237 	    DEF_USE_LAZY, /*xfail*/true);
    238 }
    239 
    240 ATF_TC(static_defuse_eager);
    241 ATF_TC_HEAD(static_defuse_eager, tc)
    242 {
    243 	atf_tc_set_md_var(tc, "descr", "extern __thread for static TLS works,"
    244 	    " loading def then use eagerly");
    245 }
    246 ATF_TC_BODY(static_defuse_eager, tc)
    247 {
    248 	tls_extern("libh_def_static.so", "libh_use_static.so",
    249 	    DEF_USE_EAGER, /*xfail*/false);
    250 }
    251 
    252 ATF_TC(static_defuse_lazy);
    253 ATF_TC_HEAD(static_defuse_lazy, tc)
    254 {
    255 	atf_tc_set_md_var(tc, "descr", "extern __thread for static TLS works,"
    256 	    " loading def then use lazyly");
    257 }
    258 ATF_TC_BODY(static_defuse_lazy, tc)
    259 {
    260 	tls_extern("libh_def_static.so", "libh_use_static.so",
    261 	    DEF_USE_LAZY, /*xfail*/false);
    262 }
    263 
    264 ATF_TC(static_usedef);
    265 ATF_TC_HEAD(static_usedef, tc)
    266 {
    267 	atf_tc_set_md_var(tc, "descr", "extern __thread for static TLS works,"
    268 	    " loading use then def");
    269 }
    270 ATF_TC_BODY(static_usedef, tc)
    271 {
    272 	tls_extern("libh_def_static.so", "libh_use_static.so",
    273 	    USE_DEF, /*xfail*/true);
    274 }
    275 
    276 ATF_TC(static_usedefnoload);
    277 ATF_TC_HEAD(static_usedefnoload, tc)
    278 {
    279 	atf_tc_set_md_var(tc, "descr", "extern __thread for static TLS works,"
    280 	    " loading use then def with RTLD_NOLOAD");
    281 }
    282 ATF_TC_BODY(static_usedefnoload, tc)
    283 {
    284 	tls_extern("libh_def_static.so", "libh_use_static.so",
    285 	    USE_DEF_NOLOAD, /*xfail*/true);
    286 }
    287 
    288 ATF_TC(onlydef_dynamic_static_eager);
    289 ATF_TC_HEAD(onlydef_dynamic_static_eager, tc)
    290 {
    291 	atf_tc_set_md_var(tc, "descr", "definition-only library,"
    292 	    " dynamic load and use, then static load fails");
    293 }
    294 ATF_TC_BODY(onlydef_dynamic_static_eager, tc)
    295 {
    296 	void *use_dynamic;
    297 	int *(*fdynamic)(void);
    298 
    299 	ATF_REQUIRE_DL(use_dynamic = dlopen("libh_onlyuse_dynamic.so", 0));
    300 	ATF_REQUIRE_DL(fdynamic = dlsym(use_dynamic, "fdynamic"));
    301 	(void)(*fdynamic)();
    302 	atf_tc_expect_fail("rtld fails to detect dynamic-then-static abuse");
    303 	ATF_CHECK_EQ_MSG(NULL, dlopen("libh_onlyuse_static.so", 0),
    304 	    "dlopen failed to detect dynamic-then-static abuse");
    305 }
    306 
    307 ATF_TC(onlydef_dynamic_static_lazy);
    308 ATF_TC_HEAD(onlydef_dynamic_static_lazy, tc)
    309 {
    310 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
    311 	    " with definition-only library, dynamic and static load and use");
    312 }
    313 ATF_TC_BODY(onlydef_dynamic_static_lazy, tc)
    314 {
    315 	void *use_dynamic, *use_static;
    316 	int *(*fdynamic)(void), *(*fstatic)(void);
    317 	int *pdynamic, *pstatic;
    318 
    319 	ATF_REQUIRE_DL(use_dynamic = dlopen("libh_onlyuse_dynamic.so", 0));
    320 	ATF_REQUIRE_DL(use_static = dlopen("libh_onlyuse_static.so", 0));
    321 	ATF_REQUIRE_DL(fdynamic = dlsym(use_dynamic, "fdynamic"));
    322 	ATF_REQUIRE_DL(fstatic = dlsym(use_static, "fstatic"));
    323 	pdynamic = (*fdynamic)();
    324 	pstatic = (*fstatic)();
    325 	atf_tc_expect_fail("PR toolchain/50277:"
    326 	    " rtld relocation bug with thread local storage");
    327 	ATF_CHECK_EQ_MSG(pdynamic, pstatic,
    328 	    "%p in dynamic tls user != %p in static tls user",
    329 	    pdynamic, pstatic);
    330 }
    331 
    332 ATF_TC(onlydef_static_dynamic_eager);
    333 ATF_TC_HEAD(onlydef_static_dynamic_eager, tc)
    334 {
    335 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
    336 	    " with definition-only library,"
    337 	    " static load and use, then dynamic load and use");
    338 }
    339 ATF_TC_BODY(onlydef_static_dynamic_eager, tc)
    340 {
    341 	void *use_static, *use_dynamic;
    342 	int *(*fstatic)(void), *(*fdynamic)(void);
    343 	int *pstatic, *pdynamic;
    344 
    345 	ATF_REQUIRE_DL(dlopen("libh_onlydef.so", 0));
    346 	ATF_REQUIRE_DL(use_static = dlopen("libh_onlyuse_static.so", 0));
    347 	ATF_REQUIRE_DL(fstatic = dlsym(use_static, "fstatic"));
    348 	pstatic = (*fstatic)();
    349 	ATF_REQUIRE_DL(use_dynamic = dlopen("libh_onlyuse_dynamic.so", 0));
    350 	ATF_REQUIRE_DL(fdynamic = dlsym(use_dynamic, "fdynamic"));
    351 	pdynamic = (*fdynamic)();
    352 	atf_tc_expect_fail("PR toolchain/50277:"
    353 	    " rtld relocation bug with thread local storage");
    354 	ATF_CHECK_EQ_MSG(pstatic, pdynamic,
    355 	    "%p in static tls user != %p in dynamic tls user",
    356 	    pstatic, pdynamic);
    357 }
    358 
    359 ATF_TC(onlydef_static_dynamic_lazy);
    360 ATF_TC_HEAD(onlydef_static_dynamic_lazy, tc)
    361 {
    362 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
    363 	    " with definition-only library, static and dynamic load and use");
    364 }
    365 ATF_TC_BODY(onlydef_static_dynamic_lazy, tc)
    366 {
    367 	void *use_static, *use_dynamic;
    368 	int *(*fstatic)(void), *(*fdynamic)(void);
    369 	int *pstatic, *pdynamic;
    370 
    371 	ATF_REQUIRE_DL(dlopen("libh_onlydef.so", 0));
    372 	ATF_REQUIRE_DL(use_static = dlopen("libh_onlyuse_static.so", 0));
    373 	ATF_REQUIRE_DL(use_dynamic = dlopen("libh_onlyuse_dynamic.so", 0));
    374 	ATF_REQUIRE_DL(fstatic = dlsym(use_static, "fstatic"));
    375 	ATF_REQUIRE_DL(fdynamic = dlsym(use_dynamic, "fdynamic"));
    376 	pstatic = (*fstatic)();
    377 	pdynamic = (*fdynamic)();
    378 	atf_tc_expect_fail("PR toolchain/50277:"
    379 	    " rtld relocation bug with thread local storage");
    380 	ATF_CHECK_EQ_MSG(pstatic, pdynamic,
    381 	    "%p in static tls user != %p in dynamic tls user",
    382 	    pstatic, pdynamic);
    383 }
    384 
    385 ATF_TP_ADD_TCS(tp)
    386 {
    387 
    388 	ATF_TP_ADD_TC(tp, dynamic_abusedef);
    389 	ATF_TP_ADD_TC(tp, dynamic_abusedefnoload);
    390 	ATF_TP_ADD_TC(tp, dynamic_defabuse_eager);
    391 	ATF_TP_ADD_TC(tp, dynamic_defabuse_lazy);
    392 	ATF_TP_ADD_TC(tp, dynamic_defuse_eager);
    393 	ATF_TP_ADD_TC(tp, dynamic_defuse_lazy);
    394 	ATF_TP_ADD_TC(tp, dynamic_usedef);
    395 	ATF_TP_ADD_TC(tp, dynamic_usedefnoload);
    396 	ATF_TP_ADD_TC(tp, onlydef_dynamic_static_eager);
    397 	ATF_TP_ADD_TC(tp, onlydef_dynamic_static_lazy);
    398 	ATF_TP_ADD_TC(tp, onlydef_static_dynamic_eager);
    399 	ATF_TP_ADD_TC(tp, onlydef_static_dynamic_lazy);
    400 	ATF_TP_ADD_TC(tp, static_abusedef);
    401 	ATF_TP_ADD_TC(tp, static_abusedefnoload);
    402 	ATF_TP_ADD_TC(tp, static_defabuse_eager);
    403 	ATF_TP_ADD_TC(tp, static_defabuse_lazy);
    404 	ATF_TP_ADD_TC(tp, static_defuse_eager);
    405 	ATF_TP_ADD_TC(tp, static_defuse_lazy);
    406 	ATF_TP_ADD_TC(tp, static_usedef);
    407 	ATF_TP_ADD_TC(tp, static_usedefnoload);
    408 	return atf_no_error();
    409 }
    410