From patchwork Wed Jun 17 14:00:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311219 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=8.43.85.97; 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=FYx+1rvu; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (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 49n6D34vc8z9sRh for ; Thu, 18 Jun 2020 00:00:51 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D77073893660; Wed, 17 Jun 2020 14:00:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D77073893660 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402437; bh=DBI3mRDxk45crg3OARe4OZIL/USiO2LsyY7hwFGcGhs=; 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=FYx+1rvuJVKztJ86Y8oXqyujQjuH/zHoTI22mevhN7QEfIuU2IcjcmUgqhbX7NaxU npU8a1zGEW3vCpPBck8xp/VXkOydTXl+igBlTxvpLhzWCEmxY8w9gB22KAdGBhoCzR AGJ5vGHKZB2Gk3d6QTbdlJkTVOYXF5bgJDrZkuCA= 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 8850738930E1 for ; Wed, 17 Jun 2020 14:00:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 8850738930E1 Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 A4F262A378B for ; Wed, 17 Jun 2020 15:00:34 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 01/16] Declare and describe the dlmopen RTLD_SHARED flag Date: Wed, 17 Jun 2020 15:00:09 +0100 Message-Id: <20200617140024.12777-2-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-15.3 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, 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" This flag will instruct dlmopen to create a shared object present in the main namespace and accessible from the selected namespace when supplied in the MODE argument. --- bits/dlfcn.h | 7 +++++++ sysdeps/mips/bits/dlfcn.h | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/bits/dlfcn.h b/bits/dlfcn.h index ed67f29bc3..9170059323 100644 --- a/bits/dlfcn.h +++ b/bits/dlfcn.h @@ -32,6 +32,13 @@ visible as if the object were linked directly into the program. */ #define RTLD_GLOBAL 0x00100 +/* If the following bit is set in the MODE argument to dlmopen + then the target object is loaded into the main namespace (if + it is not already there) and a shallow copy (proxy) is placed + in the target namespace: This allows multiple namespaces to + share a single instance of a DSO. */ +#define RTLD_SHARED 0x00080 + /* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL. The implementation does this by default and so we can define the value to zero. */ diff --git a/sysdeps/mips/bits/dlfcn.h b/sysdeps/mips/bits/dlfcn.h index e55262f3aa..fc33fd184e 100644 --- a/sysdeps/mips/bits/dlfcn.h +++ b/sysdeps/mips/bits/dlfcn.h @@ -32,6 +32,13 @@ visible as if the object were linked directly into the program. */ #define RTLD_GLOBAL 0x0004 +/* If the following bit is set in the MODE argument to dlmopen + then the target object is loaded into the main namespace (if + it is not already there) and a shallow copy (proxy) is placed + in the target namespace: This allows multiple namespaces to + share a single instance of a DSO. */ +#define RTLD_SHARED 0x00020 + /* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL. The implementation does this by default and so we can define the value to zero. */ From patchwork Wed Jun 17 14:00:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311220 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=uMjTFzSQ; 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 49n6DG1k6Lz9sRh for ; Thu, 18 Jun 2020 00:01:02 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 62CC838930CF; Wed, 17 Jun 2020 14:00:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 62CC838930CF DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402438; bh=pYkcoiL4G1z7qHThdgHGbcl5XYFuAR/MvJnOld333wc=; 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=uMjTFzSQ6IQi3jvsp5SLlzgQrGuLYWNm+UjT0kUjhdgJPhGNAwHd0uQcFZdYERVJi Sr6CUEDJ4ARwJT6+RcP8KspfuqdcI+UiFrtkodxDHzseF7pkxNUdNWU/7e/kf2vwDT JZIyur96Tnchx5YWO5PbpKzLxkoJgYBtiy1qPi4o= 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 9933F3893663 for ; Wed, 17 Jun 2020 14:00:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 9933F3893663 Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 E46402A3DAB for ; Wed, 17 Jun 2020 15:00:34 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 02/16] include/link.h: Update the link_map struct to allow proxies Date: Wed, 17 Jun 2020 15:00:10 +0100 Message-Id: <20200617140024.12777-3-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-15.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, 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" We already have an l_real pointer, used for a similar purpose by the linker for copies of ld.so in secondary namespaces. Update its documentation and add a bitfield to indicate when link_map entry is a proxy. --- include/link.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/link.h b/include/link.h index aea268439c..c63166317d 100644 --- a/include/link.h +++ b/include/link.h @@ -103,8 +103,9 @@ struct link_map 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 for ld.so when it is used in more - than one namespace. */ + 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 link_map *l_real; /* Number of the namespace this link map belongs to. */ @@ -176,6 +177,7 @@ struct link_map 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. */ From patchwork Wed Jun 17 14:00:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311222 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=yJyHQB/G; 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 49n6Dh0Mxdz9sRW for ; Thu, 18 Jun 2020 00:01:24 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7A2373893674; Wed, 17 Jun 2020 14:00:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7A2373893674 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402439; bh=XYk0mbi/bliOPgJ+dFwfAi5n36x6Cvm7Ihb1LPVEGDk=; 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=yJyHQB/GCpuA1DnmG1IqR9PH+rD7PCJ7JjCC1wvyTiz7nf/K0deVNJsIFEfwRGq/r Xi3qcKs8+/Glfajk/h0TgVSUD0oNDTwvZZFW54f8ke1EY3Yp5+fXov3yssmLGW+Yf5 SM+lkV5ZPXKqD1V9rd/Wig6eaW0yG6chT/UXREfk= 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 AB1AE38930CF for ; Wed, 17 Jun 2020 14:00:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org AB1AE38930CF Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 F3C6B2A3FA2 for ; Wed, 17 Jun 2020 15:00:34 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 03/16] elf/dl-object.c: Implement a helper function to proxy link_map entries Date: Wed, 17 Jun 2020 15:00:11 +0100 Message-Id: <20200617140024.12777-4-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-14.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, 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" Provides the minimal functionality needed to take an existing link_map entry and create a proxy for it in the specified namespace. --- elf/dl-object.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++ sysdeps/generic/ldsodefs.h | 5 +++ 2 files changed, 89 insertions(+) diff --git a/elf/dl-object.c b/elf/dl-object.c index d2cdf135cc..2ee5eee13c 100644 --- a/elf/dl-object.c +++ b/elf/dl-object.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -50,6 +51,89 @@ _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid) __rtld_lock_unlock_recursive (GL(dl_load_write_lock)); } +/* Proxy an existing link map entry into a new link map: + This is based on _dl_new_object, skipping the steps we know we won't need + because this is mostly just a shell for the l_real pointer holding the real + link map entry (normally l == l->l_real, but not for ld.so in non-main + link maps or RTLD_SHARED proxies). + It also flags the proxy by setting l_proxy, and sets the the no-delete + flag in the original if it is an lt_loaded. */ +struct link_map * +_dl_new_proxy (struct link_map *old, int mode, Lmid_t nsid) +{ + const char *name; + struct link_map *new; + struct libname_list *newname; +#ifdef SHARED + unsigned int na = GLRO(dl_naudit); + + if ((mode & __RTLD_OPENEXEC) != 0) + na = DL_NNS; + + size_t audit_space = na * sizeof (struct auditstate); +#else +# define audit_space 0 +#endif + + name = old->l_name; + + /* Find the original link map entry if `old' is itself a proxy. */ + while (old && old->l_proxy) + old = old->l_real; + + if (old == NULL) + _dl_signal_error (EINVAL, name, NULL, N_("cannot proxy NULL link_map")); + + /* Object already exists in the target namespace. This should get handled + by dl_open_worker but just in case we get this far, handle it: */ + if (__glibc_unlikely (old->l_ns == nsid)) + { + /* Not actually possible, given the sanity checks above. */ + if (old->l_proxy) + return old; + + _dl_signal_error (EEXIST, name, NULL, + N_("existing object cannot be demoted to a proxy")); + } + + /* Now duplicate as little of _dl_new_object as possible to get a + working proxied object in the target link map. */ + new = (struct link_map *) calloc (sizeof (*new) + audit_space + + sizeof (struct link_map *) + + sizeof (*newname) + PATH_MAX, 1); + + if (new == NULL) + _dl_signal_error (ENOMEM, name, NULL, + N_("cannot create shared object descriptor")); + + /* Specific to the proxy. */ + new->l_real = old; + new->l_proxy = 1; + new->l_ns = nsid; + + /* Copied from the origin. */ + new->l_libname = old->l_libname; + new->l_name = old->l_name; + /* Proxies are considered lt_loaded if the real entry type is lt_library. */ + new->l_type = (old->l_type == lt_library) ? lt_loaded : old->l_type; + + if (__glibc_unlikely (mode & RTLD_NODELETE)) + new->l_flags_1 |= DF_1_NODELETE; + + /* Specific to the origin. Ideally we'd do some accounting here but + for now it's easier to pin the original so the proxy remains valid. */ + if (old->l_type == lt_loaded) + old->l_flags_1 |= DF_1_NODELETE; + + /* Fix up the searchlist so that relocations work. */ + _dl_map_object_deps (new, NULL, 0, 0, + mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT)); + + /* And finally put the proxy in the target namespace. */ + _dl_add_to_namespace_list (new, nsid); + + return new; +} /* Allocate a `struct link_map' for a new object being loaded, and enter it into the _dl_loaded list. */ diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 497938ffa2..d3113ff4d8 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -945,6 +945,11 @@ extern lookup_t _dl_lookup_symbol_x (const char *undef, struct link_map *skip_map) attribute_hidden; +/* Proxy an existing link map entry into a new link map */ +extern struct link_map *_dl_new_proxy (struct link_map *old, + int mode, + Lmid_t nsid) + attribute_hidden; /* Add the new link_map NEW to the end of the namespace list. */ extern void _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid) From patchwork Wed Jun 17 14:00:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311223 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=JPJmDNtj; 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 49n6Dy3Vy8z9sRW for ; Thu, 18 Jun 2020 00:01:38 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 89ED6389850A; Wed, 17 Jun 2020 14:00:40 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 89ED6389850A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402440; bh=yJDYbHgv+KnyhyonZamKbHwVn+nnEKfZdLNjsaZ7ZBo=; 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=JPJmDNtjYSG7/V+BXldX+foh1khI08aY+RyPwyDudSU9uOXEXHCMhZI33wq4dwtuG pXVjyAFeppZBX0oU9KtSAfs542PM1DRiTK8TlGDUuphO9OVLe7ZQaAYou/F2c4mtwJ NWh8NHnvsY7SIyk2U7w8Iv8UiSjTAYTyjSW4yYSk= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by sourceware.org (Postfix) with ESMTPS id E34253893664 for ; Wed, 17 Jun 2020 14:00:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org E34253893664 Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 120942A3FAF for ; Wed, 17 Jun 2020 15:00:35 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 04/16] elf/dl-load.c, elf-dl-open.c: Implement RTLD_SHARED dlmopen proxying Date: Wed, 17 Jun 2020 15:00:12 +0100 Message-Id: <20200617140024.12777-5-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> MIME-Version: 1.0 X-Spam-Status: No, score=-14.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, 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" This uses the new infrastructure to implement RTLD_SHARED object proxying via dlmopen: Instead of opening the specified object in the requested namespace we open it in the main namespace (if it is not already present there) and proxy it to the destination. The following rules apply: If a proxy of the object is already present in the requested namespace, we simply return it (with an incremented direct-open count). If the object is already present in the requested namespace, a dl error is signalled, since we cannot satisfy the user's request. Proxies are never created in the main namespace: RTLD_SHARED has no effect when the requested namespace is LM_ID_BASE. --- elf/dl-load.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ elf/dl-open.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/elf/dl-load.c b/elf/dl-load.c index a6b80f9395..221589e292 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1904,6 +1904,38 @@ open_path (const char *name, size_t namelen, int mode, return -1; } +/* Search for a link map proxy in the given namespace by name. + Consider it to be an error if the found object is not a proxy. */ + +struct link_map * +_dl_find_proxy (Lmid_t nsid, const char *name) +{ + struct link_map *l; + + for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next) + { + if (__glibc_unlikely ((l->l_faked | l->l_removed) != 0)) + continue; + + if (!_dl_name_match_p (name, l)) + continue; + + /* We have a match - stop searching. */ + break; + } + + if (l) + { + if (l->l_proxy) + return l; + + _dl_signal_error (EEXIST, name, NULL, + N_("object cannot be demoted to a proxy")); + } + + return NULL; +} + /* Map in the shared object file NAME. */ struct link_map * @@ -1920,6 +1952,20 @@ _dl_map_object (struct link_map *loader, const char *name, assert (nsid >= 0); assert (nsid < GL(dl_nns)); +#ifdef SHARED + /* Only need to do proxy checks if `nsid' is not LM_ID_BASE. */ + if (__glibc_unlikely ((mode & RTLD_SHARED) && (nsid != LM_ID_BASE))) + { + /* Search the namespace in case the object is already proxied. */ + if((l = _dl_find_proxy (nsid, name)) != NULL) + return l; + + /* Further searches should be in the base ns: We will proxy the + resulting object in dl_open_worker *after* it is initialised. */ + nsid = LM_ID_BASE; + } +#endif + /* Look for this name among those already loaded. */ for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next) { diff --git a/elf/dl-open.c b/elf/dl-open.c index 623c9754eb..aca0384e5b 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -476,6 +476,8 @@ dl_open_worker (void *a) const char *file = args->file; int mode = args->mode; struct link_map *call_map = NULL; + int want_proxy = mode & RTLD_SHARED; + Lmid_t proxy_ns = LM_ID_BASE; /* Determine the caller's map if necessary. This is needed in case we have a DST, when we don't know the namespace ID we have to put @@ -500,6 +502,15 @@ dl_open_worker (void *a) args->nsid = call_map->l_ns; } + /* Now that we know the NS for sure, sanity check the mode. */ + if (__glibc_likely(args->nsid == LM_ID_BASE) && + __glibc_unlikely(mode & RTLD_SHARED)) + { + args->mode &= ~RTLD_SHARED; + mode &= ~RTLD_SHARED; + want_proxy = 0; + } + /* Retain the old value, so that it can be restored. */ args->original_global_scope_pending_adds = GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds; @@ -528,6 +539,24 @@ dl_open_worker (void *a) /* This object is directly loaded. */ ++new->l_direct_opencount; + /* Proxy already existed in the target ns, nothing left to do. */ + if (__glibc_unlikely (new->l_proxy)) + { + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) + _dl_debug_printf ("proxied file=%s [%lu]; direct_opencount=%u\n\n", + new->l_name, new->l_ns, new->l_direct_opencount); + return; + } + + /* If we want proxy and we get this far then the entry in ‘new’ will + be in the main namespace: we should revert to the main namespace code + path(s), but remember the namespace we want the proxy to be in. */ + if (__glibc_unlikely (want_proxy)) + { + proxy_ns = args->nsid; + args->nsid = LM_ID_BASE; + } + /* It was already open. */ if (__glibc_unlikely (new->l_searchlist.r_list != NULL)) { @@ -559,6 +588,16 @@ dl_open_worker (void *a) assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT); + if (__glibc_unlikely (want_proxy)) + { + args->map = new = _dl_new_proxy (new, mode, proxy_ns); + ++new->l_direct_opencount; + + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) + _dl_debug_printf ("proxying file=%s [%lu]; direct_opencount=%u\n\n", + new->l_name, new->l_ns, new->l_direct_opencount); + } + return; } @@ -762,6 +801,14 @@ dl_open_worker (void *a) if (mode & RTLD_GLOBAL) add_to_global_update (new); + if (__glibc_unlikely (want_proxy)) + { + /* args->map is the return slot which the caller sees, but keep + the original value of new hanging around so we can see the + real link map entry (for logging etc). */ + args->map = _dl_new_proxy (new, mode, proxy_ns); + ++args->map->l_direct_opencount; + } #ifndef SHARED /* We must be the static _dl_open in libc.a. A static program that has loaded a dynamic object now has competition. */ @@ -770,10 +817,19 @@ dl_open_worker (void *a) /* Let the user know about the opencount. */ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) - _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n", - new->l_name, new->l_ns, new->l_direct_opencount); + { + _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n", + new->l_name, new->l_ns, new->l_direct_opencount); + + if (args->map->l_proxy) + _dl_debug_printf ("proxying file=%s [%lu]; direct_opencount=%u\n\n", + args->map->l_name, + args->map->l_ns, + args->map->l_direct_opencount); + } } + void * _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid, int argc, char *argv[], char *env[]) From patchwork Wed Jun 17 14:00:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311227 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=8.43.85.97; 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=oRwXw/IW; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (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 49n6Fn4nh6z9sRN for ; Thu, 18 Jun 2020 00:02:21 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A9153389367E; Wed, 17 Jun 2020 14:00:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A9153389367E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402442; bh=V5TpIdLy+bBoD/RR4rme8VmGxWZW8YqrfoGrzGEUcT0=; 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=oRwXw/IWE23XjjnxRKuHVissBznuj6gBIAUjr9pwghws/UO3vTZkRzuAeGFH2T5uY AEoe7mVoPlT9NXOuMExI1c9+mVNIBxQXYE2SRgcB8K4jxUwR3q/ldXFs361kJ7Qfga vUStq3DMXFGnLVwmYoSU+p1I+Q3p1tuTlFeepcGg= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by sourceware.org (Postfix) with ESMTPS id 4DD2938930DE for ; Wed, 17 Jun 2020 14:00:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 4DD2938930DE Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 261502A3FB0 for ; Wed, 17 Jun 2020 15:00:35 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 05/16] elf/dl-fini.c: Handle proxy link_map entries in the shutdown path Date: Wed, 17 Jun 2020 15:00:13 +0100 Message-Id: <20200617140024.12777-6-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-14.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, 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" When cleaning up before exit we should not call destructors or otherwise free [most of] the contents of proxied link_map entries since they share [most of] their contents with the LM_ID_BASE objects to which they point. --- elf/dl-close.c | 43 ++++++++++++++++++++++++++----------------- elf/dl-fini.c | 6 ++++-- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/elf/dl-close.c b/elf/dl-close.c index 73b2817bbf..a4c1a92ee7 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -283,8 +283,9 @@ _dl_close_worker (struct link_map *map, bool force) /* Call its termination function. Do not do it for half-cooked objects. Temporarily disable exception - handling, so that errors are fatal. */ - if (imap->l_init_called) + handling, so that errors are fatal. + Proxies should never have this flag set, but we double check. */ + if (imap->l_init_called && !imap->l_proxy) { /* When debugging print a message first. */ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, @@ -360,7 +361,9 @@ _dl_close_worker (struct link_map *map, bool force) one for the terminating NULL pointer. */ size_t remain = (new_list != NULL) + 1; bool removed_any = false; - for (size_t cnt = 0; imap->l_scope[cnt] != NULL; ++cnt) + for (size_t cnt = 0; + imap->l_scope && imap->l_scope[cnt] != NULL; + ++cnt) /* This relies on l_scope[] entries being always set either to its own l_symbolic_searchlist address, or some map's l_searchlist address. */ @@ -686,8 +689,10 @@ _dl_close_worker (struct link_map *map, bool force) /* We can unmap all the maps at once. We determined the start address and length when we loaded the object and - the `munmap' call does the rest. */ - DL_UNMAP (imap); + the `munmap' call does the rest. Proxies do not have + any segments of their own to unmap. */ + if (!imap->l_proxy) + DL_UNMAP (imap); /* Finally, unlink the data structure and free it. */ #if DL_NNS == 1 @@ -727,19 +732,23 @@ _dl_close_worker (struct link_map *map, bool force) _dl_debug_printf ("\nfile=%s [%lu]; destroying link map\n", imap->l_name, imap->l_ns); - /* This name always is allocated. */ - free (imap->l_name); - /* Remove the list with all the names of the shared object. */ + /* Skip structures borrowed by proxies from the real map. */ + if (!imap->l_proxy) + { + /* This name always is allocated. */ + free (imap->l_name); + /* Remove the list with all the names of the shared object. */ - struct libname_list *lnp = imap->l_libname; - do - { - struct libname_list *this = lnp; - lnp = lnp->next; - if (!this->dont_free) - free (this); - } - while (lnp != NULL); + struct libname_list *lnp = imap->l_libname; + do + { + struct libname_list *this = lnp; + lnp = lnp->next; + if (!this->dont_free) + free (this); + } + while (lnp != NULL); + } /* Remove the searchlists. */ free (imap->l_initfini); diff --git a/elf/dl-fini.c b/elf/dl-fini.c index 226a6f077a..eb56923c7d 100644 --- a/elf/dl-fini.c +++ b/elf/dl-fini.c @@ -72,7 +72,7 @@ _dl_fini (void) assert (nloaded != 0 || GL(dl_ns)[ns]._ns_loaded == NULL); for (l = GL(dl_ns)[ns]._ns_loaded, i = 0; l != NULL; l = l->l_next) /* Do not handle ld.so in secondary namespaces. */ - if (l == l->l_real) + if (l == l->l_real || l->l_proxy) { assert (i < nloaded); @@ -110,7 +110,9 @@ _dl_fini (void) { struct link_map *l = maps[i]; - if (l->l_init_called) + /* Do not call fini functions via proxies, or for + objects which are not marked as initialised. */ + if (l->l_init_called && !l->l_proxy) { /* Make sure nothing happens if we are called twice. */ l->l_init_called = 0; From patchwork Wed Jun 17 14:00:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311224 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=tH5jG1oZ; 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 49n6FB63kjz9sRW for ; Thu, 18 Jun 2020 00:01:50 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 174EC389850E; Wed, 17 Jun 2020 14:00:41 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 174EC389850E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402441; bh=Nab0A4D4wYhyV90sY5lC/9XOrClLBO4jkQEU7/7G6R8=; 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=tH5jG1oZf32AiY7YgyXmlesLCG9dXGDU33Ym9CN5CwQE07PQ6W9C+ngQGWkasbl+q xwYSlKYoD9LFeG13d0cQm65CGsN/ENkte02Y1UkRrvtk+QXL8j15+EoY0UyiDVH2AL HCPMJvLJaio2YM4ZXqcmZF1j8Mx8PYF+8T0iGKUE= 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 4758238930CF for ; Wed, 17 Jun 2020 14:00:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 4758238930CF Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 34F892A3FB2 for ; Wed, 17 Jun 2020 15:00:35 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 06/16] elf/dl-init.c: Skip proxied link map entries in the dl init path Date: Wed, 17 Jun 2020 15:00:14 +0100 Message-Id: <20200617140024.12777-7-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-14.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, 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" Proxies should not trigger calls to DT_INIT constructors since they're just shims that point to the real, already loaded and initialised, objects. --- elf/dl-init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/elf/dl-init.c b/elf/dl-init.c index 55d528c7a5..2eef584cf9 100644 --- a/elf/dl-init.c +++ b/elf/dl-init.c @@ -27,8 +27,8 @@ typedef void (*init_t) (int, char **, char **); static void call_init (struct link_map *l, int argc, char **argv, char **env) { - if (l->l_init_called) - /* This object is all done. */ + if (l->l_init_called || l->l_proxy) + /* This object is all done, or a proxy (and therefore initless). */ return; /* Avoid handling this constructor again in case we have a circular From patchwork Wed Jun 17 14:00:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311225 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=8.43.85.97; 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=ObcKy1vj; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (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 49n6FP37F1z9sRW for ; Thu, 18 Jun 2020 00:02:01 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9CE043898510; Wed, 17 Jun 2020 14:00:41 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9CE043898510 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402441; bh=xuwh35EiJ33lf+xAv76MF5Hq60m5x+FzKkgHIjXyvxQ=; 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=ObcKy1vjgcR4dj4bBRsyPPLGkHfN/amnKSkQ+VLUTRkPOxguwvyEY2wLFoV9Fryy4 wt4SNBI9iToREUqxNVq/abFP887MnACcQIGpjuLmkUiJqD1qLP7VUF6webZmvq3rTo DWMhCK5nN0E1ACkhXEefx35sW/PEi5F0sAotiBJM= 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 5E08638930E1 for ; Wed, 17 Jun 2020 14:00:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 5E08638930E1 Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 4578B2A3FC2 for ; Wed, 17 Jun 2020 15:00:35 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 07/16] Define a new dynamic section tag - DT_GNU_UNIQUE Date: Wed, 17 Jun 2020 15:00:15 +0100 Message-Id: <20200617140024.12777-8-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-14.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, 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" We expect this section to be present in ELF DSOs that should only ever have one instance across all link map namespaces. libc and its constituent DSOs should have this section. --- elf/elf.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/elf/elf.h b/elf/elf.h index 2549a177d6..80d689ca02 100644 --- a/elf/elf.h +++ b/elf/elf.h @@ -895,6 +895,7 @@ typedef struct Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's approach. */ #define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_UNIQUE 0x6ffffdf4 /* Open DSO once across all namespaces */ #define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ #define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ #define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ @@ -909,7 +910,7 @@ typedef struct #define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ #define DT_VALRNGHI 0x6ffffdff #define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ -#define DT_VALNUM 12 +#define DT_VALNUM 13 /* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the Dyn.d_un.d_ptr field of the Elf*_Dyn structure. From patchwork Wed Jun 17 14:00:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311226 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=8.43.85.97; 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=f/eaiorQ; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (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 49n6Fc07gXz9sRR for ; Thu, 18 Jun 2020 00:02:12 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 299073898513; Wed, 17 Jun 2020 14:00:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 299073898513 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402442; bh=l4I1+zM8+5lw5PK3QoddbsgUGJrjzCxj6neDVb5PJ8Q=; 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=f/eaiorQooQvHLejkslzRWkmu2W7knunEESz7kJPrdpcIzCLhX3IfJ+QXWgQPEJgl stVs19PJxpIT4/pA7JlWR6iUSL9Jx2udPwQYqZ4BBT7ccY2anGTA3nLLwWMPfR3yC2 Ki+RFINMJWph3gezsVdvDq260DYSdcInTexc43fo= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by sourceware.org (Postfix) with ESMTPS id 68EC93893663 for ; Wed, 17 Jun 2020 14:00:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 68EC93893663 Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 552312A3FC3 for ; Wed, 17 Jun 2020 15:00:35 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 08/16] Abstract the loaded-DSO search code into a private helper function Date: Wed, 17 Jun 2020 15:00:16 +0100 Message-Id: <20200617140024.12777-9-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-14.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, 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/dl-load.c | 38 ++++++++++++++++++++++++++++++++++++++ sysdeps/generic/ldsodefs.h | 4 ++++ 2 files changed, 42 insertions(+) diff --git a/elf/dl-load.c b/elf/dl-load.c index 221589e292..d4d6a6318b 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1936,6 +1936,44 @@ _dl_find_proxy (Lmid_t nsid, const char *name) return NULL; } +/* search for a shared object in a given namespace. */ +struct link_map * +_dl_find_dso (const char *name, Lmid_t nsid) +{ + struct link_map *l; + + for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next) + { + /* If the requested name matches the soname of a loaded object, + use that object. Elide this check for names that have not + yet been opened. */ + if (__glibc_unlikely ((l->l_faked | l->l_removed) != 0)) + continue; + if (!_dl_name_match_p (name, l)) + { + const char *soname; + + if (__glibc_likely (l->l_soname_added) + || l->l_info[DT_SONAME] == NULL) + continue; + + soname = ((const char *) D_PTR (l, l_info[DT_STRTAB]) + + l->l_info[DT_SONAME]->d_un.d_val); + if (strcmp (name, soname) != 0) + continue; + + /* We have a match on a new name -- cache it. */ + add_name_to_object (l, soname); + l->l_soname_added = 1; + } + + /* We have a match. */ + return l; + } + + return NULL; +} + /* Map in the shared object file NAME. */ struct link_map * diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index d3113ff4d8..3b5c5e9147 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1184,6 +1184,10 @@ extern void _dl_show_scope (struct link_map *new, int from) extern struct link_map *_dl_find_dso_for_object (const ElfW(Addr) addr); rtld_hidden_proto (_dl_find_dso_for_object) +extern struct link_map *_dl_find_dso (const char *name, Lmid_t nsid); +rtld_hidden_proto (_dl_find_dso) + + /* Initialization which is normally done by the dynamic linker. */ extern void _dl_non_dynamic_init (void) attribute_hidden; From patchwork Wed Jun 17 14:00:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311228 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=DK44+nx9; 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 49n6Fz0m3Kz9sRh for ; Thu, 18 Jun 2020 00:02:31 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 367343898516; Wed, 17 Jun 2020 14:00:43 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 367343898516 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402443; bh=0GWChrmy8Tc5uEHX01NljeLdTXcPyXXMWpYnsnfjHxA=; 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=DK44+nx9Av5KJklOtAcFysF23AF4FOUdn1ydH7A3ZVf/kANAx9Qe/n2EiY4BYtj3M FsD/vP4NiBtEUapNpqqvy/x2es+7Frmv8UcyKcp6piNaOYFcOBjTm5o0ypwVjiQVM3 RAMrxFddcMSjVCIJdpwiGX4gGk9hFxlBDbAoWlHk= 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 7C80F3893668 for ; Wed, 17 Jun 2020 14:00:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 7C80F3893668 Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 6473B2A3FC4 for ; Wed, 17 Jun 2020 15:00:35 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 09/16] Compare loaded DSOs by file ID and check for DF_1_UNIQUE Date: Wed, 17 Jun 2020 15:00:17 +0100 Message-Id: <20200617140024.12777-10-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> MIME-Version: 1.0 X-Spam-Status: No, score=-14.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, 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" If _dl_map_object_from_fd finds that a DSO it was asked to load into a non-base namespace is already loaded (into the main namespace) and is flagged DF_1_UNIQUE then it should return that DSO's link map entry. In such cases _dl_open_worker must notice that this has happened and dontinue down the link map proxy generation path instead of normal link map entry preparation. --- elf/dl-load.c | 26 ++++++++++++++++++++++++++ elf/dl-open.c | 10 ++++++++++ 2 files changed, 36 insertions(+) diff --git a/elf/dl-load.c b/elf/dl-load.c index d4d6a6318b..76970f79de 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -941,6 +941,32 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, } #endif + /* DSOs in the main namespace which are flagged DF_1_UNIQUE should only + be opened into the main namespace. Other namespaces should only get + proxies. */ + if (__glibc_unlikely (nsid != LM_ID_BASE)) + { + /* Check base ns to see if the name matched another already loaded. */ + for (l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; l != NULL; l = l->l_next) + if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id)) + { + if (!(l->l_flags_1 & DF_1_UNIQUE)) + continue; + + /* Already loaded. Bump its reference count and return it. */ + __close_nocancel (fd); + + /* If the name is not listed for this object add it. */ + free (realname); + add_name_to_object (l, name); + + /* NOTE: It is important that our caller picks up on the fact + that we have NOT returned an object in the requested namespace + and handles the proxying correctly */ + return l; + } + } + if (mode & RTLD_NOLOAD) { /* We are not supposed to load the object unless it is already diff --git a/elf/dl-open.c b/elf/dl-open.c index aca0384e5b..75dc3893d3 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -548,6 +548,16 @@ dl_open_worker (void *a) return; } + /* If we were trying to load a DF_1_UNIQUE flagged DSO which was NOT + ALREADY LOADED (or not loaded with the name we are using) then + _dl_map_object will return an instance from the main namespace. + We need to detect this and set up the RTLD_SHARED flags. */ + if (__glibc_unlikely(args->nsid != LM_ID_BASE && new->l_ns == LM_ID_BASE)) + { + want_proxy = RTLD_SHARED; + mode |= RTLD_SHARED; + } + /* If we want proxy and we get this far then the entry in ‘new’ will be in the main namespace: we should revert to the main namespace code path(s), but remember the namespace we want the proxy to be in. */ From patchwork Wed Jun 17 14:00:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311230 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=GHm9ecpg; 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 49n6G86B2Yz9sRR for ; Thu, 18 Jun 2020 00:02:40 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B5E453898517; Wed, 17 Jun 2020 14:00:43 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B5E453898517 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402443; bh=r3PSAXylmRReqyWlvabxBgfWjoyIBjwwDdgNoKERE1c=; 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=GHm9ecpgQdn/sFbuLsFTG8fUhuz3LHl9+aNLi+ECNOfX7l2mWyw8K2F1Bou7TZ+Ew CdYGqKSo1EfROEZGgPO3WOCjCpP/q+RWT/4H5TItwmGZRzJPhiqCc0hXDwBOOo3WzC MKBeA4Cgi5LB5RZmVGoUdscJfOSqhQ+UpNkoXjro= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by sourceware.org (Postfix) with ESMTPS id 8CBE43893664 for ; Wed, 17 Jun 2020 14:00:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 8CBE43893664 Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 770D22A3FC5 for ; Wed, 17 Jun 2020 15:00:35 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 10/16] Use the new DSO finder helper function since we have it Date: Wed, 17 Jun 2020 15:00:18 +0100 Message-Id: <20200617140024.12777-11-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-14.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, 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/dl-load.c | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/elf/dl-load.c b/elf/dl-load.c index 76970f79de..62820167d5 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -2031,34 +2031,9 @@ _dl_map_object (struct link_map *loader, const char *name, #endif /* Look for this name among those already loaded. */ - for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next) - { - /* If the requested name matches the soname of a loaded object, - use that object. Elide this check for names that have not - yet been opened. */ - if (__glibc_unlikely ((l->l_faked | l->l_removed) != 0)) - continue; - if (!_dl_name_match_p (name, l)) - { - const char *soname; - - if (__glibc_likely (l->l_soname_added) - || l->l_info[DT_SONAME] == NULL) - continue; - - soname = ((const char *) D_PTR (l, l_info[DT_STRTAB]) - + l->l_info[DT_SONAME]->d_un.d_val); - if (strcmp (name, soname) != 0) - continue; - - /* We have a match on a new name -- cache it. */ - add_name_to_object (l, soname); - l->l_soname_added = 1; - } - - /* We have a match. */ - return l; - } + l = _dl_find_dso (name, nsid); + if (l != NULL) + return l; /* Display information if we are debugging. */ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES) From patchwork Wed Jun 17 14:00:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311232 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=8.43.85.97; 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=NNFDw88Y; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (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 49n6GV6Nkjz9sRW for ; Thu, 18 Jun 2020 00:02:58 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 238273898520; Wed, 17 Jun 2020 14:00:45 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 238273898520 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402445; bh=dqTPntQKhvmrp6rRVOxriDmZ5lTk7kIdCpAMJESCXzM=; 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=NNFDw88Yz0GevAFix6xWnu/vItv8T6IgKrqGKfs8RA2NogSlsjjZGuL5C+8A+rnUl pOkJWdaprQpaiDnh1/Hh1rpKRI+udkJK2YQgcoKki0ncVSGa2cU4RbRIzKISdXS0MV AhJH6FOQDRuVsLLFAAmN/pdQ3TJUwH8OwRNPrfRE= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by sourceware.org (Postfix) with ESMTPS id AB48B389366A for ; Wed, 17 Jun 2020 14:00:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org AB48B389366A Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 86AC12A3FC6 for ; Wed, 17 Jun 2020 15:00:35 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 11/16] Use the DSO search helper to check for preloaded DT_GNU_UNIQUE DSOs Date: Wed, 17 Jun 2020 15:00:19 +0100 Message-Id: <20200617140024.12777-12-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-14.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, 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" If a DSO already exists (with the same name) in the base namespace and it is flagged DT_GNU_UNIQUE then we should behave as if a proxy had been requested. --- elf/dl-load.c | 2 +- elf/dl-open.c | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/elf/dl-load.c b/elf/dl-load.c index 62820167d5..66848f8434 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -950,7 +950,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, for (l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; l != NULL; l = l->l_next) if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id)) { - if (!(l->l_flags_1 & DF_1_UNIQUE)) + if (l->l_info[VALIDX (DT_GNU_UNIQUE)] == NULL) continue; /* Already loaded. Bump its reference count and return it. */ diff --git a/elf/dl-open.c b/elf/dl-open.c index 75dc3893d3..43597a510e 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -476,6 +476,7 @@ dl_open_worker (void *a) const char *file = args->file; int mode = args->mode; struct link_map *call_map = NULL; + struct link_map *preloaded = NULL; int want_proxy = mode & RTLD_SHARED; Lmid_t proxy_ns = LM_ID_BASE; @@ -519,6 +520,23 @@ dl_open_worker (void *a) may not be true if this is a recursive call to dlopen. */ _dl_debug_initialize (0, args->nsid); + /* Target Lmid is not the base and we haven't explicitly asked for a proxy: + We need to check for a matching DSO in the base Lmid in case it is flagged + DT_GNU_UNIQUE in which case we add RTLD_SHARED to the mode and set + want_proxy. + NOTE: RTLD_ISOLATE in the mode suppresses this behaviour. */ + if (__glibc_unlikely (args->nsid != LM_ID_BASE) && + __glibc_likely (!want_proxy)) + { + preloaded = _dl_find_dso (file, LM_ID_BASE); + + if (preloaded && (preloaded->l_info[VALIDX (DT_GNU_UNIQUE)] != NULL)) + { + want_proxy = RTLD_SHARED; + mode |= RTLD_SHARED; + } + } + /* Load the named object. */ struct link_map *new; args->map = new = _dl_map_object (call_map, file, lt_loaded, 0, @@ -548,7 +566,7 @@ dl_open_worker (void *a) return; } - /* If we were trying to load a DF_1_UNIQUE flagged DSO which was NOT + /* If we were trying to load a DT_GNU_UNIQUE flagged DSO which was NOT ALREADY LOADED (or not loaded with the name we are using) then _dl_map_object will return an instance from the main namespace. We need to detect this and set up the RTLD_SHARED flags. */ From patchwork Wed Jun 17 14:00:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311235 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=KDcfHSss; 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 49n6H15Q9mz9sRW for ; Thu, 18 Jun 2020 00:03:25 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 44DA7389852D; Wed, 17 Jun 2020 14:00:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 44DA7389852D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402447; bh=YMuZkZsjZXAgRtNoBZ1gSz1RGNXb7lxObiCtDsujhdg=; 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=KDcfHSssj/FKfx/QzG29zMJlKvj0LLTWKrbsX4mMZLMKHlS7lEgPu9w2njWti659a 3S++8b/0VzBAruw9d4dPcM9abloxlM1XwL9TykYE/FdsTyi0UdQ1xZ7c3tYqi+CSO3 0TLqDi/oJOw2xVt+B3JMosAEOHLNPtyZcvXZVOeY= 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 A04373893669 for ; Wed, 17 Jun 2020 14:00:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org A04373893669 Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 96A892A3FC7 for ; Wed, 17 Jun 2020 15:00:35 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 12/16] When loading DSOs into alternate namespaces check for DT_GNU_UNIQUE Date: Wed, 17 Jun 2020 15:00:20 +0100 Message-Id: <20200617140024.12777-13-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-14.4 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, 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" If a DSO has not already been loaded and the target is not the main namespace then we must check to see if it's been DT_GNU_UNIQUE tagged and load it into the main namespace instead. dl_open_worker has alread been modified to notice the discrepancy between the request and the result in such cases, and will set up a proxy in the target namespace. --- elf/dl-load.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 83 insertions(+), 15 deletions(-) diff --git a/elf/dl-load.c b/elf/dl-load.c index 66848f8434..e0eced6dd2 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -827,6 +827,62 @@ _dl_init_paths (const char *llp) env_path_list.dirs = (void *) -1; } +static ElfW(Word) +_has_dt_gnu_unique (int fd, const ElfW(Ehdr) *header, const ElfW(Phdr) *phdr) +{ + int unique = 0; + const ElfW(Phdr) *ph; + ElfW(Dyn) entry = {}; + off_t reset; + off_t pos; + off_t end; + + reset = __lseek (fd, 0, SEEK_CUR); + + for (ph = phdr; ph < &phdr[header->e_phnum]; ++ph) + { + switch (ph->p_type) + { + case PT_DYNAMIC: + pos = __lseek (fd, ph->p_offset, SEEK_SET); + end = pos + ph->p_filesz; + + while (pos < end) + { + ssize_t rb = 0; + do + { + ssize_t rretl = __read_nocancel (fd, &entry + rb, + sizeof (ElfW(Dyn)) - rb); + if (rretl <= 0) + goto cleanup; + + rb += rretl; + } + while (__glibc_unlikely (rb < sizeof (ElfW(Dyn)))); + + switch (entry.d_tag) + { + case DT_GNU_UNIQUE: + unique = entry.d_un.d_val; + case DT_NULL: + goto cleanup; + break; + default: + break; + } + pos += rb; + } + break; + } + } + + cleanup: + /* Put the file descriptor offset back where it was when we were called. */ + __lseek (fd, reset, SEEK_SET); + + return unique; +} static void __attribute__ ((noreturn, noinline)) @@ -941,7 +997,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, } #endif - /* DSOs in the main namespace which are flagged DF_1_UNIQUE should only + /* DSOs in the main namespace which are flagged DT_GNU_UNIQUE should only be opened into the main namespace. Other namespaces should only get proxies. */ if (__glibc_unlikely (nsid != LM_ID_BASE)) @@ -1019,6 +1075,32 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, else assert (r->r_state == RT_ADD); + /* Load the ELF header using preallocated struct space if it's big enough. */ + maplength = header->e_phnum * sizeof (ElfW(Phdr)); + if (header->e_phoff + maplength <= (size_t) fbp->len) + phdr = (void *) (fbp->buf + header->e_phoff); + else + { + phdr = alloca (maplength); + if ((size_t) __pread64_nocancel (fd, (void *) phdr, maplength, + header->e_phoff) != maplength) + { + errstring = N_("cannot read file data"); + goto call_lose_errno; + } + } + + /* We need to check for DT_GNU_UNIQUE before we start + initialising any namespace dependent metatada. */ + if (nsid != LM_ID_BASE) + { + /* Target DSO is flagged as unique: Make sure it gets loaded into + the base namespace. It is up to our caller to generate a proxy in + the target nsid. */ + if (_has_dt_gnu_unique (fd, header, phdr)) + nsid = LM_ID_BASE; + } + /* Enter the new object in the list of loaded objects. */ l = _dl_new_object (realname, name, l_type, loader, mode, nsid); if (__glibc_unlikely (l == NULL)) @@ -1036,20 +1118,6 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, type = header->e_type; l->l_phnum = header->e_phnum; - maplength = header->e_phnum * sizeof (ElfW(Phdr)); - if (header->e_phoff + maplength <= (size_t) fbp->len) - phdr = (void *) (fbp->buf + header->e_phoff); - else - { - phdr = alloca (maplength); - if ((size_t) __pread64_nocancel (fd, (void *) phdr, maplength, - header->e_phoff) != maplength) - { - errstring = N_("cannot read file data"); - goto call_lose_errno; - } - } - /* On most platforms presume that PT_GNU_STACK is absent and the stack is * executable. Other platforms default to a nonexecutable stack and don't * need PT_GNU_STACK to do so. */ From patchwork Wed Jun 17 14:00:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311233 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=dDRX3HbK; 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 49n6Gg2bmcz9sRW for ; Thu, 18 Jun 2020 00:03:07 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A4D5D3898524; Wed, 17 Jun 2020 14:00:45 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A4D5D3898524 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402445; bh=18R9XgWZmnOv8PnPwvIPiBDk+ZrLcRtiJGkEGl7dZ3w=; 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=dDRX3HbKP3I9Xyu1NUrbMU/q46ZfHU/1ChWPocha+siHPS2ZIpNLyhTQJ77PZMuUm QRfCWAE0G/2/1GLtXkJPMLIS9nghb/Tc8T5wBHc7ijUV9A+t/aUkTLz4dlRmjIDHHk e2kE4yrJ60NgpvUN4BuZ5lJSk7DaDmH5PldGivyU= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by sourceware.org (Postfix) with ESMTPS id 3B9F4389366E for ; Wed, 17 Jun 2020 14:00:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 3B9F4389366E Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 A77812A3FC8 for ; Wed, 17 Jun 2020 15:00:35 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 13/16] Suppress inter-namespace DSO sharing for audit libraries Date: Wed, 17 Jun 2020 15:00:21 +0100 Message-Id: <20200617140024.12777-14-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-14.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, 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" Audit libraries should not participate in DSO sharing: In particular libraries tagged with DF_1_UNIQUE should not be shared between the audit namespace and any others - they should get their own copy. This is signalled to the loader code by passing the RTLD_ISOLATE flag from the relevant entry point in the dl modes argument. --- bits/dlfcn.h | 3 +++ elf/dl-load.c | 5 +++-- elf/dl-open.c | 13 +++++++++++-- elf/rtld.c | 2 +- sysdeps/mips/bits/dlfcn.h | 3 +++ 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/bits/dlfcn.h b/bits/dlfcn.h index 9170059323..ef079709f9 100644 --- a/bits/dlfcn.h +++ b/bits/dlfcn.h @@ -32,6 +32,9 @@ visible as if the object were linked directly into the program. */ #define RTLD_GLOBAL 0x00100 +/* Suppress RTLD_SHARED and/or DF_1_UNIQUE. */ +#define RTLD_ISOLATE 0x00040 + /* If the following bit is set in the MODE argument to dlmopen then the target object is loaded into the main namespace (if it is not already there) and a shallow copy (proxy) is placed diff --git a/elf/dl-load.c b/elf/dl-load.c index e0eced6dd2..bf86d3c7f9 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1000,7 +1000,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, /* DSOs in the main namespace which are flagged DT_GNU_UNIQUE should only be opened into the main namespace. Other namespaces should only get proxies. */ - if (__glibc_unlikely (nsid != LM_ID_BASE)) + if (__glibc_unlikely ((nsid != LM_ID_BASE) && !(mode & RTLD_ISOLATE))) { /* Check base ns to see if the name matched another already loaded. */ for (l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; l != NULL; l = l->l_next) @@ -1092,7 +1092,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, /* We need to check for DT_GNU_UNIQUE before we start initialising any namespace dependent metatada. */ - if (nsid != LM_ID_BASE) + if (__glibc_unlikely ((nsid != LM_ID_BASE) && !(mode & RTLD_ISOLATE))) { /* Target DSO is flagged as unique: Make sure it gets loaded into the base namespace. It is up to our caller to generate a proxy in @@ -2083,6 +2083,7 @@ _dl_map_object (struct link_map *loader, const char *name, assert (nsid >= 0); assert (nsid < GL(dl_nns)); + assert (!((mode & RTLD_ISOLATE) && (mode & RTLD_SHARED))); #ifdef SHARED /* Only need to do proxy checks if `nsid' is not LM_ID_BASE. */ diff --git a/elf/dl-open.c b/elf/dl-open.c index 43597a510e..67d5825510 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -477,9 +477,16 @@ dl_open_worker (void *a) int mode = args->mode; struct link_map *call_map = NULL; struct link_map *preloaded = NULL; - int want_proxy = mode & RTLD_SHARED; + int want_proxy = 0; + int dl_isolate = mode & RTLD_ISOLATE; Lmid_t proxy_ns = LM_ID_BASE; + /* Isolation means we should suppress all inter-namespace sharing. */ + if (dl_isolate) + mode &= ~RTLD_SHARED; + else + want_proxy = mode & RTLD_SHARED; + /* Determine the caller's map if necessary. This is needed in case we have a DST, when we don't know the namespace ID we have to put the new object in, or when the file name has no path in which @@ -526,6 +533,7 @@ dl_open_worker (void *a) want_proxy. NOTE: RTLD_ISOLATE in the mode suppresses this behaviour. */ if (__glibc_unlikely (args->nsid != LM_ID_BASE) && + __glibc_likely (!dl_isolate) && __glibc_likely (!want_proxy)) { preloaded = _dl_find_dso (file, LM_ID_BASE); @@ -636,7 +644,8 @@ dl_open_worker (void *a) /* Load that object's dependencies. */ _dl_map_object_deps (new, NULL, 0, 0, - mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT)); + mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT | + RTLD_ISOLATE)); /* So far, so good. Now check the versions. */ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) diff --git a/elf/rtld.c b/elf/rtld.c index 553cfbd1b7..be08786419 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -616,7 +616,7 @@ dlmopen_doit (void *a) struct dlmopen_args *args = (struct dlmopen_args *) a; args->map = _dl_open (args->fname, (RTLD_LAZY | __RTLD_DLOPEN | __RTLD_AUDIT - | __RTLD_SECURE), + | __RTLD_SECURE | RTLD_ISOLATE), dl_main, LM_ID_NEWLM, _dl_argc, _dl_argv, __environ); } diff --git a/sysdeps/mips/bits/dlfcn.h b/sysdeps/mips/bits/dlfcn.h index fc33fd184e..372dcf4097 100644 --- a/sysdeps/mips/bits/dlfcn.h +++ b/sysdeps/mips/bits/dlfcn.h @@ -39,6 +39,9 @@ share a single instance of a DSO. */ #define RTLD_SHARED 0x00020 +/* Suppress RTLD_SHARED and/or DF_1_UNIQUE. */ +#define RTLD_ISOLATE 0x00040 + /* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL. The implementation does this by default and so we can define the value to zero. */ From patchwork Wed Jun 17 14:00:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311231 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=8.43.85.97; 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=hKyw6ckE; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (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 49n6GK4Xbdz9sRW for ; Thu, 18 Jun 2020 00:02:49 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6F59C3898519; Wed, 17 Jun 2020 14:00:44 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6F59C3898519 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402444; bh=6KPc4FWdq38pndNSLN0KIOos1BdcAk2WD90n12PjiRU=; 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=hKyw6ckEBCcJANEBe1wfiOYbzoRcvOtETowxmtQo0s9UU5Q9CSJn9DCdrWF9rBAcV u3yTNxSmwRzP0XrPWmL5mc4BWy5d6ju+5FajBkJm9l8L1iaGwxIGAacatSn9c3sm7H NPTAXdxdR21A0GxULp9fDplVZvXPsUVet8wzORIU= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by sourceware.org (Postfix) with ESMTPS id 341D5389366D for ; Wed, 17 Jun 2020 14:00:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 341D5389366D Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 B70122A3FC9 for ; Wed, 17 Jun 2020 15:00:35 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 14/16] dlsym, dlvsym should be able to look up symbols via DSO proxies Date: Wed, 17 Jun 2020 15:00:22 +0100 Message-Id: <20200617140024.12777-15-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-14.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, 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/dl-sym.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/elf/dl-sym.c b/elf/dl-sym.c index b43a50e544..2974efd60a 100644 --- a/elf/dl-sym.c +++ b/elf/dl-sym.c @@ -108,6 +108,10 @@ do_sym (void *handle, const char *name, void *who, { match = find_caller_link_map (caller); + /* Proxies don't contain any symbols: Need to look at the real DSO. */ + if (__glibc_unlikely (match->l_proxy)) + match = match->l_real; + /* Search the global scope. We have the simple case where we look up in the scope of an object which was part of the initial binary. And then the more complex part @@ -152,6 +156,11 @@ RTLD_NEXT used in code not dynamically loaded")); } struct link_map *l = match; + + /* Proxies don't contain any symbols: Need to look at the real DSO. */ + if (__glibc_unlikely (l->l_proxy)) + l = l->l_real; + while (l->l_loader != NULL) l = l->l_loader; @@ -162,6 +171,11 @@ RTLD_NEXT used in code not dynamically loaded")); { /* Search the scope of the given object. */ struct link_map *map = handle; + + /* Proxies don't contain any symbols: Need to look at the real DSO. */ + if (__glibc_unlikely (map->l_proxy)) + map = map->l_real; + result = GLRO(dl_lookup_symbol_x) (name, map, &ref, map->l_local_scope, vers, 0, flags, NULL); } From patchwork Wed Jun 17 14:00:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311234 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=8.43.85.97; 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=XeMGEQfH; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (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 49n6Gr2y5Kz9sRW for ; Thu, 18 Jun 2020 00:03:16 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BA32F389852A; Wed, 17 Jun 2020 14:00:46 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BA32F389852A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402446; bh=wlzhEK4rfZmeHoqsNgwWQA/lMS/3AC5yctXJIiwQahQ=; 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=XeMGEQfH5sPdWoONngBfQcvwzvjvPDBJmMuXbrd6SV7kKIU02+OPfyFE0w1jrUWif Txp+MruXPkB8FDT3JC5FFFWiWCKI97WEW7BKVJWi8kBCdkH10hAnKMx077+Y8aI8XM lGV0WOv+tHpf6sWQPchNCeEL+zc5l4/lipakFFCA= 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 E55F83893665 for ; Wed, 17 Jun 2020 14:00:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org E55F83893665 Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 CAFB42A3FCA for ; Wed, 17 Jun 2020 15:00:35 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 15/16] Add a DT_GNU_UNIQUE dynamic section to the glibc cluster DSOs Date: Wed, 17 Jun 2020 15:00:23 +0100 Message-Id: <20200617140024.12777-16-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-14.4 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, 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" --- Makeconfig | 1 + Makerules | 2 +- iconvdata/Makefile | 1 + nptl/Makefile | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Makeconfig b/Makeconfig index f252842979..ac38994c52 100644 --- a/Makeconfig +++ b/Makeconfig @@ -398,6 +398,7 @@ LDFLAGS-lib.so += -Wl,-z,now # Extra flags for dynamically linked non-test main programs. link-extra-flags += -Wl,-z,now endif +LDFLAGS-lib.so += -Wl,--unique-dso # Command to run after every final link (executable or shared object). # This is invoked with $(call after-link,...), so it should operate on diff --git a/Makerules b/Makerules index 1e9c18f0d8..c98db0556b 100644 --- a/Makerules +++ b/Makerules @@ -635,7 +635,7 @@ build-shlib-objlist = $(build-module-helper-objlist) \ # Don't try to use -lc when making libc.so itself. # Also omits crti.o and crtn.o, which we do not want # since we define our own `.init' section specially. -LDFLAGS-c.so = -nostdlib -nostartfiles +LDFLAGS-c.so = -nostdlib -nostartfiles -Wl,--unique-dso # But we still want to link libc.so against $(libc.so-gnulib). LDLIBS-c.so += $(libc.so-gnulib) # Give libc.so an entry point and make it directly runnable itself. diff --git a/iconvdata/Makefile b/iconvdata/Makefile index c83962f351..aa5f47532e 100644 --- a/iconvdata/Makefile +++ b/iconvdata/Makefile @@ -67,6 +67,7 @@ modules := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \ ifeq ($(bind-now),yes) LDFLAGS.so += -Wl,-z,now endif +LDFLAGS.so += -Wl,--unique-dso modules.so := $(addsuffix .so, $(modules)) diff --git a/nptl/Makefile b/nptl/Makefile index 584e0ffd96..92c30f7260 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -380,7 +380,7 @@ else tests-printers-libs := $(static-thread-library) endif -LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst +LDFLAGS-pthread.so = -Wl,--enable-new-dtags,--unique-dso,-z,nodelete,-z,initfirst # GCC-4.9 compiles 'sprintf(NULL, ...)' into UD2 on x86_64 without -fno-builtin CFLAGS-tst-cleanup2.c += -fno-builtin From patchwork Wed Jun 17 14:00:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 1311236 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=8.43.85.97; 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=rnZI+XRE; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (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 49n6HB1WHRz9sRR for ; Thu, 18 Jun 2020 00:03:34 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id CB8493898531; Wed, 17 Jun 2020 14:00:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CB8493898531 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1592402447; bh=Zhx8S7LFpoUWwGTWNQVl+HPBcqXyvLMneOzwTlO4A30=; 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=rnZI+XRERLmOHlqxfNxX1KY77gXGzzBQ/xRf9acW6M0AoUokr/p3ZaW7YZ+MPgp2b NlIkH9Vl2g4G4brY+X0yclT952f2WwJhEvV27ahu/IW1aHxGCydeFPVtCc1rHxCAz3 ZLgPzPK/IMgkXV4WVht0dX5fZvn2c9UNw8BYMg6Y= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by sourceware.org (Postfix) with ESMTPS id 047653893668 for ; Wed, 17 Jun 2020 14:00:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 047653893668 Received: from noise.collabora.co.uk (unknown [IPv6:2001:4d48:ad56:3000:88ff:22ff:81f3:30c8]) (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 DB9C82A3FCB for ; Wed, 17 Jun 2020 15:00:35 +0100 (BST) To: libc-alpha@sourceware.org Subject: [RFC][PATCH v5 16/16] Add dlmopen / RTLD_SHARED tests Date: Wed, 17 Jun 2020 15:00:24 +0100 Message-Id: <20200617140024.12777-17-vivek@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200617140024.12777-1-vivek@collabora.com> References: <20200617140024.12777-1-vivek@collabora.com> X-Spam-Status: No, score=-14.3 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, 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 | 42 +- elf/tst-dlmopen-common.h | 15 + elf/tst-dlmopen-main.h | 899 +++++++++++++++++++++++++++++++++++++++ elf/tst-dlmopen-modules.h | 3 + elf/tst-dlmopen-rtld-shared1.c | 74 ++++ elf/tst-dlmopen-rtld-shared2.c | 76 ++++ elf/tst-dlmopen-rtld-shared3.c | 53 +++ elf/tst-dlmopen-rtld-shared4.c | 24 ++ elf/tst-dlmopen-rtld-shared5.c | 35 ++ elf/tst-dlmopen-rtld-shared6.c | 46 ++ elf/tst-dlmopen-rtld-unique1.c | 96 +++++ elf/tst-dlmopen-rtld-unique2.c | 35 ++ elf/tst-dlmopen-rtld-unique3.c | 23 + elf/tst-dlmopen-rtld-unique4.c | 24 ++ elf/tst-dlmopen-sharedmod-norm.c | 11 + elf/tst-dlmopen-sharedmod-uniq.c | 11 + elf/tst-dlmopen-std-do-test.h | 11 + 17 files changed, 1477 insertions(+), 1 deletion(-) 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-shared1.c create mode 100644 elf/tst-dlmopen-rtld-shared2.c create mode 100644 elf/tst-dlmopen-rtld-shared3.c create mode 100644 elf/tst-dlmopen-rtld-shared4.c create mode 100644 elf/tst-dlmopen-rtld-shared5.c create mode 100644 elf/tst-dlmopen-rtld-shared6.c create mode 100644 elf/tst-dlmopen-rtld-unique1.c create mode 100644 elf/tst-dlmopen-rtld-unique2.c create mode 100644 elf/tst-dlmopen-rtld-unique3.c create mode 100644 elf/tst-dlmopen-rtld-unique4.c 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 632a4d8b0f..88e500cad4 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -177,6 +177,20 @@ tests-static += tst-tls9-static tst-tls9-static-ENV = \ LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)dlfcn +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 + tests += restest1 preloadtest loadfail multiload origtest resolvfail \ constload1 order noload filter \ reldep reldep2 reldep3 reldep4 nodelete nodelete2 \ @@ -201,7 +215,9 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-unwind-ctor tst-unwind-main tst-audit13 \ tst-sonamemove-link tst-sonamemove-dlopen tst-dlopen-tlsmodid \ tst-dlopen-self tst-auditmany tst-initfinilazyfail tst-dlopenfail \ - tst-dlopenfail-2 + tst-dlopenfail-2 \ + $(dlmopen-rtld-tests-norm) \ + $(dlmopen-rtld-tests-uniq) # reldep9 tests-internal += loadtest unload unload2 circleload1 \ neededtest neededtest2 neededtest3 neededtest4 \ @@ -262,6 +278,8 @@ 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 \ unload3mod1 unload3mod2 unload3mod3 unload3mod4 \ unload4mod1 unload4mod2 unload4mod3 unload4mod4 \ unload6mod1 unload6mod2 unload6mod3 \ @@ -773,6 +791,8 @@ 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 ifeq ($(build-shared),yes) # Build all the modules even when not actually running test programs. @@ -1245,6 +1265,26 @@ $(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,--unique-dso +$(objpfx)tst-dlmopen-sharedmod-norm.so: $(libdl) +$(objpfx)tst-dlmopen-sharedmod-uniq.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-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 + $(objpfx)tst-audit1.out: $(objpfx)tst-auditmod1.so tst-audit1-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so diff --git a/elf/tst-dlmopen-common.h b/elf/tst-dlmopen-common.h new file mode 100644 index 0000000000..f93ceb5465 --- /dev/null +++ b/elf/tst-dlmopen-common.h @@ -0,0 +1,15 @@ +#pragma once + +#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..80bf3a6d8b --- /dev/null +++ b/elf/tst-dlmopen-main.h @@ -0,0 +1,899 @@ +#pragma once + +#include "tst-dlmopen-common.h" +#include +#include + +#define DSO_DUMMY "$ORIGIN/tst-dlmopen-sharedmod-noop.so" +#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 POISON 0xabad1dea + +#define LM_ID_NONE -2 + +#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; +} 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, Lmid_t expect_ns) +{ + 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 != expect_ns) + { + ERROR (test, + "free() function from test module was from ns %d, expected %d\n", + (int)lm->l_ns, (int)expect_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("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)"); + + 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, LM_ID_BASE); + 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..796d8855fe --- /dev/null +++ b/elf/tst-dlmopen-modules.h @@ -0,0 +1,3 @@ +#pragma once + +#include "tst-dlmopen-common.h" diff --git a/elf/tst-dlmopen-rtld-shared1.c b/elf/tst-dlmopen-rtld-shared1.c new file mode 100644 index 0000000000..152eaf933c --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared1.c @@ -0,0 +1,74 @@ +#include +#include "tst-dlmopen-main.h" + +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--ns1", + .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, [1] = DSO|NEW }, + .handle_type = DSO, + .handle_ns = 1, + }, + { + .name = "dlmopen:0:ns0-ns1--ns0-ns1", + .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, [1] = DSO }, + .loaded = { [0] = DSO, [1] = DSO }, + .handle_type = DSO, + .handle_ns = LM_ID_BASE, + }, + { + .name = "dlmopen-shared:0:ns0-ns1--ns0-ns1", + .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, [1] = DSO }, + .loaded = { [0] = DSO, [1] = DSO }, + .handle_type = DSO, + .handle_ns = LM_ID_BASE, + }, + END_TESTS + }; + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-shared2.c b/elf/tst-dlmopen-rtld-shared2.c new file mode 100644 index 0000000000..ffa5779e34 --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared2.c @@ -0,0 +1,76 @@ +#include +#include "tst-dlmopen-main.h" + +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:1:ns0--ns0-ns1p", + .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 = 1, + .handle_type = PROXY, + .preloaded = { [0] = DSO }, + .loaded = { [0] = DSO, [1] = PROXY|NEW } + }, + { + .name = "dlmopen:0:ns0-ns1p--ns0-ns1p", + .desc = "dlmopen into base NS while proxy already in ns1", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [0] = DSO, [1] = PROXY }, + .loaded = { [0] = DSO, [1] = PROXY }, + }, + { + .name = "dlmopen-shared:0:ns0-ns1p--ns0-ns1p", + .desc = "dlmopen with RTLD_SHARED into base NS while proxy already in ns1", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .args.flags = RTLD_SHARED, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [0] = DSO, [1] = PROXY }, + .loaded = { [0] = DSO, [1] = PROXY }, + }, + { + .name = "dlmopen:1:ns0-ns1p--ns0-ns1p", + .desc = "dlmopen into NS 1 while proxy already in ns1", + .args.dso_path = DSO_NORMAL, + .args.ns = 1, + .handle_ns = 1, + .handle_type = PROXY, + .preloaded = { [0] = DSO, [1] = PROXY }, + .loaded = { [0] = DSO, [1] = PROXY }, + }, + { + .name = "dlmopen-shared:1:ns0-ns1p--ns0-ns1p", + .desc = "dlmopen with RTLD_SHARED into NS 1 while proxy already in ns1", + .args.dso_path = DSO_NORMAL, + .args.ns = 1, + .args.flags = RTLD_SHARED, + .handle_ns = 1, + .handle_type = PROXY, + .preloaded = { [0] = DSO, [1] = PROXY }, + .loaded = { [0] = DSO, [1] = PROXY }, + }, + END_TESTS + }; + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-shared3.c b/elf/tst-dlmopen-rtld-shared3.c new file mode 100644 index 0000000000..cc2d411b5f --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared3.c @@ -0,0 +1,53 @@ +#include +#include "tst-dlmopen-main.h" + +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen:1:none--ns1", + .desc = "dlmopen into ns1, no copies preloaded", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_NEWLM, + .handle_ns = 1, + .handle_type = DSO, + .preloaded = { }, + .loaded = { [1] = DSO|NEW }, + }, + { + .name = "dlmopen:0:ns1--ns0-ns1", + .desc = "dlmopen into ns 0, copy already loaded in ns 1", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [1] = DSO }, + .loaded = { [0] = DSO|NEW, [1] = DSO }, + }, + { + .name = "dlmopen:1:ns0-ns1--ns1", + .desc = "dlmopen into ns 1, copies already in ns 0 and ns 1", + .args.dso_path = DSO_NORMAL, + .args.ns = 1, + .handle_ns = 1, + .handle_type = DSO, + .preloaded = { [0] = DSO, [1] = DSO }, + .loaded = { [0] = DSO, [1] = DSO }, + }, + { + .name = "dlmopen-shared:1:ns0-ns1--ns1", + .desc = "dlmopen RTLD_SHARED into ns1 with a DSO already in NS0 and NS1", + .args.dso_path = DSO_NORMAL, + .args.ns = 1, + .args.flags = RTLD_SHARED, + .failure = 1, + .preloaded = { [0] = DSO, [1] = DSO }, + .loaded = { [0] = DSO, [1] = DSO }, + }, + END_TESTS + }; + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-shared4.c b/elf/tst-dlmopen-rtld-shared4.c new file mode 100644 index 0000000000..72c2d08506 --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared4.c @@ -0,0 +1,24 @@ +#include +#include "tst-dlmopen-main.h" + +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-shared:1:none--ns0-ns1", + .desc = "dlmopen a new proxy in ns1 with no preexisting dso in ns0", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_NEWLM, + .args.flags = RTLD_SHARED, + .handle_ns = 1, + .handle_type = PROXY, + .preloaded = { }, + .loaded = { [0] = DSO|NEW, [1] = PROXY|NEW }, + }, + END_TESTS + }; + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-shared5.c b/elf/tst-dlmopen-rtld-shared5.c new file mode 100644 index 0000000000..d824214402 --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared5.c @@ -0,0 +1,35 @@ +#include +#include "tst-dlmopen-main.h" + +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-preload:1:none--ns1", + .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 = 1, + .handle_type = DSO, + .preloaded = { }, + .loaded = { [1] = DSO|NEW }, + }, + { + .name = "dlmopen-shared:0:ns1--ns1-ns0", + .desc = "dlmopen RTLD_SHARED into ns0 when preloaded into ns1", + .args.dso_path = DSO_NORMAL, + .args.ns = LM_ID_BASE, + .args.flags = RTLD_SHARED, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [1] = DSO }, + .loaded = { [0] = DSO|NEW, [1] = DSO }, + }, + END_TESTS + }; + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-shared6.c b/elf/tst-dlmopen-rtld-shared6.c new file mode 100644 index 0000000000..886f03f8e0 --- /dev/null +++ b/elf/tst-dlmopen-rtld-shared6.c @@ -0,0 +1,46 @@ +#include +#include "tst-dlmopen-main.h" + +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-preload:1:none--ns1", + .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 = 1, + .handle_type = DSO, + .preloaded = { }, + .loaded = { [1] = DSO|NEW }, + }, + { + .name = "dlmopen:1:ns1--ns1", + .desc = "dlmopen a dso in ns1 while already loaded there", + .args.dso_path = DSO_NORMAL, + .args.ns = 1, + .handle_ns = 1, + .handle_type = DSO, + .preloaded = { [1] = DSO }, + .loaded = { [1] = DSO }, + }, + { + .name = "dlmopen-shared:1:ns1--ns1", + .desc = "dlmopen RTLD_SHARED a dso in ns1 while already loaded there", + .failure = 1, + .args.dso_path = DSO_NORMAL, + .args.ns = 1, + .args.flags = RTLD_SHARED, + .handle_ns = 1, + .handle_type = DSO, + .preloaded = { [1] = DSO }, + .loaded = { [1] = DSO }, + }, + END_TESTS + }; + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-unique1.c b/elf/tst-dlmopen-rtld-unique1.c new file mode 100644 index 0000000000..6fc6d12721 --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique1.c @@ -0,0 +1,96 @@ +#include +#include "tst-dlmopen-main.h" + +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-unique:0:none--ns0", + .desc = "dlmopen a DF_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_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_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:1:ns0--ns1", + .desc = "dlmopen a DF_1_UNIQUE dso into ns1 while present in ns0", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_NEWLM, + .handle_ns = 1, + .handle_type = PROXY, + .preloaded = { [0] = DSO }, + .loaded = { [0] = DSO, [1] = PROXY|NEW }, + }, + { + .name = "dlmopen-unique:0:ns0-ns1p--ns0--ns1p", + .desc = "dlmopen a DF_1_UNIQUE dso already in ns0 proxied in ns1", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_BASE, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [0] = DSO, [1] = PROXY }, + .loaded = { [0] = DSO, [1] = PROXY }, + }, + { + .name = "dlmopen-shared-unique:0:ns0-ns1p--ns0-ns1p", + .desc = "dlmopen RTLD_SHARED a DF_1_UNIQUE dso into ns0 already in ns0 and proxied in ns1", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_BASE, + .args.flags = RTLD_SHARED, + .handle_ns = 0, + .handle_type = DSO, + .preloaded = { [0] = DSO, [1] = PROXY }, + .loaded = { [0] = DSO, [1] = PROXY }, + }, + { + .name = "dlmopen-unique:0:ns0-ns1p--ns0-ns1p", + .desc = "dlmopen a DF_1_UNIQUE dso into ns0 already in ns0 and proxied in ns1", + .args.dso_path = DSO_UNIQUE, + .args.ns = 1, + .handle_ns = 1, + .handle_type = PROXY, + .preloaded = { [0] = DSO, [1] = PROXY }, + .loaded = { [0] = DSO, [1] = PROXY }, + }, + { + .name = "dlmopen-unique:0:ns0-ns1p--ns0-ns1p", + .desc = "dlmopen RTLD_SHARED a DF_1_UNIQUE dso into ns0 already in ns0 and proxied in ns1", + .args.dso_path = DSO_UNIQUE, + .args.ns = 1, + .args.flags = RTLD_SHARED, + .handle_ns = 1, + .handle_type = PROXY, + .preloaded = { [0] = DSO, [1] = PROXY }, + .loaded = { [0] = DSO, [1] = PROXY }, + }, + END_TESTS + }; + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-unique2.c b/elf/tst-dlmopen-rtld-unique2.c new file mode 100644 index 0000000000..865c1532c4 --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique2.c @@ -0,0 +1,35 @@ +#include +#include "tst-dlmopen-main.h" + +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-shared-unique:0:none--ns0", + .desc = "dlmopen RTLD_SHARED a DF_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_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 = 1, + .handle_type = PROXY, + .preloaded = { [0] = DSO }, + .loaded = { [0] = DSO, [1] = PROXY|NEW }, + }, + END_TESTS + }; + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-unique3.c b/elf/tst-dlmopen-rtld-unique3.c new file mode 100644 index 0000000000..f05b9dd733 --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique3.c @@ -0,0 +1,23 @@ +#include +#include "tst-dlmopen-main.h" + +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-unique:1:none--ns0-ns1p", + .desc = "dlmopen a DF_1_UNIQUE dso into ns1", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_NEWLM, + .handle_ns = 1, + .handle_type = PROXY, + .preloaded = { }, + .loaded = { [0] = DSO|NEW, [1] = PROXY|NEW }, + }, + END_TESTS + }; + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include diff --git a/elf/tst-dlmopen-rtld-unique4.c b/elf/tst-dlmopen-rtld-unique4.c new file mode 100644 index 0000000000..247085f5d7 --- /dev/null +++ b/elf/tst-dlmopen-rtld-unique4.c @@ -0,0 +1,24 @@ +#include +#include "tst-dlmopen-main.h" + +static dlmopen_test_spec dltest[] = + { + { + .name = "dlmopen-shared-unique:1:none--ns0-ns1p", + .desc = "dlmopen a DF_1_UNIQUE dso", + .args.dso_path = DSO_UNIQUE, + .args.ns = LM_ID_NEWLM, + .args.flags = RTLD_SHARED, + .handle_ns = 1, + .handle_type = PROXY, + .preloaded = { }, + .loaded = { [0] = DSO|NEW, [1] = PROXY|NEW }, + }, + END_TESTS + }; + +#include "tst-dlmopen-std-do-test.h" + +DEFINE_DLMOPEN_TEST(dltest) + +#include 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; \ + }