From patchwork Wed May 16 17:11:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Vivek Dasmohapatra X-Patchwork-Id: 914810 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-92575-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=collabora.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="a+Gwb+he"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40mLZY4jVJz9s2R for ; Thu, 17 May 2018 03:11:49 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-type:content-transfer-encoding; q=dns; s=default; b=iFxoFqBd1T2YptHlSb4MbBzttqG130w+/aWEpXOSPgo YbTq0APD9xrdFokoiTeH0XgTAFxemSWXpv8xA+/ryiTJst3gfhWbIheTkFTdKP75 f0YOQ7VyudKNt7mIcazYVXTA47bK0vaiDRmmcl0yRganGDeHGAsS5jTlgfKSHSTs = DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-type:content-transfer-encoding; s=default; bh=dOIIWHFusSEq4ce4GOoLEn30iQM=; b=a+Gwb+he69YtLZNgz XKqgP96ENZWevuRyFt3b4XKbRD08yY7ZhOWxG9qO+nXZe+kbCQp3jrcnVlj4rtuA R/IUS9Gfz7PPlQXgBqXiaTyvNCP150dPRIq4dT+zOQBUBch/1oWeehsVDWqaDu89 rrdSwOpcunAPyrV3ZbQ78zLuzQ= Received: (qmail 60236 invoked by alias); 16 May 2018 17:11:35 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 59383 invoked by uid 89); 16 May 2018 17:11:34 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 spammy=arrived, H*r:74c6, HContent-Transfer-Encoding:8bit X-HELO: bhuna.collabora.co.uk From: =?utf-8?q?Vivek_Das=C2=A0Mohapatra?= To: libc-alpha@sourceware.org Cc: =?utf-8?q?Vivek_Das=C2=A0Mohapatra?= Subject: [RFC][PATCH v1 3/5] elf/dl-object.c: Implement a helper function to clone link_map entries Date: Wed, 16 May 2018 18:11:22 +0100 Message-Id: <20180516171124.24962-4-vivek@collabora.com> In-Reply-To: <20180516171124.24962-1-vivek@collabora.com> References: <20180516171124.24962-1-vivek@collabora.com> MIME-Version: 1.0 From: Vivek Das Mohapatra Provides the minimal functionality needed to take an existing link_map entry and create a clone of it in the specified namespace. --- elf/dl-object.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ sysdeps/generic/ldsodefs.h | 6 ++++ 2 files changed, 83 insertions(+) diff --git a/elf/dl-object.c b/elf/dl-object.c index b37bcc1295..144ba6c993 100644 --- a/elf/dl-object.c +++ b/elf/dl-object.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -50,6 +51,82 @@ _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid) __rtld_lock_unlock_recursive (GL(dl_load_write_lock)); } +/* Clone 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 clones). + It also flags the clone by setting l_clone, and sets the the no-delete + flag in the original. */ +struct link_map * +_dl_clone_object (struct link_map *old, int mode, Lmid_t nsid) +{ + const char *name; + struct link_map *new; + struct libname_list *newname; +#ifdef SHARED + /* See _dl_new_object for how this number is arrived at: */ + unsigned int na = GLRO(dl_naudit) ?: ((mode & __RTLD_OPENEXEC) ? DL_NNS : 0); + size_t audit_space = na * sizeof (new->l_audit[0]); +#else +# define audit_space 0 +#endif + + name = old->l_name; + + /* Don't clone a clone: Go to the progenitor. */ + while (old && old->l_clone) + old = old->l_real; + + if (old == NULL) + _dl_signal_error (EINVAL, name, NULL, N_("cannot clone 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_clone) + return old; + + _dl_signal_error (EEXIST, name, NULL, + N_("object cannot be demoted to a clone")); + } + + /* Now duplicate as little of _dl_new_object as possible to get a + working cloned object in the target link map. */ + new = (struct link_map *) calloc (sizeof (*new) + audit_space + + sizeof (struct link_map *) + + sizeof (*newname) + PATH_MAX, 1); + + /* Specific to the clone. */ + new->l_real = old; + new->l_clone = 1; + new->l_ns = nsid; + + /* Copied from the origin. */ + new->l_libname = old->l_libname; + new->l_name = old->l_name; + new->l_type = 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 clone remains valid. */ + old->l_flags_1 |= DF_1_NODELETE; + + /* Fix up the searchlist so that relocations work. */ + /* TODO: figure out if we should call _dl_map_object_deps + or copy the contents of l_scope, l_searchlist et al. */ + _dl_map_object_deps (new, NULL, 0, 0, + mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT)); + + /* And finally put the clone into 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 5e1b24ecb5..573d24f611 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -913,6 +913,12 @@ extern lookup_t _dl_lookup_symbol_x (const char *undef, extern void _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid) attribute_hidden; +/* Clone an existing link map entry into a new link map */ +extern struct link_map *_dl_clone_object (struct link_map *old, + int mode, + Lmid_t nsid) + attribute_hidden; + /* Allocate a `struct link_map' for a new object being loaded. */ extern struct link_map *_dl_new_object (char *realname, const char *libname, int type, struct link_map *loader,