From patchwork Wed Dec 16 13:26:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1417163 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=libc-alpha-bounces@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=sourceware.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.a=rsa-sha256 header.s=default header.b=TiX+p4QL; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Cwwvs2l8hz9sSf for ; Thu, 17 Dec 2020 00:29:29 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7C81E3875406; Wed, 16 Dec 2020 13:28:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7C81E3875406 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1608125284; bh=luOxPITFZPwr0ZIzjQVoIX3C6t8ktWUkhPdrKthx+J0=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=TiX+p4QLydoScjKJm63JazMgi2bPaVhBNHt46yLx+PWV55k+7S9NJicR4XYFuQa4C XZEGTj2p9FynmRJEn7gQyHH0Jn5Ka8cSLZgyg+vi/WqM8Dqgutf+2rTwqbj6678io3 wD7Q4vEVKceCVpz+5SStijDJOQQDOB3105WBPCNU= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3]) by sourceware.org (Postfix) with ESMTPS id 52CA13840C21 for ; Wed, 16 Dec 2020 13:27:50 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 52CA13840C21 Received: from noise.cbg.collabora.co.uk (unknown [IPv6:2001:4d48:ad5c:ef00:8e70:5aff:fe59:c29c]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: vivek) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id E71F91F456A9 for ; Wed, 16 Dec 2020 13:27:46 +0000 (GMT) To: libc-alpha Subject: [RFC][PATCH v7 19/20] Add dlmopen / RTLD_SHARED tests Date: Wed, 16 Dec 2020 13:26:49 +0000 Message-Id: <20201216132650.22949-20-vivek@collabora.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201216132650.22949-1-vivek@collabora.com> References: <20201216132650.22949-1-vivek@collabora.com> MIME-Version: 1.0 X-Spam-Status: No, score=-13.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: =?utf-8?q?Vivek_Das=C2=A0Mohapatra_via_Libc-alpha?= From: Vivek Dasmohapatra Reply-To: =?utf-8?q?Vivek_Das=C2=A0Mohapatra?= Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" --- elf/Makefile | 97 ++- elf/tst-dlmopen-auditmod.c | 23 + elf/tst-dlmopen-common.h | 33 + elf/tst-dlmopen-main.h | 1022 ++++++++++++++++++++++++++ elf/tst-dlmopen-modules.h | 20 + elf/tst-dlmopen-rtld-audit-shared1.c | 11 + elf/tst-dlmopen-rtld-audit-shared2.c | 11 + elf/tst-dlmopen-rtld-audit-shared3.c | 11 + elf/tst-dlmopen-rtld-audit-shared4.c | 11 + elf/tst-dlmopen-rtld-audit-shared5.c | 11 + elf/tst-dlmopen-rtld-audit-shared6.c | 11 + elf/tst-dlmopen-rtld-audit-unique1.c | 11 + elf/tst-dlmopen-rtld-audit-unique2.c | 11 + elf/tst-dlmopen-rtld-audit-unique3.c | 11 + elf/tst-dlmopen-rtld-audit-unique4.c | 11 + elf/tst-dlmopen-rtld-audit-unique5.c | 11 + elf/tst-dlmopen-rtld-audit-unique6.c | 11 + elf/tst-dlmopen-rtld-shared1.c | 11 + elf/tst-dlmopen-rtld-shared1.h | 65 ++ elf/tst-dlmopen-rtld-shared2.c | 11 + elf/tst-dlmopen-rtld-shared2.h | 67 ++ elf/tst-dlmopen-rtld-shared3.c | 11 + elf/tst-dlmopen-rtld-shared3.h | 44 ++ elf/tst-dlmopen-rtld-shared4.c | 11 + elf/tst-dlmopen-rtld-shared4.h | 15 + elf/tst-dlmopen-rtld-shared5.c | 11 + elf/tst-dlmopen-rtld-shared5.h | 26 + elf/tst-dlmopen-rtld-shared6.c | 11 + elf/tst-dlmopen-rtld-shared6.h | 37 + elf/tst-dlmopen-rtld-unique1.c | 11 + elf/tst-dlmopen-rtld-unique1.h | 87 +++ elf/tst-dlmopen-rtld-unique2.c | 11 + elf/tst-dlmopen-rtld-unique2.h | 26 + elf/tst-dlmopen-rtld-unique3.c | 11 + elf/tst-dlmopen-rtld-unique3.h | 14 + elf/tst-dlmopen-rtld-unique4.c | 11 + elf/tst-dlmopen-rtld-unique4.h | 15 + elf/tst-dlmopen-rtld-unique5.c | 11 + elf/tst-dlmopen-rtld-unique5.h | 59 ++ elf/tst-dlmopen-rtld-unique6.c | 11 + elf/tst-dlmopen-rtld-unique6.h | 52 ++ elf/tst-dlmopen-sharedmod-norm.c | 11 + elf/tst-dlmopen-sharedmod-uniq.c | 11 + elf/tst-dlmopen-std-do-test.h | 11 + 44 files changed, 1998 insertions(+), 1 deletion(-) create mode 100644 elf/tst-dlmopen-auditmod.c create mode 100644 elf/tst-dlmopen-common.h create mode 100644 elf/tst-dlmopen-main.h create mode 100644 elf/tst-dlmopen-modules.h create mode 100644 elf/tst-dlmopen-rtld-audit-shared1.c create mode 100644 elf/tst-dlmopen-rtld-audit-shared2.c create mode 100644 elf/tst-dlmopen-rtld-audit-shared3.c create mode 100644 elf/tst-dlmopen-rtld-audit-shared4.c create mode 100644 elf/tst-dlmopen-rtld-audit-shared5.c create mode 100644 elf/tst-dlmopen-rtld-audit-shared6.c create mode 100644 elf/tst-dlmopen-rtld-audit-unique1.c create mode 100644 elf/tst-dlmopen-rtld-audit-unique2.c create mode 100644 elf/tst-dlmopen-rtld-audit-unique3.c create mode 100644 elf/tst-dlmopen-rtld-audit-unique4.c create mode 100644 elf/tst-dlmopen-rtld-audit-unique5.c create mode 100644 elf/tst-dlmopen-rtld-audit-unique6.c create mode 100644 elf/tst-dlmopen-rtld-shared1.c create mode 100644 elf/tst-dlmopen-rtld-shared1.h create mode 100644 elf/tst-dlmopen-rtld-shared2.c create mode 100644 elf/tst-dlmopen-rtld-shared2.h create mode 100644 elf/tst-dlmopen-rtld-shared3.c create mode 100644 elf/tst-dlmopen-rtld-shared3.h create mode 100644 elf/tst-dlmopen-rtld-shared4.c create mode 100644 elf/tst-dlmopen-rtld-shared4.h create mode 100644 elf/tst-dlmopen-rtld-shared5.c create mode 100644 elf/tst-dlmopen-rtld-shared5.h create mode 100644 elf/tst-dlmopen-rtld-shared6.c create mode 100644 elf/tst-dlmopen-rtld-shared6.h create mode 100644 elf/tst-dlmopen-rtld-unique1.c create mode 100644 elf/tst-dlmopen-rtld-unique1.h create mode 100644 elf/tst-dlmopen-rtld-unique2.c create mode 100644 elf/tst-dlmopen-rtld-unique2.h create mode 100644 elf/tst-dlmopen-rtld-unique3.c create mode 100644 elf/tst-dlmopen-rtld-unique3.h create mode 100644 elf/tst-dlmopen-rtld-unique4.c create mode 100644 elf/tst-dlmopen-rtld-unique4.h create mode 100644 elf/tst-dlmopen-rtld-unique5.c create mode 100644 elf/tst-dlmopen-rtld-unique5.h create mode 100644 elf/tst-dlmopen-rtld-unique6.c create mode 100644 elf/tst-dlmopen-rtld-unique6.h create mode 100644 elf/tst-dlmopen-sharedmod-norm.c create mode 100644 elf/tst-dlmopen-sharedmod-uniq.c create mode 100644 elf/tst-dlmopen-std-do-test.h diff --git a/elf/Makefile b/elf/Makefile index 0b4d78c874..6f6f7891be 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -192,6 +192,38 @@ static-dlopen-environment = \ tst-tls9-static-ENV = $(static-dlopen-environment) tst-single_threaded-static-dlopen-ENV = $(static-dlopen-environment) +dlmopen-rtld-tests-norm := \ + tst-dlmopen-rtld-shared1 \ + tst-dlmopen-rtld-shared2 \ + tst-dlmopen-rtld-shared3 \ + tst-dlmopen-rtld-shared4 \ + tst-dlmopen-rtld-shared5 \ + tst-dlmopen-rtld-shared6 + +dlmopen-rtld-tests-uniq := \ + tst-dlmopen-rtld-unique1 \ + tst-dlmopen-rtld-unique2 \ + tst-dlmopen-rtld-unique3 \ + tst-dlmopen-rtld-unique4 \ + tst-dlmopen-rtld-unique5 \ + tst-dlmopen-rtld-unique6 + +dlmopen-rtld-audit-tests-norm := \ + tst-dlmopen-rtld-audit-shared1 \ + tst-dlmopen-rtld-audit-shared2 \ + tst-dlmopen-rtld-audit-shared3 \ + tst-dlmopen-rtld-audit-shared4 \ + tst-dlmopen-rtld-audit-shared5 \ + tst-dlmopen-rtld-audit-shared6 + +dlmopen-rtld-audit-tests-uniq := \ + tst-dlmopen-rtld-audit-unique1 \ + tst-dlmopen-rtld-audit-unique2 \ + tst-dlmopen-rtld-audit-unique3 \ + tst-dlmopen-rtld-audit-unique4 \ + tst-dlmopen-rtld-audit-unique5 \ + tst-dlmopen-rtld-audit-unique6 + tests += restest1 preloadtest loadfail multiload origtest resolvfail \ constload1 order noload filter \ reldep reldep2 reldep3 reldep4 nodelete nodelete2 \ @@ -221,7 +253,11 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-audit14 tst-audit15 tst-audit16 \ tst-single_threaded tst-single_threaded-pthread \ tst-tls-ie tst-tls-ie-dlmopen argv0test \ - tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask + tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \ + $(dlmopen-rtld-tests-norm) \ + $(dlmopen-rtld-tests-uniq) \ + $(dlmopen-rtld-audit-tests-norm) \ + $(dlmopen-rtld-audit-tests-uniq) # reldep9 tests-internal += loadtest unload unload2 circleload1 \ neededtest neededtest2 neededtest3 neededtest4 \ @@ -282,6 +318,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ $(modules-execstack-$(have-z-execstack)) \ tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \ tst-dlmopen1mod tst-auditmod1 \ + tst-dlmopen-sharedmod-norm \ + tst-dlmopen-sharedmod-uniq \ + tst-dlmopen-auditmod \ unload3mod1 unload3mod2 unload3mod3 unload3mod4 \ unload4mod1 unload4mod2 unload4mod3 unload4mod4 \ unload6mod1 unload6mod2 unload6mod3 \ @@ -321,6 +360,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \ tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \ tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \ + tst-dlmopen-auditmod \ tst-latepthreadmod $(tst-tls-many-dynamic-modules) \ tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \ tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \ @@ -822,6 +862,9 @@ tst-nodelete-uniquemod.so-no-z-defs = yes tst-nodelete-rtldmod.so-no-z-defs = yes tst-nodelete-zmod.so-no-z-defs = yes tst-nodelete2mod.so-no-z-defs = yes +tst-dlmopen-sharedmod-norm.so-no-z-defs = yes +tst-dlmopen-sharedmod-uniq.so-no-z-defs = yes +tst-dlmopen-auditmod.so-no-z-defs = yes ifeq ($(build-shared),yes) # Build all the modules even when not actually running test programs. @@ -1300,6 +1343,58 @@ $(objpfx)tst-dlmopen2.out: $(objpfx)tst-dlmopen1mod.so $(objpfx)tst-dlmopen3: $(libdl) $(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so +LDFLAGS-tst-dlmopen-sharedmod-uniq.so = -Wl,-z,unique +$(objpfx)tst-dlmopen-sharedmod-norm.so: $(libdl) +$(objpfx)tst-dlmopen-sharedmod-uniq.so: $(libdl) +$(objpfx)tst-dlmopen-auditmod.so: $(libdl) + +dlmopen-rtld-tests-norm-executables := \ + $(foreach x,$(dlmopen-rtld-tests-norm),$(objpfx)$(x)) +dlmopen-rtld-tests-norm-out := \ + $(foreach x,$(dlmopen-rtld-tests-norm),$(objpfx)$(x).out) + +dlmopen-rtld-tests-uniq-executables := \ + $(foreach x,$(dlmopen-rtld-tests-uniq),$(objpfx)$(x)) +dlmopen-rtld-tests-uniq-out := \ + $(foreach x,$(dlmopen-rtld-tests-uniq),$(objpfx)$(x).out) + +dlmopen-rtld-audit-tests-norm-executables := \ + $(foreach x,$(dlmopen-rtld-audit-tests-norm),$(objpfx)$(x)) +dlmopen-rtld-audit-tests-norm-out := \ + $(foreach x,$(dlmopen-rtld-audit-tests-norm),$(objpfx)$(x).out) + +dlmopen-rtld-audit-tests-uniq-executables := \ + $(foreach x,$(dlmopen-rtld-audit-tests-uniq),$(objpfx)$(x)) +dlmopen-rtld-audit-tests-uniq-out := \ + $(foreach x,$(dlmopen-rtld-audit-tests-uniq),$(objpfx)$(x).out) + +$(dlmopen-rtld-tests-norm-executables): $(libdl) +$(dlmopen-rtld-tests-norm-out): $(objpfx)tst-dlmopen-sharedmod-norm.so + +$(dlmopen-rtld-tests-uniq-executables): $(libdl) +$(dlmopen-rtld-tests-uniq-out): $(objpfx)tst-dlmopen-sharedmod-uniq.so + + +$(dlmopen-rtld-audit-tests-norm-executables): $(libdl) +$(dlmopen-rtld-audit-tests-norm-out): $(objpfx)tst-dlmopen-sharedmod-norm.so +$(dlmopen-rtld-audit-tests-norm-out): $(objpfx)tst-dlmopen-auditmod.so +tst-dlmopen-rtld-audit-shared1-ENV = LD_AUDIT=$(objpfx)tst-dlmopen-auditmod.so +tst-dlmopen-rtld-audit-shared2-ENV = LD_AUDIT=$(objpfx)tst-dlmopen-auditmod.so +tst-dlmopen-rtld-audit-shared3-ENV = LD_AUDIT=$(objpfx)tst-dlmopen-auditmod.so +tst-dlmopen-rtld-audit-shared4-ENV = LD_AUDIT=$(objpfx)tst-dlmopen-auditmod.so +tst-dlmopen-rtld-audit-shared5-ENV = LD_AUDIT=$(objpfx)tst-dlmopen-auditmod.so +tst-dlmopen-rtld-audit-shared6-ENV = LD_AUDIT=$(objpfx)tst-dlmopen-auditmod.so + +$(dlmopen-rtld-audit-tests-uniq-executables): $(libdl) +$(dlmopen-rtld-audit-tests-uniq-out): $(objpfx)tst-dlmopen-sharedmod-uniq.so +$(dlmopen-rtld-audit-tests-uniq-out): $(objpfx)tst-dlmopen-auditmod.so +tst-dlmopen-rtld-audit-unique1-ENV = LD_AUDIT=$(objpfx)tst-dlmopen-auditmod.so +tst-dlmopen-rtld-audit-unique2-ENV = LD_AUDIT=$(objpfx)tst-dlmopen-auditmod.so +tst-dlmopen-rtld-audit-unique3-ENV = LD_AUDIT=$(objpfx)tst-dlmopen-auditmod.so +tst-dlmopen-rtld-audit-unique4-ENV = LD_AUDIT=$(objpfx)tst-dlmopen-auditmod.so +tst-dlmopen-rtld-audit-unique5-ENV = LD_AUDIT=$(objpfx)tst-dlmopen-auditmod.so +tst-dlmopen-rtld-audit-unique6-ENV = LD_AUDIT=$(objpfx)tst-dlmopen-auditmod.so + $(objpfx)tst-audit1.out: $(objpfx)tst-auditmod1.so tst-audit1-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so diff --git a/elf/tst-dlmopen-auditmod.c b/elf/tst-dlmopen-auditmod.c new file mode 100644 index 0000000000..04457249d0 --- /dev/null +++ b/elf/tst-dlmopen-auditmod.c @@ -0,0 +1,23 @@ +/* Audit module for tst-dlmopen-rtld-audit-* + Copyright © 2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +unsigned int +la_version (unsigned int version) +{ + return version; +} diff --git a/elf/tst-dlmopen-common.h b/elf/tst-dlmopen-common.h new file mode 100644 index 0000000000..5653c9c02c --- /dev/null +++ b/elf/tst-dlmopen-common.h @@ -0,0 +1,33 @@ +#pragma once + +/* Common infrastructure for tst-dlmopen-rtld-* + Copyright © 2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include + +typedef struct +{ + const char *name; + void *free; +} dlmopen_testresult; + +typedef dlmopen_testresult * (*dlmopen_testfunc) (void); + diff --git a/elf/tst-dlmopen-main.h b/elf/tst-dlmopen-main.h new file mode 100644 index 0000000000..2e091e9b8d --- /dev/null +++ b/elf/tst-dlmopen-main.h @@ -0,0 +1,1022 @@ +#pragma once + +/* Main infrastructure for tst-dlmopen-rtld-* + Copyright © 2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* dlmopen ± RTLD_SHARED/RTLD_ISOLATE semantics: + + RTLD_ISOLATE's purpose is to suppress all shared behaviour, + mainly used fir LD_AUDIT code paths but available to the user + and also useful for constructing test case preconditions. + + dlmopen should have the following behaviour: + + Notation: + Number of namespace (+ = make a new one in an empty NS) + | + [+]X[p] - p indicates a proxy + | + + → new enry after the dlmopen call + + Need to be able to inspect: + + list of dl handles before we start (base state) + list of dl handles after an action in each namespace + ns of a given dl handle + _real_ ns of a given handle (ie where does a proxy point) + + Target is a normal DSO: + Before | Target NS | RTLD Flags | After | handle NS | libc NS + =======+===========+============+========+===========+========= + dlmopen-rtld-shared1: + -------+-----------+------------+--------+-----------+--------- + - | 0 | - | +0 | 0 | 0 + 0 | 0 | - | 0 | 0 | 0 + 0 | 0 | SHARED | 0 | 0 | 0 + 0 | + | - | 0,+1 | 1 | 0 + 0,1 | 0 | - | 0,1 | 0 | 0 + 0,1 | 0 | SHARED | 0,1 | 0 | 0 + =======+===========+============+========+===========+========= + dlmopen-rtld-shared2: + -------+-----------+------------+--------+-----------+--------- + - | 0 | SHARED | +0 | 0 | 0 + 0 | + | SHARED | 0,+1p | 1p | 0 + 0,1p | 0 | - | 0,1p | 0 | 0 + 0,1p | 0 | SHARED | 0,1p | 0 | 0 + 0,1p | 1 | - | 0,1p | 1p | 0 + 0,1p | 1 | SHARED | 0,1p | 1p | 0 + =======+===========+============+========+===========+========= + dlmopen-rtld-shared3 + -------+-----------+------------+--------+-----------+--------- + - | + | - | +1 | 1 | 0 + 1 | 0 | - | +0,1 | 0 | 0 + 0,1 | 1 | - | 0,1 | 1 | 0 + 0,1 | 1 | SHARED | 0,1 | ERR | - + =======+===========+============+========+===========+========= + dlmopen-rtld-shared4 + -------+-----------+------------+--------+-----------+--------- + - | + | SHARED | +0,+1p | 1p | 0 + =======+===========+============+========+===========+========= + dlmopen-rtld-shared5 + -------+-----------+------------+--------+-----------+--------- + 1 | 0 | SHARED | +0,1 | 0 | 0 + =======+===========+============+========+===========+========= + dlmopen-rtld-shared6 + -------+-----------+------------+--------+-----------+--------- + 1 | 1 | - | 1 | 0 | 0 + 1 | 1 | SHARED | 1 | ERR | - + + Target is a DF_GNU_1_UNIQUE DSO: + Before | Target NS | RTLD Flags | After | handle NS | libc NS + =======+===========+============+========+===========+========= + dlmopen-rtld-unique1: + -------+-----------+------------+--------+-----------+--------- + - | 0 | - | +0 | 0 | 0 + 0 | 0 | - | 0 | 0 | 0 + 0 | 0 | SHARED | 0 | 0 | 0 + 0 | + | - | 0,+1p | 1p | 0 + 0,1p | 0 | - | 0,1p | 0 | 0 + 0,1p | 0 | SHARED | 0,1p | 0 | 0 + 0,1p | 1 | - | 0,1p | 1p | 0 + 0,1p | 1 | SHARED | 0,1p | 1p | 0 + =======+===========+============+========+===========+========= + dlmopen-rtld-unique2: + -------+-----------+------------+--------+-----------+--------- + - | 0 | SHARED | +0 | 0 | 0 + 0 | + | SHARED | 0,+1p | 1p | 0 + =======+===========+============+========+===========+========= + dlmopen-rtld-unique3: + -------+-----------+------------+--------+-----------+--------- + - | + | - | +0,+1p | 1p | 0 + =======+===========+============+========+===========+========= + dlmopen-rtld-unique4: + -------+-----------+------------+--------+-----------+--------- + - | + | SHARED | +0,+1p | 1p | 0 + =======+===========+============+========+===========+========= + dlmopen-rtld-unique5: + -------+-----------+------------+--------+-----------+--------- + - | + | ISOLATE | +1 | 1 | 1 + 1 | 0 | - | +0,1 | 0 | 0 + 0,1 | 0 | - | 0,1 | 0 | 0 + 0,1 | 0 | SHARED | 0,1 | 0 | 0 + 0,1 | 1 | - | 0,1 | ERR | - + =======+===========+============+========+===========+========= + dlmopen-rtld-unique6: + -------+-----------+------------+--------+-----------+--------- + - | +1 | ISOLATE | +1 | 1 | 1 + 1 | 1 | - | 1 | ERR | - + 1 | 1 | SHARED | 1 | ERR | - + 1 | 0 | SHARED | +0,1 | 0 | 0 + 0,1 | 1 | SHARED | 0,1 | ERR | - +*/ + +#include "tst-dlmopen-common.h" +#include +#include + +#define DSO_NORMAL "$ORIGIN/tst-dlmopen-sharedmod-norm.so" +#define DSO_UNIQUE "$ORIGIN/tst-dlmopen-sharedmod-uniq.so" +#define DSO_TESTFN "rtld_shared_testfunc" +#define DSO_NAMESTUB "tst-dlmopen-sharedmod-" +#define MAX_NS 16 + +#define END_TESTS { .name = NULL }, + +#define ERROR(test, fmt, ...) \ + ({ if (last_test != test) \ + printf ("FAILED: %s (%s):\n", test->name, test->desc); \ + printf ("%s @ %d - " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ + last_test = test; }) + +static void *last_test; + +typedef enum + { + NONE = 0, + DSO = 1, + PROXY = 2, + NEW = 4, + } dso_type; + +typedef struct +{ + const char *name; + const char *desc; + int is_prep_stage; + const char *dso_name; + int failure; + + struct + { + const char *dso_path; + Lmid_t ns; + int flags; + } args; + + dso_type preloaded[MAX_NS]; + dso_type loaded[MAX_NS]; + dso_type handle_type; + Lmid_t handle_ns; + Lmid_t free_ns; +} dlmopen_test_spec; + +struct r_scope_elem +{ + struct tst_lm **r_list; + unsigned int r_nlist; +}; + +/* This is a copy of the first part of the internal definition of + struct link_map from . We use it to check some + expected internal state that's not readily accessible via public APIs. + */ +struct tst_lm + { + /* These first few members are part of the protocol with the debugger. + This is the same format used in SVR4. */ + + ElfW(Addr) l_addr; /* Difference between the address in the ELF + file and the addresses in memory. */ + char *l_name; /* Absolute file name object was found in. */ + ElfW(Dyn) *l_ld; /* Dynamic section of the shared object. */ + struct tst_lm *l_next, *l_prev; /* Chain of loaded objects. */ + + /* All following members are internal to the dynamic linker. + They may change without notice. */ + + /* This is an element which is only ever different from a pointer to + the very same copy of this type when: + - A shallow copy of ld.so is placed in namespaces other than LM_ID_BASE. + - An object is proxied into a namespace by dlmopen with RTLD_SHARED. */ + struct tst_lm *l_real; + + /* Number of the namespace this link map belongs to. */ + Lmid_t l_ns; + + struct libname_list *l_libname; + /* Indexed pointers to dynamic section. + [0,DT_NUM) are indexed by the processor-independent tags. + [DT_NUM,DT_NUM+DT_THISPROCNUM) are indexed by the tag minus DT_LOPROC. + [DT_NUM+DT_THISPROCNUM,DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM) are + indexed by DT_VERSIONTAGIDX(tagvalue). + [DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM, + DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM) are indexed by + DT_EXTRATAGIDX(tagvalue). + [DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM, + DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM) are + indexed by DT_VALTAGIDX(tagvalue) and + [DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM, + DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM+DT_ADDRNUM) + are indexed by DT_ADDRTAGIDX(tagvalue), see . */ + + ElfW(Dyn) *l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM]; + const ElfW(Phdr) *l_phdr; /* Pointer to program header table in core. */ + ElfW(Addr) l_entry; /* Entry point location. */ + ElfW(Half) l_phnum; /* Number of program header entries. */ + ElfW(Half) l_ldnum; /* Number of dynamic segment entries. */ + + /* Array of DT_NEEDED dependencies and their dependencies, in + dependency order for symbol lookup (with and without + duplicates). There is no entry before the dependencies have + been loaded. */ + struct r_scope_elem l_searchlist; + + /* We need a special searchlist to process objects marked with + DT_SYMBOLIC. */ + struct r_scope_elem l_symbolic_searchlist; + + /* Dependent object that first caused this object to be loaded. */ + struct link_map *l_loader; + + /* Array with version names. */ + struct r_found_version *l_versions; + unsigned int l_nversions; + + /* Symbol hash table. */ + Elf_Symndx l_nbuckets; + Elf32_Word l_gnu_bitmask_idxbits; + Elf32_Word l_gnu_shift; + const ElfW(Addr) *l_gnu_bitmask; + union + { + const Elf32_Word *l_gnu_buckets; + const Elf_Symndx *l_chain; + }; + union + { + const Elf32_Word *l_gnu_chain_zero; + const Elf_Symndx *l_buckets; + }; + + unsigned int l_direct_opencount; /* Reference count for dlopen/dlclose. */ + enum /* Where this object came from. */ + { + lt_executable, /* The main executable program. */ + lt_library, /* Library needed by main executable. */ + lt_loaded /* Extra run-time loaded shared object. */ + } l_type:2; + unsigned int l_relocated:1; /* Nonzero if object's relocations done. */ + unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */ + unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */ + unsigned int l_proxy:1; /* Nonzero if object is a shallow copy. */ + unsigned int l_reserved:2; /* Reserved for internal use. */ + unsigned int l_phdr_allocated:1; /* Nonzero if the data structure pointed + to by `l_phdr' is allocated. */ + unsigned int l_soname_added:1; /* Nonzero if the SONAME is for sure in + the l_libname list. */ + unsigned int l_faked:1; /* Nonzero if this is a faked descriptor + without associated file. */ + unsigned int l_need_tls_init:1; /* Nonzero if GL(dl_init_static_tls) + should be called on this link map + when relocation finishes. */ + unsigned int l_auditing:1; /* Nonzero if the DSO is used in auditing. */ + unsigned int l_audit_any_plt:1; /* Nonzero if at least one audit module + is interested in the PLT interception.*/ + unsigned int l_removed:1; /* Nozero if the object cannot be used anymore + since it is removed. */ + unsigned int l_contiguous:1; /* Nonzero if inter-segment holes are + mprotected or if no holes are present at + all. */ + unsigned int l_symbolic_in_local_scope:1; /* Nonzero if l_local_scope + during LD_TRACE_PRELINKING=1 + contains any DT_SYMBOLIC + libraries. */ + unsigned int l_free_initfini:1; /* Nonzero if l_initfini can be + freed, ie. not allocated with + the dummy malloc in ld.so. */ + }; + +typedef struct { void *handle; Lmid_t ns; } test_handle; +static test_handle cached_handles[32]; + +static void +cache_test_handle (void *handle, Lmid_t ns) +{ + int i; + + for (i = 0; i < sizeof(cached_handles)/sizeof(test_handle); i++) + if (cached_handles[i].handle == NULL) + { + cached_handles[i].handle = handle; + cached_handles[i].ns = ns; + break; + } +} + +__attribute__((unused)) +static struct tst_lm * +link_map_of_dl_handle (void *handle) +{ + struct tst_lm *lm = NULL; + + if (dlinfo (handle, RTLD_DI_LINKMAP, &lm) == 0) + return lm; + + printf ("dlinfo (LINKMAP) for %s in %s failed: %s\n", + LIBC_SO, __func__, dlerror ()); + + return NULL; +} + +__attribute__((unused)) +static Lmid_t +ns_of_dl_handle (void *handle) +{ + Lmid_t ns = 0; + + if (dlinfo (handle, RTLD_DI_LMID, &ns) == 0) + return ns; + + printf ("dlinfo (LMID) for %s in %s failed: %s\n", + LIBC_SO, __func__, dlerror ()); + + return -1; +} + +__attribute__((unused)) +static Lmid_t real_ns_of_dl_handle (void *handle) +{ + Lmid_t ns = 0; + struct tst_lm *lm = link_map_of_dl_handle (handle); + + if (lm == NULL) + return -1; + + // printf ("DEBUG: handle %p; LM %p; proxy: %d / %p\n", + // handle, lm, lm->l_proxy, lm->l_real); + + if (lm->l_proxy) + { + // printf ("DEBUG: proxy %p vs real %p\n", lm, lm->l_real); + ns = ns_of_dl_handle ((void *) lm->l_real); + } + else + ns = ns_of_dl_handle (handle); + + return ns; +} + +__attribute__((unused)) +static const char *str_soname (const char *name) +{ + char *slash = NULL; + + if (name == NULL) + return NULL; + + if ((slash = strrchr (name, '/'))) + return ++slash; + else + return name; +} + +__attribute__((unused)) +static const char *lm_name (struct tst_lm *lm) +{ + if (lm) + return lm->l_name; + + return NULL; +} + + +static int dlm_dso_is_loaded (void *handle) +{ + if (handle != RTLD_DEFAULT) + { +#ifdef DEBUG_DSO_LOADCHECK + Dl_info sinfo = {}; +#endif + + if (((struct tst_lm *) handle)->l_type != lt_loaded) + return 0; + +#ifdef DEBUG_DSO_LOADCHECK + printf ("checking %p %s for %s\n", + handle, ((struct tst_lm *)handle)->l_name, DSO_TESTFN); +#endif + + void *symbol = dlsym (handle, DSO_TESTFN); + +#ifdef DEBUG_DSO_LOADCHECK + dladdr (symbol, &sinfo); + printf (" -> %s (in %s (%p))\n", + sinfo.dli_fname, + sinfo.dli_sname, + sinfo.dli_saddr); +#endif + + return symbol ? 1 : 0; + } + + for (int i = 0; i < sizeof(cached_handles)/sizeof(test_handle); i++) + { + if (cached_handles[i].handle == NULL) + break; + + if (((struct tst_lm *) cached_handles[i].handle)->l_type != lt_loaded) + continue; + +#ifdef DEBUG_DSO_LOADCHECK + printf ("checking %p %s for %s\n", + cached_handles[i].handle, + ((struct tst_lm *)cached_handles[i].handle)->l_name, + DSO_TESTFN); +#endif + + if (dlsym (cached_handles[i].handle, DSO_TESTFN) != NULL) + return 1; + } + + return 0; +} + +static int call_testfunc (dlmopen_test_spec *test, void *handle) +{ + Dl_info dli = {}; + struct tst_lm *lm = NULL; + dlmopen_testfunc func = NULL; + dlmopen_testresult *result = NULL; + + if (handle != RTLD_DEFAULT) + func = dlsym (handle, DSO_TESTFN); + + if (func == NULL) + { + ERROR (test, "test function %s not found\n", DSO_TESTFN); + return 0; + } + + result = (func)(); + + if (result == NULL) + { + ERROR (test, "test function %s returned NULL\n", DSO_TESTFN); + return 0; + } + + dladdr1 (result->free, &dli, (void **)&lm, RTLD_DL_LINKMAP); + + if (lm == NULL) + { + ERROR (test, "free() implementation from test module is invalid\n"); + return 0; + } + + if (lm->l_ns != test->free_ns) + { + ERROR (test, + "free() function from test module was from ns %d, expected %d\n", + (int)lm->l_ns, (int)test->free_ns); + return 0; + } + + printf ("%s: %s: %s in ns %d using free() from ns %d: OK\n", + test->name, test->args.dso_path, DSO_TESTFN, + (int)test->handle_ns, (int)lm->l_ns); + + return 1; +} + +static void *link_map_snapshot_array (void *handle, void *func, Lmid_t ns, size_t *len) +{ + struct tst_lm *lm = NULL; + struct tst_lm *start = NULL; + + if (len) + *len = 0; + + if (handle != NULL) + { + dlinfo (handle, RTLD_DI_LINKMAP, &lm); + } + else if (func != NULL) + { + Dl_info dli = {}; + + dladdr1 (func, &dli, (void **)&lm, RTLD_DL_LINKMAP); + } + else if (ns >= LM_ID_BASE) + { + for (int i = 0; i < sizeof(cached_handles)/sizeof(test_handle); i++) + { + if (cached_handles[i].handle == NULL) + break; + + if (cached_handles[i].ns != ns) + continue; + + dlinfo (cached_handles[i].handle, RTLD_DI_LINKMAP, &lm); + break; + } + } + + if (lm == NULL) + return NULL; + + start = lm; + + while (start->l_prev) + start = start->l_prev; + + size_t lm_size = 0; + + for (lm = start; lm; lm = lm->l_next) + lm_size++; + + struct tst_lm **lm_list = calloc (lm_size + 1, sizeof (struct tst_lm *)); + + if (len) + *len = lm_size; + + int i = 0; + + for (lm = start; lm; lm = lm->l_next) + lm_list[i++] = lm; + lm_list[i] = NULL; + + return lm_list; +} + +__attribute__((unused)) +static int search_link_map_array (struct tst_lm **lma, size_t len, void *handle) +{ + if (lma == NULL) + return 0; + + if (len == 0) + return 0; + + struct tst_lm *target = link_map_of_dl_handle (handle); + + for (int i = 0; i < len; i++) + { + //printf ("searching for %p in <%p>[%d] == %p\n", + // handle, lma, i, lma[i]); + if (handle == (struct tst_lm *)(lma[i])) + return 1; + + if (target->l_proxy) + if (target->l_real == (struct tst_lm *)(lma[i])) + return 1; + } + + return 0; +} + +#ifdef DEBUG_DSO_SEARCH +#define TRACE2(fmt, ...) \ + printf (" find-test-dso (%s @ %d): " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#else +#define TRACE2(fmt, ...) +#endif + +static struct tst_lm * +find_test_dso_in_link_map_array (struct tst_lm **lma, size_t len) +{ + if (lma == NULL) + return NULL; + + if (len == 0) + return NULL; + + for (int i = 0; i < len; i++) + { + if (!lma[i] || !lma[i]->l_name) + continue; + + TRACE2 ("%p [%d/%d] %s", lma, i, (int)len - 1, + lma[i] ? (lma[i]->l_name ?: "???.so") : "NULL" ); + + if (lma[i] && lma[i]->l_name) + if (strstr (lma[i]->l_name, DSO_NAMESTUB)) + if (dlsym (lma[i], DSO_TESTFN) != NULL) + return (struct tst_lm *)lma[i]; + } + + return NULL; +} + +__attribute__((unused)) +static void *link_map_list (void *handle, void *func, int *len, Lmid_t *ns) +{ + struct tst_lm *lm = NULL; + struct tst_lm *start = NULL; + + if (len) + *len = 0; + + if (handle != NULL) + { + dlinfo (handle, RTLD_DI_LINKMAP, &lm); + } + else if (func != NULL) + { + Dl_info dli = {}; + + dladdr1 (func, &dli, (void **)&lm, RTLD_DL_LINKMAP); + } + + if (lm == NULL) + return NULL; + + if (ns) + *ns = lm->l_ns; + + // rewind to start of link map list: + start = lm; + + while (start->l_prev) + start = start->l_prev; + + size_t lm_size = 0; + + for (lm = start; lm; lm = lm->l_next) + lm_size++; + + if (len) + *len = lm_size; + + return start; +} + +#ifdef DEBUG_DLMOPEN_TEST_WRAPPER +#define TRACE(fmt, ...) \ + printf ("%s (%s @ %d): " fmt "\n", test->name, __FILE__, __LINE__, ##__VA_ARGS__) +#else +#define TRACE(fmt, ...) +#endif + +static int process_test_spec (dlmopen_test_spec *test) +{ + void *handle = NULL; + size_t lm_before_len[MAX_NS] = { 0 }; + size_t lm_after_len[MAX_NS] = { 0 }; + struct tst_lm **lm_before[MAX_NS] = { NULL }; + struct tst_lm **lm_after[MAX_NS] = { NULL }; + struct tst_lm *preloads[MAX_NS] = { NULL }; + int want_preload = 0; + int test_status = 0; + + memset (&lm_after[0], 0, sizeof (lm_after)); + memset (&lm_before[0], 0, sizeof (lm_before)); + memset (&preloads[0], 0, sizeof (preloads)); + + TRACE("LD_AUDIT = %s", getenv("LD_AUDIT") ?: "-"); + TRACE("BEFORE SNAPSHOTS: %p", &lm_before[0]); + TRACE("AFTER SNAPSHOTS: %p", &lm_after[0]); + TRACE("preloads : %p", preloads); + TRACE("setup done"); + + if (test->args.dso_path && *test->args.dso_path && !test->dso_name) + test->dso_name = str_soname (test->args.dso_path); + + TRACE("DSO short name: %s", test->dso_name); + + // get the existing link map contents before the test runs: + lm_before[0] = link_map_snapshot_array (NULL, process_test_spec, + LM_ID_BASE, &lm_before_len[0]); + for (int i = 1; i < MAX_NS; i++) + lm_before[i] = link_map_snapshot_array (NULL, NULL, i, &lm_before_len[i]); + + TRACE("link map snapshots cached"); + + for (int i = 0; i < MAX_NS; i++) + { + if (test->preloaded[i] & PROXY) + { + struct tst_lm **lm = lm_before[i]; + want_preload++; + + if (lm != NULL) + for (int j = 0; !preloads[i] && (j < lm_before_len[i]); j++) + if (dlm_dso_is_loaded (lm[j]) && lm[j]->l_proxy) + preloads[i] = lm[j]; + + if (!preloads[i]) + { + ERROR (test, + "needed proxy for %s preloaded in NS %d, not found\n", + test->dso_name, i); + goto cleanup; + } + } + else if (test->preloaded[i] & DSO) + { + struct tst_lm **lm = lm_before[i]; + int lm_max = lm_before_len[i]; + want_preload++; + + if (lm != NULL) + for (int j = 0; !preloads[i] && (j < lm_max); j++) + { + if (dlm_dso_is_loaded (lm[j]) && !lm[j]->l_proxy) + preloads[i] = lm[j]; + } + if (!preloads[i]) + { + ERROR (test, + "needed %s preloaded in NS %d, not found\n", + test->dso_name, i); + goto cleanup; + } + } + } + TRACE("preload checks (A)"); + + if (dlm_dso_is_loaded (RTLD_DEFAULT)) + { + // test DSO module must _not_ be preloaded, and is: + if (!want_preload) + { + ERROR (test, "DSO %s unexpectedly loaded before test\n", test->dso_name); + goto cleanup; + } + } + else + { + // DSO is not loaded, and must be: + // In theory we can never see this error as it + // should be caught by the preceding preload loop: + if (want_preload) + { + ERROR (test, "DSO %s must be preloaded (and is not)\n", test->args.dso_path); + goto cleanup; + } + } + TRACE("preload checks (B) %s", test->name); + + if (!(test->args.flags & (RTLD_NOW|RTLD_LAZY))) + test->args.flags |= RTLD_NOW; + + handle = dlmopen (test->args.ns, test->args.dso_path, test->args.flags); + TRACE("dlmopen returned %p", handle); + + if (handle == NULL) + { + const char *status = "failed"; + + if (test->failure) + { + status = "failed (EXPECTED)"; + test_status = 1; + + printf ("%s: dlmopen(%s, %d, 0x%0x) failed: OK\n", + test->name, test->args.dso_path, + (int)test->args.ns, (int)test->args.flags); + printf ("Returned: %p\n\n", handle); + + goto cleanup; + } + + ERROR (test, ""); + + if (test->is_prep_stage) + printf ("(during setup of preconditions): "); + else + printf (": "); + + if (test->args.ns == LM_ID_BASE) + printf ("dlmopen (LM_ID_BASE, \"%s\", 0x%x) %s: %s\n", + test->args.dso_path, test->args.flags, status, dlerror ()); + else + printf ("dlmopen (%d, \"%s\", 0x%x) %s: %s\n", + (int)test->args.ns, test->args.dso_path, test->args.flags, status, dlerror ()); + + goto cleanup; + } + else if (test->failure) + { + ERROR (test, "dlmopen() call should have failed, but did not\n"); + goto cleanup; + } + + TRACE("return status checked"); + + if (!dlm_dso_is_loaded (handle)) + { + ERROR (test, "DSO %s (%p) missing function (%s)\n", + test->args.dso_path, handle, DSO_TESTFN); + goto cleanup; + } + + TRACE ("loaded DSO sanity checked"); + + Lmid_t hns = ns_of_dl_handle (handle); + Lmid_t real_hns = real_ns_of_dl_handle (handle); + Lmid_t proxy_ns = 0; + + call_testfunc (test, handle); + TRACE (DSO_TESTFN "called"); + + cache_test_handle (handle, hns); + TRACE ("handle %p cached (ns %d)", handle, (int)hns); + + // if the real ns was different to the apparent one + // then we have a proxy and we need to shuffle the values, + // else leave the proxy ns as 0 as an expect.proxy_ns of 0 + // means we weren't expecting a proxy: + if (real_hns != hns) + { + proxy_ns = hns; + hns = real_hns; + } + + if (proxy_ns) + printf ("Returned: proxy ns:%d (real ns: %d)\n\n", (int)proxy_ns, (int)hns); + else + printf ("Returned: dso ns:%d\n\n", (int)hns); + + Lmid_t expected; + if (test->handle_type & PROXY) + expected = proxy_ns; + else + expected = hns; + + TRACE("check expected ns %d", (int)expected); + + if (test->args.ns == LM_ID_NEWLM) + { + if (expected <= LM_ID_BASE) + { + ERROR (test, "DSO should have been in NS > %d, was in %d\n", + LM_ID_BASE, (int)expected); + goto cleanup; + } + + // for any cases where we can't predict + // the namespace in advance: + if (test->handle_ns == LM_ID_NEWLM) + test->handle_ns = expected; + } + else + { + if (test->args.ns != expected) + { + ERROR (test, "DSO should have been in NS %d, was in %d\n", + (int)test->args.ns, (int)expected); + goto cleanup; + } + } + + TRACE("ns %d Ok", (int)expected); + + if (test->handle_type & PROXY) // expecting a proxy + { + if (proxy_ns != 0) // got a proxy + { + if (test->handle_ns != proxy_ns) // but not in the right place + { + ERROR (test, "DSO proxy should have been in ns %d, was in %d\n", + (int)test->handle_ns, (int)proxy_ns); + goto cleanup; + } + } + else // didn't get a proxy + { + ERROR (test, + "DSO should have been a proxy in ns %d," + " was a non-proxy in ns %d\n", + (int)test->handle_ns, (int)hns); + goto cleanup; + } + } + else // not expecting a proxy + { + if (proxy_ns > 0) + { + ERROR (test, + "DSO should NOT have been a proxy," + " was a proxy in ns %d (real ns %d)\n", + (int)proxy_ns, (int)hns); + goto cleanup; + } + + if (test->handle_ns != hns) + { + ERROR (test, + "DSO should have been in ns %d," + " was in ns %d\n", + (int)test->handle_ns, (int)hns); + goto cleanup; + } + } + TRACE ("proxy status Ok"); + + // get the new link map contents after the test has run: + lm_after[0] = link_map_snapshot_array (NULL, process_test_spec, + LM_ID_BASE, &lm_after_len[0]); + for (int i = 1; i < MAX_NS; i++) + lm_after[i] = link_map_snapshot_array (NULL, NULL, i, &lm_after_len[i]); + + for (int i = 0; i < MAX_NS; i++) + { + TRACE("checking status of NS %d", i); + void *old_handle = + find_test_dso_in_link_map_array (lm_before[i], lm_before_len[i]); + TRACE ("old handle is %p", old_handle); + + void *new_handle = + find_test_dso_in_link_map_array (lm_after[i], lm_after_len[i]); + TRACE ("new handle is %p", new_handle); + + if (test->loaded[i] == NONE) + { + TRACE ("ns %d requirement is NONE", i); + if (old_handle != NULL) + { + ERROR (test, + "Unexpected preload DSO %s in ns %d\n", + lm_name (old_handle), i); + goto cleanup; + } + if (new_handle != NULL) + { + ERROR (test, "Unexpected new DSO %s in ns %d\n", + lm_name (new_handle), i); + goto cleanup; + } + continue; + } + + if (test->loaded[i] & NEW) + { + TRACE("ns %d requirement is NEW", i); + if (old_handle != NULL) + { + ERROR (test, + "DSO in ns %d should have been a new load," + " found to have been preloaded\n", i); + goto cleanup; + } + if (new_handle == NULL) + { + ERROR (test, "Expected DSO in ns %d, not found\n", i); + goto cleanup; + } + } + else + { + TRACE("ns %d requirement is OLD", i); + if (new_handle == NULL) + { + ERROR (test, "Expected new DSO in ns %d, not found\n", i); + goto cleanup; + } + + if (old_handle != new_handle) + { + ERROR (test, "DSO in ns %d changed. This should be impossible, " + "sanity check the test code in %s\n", i, __FILE__); + goto cleanup; + } + } + + if (test->loaded[i] & PROXY) + { + TRACE ("rechecking DSO status in ns %d", i); + if (!((struct tst_lm *)new_handle)->l_proxy) + { + ERROR (test, "DSO in ns %d should be a proxy but is not\n", i); + goto cleanup; + } + } + else + { + TRACE ("rechecking proxy status in ns %d", i); + if (((struct tst_lm *)new_handle)->l_proxy) + { + ERROR (test, "DSO in ns %d should NOT be a proxy but is\n", i); + goto cleanup; + } + } + } + + test_status = 1; + + cleanup: + for (int i = 0; i < MAX_NS; i++) + free (lm_after[i]); + for (int i = 0; i < MAX_NS; i++) + free (lm_before[i]); + + return test_status; +} + + diff --git a/elf/tst-dlmopen-modules.h b/elf/tst-dlmopen-modules.h new file mode 100644 index 0000000000..4bbf431ec3 --- /dev/null +++ b/elf/tst-dlmopen-modules.h @@ -0,0 +1,20 @@ +#pragma once +/* Module-specific infrastructure for tst-dlmopen-rtld-* + Copyright © 2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include "tst-dlmopen-common.h" diff --git a/elf/tst-dlmopen-rtld-audit-shared1.c b/elf/tst-dlmopen-rtld-audit-shared1.c new file mode 100644 index 0000000000..1e9f604327 --- /dev/null +++ b/elf/tst-dlmopen-rtld-audit-shared1.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 2 +#include "tst-dlmopen-rtld-shared1.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-audit-shared2.c b/elf/tst-dlmopen-rtld-audit-shared2.c new file mode 100644 index 0000000000..53064dd345 --- /dev/null +++ b/elf/tst-dlmopen-rtld-audit-shared2.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 2 +#include "tst-dlmopen-rtld-shared2.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-audit-shared3.c b/elf/tst-dlmopen-rtld-audit-shared3.c new file mode 100644 index 0000000000..de90bc1258 --- /dev/null +++ b/elf/tst-dlmopen-rtld-audit-shared3.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 2 +#include "tst-dlmopen-rtld-shared3.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-audit-shared4.c b/elf/tst-dlmopen-rtld-audit-shared4.c new file mode 100644 index 0000000000..c600b2f4dc --- /dev/null +++ b/elf/tst-dlmopen-rtld-audit-shared4.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 2 +#include "tst-dlmopen-rtld-shared4.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-audit-shared5.c b/elf/tst-dlmopen-rtld-audit-shared5.c new file mode 100644 index 0000000000..cd223d041b --- /dev/null +++ b/elf/tst-dlmopen-rtld-audit-shared5.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 2 +#include "tst-dlmopen-rtld-shared5.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-audit-shared6.c b/elf/tst-dlmopen-rtld-audit-shared6.c new file mode 100644 index 0000000000..f84303b1b4 --- /dev/null +++ b/elf/tst-dlmopen-rtld-audit-shared6.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 2 +#include "tst-dlmopen-rtld-shared6.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-audit-unique1.c b/elf/tst-dlmopen-rtld-audit-unique1.c new file mode 100644 index 0000000000..f60b9c05d4 --- /dev/null +++ b/elf/tst-dlmopen-rtld-audit-unique1.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 2 +#include "tst-dlmopen-rtld-unique1.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-audit-unique2.c b/elf/tst-dlmopen-rtld-audit-unique2.c new file mode 100644 index 0000000000..199b1d3606 --- /dev/null +++ b/elf/tst-dlmopen-rtld-audit-unique2.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 2 +#include "tst-dlmopen-rtld-unique2.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-audit-unique3.c b/elf/tst-dlmopen-rtld-audit-unique3.c new file mode 100644 index 0000000000..f3ebe58828 --- /dev/null +++ b/elf/tst-dlmopen-rtld-audit-unique3.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 2 +#include "tst-dlmopen-rtld-unique3.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-audit-unique4.c b/elf/tst-dlmopen-rtld-audit-unique4.c new file mode 100644 index 0000000000..ef555672d2 --- /dev/null +++ b/elf/tst-dlmopen-rtld-audit-unique4.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 2 +#include "tst-dlmopen-rtld-unique4.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-audit-unique5.c b/elf/tst-dlmopen-rtld-audit-unique5.c new file mode 100644 index 0000000000..b7faa5d02c --- /dev/null +++ b/elf/tst-dlmopen-rtld-audit-unique5.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 2 +#include "tst-dlmopen-rtld-unique5.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-audit-unique6.c b/elf/tst-dlmopen-rtld-audit-unique6.c new file mode 100644 index 0000000000..d431e3a787 --- /dev/null +++ b/elf/tst-dlmopen-rtld-audit-unique6.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 2 +#include "tst-dlmopen-rtld-unique6.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-shared1.c b/elf/tst-dlmopen-rtld-shared1.c new file mode 100644 index 0000000000..812d21e692 --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared1.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 1 +#include "tst-dlmopen-rtld-shared1.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-shared1.h b/elf/tst-dlmopen-rtld-shared1.h new file mode 100644 index 0000000000..bd733cb3c4 --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared1.h @@ -0,0 +1,65 @@ +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen:0:none--ns0", + .desc = "dlmopen as dlopen", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .loaded = { [0] = DSO|NEW }, + .handle_type = DSO, + .handle_ns = LM_ID_BASE, + }, + { + .name = "dlmopen:0:ns0--ns0", + .desc = "dlmopen a preloaded DSO in the base NS", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .preloaded = { [0] = DSO }, + .loaded = { [0] = DSO }, + .handle_type = DSO, + .handle_ns = LM_ID_BASE, + }, + { + .name = "dlmopen-shared:0:ns0--ns0", + .desc = "dlmopen a preloaded DSO in the base NS with RTLD_SHARED", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .args.flags = RTLD_SHARED, + .preloaded = { [0] = DSO }, + .loaded = { [0] = DSO }, + .handle_type = DSO, + .handle_ns = LM_ID_BASE, + }, + { + .name = "dlmopen:0:ns0--nsX", + .desc = "dlmopen a preloaded DSO in the base NS into a new NS", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_NEWLM, + .preloaded = { [0] = DSO }, + .loaded = { [0] = DSO, [EXPECTED_NS] = DSO|NEW }, + .handle_type = DSO, + .handle_ns = EXPECTED_NS, + }, + { + .name = "dlmopen:0:ns0-nsX--ns0-nsX", + .desc = "dlmopen a preloaded DSO in the base & secondary NS into the base NS", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .preloaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + .loaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + .handle_type = DSO, + .handle_ns = LM_ID_BASE, + }, + { + .name = "dlmopen-shared:0:ns0-nsX--ns0-nsX", + .desc = "dlmopen a preloaded DSO in the base & secondary NS into the base NS", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .args.flags = RTLD_SHARED, + .preloaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + .loaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + .handle_type = DSO, + .handle_ns = LM_ID_BASE, + }, + END_TESTS + }; diff --git a/elf/tst-dlmopen-rtld-shared2.c b/elf/tst-dlmopen-rtld-shared2.c new file mode 100644 index 0000000000..f830832a0a --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared2.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 1 +#include "tst-dlmopen-rtld-shared2.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-shared2.h b/elf/tst-dlmopen-rtld-shared2.h new file mode 100644 index 0000000000..9775619b9a --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared2.h @@ -0,0 +1,67 @@ +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-shared:0:none--ns0", + .desc = "dlmopen as dlopen with RTLD_SHARED", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .args.flags = RTLD_SHARED, + .loaded = { [0] = DSO|NEW }, + .handle_ns = LM_ID_BASE, + .handle_type = DSO, + }, + { + .name = "dlmopen-shared:X:ns0--ns0-nsXp", + .desc = "dlmopen into a new namespace with the target already in the base NS", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_NEWLM, + .args.flags = RTLD_SHARED, + .handle_ns = EXPECTED_NS, + .handle_type = PROXY, + .preloaded = { [0] = DSO }, + .loaded = { [0] = DSO, [EXPECTED_NS] = PROXY|NEW } + }, + { + .name = "dlmopen:0:ns0-nsXp--ns0-nsXp", + .desc = "dlmopen into base NS while proxy already in nsX", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + .loaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + }, + { + .name = "dlmopen-shared:0:ns0-nsXp--ns0-nsXp", + .desc = "dlmopen with RTLD_SHARED into base NS while proxy already in nsX", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .args.flags = RTLD_SHARED, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + .loaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + }, + { + .name = "dlmopen:X:ns0-nsXp--ns0-nsXp", + .desc = "dlmopen into NS X while proxy already in nsX", + .args.dso_path = DSO_NORMAL, + .args.ns = EXPECTED_NS, + .handle_ns = EXPECTED_NS, + .handle_type = PROXY, + .preloaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + .loaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + }, + { + .name = "dlmopen-shared:X:ns0-nsXp--ns0-nsXp", + .desc = "dlmopen with RTLD_SHARED into NS X while proxy already in nsX", + .args.dso_path = DSO_NORMAL, + .args.ns = EXPECTED_NS, + .args.flags = RTLD_SHARED, + .handle_ns = EXPECTED_NS, + .handle_type = PROXY, + .preloaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + .loaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + }, + END_TESTS + }; diff --git a/elf/tst-dlmopen-rtld-shared3.c b/elf/tst-dlmopen-rtld-shared3.c new file mode 100644 index 0000000000..a63753eb84 --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared3.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 1 +#include "tst-dlmopen-rtld-shared3.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-shared3.h b/elf/tst-dlmopen-rtld-shared3.h new file mode 100644 index 0000000000..23fce58bae --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared3.h @@ -0,0 +1,44 @@ +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen:X:none--nsX", + .desc = "dlmopen into nsX, no copies preloaded", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_NEWLM, + .handle_ns = EXPECTED_NS, + .handle_type = DSO, + .preloaded = { }, + .loaded = { [EXPECTED_NS] = DSO|NEW }, + }, + { + .name = "dlmopen:0:nsX--ns0-nsX", + .desc = "dlmopen into ns 0, copy already loaded in ns X", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [EXPECTED_NS] = DSO }, + .loaded = { [0] = DSO|NEW, [EXPECTED_NS] = DSO }, + }, + { + .name = "dlmopen:X:ns0-nsX--nsX", + .desc = "dlmopen into ns X, copies already in ns 0 and ns X", + .args.dso_path = DSO_NORMAL, + .args.ns = EXPECTED_NS, + .handle_ns = EXPECTED_NS, + .handle_type = DSO, + .preloaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + .loaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + }, + { + .name = "dlmopen-shared:X:ns0-nsX--nsX", + .desc = "dlmopen RTLD_SHARED into nsX with a DSO already in NS0 and NSX", + .args.dso_path = DSO_NORMAL, + .args.ns = EXPECTED_NS, + .args.flags = RTLD_SHARED, + .failure = 1, + .preloaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + .loaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + }, + END_TESTS + }; diff --git a/elf/tst-dlmopen-rtld-shared4.c b/elf/tst-dlmopen-rtld-shared4.c new file mode 100644 index 0000000000..7c3d92e37b --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared4.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 1 +#include "tst-dlmopen-rtld-shared4.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-shared4.h b/elf/tst-dlmopen-rtld-shared4.h new file mode 100644 index 0000000000..9ad29b9a6d --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared4.h @@ -0,0 +1,15 @@ +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-shared:X:none--ns0-nsX", + .desc = "dlmopen a new proxy in nsX with no preexisting dso in ns0", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_NEWLM, + .args.flags = RTLD_SHARED, + .handle_ns = EXPECTED_NS, + .handle_type = PROXY, + .preloaded = { }, + .loaded = { [0] = DSO|NEW, [EXPECTED_NS] = PROXY|NEW }, + }, + END_TESTS + }; diff --git a/elf/tst-dlmopen-rtld-shared5.c b/elf/tst-dlmopen-rtld-shared5.c new file mode 100644 index 0000000000..f59d14e7b6 --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared5.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 1 +#include "tst-dlmopen-rtld-shared5.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-shared5.h b/elf/tst-dlmopen-rtld-shared5.h new file mode 100644 index 0000000000..220129a5cf --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared5.h @@ -0,0 +1,26 @@ +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-preload:X:none--nsX", + .desc = "preload a DSO into ns1 to prepare for other tests", + .is_prep_stage = 1, + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_NEWLM, + .handle_ns = EXPECTED_NS, + .handle_type = DSO, + .preloaded = { }, + .loaded = { [EXPECTED_NS] = DSO|NEW }, + }, + { + .name = "dlmopen-shared:0:nsX--nsX-ns0", + .desc = "dlmopen RTLD_SHARED into ns0 when preloaded into nsX", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .args.flags = RTLD_SHARED, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [EXPECTED_NS] = DSO }, + .loaded = { [0] = DSO|NEW, [EXPECTED_NS] = DSO }, + }, + END_TESTS + }; diff --git a/elf/tst-dlmopen-rtld-shared6.c b/elf/tst-dlmopen-rtld-shared6.c new file mode 100644 index 0000000000..469fb3566d --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared6.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 1 +#include "tst-dlmopen-rtld-shared6.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-shared6.h b/elf/tst-dlmopen-rtld-shared6.h new file mode 100644 index 0000000000..116e53ea51 --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared6.h @@ -0,0 +1,37 @@ +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-preload:X:none--nsX", + .desc = "preload a DSO into nsX to prepare for other tests", + .is_prep_stage = 1, + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_NEWLM, + .handle_ns = EXPECTED_NS, + .handle_type = DSO, + .preloaded = { }, + .loaded = { [EXPECTED_NS] = DSO|NEW }, + }, + { + .name = "dlmopen:X:nsX--nsX", + .desc = "dlmopen a dso in nsX while already loaded there", + .args.dso_path = DSO_NORMAL, + .args.ns = EXPECTED_NS, + .handle_ns = EXPECTED_NS, + .handle_type = DSO, + .preloaded = { [EXPECTED_NS] = DSO }, + .loaded = { [EXPECTED_NS] = DSO }, + }, + { + .name = "dlmopen-shared:X:nsX--nsX", + .desc = "dlmopen RTLD_SHARED a dso in nsX while already loaded there", + .failure = 1, + .args.dso_path = DSO_NORMAL, + .args.ns = EXPECTED_NS, + .args.flags = RTLD_SHARED, + .handle_ns = EXPECTED_NS, + .handle_type = DSO, + .preloaded = { [EXPECTED_NS] = DSO }, + .loaded = { [EXPECTED_NS] = DSO }, + }, + END_TESTS + }; diff --git a/elf/tst-dlmopen-rtld-unique1.c b/elf/tst-dlmopen-rtld-unique1.c new file mode 100644 index 0000000000..867345582f --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique1.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 1 +#include "tst-dlmopen-rtld-unique1.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-unique1.h b/elf/tst-dlmopen-rtld-unique1.h new file mode 100644 index 0000000000..f7d32959c2 --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique1.h @@ -0,0 +1,87 @@ +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-unique:0:none--ns0", + .desc = "dlmopen a DF_GNU_1_UNIQUE dso into ns0", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_BASE, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { }, + .loaded = { [0] = DSO|NEW }, + }, + { + .name = "dlmopen-unique:0:ns0--ns0", + .desc = "dlmopen a DF_GNU_1_UNIQUE dso into ns0 while already present", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_BASE, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [0] = DSO }, + .loaded = { [0] = DSO }, + }, + { + .name = "dlmopen-unique-shared:0:ns0--ns0", + .desc = "dlmopen RTLD_SHARED a DF_GNU_1_UNIQUE dso into ns0 while already present", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_BASE, + .args.flags = RTLD_SHARED, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [0] = DSO }, + .loaded = { [0] = DSO }, + }, + { + .name = "dlmopen-unique:X:ns0--nsX", + .desc = "dlmopen a DF_GNU_1_UNIQUE dso into nsX while present in ns0", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_NEWLM, + .handle_ns = EXPECTED_NS, + .handle_type = PROXY, + .preloaded = { [0] = DSO }, + .loaded = { [0] = DSO, [EXPECTED_NS] = PROXY|NEW }, + }, + { + .name = "dlmopen-unique:0:ns0-nsXp--ns0--nsXp", + .desc = "dlmopen a DF_GNU_1_UNIQUE dso already in ns0 proxied in nsX", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_BASE, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + .loaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + }, + { + .name = "dlmopen-shared-unique:0:ns0-nsXp--ns0-nsXp", + .desc = "dlmopen RTLD_SHARED a DF_GNU_1_UNIQUE dso into ns0 already in ns0 and proxied in nsX", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_BASE, + .args.flags = RTLD_SHARED, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + .loaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + }, + { + .name = "dlmopen-unique:0:ns0-nsXp--ns0-nsXp", + .desc = "dlmopen a DF_GNU_1_UNIQUE dso into ns0 already in ns0 and proxied in nsX", + .args.dso_path = DSO_UNIQUE, + .args.ns = EXPECTED_NS, + .handle_ns = EXPECTED_NS, + .handle_type = PROXY, + .preloaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + .loaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + }, + { + .name = "dlmopen-unique:0:ns0-nsXp--ns0-nsXp", + .desc = "dlmopen RTLD_SHARED a DF_GNU_1_UNIQUE dso into ns0 already in ns0 and proxied in nsX", + .args.dso_path = DSO_UNIQUE, + .args.ns = EXPECTED_NS, + .args.flags = RTLD_SHARED, + .handle_ns = EXPECTED_NS, + .handle_type = PROXY, + .preloaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + .loaded = { [0] = DSO, [EXPECTED_NS] = PROXY }, + }, + END_TESTS + }; diff --git a/elf/tst-dlmopen-rtld-unique2.c b/elf/tst-dlmopen-rtld-unique2.c new file mode 100644 index 0000000000..dabb87b43f --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique2.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 1 +#include "tst-dlmopen-rtld-unique2.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-unique2.h b/elf/tst-dlmopen-rtld-unique2.h new file mode 100644 index 0000000000..911e0180ab --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique2.h @@ -0,0 +1,26 @@ +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-shared-unique:0:none--ns0", + .desc = "dlmopen RTLD_SHARED a DF_GNU_1_UNIQUE dso in the base ns", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_BASE, + .args.flags = RTLD_SHARED, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { }, + .loaded = { [0] = DSO|NEW }, + }, + { + .name = "dlmopen-shared-unique:1:ns0--ns0-ns1p", + .desc = "dlmopen RTLD_SHARED a DF_GNU_1_UNIQUE dso into ns1 while present in ns0", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_NEWLM, + .args.flags = RTLD_SHARED, + .handle_ns = EXPECTED_NS, + .handle_type = PROXY, + .preloaded = { [0] = DSO }, + .loaded = { [0] = DSO, [EXPECTED_NS] = PROXY|NEW }, + }, + END_TESTS + }; diff --git a/elf/tst-dlmopen-rtld-unique3.c b/elf/tst-dlmopen-rtld-unique3.c new file mode 100644 index 0000000000..db8a567a3f --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique3.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 1 +#include "tst-dlmopen-rtld-unique3.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-unique3.h b/elf/tst-dlmopen-rtld-unique3.h new file mode 100644 index 0000000000..b400bad07f --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique3.h @@ -0,0 +1,14 @@ +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-unique:X:none--ns0-ns1p", + .desc = "dlmopen a DF_GNU_1_UNIQUE dso into nsX", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_NEWLM, + .handle_ns = EXPECTED_NS, + .handle_type = PROXY, + .preloaded = { }, + .loaded = { [0] = DSO|NEW, [EXPECTED_NS] = PROXY|NEW }, + }, + END_TESTS + }; diff --git a/elf/tst-dlmopen-rtld-unique4.c b/elf/tst-dlmopen-rtld-unique4.c new file mode 100644 index 0000000000..58b8e017b4 --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique4.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 1 +#include "tst-dlmopen-rtld-unique4.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-unique4.h b/elf/tst-dlmopen-rtld-unique4.h new file mode 100644 index 0000000000..36d5915172 --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique4.h @@ -0,0 +1,15 @@ +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-shared-unique:X:none--ns0-nsXp", + .desc = "dlmopen a DF_GNU_1_UNIQUE dso", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_NEWLM, + .args.flags = RTLD_SHARED, + .handle_ns = EXPECTED_NS, + .handle_type = PROXY, + .preloaded = { }, + .loaded = { [0] = DSO|NEW, [EXPECTED_NS] = PROXY|NEW }, + }, + END_TESTS + }; diff --git a/elf/tst-dlmopen-rtld-unique5.c b/elf/tst-dlmopen-rtld-unique5.c new file mode 100644 index 0000000000..b2e8329461 --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique5.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 1 +#include "tst-dlmopen-rtld-unique5.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-unique5.h b/elf/tst-dlmopen-rtld-unique5.h new file mode 100644 index 0000000000..29882ea782 --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique5.h @@ -0,0 +1,59 @@ +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-isolate-unique:X:none--nsX", + .desc = "dlmopen a DF_GNU_1_UNIQUE dso into NSX with RTLD_ISOLATE", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_NEWLM, + .args.flags = RTLD_ISOLATE, + .handle_ns = EXPECTED_NS, + .free_ns = EXPECTED_NS, + .handle_type = DSO, + .preloaded = { }, + .loaded = { [EXPECTED_NS] = DSO|NEW }, + }, + { + .name = "dlmopen-unique:0:nsX--ns0-nsX", + .desc = "dlmopen a DF_GNU_1_UNIQUE dso already present in NS X", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_BASE, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [EXPECTED_NS] = DSO }, + .loaded = { [0] = DSO|NEW, [EXPECTED_NS] = DSO }, + }, + { + .name = "dlmopen-unique:0:ns0-nsX--ns0-nsX", + .desc = "dlmopen a DF_GNU_1_UNIQUE dso already in the base NS and NS X", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_BASE, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + .loaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + }, + { + .name = "dlmopen-shared-unique:0:ns0-nsX--ns0-nsX", + .desc = "dlmopen RTLD_SHARED a DF_GNU_1_UNIQUE dso already in the base NS and NS X", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_BASE, + .args.flags = RTLD_SHARED, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + .loaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + }, + { + .name = "dlmopen-shared-unique:X:ns0-nsX--ns0-nsX", + .desc = "dlmopen RTLD_SHARED a DF_GNU_1_UNIQUE dso already in the base NS and NS X into NS X", + .failure = 1, + .args.dso_path = DSO_UNIQUE, + .args.ns = EXPECTED_NS, + .args.flags = RTLD_SHARED, + .handle_ns = EXPECTED_NS, + .handle_type = DSO, + .preloaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + .loaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + }, + END_TESTS + }; diff --git a/elf/tst-dlmopen-rtld-unique6.c b/elf/tst-dlmopen-rtld-unique6.c new file mode 100644 index 0000000000..fecaf559a3 --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique6.c @@ -0,0 +1,11 @@ +#include +#include "tst-dlmopen-main.h" + +#define EXPECTED_NS 1 +#include "tst-dlmopen-rtld-unique6.h" + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-unique6.h b/elf/tst-dlmopen-rtld-unique6.h new file mode 100644 index 0000000000..3c25127fa1 --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique6.h @@ -0,0 +1,52 @@ +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-isolate-unique:1:none--ns1--prep", + .desc = "dlmopen a DF_GNU_1_UNIQUE dso into NS1 with RTLD_ISOLATE", + .is_prep_stage = 1, + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_NEWLM, + .args.flags = RTLD_ISOLATE, + .handle_ns = EXPECTED_NS, + .free_ns = EXPECTED_NS, + .handle_type = DSO, + .preloaded = { }, + .loaded = { [EXPECTED_NS] = DSO|NEW }, + }, + { + .name = "dlmopen-unique:1:nsX--nsX--FAIL", + .desc = "dlmopen a DF_GNU_1_UNIQUE dso into NSX when already there", + .args.dso_path = DSO_UNIQUE, + .args.ns = EXPECTED_NS, + .failure = 1, + .preloaded = { [EXPECTED_NS] = DSO }, + }, + { + .name = "dlmopen-shared-unique:X:nsX--nsX--FAIL", + .desc = "dlmopen RTLD_SHARED a DF_GNU_1_UNIQUE dso into NSX when already there", + .args.dso_path = DSO_UNIQUE, + .args.ns = EXPECTED_NS, + .args.flags = RTLD_SHARED, + .failure = 1, + .preloaded = { [EXPECTED_NS] = DSO }, + }, + { + .name = "dlmopen-shared-unique:0:nsX--ns0-nsX", + .desc = "dlmopen RTLD_SHARED a DF_GNU_1_UNIQUE dso already present in NS X", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_BASE, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [EXPECTED_NS] = DSO }, + .loaded = { [0] = DSO|NEW, [EXPECTED_NS] = DSO }, + }, + { + .name = "dlmopen-shared-unique:X:ns0-nsX--ns0-nsX--FAIL", + .desc = "dlmopen RTLD_SHARED a DF_GNU_1_UNIQUE dso already in the base NS and NS 1", + .args.dso_path = DSO_UNIQUE, + .args.ns = EXPECTED_NS, + .failure = 1, + .preloaded = { [0] = DSO, [EXPECTED_NS] = DSO }, + }, + END_TESTS + }; diff --git a/elf/tst-dlmopen-sharedmod-norm.c b/elf/tst-dlmopen-sharedmod-norm.c new file mode 100644 index 0000000000..fd049903f4 --- /dev/null +++ b/elf/tst-dlmopen-sharedmod-norm.c @@ -0,0 +1,11 @@ +#include "tst-dlmopen-modules.h" + +dlmopen_testresult *rtld_shared_testfunc (void) +{ + static dlmopen_testresult result; + + result.name = "norm"; + result.free = free; + + return &result; +} diff --git a/elf/tst-dlmopen-sharedmod-uniq.c b/elf/tst-dlmopen-sharedmod-uniq.c new file mode 100644 index 0000000000..5c9701da41 --- /dev/null +++ b/elf/tst-dlmopen-sharedmod-uniq.c @@ -0,0 +1,11 @@ +#include "tst-dlmopen-modules.h" + +dlmopen_testresult *rtld_shared_testfunc (void) +{ + static dlmopen_testresult result; + + result.name = "noop"; + result.free = free; + + return &result; +} diff --git a/elf/tst-dlmopen-std-do-test.h b/elf/tst-dlmopen-std-do-test.h new file mode 100644 index 0000000000..595f6f764d --- /dev/null +++ b/elf/tst-dlmopen-std-do-test.h @@ -0,0 +1,11 @@ +#pragma once + +#define DEFINE_DLMOPEN_TEST(x) \ + static int \ + do_test (void) \ + { \ + for (int i = 0; x[i].name; i++) \ + if (!process_test_spec (&x[i])) \ + return 1; \ + return 0; \ + }