Home | History | Annotate | Line # | Download | only in ld.elf_so
t_tls_extern.c revision 1.11
      1 /*	$NetBSD: t_tls_extern.c,v 1.11 2023/06/02 19:09:11 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_ctor);
    289 ATF_TC_HEAD(onlydef_dynamic_static_ctor, tc)
    290 {
    291 	atf_tc_set_md_var(tc, "descr", "definition-only library,"
    292 	    " dynamic load and use in ctor, then static load fails");
    293 }
    294 ATF_TC_BODY(onlydef_dynamic_static_ctor, tc)
    295 {
    296 
    297 	ATF_REQUIRE_DL(dlopen("libh_onlydef.so", 0));
    298 	ATF_REQUIRE_DL(dlopen("libh_onlyctor_dynamic.so", 0));
    299 	atf_tc_expect_fail("rtld fails to detect dynamic-then-static abuse");
    300 	ATF_CHECK_EQ_MSG(NULL, dlopen("libh_onlyuse_static.so", 0),
    301 	    "dlopen failed to detect dynamic-then-static abuse");
    302 }
    303 
    304 ATF_TC(onlydef_dynamic_static_eager);
    305 ATF_TC_HEAD(onlydef_dynamic_static_eager, tc)
    306 {
    307 	atf_tc_set_md_var(tc, "descr", "definition-only library,"
    308 	    " dynamic load and use, then static load fails");
    309 }
    310 ATF_TC_BODY(onlydef_dynamic_static_eager, tc)
    311 {
    312 	void *use_dynamic;
    313 	int *(*fdynamic)(void);
    314 
    315 	ATF_REQUIRE_DL(use_dynamic = dlopen("libh_onlyuse_dynamic.so", 0));
    316 	ATF_REQUIRE_DL(fdynamic = dlsym(use_dynamic, "fdynamic"));
    317 	(void)(*fdynamic)();
    318 	atf_tc_expect_fail("rtld fails to detect dynamic-then-static abuse");
    319 	ATF_CHECK_EQ_MSG(NULL, dlopen("libh_onlyuse_static.so", 0),
    320 	    "dlopen failed to detect dynamic-then-static abuse");
    321 }
    322 
    323 ATF_TC(onlydef_dynamic_static_lazy);
    324 ATF_TC_HEAD(onlydef_dynamic_static_lazy, tc)
    325 {
    326 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
    327 	    " with definition-only library, dynamic and static load and use");
    328 }
    329 ATF_TC_BODY(onlydef_dynamic_static_lazy, tc)
    330 {
    331 	void *use_dynamic, *use_static;
    332 	int *(*fdynamic)(void), *(*fstatic)(void);
    333 	int *pdynamic, *pstatic;
    334 
    335 	ATF_REQUIRE_DL(use_dynamic = dlopen("libh_onlyuse_dynamic.so", 0));
    336 	ATF_REQUIRE_DL(use_static = dlopen("libh_onlyuse_static.so", 0));
    337 	ATF_REQUIRE_DL(fdynamic = dlsym(use_dynamic, "fdynamic"));
    338 	ATF_REQUIRE_DL(fstatic = dlsym(use_static, "fstatic"));
    339 	pdynamic = (*fdynamic)();
    340 	pstatic = (*fstatic)();
    341 	atf_tc_expect_fail("PR toolchain/50277:"
    342 	    " rtld relocation bug with thread local storage");
    343 	ATF_CHECK_EQ_MSG(pdynamic, pstatic,
    344 	    "%p in dynamic tls user != %p in static tls user",
    345 	    pdynamic, pstatic);
    346 }
    347 
    348 ATF_TC(onlydef_static_dynamic_eager);
    349 ATF_TC_HEAD(onlydef_static_dynamic_eager, tc)
    350 {
    351 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
    352 	    " with definition-only library,"
    353 	    " static load and use, then dynamic load and use");
    354 }
    355 ATF_TC_BODY(onlydef_static_dynamic_eager, tc)
    356 {
    357 	void *use_static, *use_dynamic;
    358 	int *(*fstatic)(void), *(*fdynamic)(void);
    359 	int *pstatic, *pdynamic;
    360 
    361 	ATF_REQUIRE_DL(dlopen("libh_onlydef.so", 0));
    362 	ATF_REQUIRE_DL(use_static = dlopen("libh_onlyuse_static.so", 0));
    363 	ATF_REQUIRE_DL(fstatic = dlsym(use_static, "fstatic"));
    364 	pstatic = (*fstatic)();
    365 	ATF_REQUIRE_DL(use_dynamic = dlopen("libh_onlyuse_dynamic.so", 0));
    366 	ATF_REQUIRE_DL(fdynamic = dlsym(use_dynamic, "fdynamic"));
    367 	pdynamic = (*fdynamic)();
    368 	atf_tc_expect_fail("PR toolchain/50277:"
    369 	    " rtld relocation bug with thread local storage");
    370 	ATF_CHECK_EQ_MSG(pstatic, pdynamic,
    371 	    "%p in static tls user != %p in dynamic tls user",
    372 	    pstatic, pdynamic);
    373 }
    374 
    375 ATF_TC(onlydef_static_dynamic_lazy);
    376 ATF_TC_HEAD(onlydef_static_dynamic_lazy, tc)
    377 {
    378 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
    379 	    " with definition-only library, static and dynamic load and use");
    380 }
    381 ATF_TC_BODY(onlydef_static_dynamic_lazy, tc)
    382 {
    383 	void *use_static, *use_dynamic;
    384 	int *(*fstatic)(void), *(*fdynamic)(void);
    385 	int *pstatic, *pdynamic;
    386 
    387 	ATF_REQUIRE_DL(dlopen("libh_onlydef.so", 0));
    388 	ATF_REQUIRE_DL(use_static = dlopen("libh_onlyuse_static.so", 0));
    389 	ATF_REQUIRE_DL(use_dynamic = dlopen("libh_onlyuse_dynamic.so", 0));
    390 	ATF_REQUIRE_DL(fstatic = dlsym(use_static, "fstatic"));
    391 	ATF_REQUIRE_DL(fdynamic = dlsym(use_dynamic, "fdynamic"));
    392 	pstatic = (*fstatic)();
    393 	pdynamic = (*fdynamic)();
    394 	atf_tc_expect_fail("PR toolchain/50277:"
    395 	    " rtld relocation bug with thread local storage");
    396 	ATF_CHECK_EQ_MSG(pstatic, pdynamic,
    397 	    "%p in static tls user != %p in dynamic tls user",
    398 	    pstatic, pdynamic);
    399 }
    400 
    401 ATF_TP_ADD_TCS(tp)
    402 {
    403 
    404 	ATF_TP_ADD_TC(tp, dynamic_abusedef);
    405 	ATF_TP_ADD_TC(tp, dynamic_abusedefnoload);
    406 	ATF_TP_ADD_TC(tp, dynamic_defabuse_eager);
    407 	ATF_TP_ADD_TC(tp, dynamic_defabuse_lazy);
    408 	ATF_TP_ADD_TC(tp, dynamic_defuse_eager);
    409 	ATF_TP_ADD_TC(tp, dynamic_defuse_lazy);
    410 	ATF_TP_ADD_TC(tp, dynamic_usedef);
    411 	ATF_TP_ADD_TC(tp, dynamic_usedefnoload);
    412 	ATF_TP_ADD_TC(tp, onlydef_dynamic_static_ctor);
    413 	ATF_TP_ADD_TC(tp, onlydef_dynamic_static_eager);
    414 	ATF_TP_ADD_TC(tp, onlydef_dynamic_static_lazy);
    415 	ATF_TP_ADD_TC(tp, onlydef_static_dynamic_eager);
    416 	ATF_TP_ADD_TC(tp, onlydef_static_dynamic_lazy);
    417 	ATF_TP_ADD_TC(tp, static_abusedef);
    418 	ATF_TP_ADD_TC(tp, static_abusedefnoload);
    419 	ATF_TP_ADD_TC(tp, static_defabuse_eager);
    420 	ATF_TP_ADD_TC(tp, static_defabuse_lazy);
    421 	ATF_TP_ADD_TC(tp, static_defuse_eager);
    422 	ATF_TP_ADD_TC(tp, static_defuse_lazy);
    423 	ATF_TP_ADD_TC(tp, static_usedef);
    424 	ATF_TP_ADD_TC(tp, static_usedefnoload);
    425 	return atf_no_error();
    426 }
    427