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: 39659 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org 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. */