From patchwork Mon Jan 3 12:53:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 49466 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 82FA43858C2C for ; Mon, 3 Jan 2022 12:54:24 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 82FA43858C2C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1641214464; bh=ZXyBa2+9Lrcn0L34hh5azG0zfP9C9lRbBH8XDs352zo=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=i1XcKwiAoCSS1ckv7TC9OGIMbcBVNv56/JVYyocQbUTVKeokxbLLoXWrbPBlHBHv/ DV9Mc0cljtR36poCbTAShV9Ssg0aum2szpzprCFCrJtIRI0vg1uhtBUh1inSE843Sg ikLPCddYiaXm4bQRxkocEb2ORr+HX7m8ixLYsG4k= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qv1-xf2a.google.com (mail-qv1-xf2a.google.com [IPv6:2607:f8b0:4864:20::f2a]) by sourceware.org (Postfix) with ESMTPS id DCF8E385841A for ; Mon, 3 Jan 2022 12:53:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DCF8E385841A Received: by mail-qv1-xf2a.google.com with SMTP id q3so30835170qvc.7 for ; Mon, 03 Jan 2022 04:53:12 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ZXyBa2+9Lrcn0L34hh5azG0zfP9C9lRbBH8XDs352zo=; b=KNq2otJvpgoewQ+SPKzSkWJlqAPTAbG6zJeI63sxuoxSrPnKvzAJ49CoU7vDXA6quQ lL+tK4dr/QHHIZQCb0l9ntzZuWosjYEcQzHMTs0ziVjY6quiDew8CzMXzIs0pnO8YEI1 ISotBiXAd57naNHhAsOzITih0qJ55y6kRzJqfHzYWdhAUvqPG81djDeZBk5WP7cx9dZw ZTgTl/HA1voAl32CbsPHbzC/hz/Kui6kJFLJ7d6ZcZRvv+uLjZSp25R5Kr+Xr/V8ycrm sD9sDgbXpikPXcGdyglzxggb78P98AFRZy57wkXmysVcs+S1M6Zz8zcJ2cDNCC0tuz6f ga6A== X-Gm-Message-State: AOAM530NbvPi/eo7Ulk7TRK6E/L4WtbrAw2Y3VUgEKLgRoOLezLK4p7/ 1ykZFIXNXLrizNBME6qgB2XeeMR7v1gfqQ== X-Google-Smtp-Source: ABdhPJxuJob0YGYXs2StGprj9cPBtz7trCc5pTcKXRai8eM9aEXb0C5aRVr2tMSEU2O6oQ+CgpOZnQ== X-Received: by 2002:ad4:4dca:: with SMTP id cw10mr41144863qvb.21.1641214392210; Mon, 03 Jan 2022 04:53:12 -0800 (PST) Received: from birita.. ([2804:431:c7ca:a350:6969:50a8:eab8:8f2f]) by smtp.gmail.com with ESMTPSA id c8sm28921141qkp.8.2022.01.03.04.53.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Jan 2022 04:53:12 -0800 (PST) To: libc-alpha@sourceware.org, jma14 Subject: [PATCH v9 1/4] elf: Add la_activity during application exit Date: Mon, 3 Jan 2022 09:53:03 -0300 Message-Id: <20220103125306.4151129-2-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220103125306.4151129-1-adhemerval.zanella@linaro.org> References: <20220103125306.4151129-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLACK autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Reply-To: Adhemerval Zanella Cc: John Mellor-Crummey Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" la_activity is not called during application exit, even though la_objclose is. Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. --- elf/Makefile | 8 +- elf/dl-fini.c | 10 ++ elf/tst-audit23.c | 240 +++++++++++++++++++++++++++++++++++++++++++ elf/tst-audit23mod.c | 23 +++++ elf/tst-auditmod23.c | 74 +++++++++++++ 5 files changed, 354 insertions(+), 1 deletion(-) create mode 100644 elf/tst-audit23.c create mode 100644 elf/tst-audit23mod.c create mode 100644 elf/tst-auditmod23.c diff --git a/elf/Makefile b/elf/Makefile index 06bfa1642f..d486be67d8 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -240,7 +240,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-audit19b \ tst-audit20 \ tst-audit22 \ - tst-rtld-run-static \ + tst-audit23 \ # reldep9 tests-internal += loadtest unload unload2 circleload1 \ neededtest neededtest2 neededtest3 neededtest4 \ @@ -393,6 +393,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-audit19bmod \ tst-auditmod20 \ tst-auditmod22 \ + tst-auditmod23 \ + tst-audit23mod \ tst-dl_find_object-mod1 \ tst-dl_find_object-mod2 \ tst-dl_find_object-mod3 \ @@ -1620,6 +1622,10 @@ tst-audit20-ENV = LD_AUDIT=$(objpfx)tst-auditmod20.so $(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so tst-audit22-ARGS = -- $(host-test-program-cmd) +$(objpfx)tst-audit23.out: $(objpfx)tst-auditmod23.so \ + $(objpfx)tst-audit23mod.so +tst-audit23-ARGS = -- $(host-test-program-cmd) + # tst-sonamemove links against an older implementation of the library. LDFLAGS-tst-sonamemove-linkmod1.so = \ -Wl,--version-script=tst-sonamemove-linkmod1.map \ diff --git a/elf/dl-fini.c b/elf/dl-fini.c index de8eb1b3c9..2705a15c88 100644 --- a/elf/dl-fini.c +++ b/elf/dl-fini.c @@ -64,6 +64,11 @@ _dl_fini (void) __rtld_lock_unlock_recursive (GL(dl_load_lock)); else { +#ifdef SHARED + /* Auditing checkpoint: we will start deleting objects. */ + _dl_audit_activity_nsid (ns, LA_ACT_DELETE); +#endif + /* Now we can allocate an array to hold all the pointers and copy the pointers in. */ struct link_map *maps[nloaded]; @@ -153,6 +158,11 @@ _dl_fini (void) /* Correct the previous increment. */ --l->l_direct_opencount; } + +#ifdef SHARED + /* Auditing checkpoint: we will start deleting objects. */ + _dl_audit_activity_nsid (ns, LA_ACT_CONSISTENT); +#endif } } diff --git a/elf/tst-audit23.c b/elf/tst-audit23.c new file mode 100644 index 0000000000..29358a18a8 --- /dev/null +++ b/elf/tst-audit23.c @@ -0,0 +1,240 @@ +/* Check DT_AUDIT la_objopen and la_objclose for all objects. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int restart; +#define CMDLINE_OPTIONS \ + { "restart", no_argument, &restart, 1 }, + +static int +handle_restart (void) +{ + xdlopen ("tst-audit23mod.so", RTLD_NOW); + xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW); + + return 0; +} + +static inline bool +startswith (const char *str, const char *pre) +{ + size_t lenpre = strlen (pre); + size_t lenstr = strlen (str); + return lenstr >= lenpre && memcmp (pre, str, lenpre) == 0; +} + +static inline bool +is_vdso (const char *str) +{ + return startswith (str, "linux-gate") + || startswith (str, "linux-vdso"); +} + +static int +do_test (int argc, char *argv[]) +{ + /* We must have either: + - One our fource parameters left if called initially: + + path to ld.so optional + + "--library-path" optional + + the library path optional + + the application name */ + if (restart) + return handle_restart (); + + char *spargv[9]; + int i = 0; + for (; i < argc - 1; i++) + spargv[i] = argv[i + 1]; + spargv[i++] = (char *) "--direct"; + spargv[i++] = (char *) "--restart"; + spargv[i] = NULL; + + setenv ("LD_AUDIT", "tst-auditmod23.so", 0); + struct support_capture_subprocess result + = support_capture_subprogram (spargv[0], spargv); + support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr); + + /* The expected la_objopen/la_objclose: + 1. executable + 2. loader + 3. libc.so + 4. tst-audit23mod.so + 5. libc.so (LM_ID_NEWLM). + 6. vdso (optional and ignored). */ + enum { max_objs = 6 }; + struct la_obj_t + { + char *lname; + uintptr_t laddr; + Lmid_t lmid; + bool closed; + } objs[max_objs] = { [0 ... max_objs-1] = { .closed = false } }; + size_t nobjs = 0; + + /* The expected namespaces are one for the audit module, one for the + application, and another for the dlmopen on handle_restart. */ + enum { max_ns = 3 }; + uintptr_t acts[max_ns]; + size_t nacts = 0; + int last_act = -1; + uintptr_t last_act_cookie = -1; + bool seen_first_objclose = false; + + FILE *out = fmemopen (result.err.buffer, result.err.length, "r"); + TEST_VERIFY (out != NULL); + char *buffer = NULL; + size_t buffer_length = 0; + while (xgetline (&buffer, &buffer_length, out)) + { + printf ("%s", buffer); + if (startswith (buffer, "la_activity: ")) + { + uintptr_t cookie; + int this_act; + int r = sscanf (buffer + strlen ("la_activity: "), + "%d %"SCNxPTR"", &this_act, &cookie); + TEST_COMPARE (r, 2); + + /* The cookie identifies the object at the head of the link map, + so we only add a new namespace if it changes from previous + one. This work since dlmopen is the last in the test body. */ + if (cookie != last_act_cookie && last_act_cookie != -1) + TEST_COMPARE (last_act, LA_ACT_CONSISTENT); + + if (this_act == LA_ACT_ADD && acts[nacts - 1] != cookie) + { + acts[nacts++] = cookie; + last_act_cookie = cookie; + } + /* The LA_ACT_DELETE is called in the reverse order of LA_ACT_ADD + at program termination (if the tests adds a dlclose or a library + with extra dependencies this require to be adapted). */ + else if (this_act == LA_ACT_DELETE) + { + last_act_cookie = acts[--nacts]; + TEST_COMPARE (acts[nacts], cookie); + acts[nacts] = 0; + } + else if (this_act == LA_ACT_CONSISTENT) + { + TEST_COMPARE (cookie, last_act_cookie); + + /* LA_ACT_DELETE must always be followed by an la_objclose. */ + if (last_act == LA_ACT_DELETE) + TEST_COMPARE (seen_first_objclose, true); + else + TEST_COMPARE (last_act, LA_ACT_ADD); + } + + last_act = this_act; + seen_first_objclose = false; + } + else if (startswith (buffer, "la_objopen: ")) + { + char *lname; + uintptr_t laddr; + Lmid_t lmid; + uintptr_t cookie; + int r = sscanf (buffer + strlen ("la_objopen: "), + "%"SCNxPTR" %ms %"SCNxPTR" %ld", &cookie, &lname, + &laddr, &lmid); + TEST_COMPARE (r, 4); + + /* la_objclose is not triggered by vDSO because glibc does not + unload it. */ + if (is_vdso (lname)) + continue; + if (nobjs == max_objs) + FAIL_EXIT1 ("non expected la_objopen: %s %"PRIxPTR" %ld", + lname, laddr, lmid); + objs[nobjs].lname = lname; + objs[nobjs].laddr = laddr; + objs[nobjs].lmid = lmid; + objs[nobjs].closed = false; + nobjs++; + + /* This indirectly checks that la_objopen always come before + la_objclose btween la_activity calls. */ + seen_first_objclose = false; + } + else if (startswith (buffer, "la_objclose: ")) + { + char *lname; + uintptr_t laddr; + Lmid_t lmid; + uintptr_t cookie; + int r = sscanf (buffer + strlen ("la_objclose: "), + "%"SCNxPTR" %ms %"SCNxPTR" %ld", &cookie, &lname, + &laddr, &lmid); + TEST_COMPARE (r, 4); + + for (size_t i = 0; i < nobjs; i++) + { + if (strcmp (lname, objs[i].lname) == 0 && lmid == objs[i].lmid) + { + TEST_COMPARE (objs[i].closed, false); + objs[i].closed = true; + break; + } + } + + /* la_objclose should be called after la_activity(LA_ACT_DELETE) for + the closed object's namespace. */ + TEST_COMPARE (last_act, LA_ACT_DELETE); + if (!seen_first_objclose) + { + TEST_COMPARE (last_act_cookie, cookie); + seen_first_objclose = true; + } + } + } + + for (size_t i = 0; i < nobjs; i++) + { + TEST_COMPARE (objs[i].closed, true); + free (objs[i].lname); + } + + /* la_activity(LA_ACT_CONSISTENT) should be the last callback received. + Since only one link map may be not-CONSISTENT at a time, this also + ensures la_activity(LA_ACT_CONSISTENT) is the last callback received + for every namespace. */ + TEST_COMPARE (last_act, LA_ACT_CONSISTENT); + + free (buffer); + xfclose (out); + + return 0; +} + +#define TEST_FUNCTION_ARGV do_test +#include diff --git a/elf/tst-audit23mod.c b/elf/tst-audit23mod.c new file mode 100644 index 0000000000..4ca66cf772 --- /dev/null +++ b/elf/tst-audit23mod.c @@ -0,0 +1,23 @@ +/* Extra modules for tst-audit23 + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +int +foo (void) +{ + return 0; +} diff --git a/elf/tst-auditmod23.c b/elf/tst-auditmod23.c new file mode 100644 index 0000000000..7a6d24ee80 --- /dev/null +++ b/elf/tst-auditmod23.c @@ -0,0 +1,74 @@ +/* Audit modules loaded by tst-audit23. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include + +unsigned int +la_version (unsigned int version) +{ + return LAV_CURRENT; +} + +struct map_desc_t +{ + char *lname; + uintptr_t laddr; + Lmid_t lmid; +}; + +void +la_activity (uintptr_t *cookie, unsigned int flag) +{ + fprintf (stderr, "%s: %d %"PRIxPTR"\n", __func__, flag, (uintptr_t) cookie); +} + +unsigned int +la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) +{ + const char *l_name = map->l_name[0] == '\0' ? "mainapp" : map->l_name; + fprintf (stderr, "%s: %"PRIxPTR" %s %"PRIxPTR" %ld\n", __func__, + (uintptr_t) cookie, l_name, map->l_addr, lmid); + + struct map_desc_t *map_desc = malloc (sizeof (struct map_desc_t)); + if (map_desc == NULL) + abort (); + + map_desc->lname = strdup (l_name); + map_desc->laddr = map->l_addr; + map_desc->lmid = lmid; + + *cookie = (uintptr_t) map_desc; + + return 0; +} + +unsigned int +la_objclose (uintptr_t *cookie) +{ + struct map_desc_t *map_desc = (struct map_desc_t *) *cookie; + fprintf (stderr, "%s: %"PRIxPTR" %s %"PRIxPTR" %ld\n", __func__, + (uintptr_t) cookie, map_desc->lname, map_desc->laddr, + map_desc->lmid); + + return 0; +} From patchwork Mon Jan 3 12:53:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 49467 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 B73B63858421 for ; Mon, 3 Jan 2022 12:55:11 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B73B63858421 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1641214511; bh=bxd+EsHYMjfEgTVE2namKYl46zsJCHdnqgKn1GDucYU=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=An5DDNy1gooFModjy+T5w2ry/DQgVPt6+bL3TxANzG6HZA8ieJwfcMJGXxRb5f2hX pscKVqR580LvFRf2rzV9rP/rLXKYWdJ4tYXiml2wPR1O2flkzPVGRP583KUuHpIc1E m4cA7+jhoirEVbzi5EzYuLzpe/HdoGY/JFA16HkQ= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x731.google.com (mail-qk1-x731.google.com [IPv6:2607:f8b0:4864:20::731]) by sourceware.org (Postfix) with ESMTPS id 88AF83858411 for ; Mon, 3 Jan 2022 12:53:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 88AF83858411 Received: by mail-qk1-x731.google.com with SMTP id 202so27432321qkg.13 for ; Mon, 03 Jan 2022 04:53:14 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bxd+EsHYMjfEgTVE2namKYl46zsJCHdnqgKn1GDucYU=; b=o5Zm8rEKXI0Rdv1hgcQN9h1BoxVF65HeqMyh0pikIp97NtK0YzlbJg/d9SySpBzHJ9 Qy2R/IhbOLv1rgnpEIxrIEX96OINp0gN7rr0FMxrQvse2NeRoeAxIaKW2d73zMQWkHLc 2+xW9iSc5/niDee8CHnnfF/IK5wrb/XqnuJ96Cykc+5T1ClgG3OQde3+0eF4yIAEbnKy bSTpz6v25mWSUMn5U1aqkKG3iMd3QqsKeNz8f4X0e3QX6WD9shfzdmWMt8UYkk48jRNG sWkOicXASz1eVC8YmsTynzTJ1X0d3OCzct0UL/bPzhGNWJ7ay0DLSdILhui7WjnchKlQ AyRg== X-Gm-Message-State: AOAM533KoxBJyrHuW4QXG3iergnTZGYL1cTh6LJWgd+cSdqhk0x0+fZF Kyo7qalvjMEK9opOTkvTHzugusUfw1UJuQ== X-Google-Smtp-Source: ABdhPJxaQCfPfzH12crvhE+N8A/NBMUv806tdG5xPkKUG2sQOn4edx+Qht1Zy3vpEN+caDXAE89EOA== X-Received: by 2002:a05:620a:2550:: with SMTP id s16mr31242405qko.275.1641214393901; Mon, 03 Jan 2022 04:53:13 -0800 (PST) Received: from birita.. ([2804:431:c7ca:a350:6969:50a8:eab8:8f2f]) by smtp.gmail.com with ESMTPSA id c8sm28921141qkp.8.2022.01.03.04.53.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Jan 2022 04:53:13 -0800 (PST) To: libc-alpha@sourceware.org, jma14 Subject: [PATCH v9 2/4] elf: Fix initial-exec TLS access on audit modules (BZ #28096) Date: Mon, 3 Jan 2022 09:53:04 -0300 Message-Id: <20220103125306.4151129-3-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220103125306.4151129-1-adhemerval.zanella@linaro.org> References: <20220103125306.4151129-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Reply-To: Adhemerval Zanella Cc: John Mellor-Crummey Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" For audit modules and dependencies with initial-exec TLS, we can not set the initial TLS image on default loader initialization because it would already be set by the audit setup. However, subsequent thread creation would need to follow the default behaviour. This patch fixes it by setting l_auditing link_map field not only for the audit modules, but also for all its dependencies. This is used on _dl_allocate_tls_init to avoid the static TLS initialization only at loading time. Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. --- elf/Makefile | 8 ++++ elf/dl-load.c | 3 ++ elf/dl-tls.c | 13 +++++-- elf/rtld.c | 5 +-- elf/tst-audit21.c | 42 ++++++++++++++++++++ elf/tst-auditmod21a.c | 80 ++++++++++++++++++++++++++++++++++++++ elf/tst-auditmod21b.c | 22 +++++++++++ nptl/allocatestack.c | 2 +- sysdeps/generic/ldsodefs.h | 2 +- 9 files changed, 168 insertions(+), 9 deletions(-) create mode 100644 elf/tst-audit21.c create mode 100644 elf/tst-auditmod21a.c create mode 100644 elf/tst-auditmod21b.c diff --git a/elf/Makefile b/elf/Makefile index d486be67d8..4f9a9f3c8e 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -239,6 +239,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-audit18 \ tst-audit19b \ tst-audit20 \ + tst-audit21 \ tst-audit22 \ tst-audit23 \ # reldep9 @@ -392,6 +393,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-auditmod19b \ tst-audit19bmod \ tst-auditmod20 \ + tst-auditmod21a \ + tst-auditmod21b \ tst-auditmod22 \ tst-auditmod23 \ tst-audit23mod \ @@ -1619,6 +1622,11 @@ tst-audit19b-ARGS = -- $(host-test-program-cmd) $(objpfx)tst-audit20.out: $(objpfx)tst-auditmod20.so tst-audit20-ENV = LD_AUDIT=$(objpfx)tst-auditmod20.so +$(objpfx)tst-audit21: $(shared-thread-library) +$(objpfx)tst-audit21.out: $(objpfx)tst-auditmod21a.so +$(objpfx)tst-auditmod21a.so: $(objpfx)tst-auditmod21b.so +tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21a.so + $(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so tst-audit22-ARGS = -- $(host-test-program-cmd) diff --git a/elf/dl-load.c b/elf/dl-load.c index ddc4295ef5..0aed95cbb6 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1502,6 +1502,9 @@ cannot enable executable stack as shared object requires"); /* Auditing checkpoint: we have a new object. */ if (!GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing) _dl_audit_objopen (l, nsid); + + if ((mode & __RTLD_AUDIT)) + l->l_auditing = 1; #endif return l; diff --git a/elf/dl-tls.c b/elf/dl-tls.c index 8ba70c9a9d..8ed91ff599 100644 --- a/elf/dl-tls.c +++ b/elf/dl-tls.c @@ -520,7 +520,7 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid) void * -_dl_allocate_tls_init (void *result) +_dl_allocate_tls_init (void *result, bool init_tls) { if (result == NULL) /* The memory allocation failed. */ @@ -593,7 +593,14 @@ _dl_allocate_tls_init (void *result) some platforms use in static programs requires it. */ dtv[map->l_tls_modid].pointer.val = dest; - /* Copy the initialization image and clear the BSS part. */ + /* Copy the initialization image and clear the BSS part. For + audit modules or depedencies with initial-exec TLS, we can not + set the initial TLS image on default loader initialization + because it would already be set by the audit setup. However, + subsequent thread creation would need to follow the default + behaviour. */ + if (__glibc_unlikely (map->l_auditing && !init_tls)) + continue; memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size), '\0', map->l_tls_blocksize - map->l_tls_initimage_size); @@ -620,7 +627,7 @@ _dl_allocate_tls (void *mem) { return _dl_allocate_tls_init (mem == NULL ? _dl_allocate_tls_storage () - : allocate_dtv (mem)); + : allocate_dtv (mem), true); } rtld_hidden_def (_dl_allocate_tls) diff --git a/elf/rtld.c b/elf/rtld.c index 24e48bf3fa..75583db2f2 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1059,9 +1059,6 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d); = (intptr_t) &GL (dl_rtld_map); ++GLRO(dl_naudit); - - /* Mark the DSO as being used for auditing. */ - dlmargs.map->l_auditing = 1; } /* Load all audit modules. */ @@ -2427,7 +2424,7 @@ dl_main (const ElfW(Phdr) *phdr, into the main thread's TLS area, which we allocated above. Note: thread-local variables must only be accessed after completing the next step. */ - _dl_allocate_tls_init (tcbp); + _dl_allocate_tls_init (tcbp, false); /* And finally install it for the main thread. */ if (! tls_init_tp_called) diff --git a/elf/tst-audit21.c b/elf/tst-audit21.c new file mode 100644 index 0000000000..307cb6fc3b --- /dev/null +++ b/elf/tst-audit21.c @@ -0,0 +1,42 @@ +/* Check DT_AUDIT with static TLS. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +static volatile __thread int out __attribute__ ((tls_model ("initial-exec"))); + +static void * +tf (void *arg) +{ + TEST_COMPARE (out, 0); + out = isspace (' '); + return NULL; +} + +int main (int argc, char *argv[]) +{ + TEST_COMPARE (out, 0); + out = isspace (' '); + + pthread_t t = xpthread_create (NULL, tf, NULL); + xpthread_join (t); + + return 0; +} diff --git a/elf/tst-auditmod21a.c b/elf/tst-auditmod21a.c new file mode 100644 index 0000000000..f00470e105 --- /dev/null +++ b/elf/tst-auditmod21a.c @@ -0,0 +1,80 @@ +/* Check DT_AUDIT with static TLS. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +#define tls_ie __attribute__ ((tls_model ("initial-exec"))) + +__thread int tls_var0 tls_ie; +__thread int tls_var1 tls_ie = 0x10; + +/* Defined at tst-auditmod21b.so */ +extern __thread int tls_var2; +extern __thread int tls_var3; + +static volatile int out; + +static void +call_libc (void) +{ + /* isspace access the initial-exec glibc TLS variables, which are + setup in glibc initialization. */ + out = isspace (' '); +} + +unsigned int +la_version (unsigned int v) +{ + tls_var0 = 0x1; + if (tls_var1 != 0x10) + abort (); + tls_var1 = 0x20; + + tls_var2 = 0x2; + if (tls_var3 != 0x20) + abort (); + tls_var3 = 0x40; + + call_libc (); + + return LAV_CURRENT; +} + +unsigned int +la_objopen (struct link_map* map, Lmid_t lmid, uintptr_t* cookie) +{ + call_libc (); + *cookie = (uintptr_t) map; + return 0; +} + +void +la_activity (uintptr_t* cookie, unsigned int flag) +{ + if (tls_var0 != 0x1 || tls_var1 != 0x20) + abort (); + call_libc (); +} + +void +la_preinit (uintptr_t* cookie) +{ + call_libc (); +} diff --git a/elf/tst-auditmod21b.c b/elf/tst-auditmod21b.c new file mode 100644 index 0000000000..550f858b1d --- /dev/null +++ b/elf/tst-auditmod21b.c @@ -0,0 +1,22 @@ +/* Check DT_AUDIT with static TLS. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#define tls_ie __attribute__ ((tls_model ("initial-exec"))) + +__thread int tls_var2 tls_ie; +__thread int tls_var3 tls_ie = 0x20; diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c index 3fb085f9a1..34a33164ff 100644 --- a/nptl/allocatestack.c +++ b/nptl/allocatestack.c @@ -138,7 +138,7 @@ get_cached_stack (size_t *sizep, void **memp) memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t)); /* Re-initialize the TLS. */ - _dl_allocate_tls_init (TLS_TPADJ (result)); + _dl_allocate_tls_init (TLS_TPADJ (result), true); return result; } diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index f6b2b415a6..97061bdf9f 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1282,7 +1282,7 @@ extern void _dl_allocate_static_tls (struct link_map *map) attribute_hidden; /* These are internal entry points to the two halves of _dl_allocate_tls, only used within rtld.c itself at startup time. */ extern void *_dl_allocate_tls_storage (void) attribute_hidden; -extern void *_dl_allocate_tls_init (void *); +extern void *_dl_allocate_tls_init (void *, bool); rtld_hidden_proto (_dl_allocate_tls_init) /* Deallocate memory allocated with _dl_allocate_tls. */ From patchwork Mon Jan 3 12:53:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 49468 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 4F5263858434 for ; Mon, 3 Jan 2022 12:55:56 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4F5263858434 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1641214556; bh=YGnLLi4PXb3PBymivCZANN3EGnbdTqL7lFDMQrrhfA0=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=ZG5I6yWFvHHj394bRJPLHmUiDYSojXWbV+ASCWn6t0Tp/cYXFzTpeav1iR++6BU+H iK8CIPg25ZX1NbBT5ZLHyP4a5SfHay2QhPnGDb5EGD/NyL3DlImFSsjwGP6I6cOFqf rCXXv56xYBTZl057cH/53Jkg+s7lsnqwb43gNOu4= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qv1-xf2f.google.com (mail-qv1-xf2f.google.com [IPv6:2607:f8b0:4864:20::f2f]) by sourceware.org (Postfix) with ESMTPS id B39B5385841D for ; Mon, 3 Jan 2022 12:53:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B39B5385841D Received: by mail-qv1-xf2f.google.com with SMTP id q3so30835322qvc.7 for ; Mon, 03 Jan 2022 04:53:17 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=YGnLLi4PXb3PBymivCZANN3EGnbdTqL7lFDMQrrhfA0=; b=7V17MyHNa5LDkXj69gmeXQfel3noeHTemkNHlLzt/FMISaOGBXw+hi2ZIkFZowSfaL q2JvvF7lHiX11YNTvKpTtZX11nyg2UegacFqp9pfSOV8voCIeqVKXn5vsr0SC8V5x5yF 1inXV/r87f8GRlHzxY7Bz2dUbS9afTa15Lz/VgSM89aCBQFWL6s8EgKy4VXRhk1lhozY swaavYxCLUGMMlu1sAwHROrRYtXf2R7fUwBi4l+S3KxgVpFlxoiTq0lWkTEJXLECYIET ZVyW2EgxSyBlUZXKTxasjBZBWLmIzKFL0PWrsmm0STG4fbpb8JNoqPHc5U37S64LQB8R 9aBQ== X-Gm-Message-State: AOAM531k+fjk53vBUUQ2WoNhLRQemTzWDRENXj7mMBJumRtV17cRaIN7 jUuVu8JlYWipayTXzkf79KzWjfUZUvIWEw== X-Google-Smtp-Source: ABdhPJymBaSfb0BxdLQCOJpdo6DwbQCa4FV3JuL6lqPwP6k7jvreu5y3yQYMZlKecNmok4HSm8QI3Q== X-Received: by 2002:a05:6214:518f:: with SMTP id kl15mr41574198qvb.4.1641214395664; Mon, 03 Jan 2022 04:53:15 -0800 (PST) Received: from birita.. ([2804:431:c7ca:a350:6969:50a8:eab8:8f2f]) by smtp.gmail.com with ESMTPSA id c8sm28921141qkp.8.2022.01.03.04.53.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Jan 2022 04:53:15 -0800 (PST) To: libc-alpha@sourceware.org, jma14 Subject: [PATCH v9 3/4] elf: Issue la_symbind for bind-now (BZ #23734) Date: Mon, 3 Jan 2022 09:53:05 -0300 Message-Id: <20220103125306.4151129-4-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220103125306.4151129-1-adhemerval.zanella@linaro.org> References: <20220103125306.4151129-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-10.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLACK autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Reply-To: Adhemerval Zanella Cc: John Mellor-Crummey Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" The audit symbind callback is not called for binaries built with -Wl,-z,now or when LD_BIND_NOW=1 is used, nor the PLT tracking callbacks (plt_enter and plt_exit) since this will would change the expected program semantic (where no PTL is expected) and would incur in performance implications (such as for BZ#15533). LAV_CURRENT is also bumped to indicate the audit ABI change (where la_symbind flags are set by the loader to indicate no possible PTL trace). To handle powerpc64 ELFv1 function descriptor, _dl_audit_symbind requires to know whether bind-now is used so the symbol value is updated to function text segment instead of the OPD (for lazy binding this is done by PPC64_LOAD_FUNCPTR on _dl_runtime_resolve). Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, powerpc64-linux-gnu. --- NEWS | 4 ++ bits/link_lavcurrent.h | 2 +- elf/Makefile | 89 ++++++++++++++++++++++- elf/dl-audit.c | 58 +++++++++------ elf/do-rel.h | 57 +++++++++++---- elf/sotruss-lib.c | 7 ++ elf/tst-audit24a.c | 36 ++++++++++ elf/tst-audit24amod1.c | 31 ++++++++ elf/tst-audit24amod2.c | 25 +++++++ elf/tst-audit24b.c | 37 ++++++++++ elf/tst-audit24bmod1.c | 31 ++++++++ elf/tst-audit24bmod2.c | 23 ++++++ elf/tst-audit24c.c | 2 + elf/tst-audit24d.c | 36 ++++++++++ elf/tst-audit24dmod1.c | 33 +++++++++ elf/tst-audit24dmod2.c | 28 ++++++++ elf/tst-audit24dmod3.c | 31 ++++++++ elf/tst-audit24dmod4.c | 25 +++++++ elf/tst-audit25a.c | 127 ++++++++++++++++++++++++++++++++ elf/tst-audit25b.c | 128 +++++++++++++++++++++++++++++++++ elf/tst-audit25mod1.c | 30 ++++++++ elf/tst-audit25mod2.c | 30 ++++++++ elf/tst-audit25mod3.c | 22 ++++++ elf/tst-audit25mod4.c | 22 ++++++ elf/tst-auditmod24.h | 29 ++++++++ elf/tst-auditmod24a.c | 114 +++++++++++++++++++++++++++++ elf/tst-auditmod24b.c | 104 +++++++++++++++++++++++++++ elf/tst-auditmod24c.c | 3 + elf/tst-auditmod24d.c | 120 +++++++++++++++++++++++++++++++ elf/tst-auditmod25.c | 79 ++++++++++++++++++++ sysdeps/generic/dl-lookupcfg.h | 3 + sysdeps/generic/ldsodefs.h | 5 +- sysdeps/hppa/dl-lookupcfg.h | 3 + sysdeps/ia64/dl-lookupcfg.h | 3 + sysdeps/powerpc/dl-lookupcfg.h | 39 ++++++++++ 35 files changed, 1377 insertions(+), 39 deletions(-) create mode 100644 elf/tst-audit24a.c create mode 100644 elf/tst-audit24amod1.c create mode 100644 elf/tst-audit24amod2.c create mode 100644 elf/tst-audit24b.c create mode 100644 elf/tst-audit24bmod1.c create mode 100644 elf/tst-audit24bmod2.c create mode 100644 elf/tst-audit24c.c create mode 100644 elf/tst-audit24d.c create mode 100644 elf/tst-audit24dmod1.c create mode 100644 elf/tst-audit24dmod2.c create mode 100644 elf/tst-audit24dmod3.c create mode 100644 elf/tst-audit24dmod4.c create mode 100644 elf/tst-audit25a.c create mode 100644 elf/tst-audit25b.c create mode 100644 elf/tst-audit25mod1.c create mode 100644 elf/tst-audit25mod2.c create mode 100644 elf/tst-audit25mod3.c create mode 100644 elf/tst-audit25mod4.c create mode 100644 elf/tst-auditmod24.h create mode 100644 elf/tst-auditmod24a.c create mode 100644 elf/tst-auditmod24b.c create mode 100644 elf/tst-auditmod24c.c create mode 100644 elf/tst-auditmod24d.c create mode 100644 elf/tst-auditmod25.c create mode 100644 sysdeps/powerpc/dl-lookupcfg.h diff --git a/NEWS b/NEWS index 9da2a740ec..1e6aed1ace 100644 --- a/NEWS +++ b/NEWS @@ -126,6 +126,10 @@ Deprecated and removed features, and other changes affecting compatibility: configuration script now automatically detects static-pie support in the toolchain and architecture and enables it if available. +* The audit module interface version LAV_CURRENT is increased to enable + proper bind-now support. The loader now advertise on the la_symbind + flags that PLT trace is not possible. + Changes to build and runtime requirements: [Add changes to build and runtime requirements here] diff --git a/bits/link_lavcurrent.h b/bits/link_lavcurrent.h index 7bfa4b9f4e..a852d41302 100644 --- a/bits/link_lavcurrent.h +++ b/bits/link_lavcurrent.h @@ -22,4 +22,4 @@ #endif /* Version numbers for la_version handshake interface. */ -#define LAV_CURRENT 1 +#define LAV_CURRENT 2 diff --git a/elf/Makefile b/elf/Makefile index 4f9a9f3c8e..10c494e1e2 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -242,6 +242,12 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-audit21 \ tst-audit22 \ tst-audit23 \ + tst-audit24a \ + tst-audit24b \ + tst-audit24c \ + tst-audit24d \ + tst-audit25a \ + tst-audit25b \ # reldep9 tests-internal += loadtest unload unload2 circleload1 \ neededtest neededtest2 neededtest3 neededtest4 \ @@ -398,6 +404,23 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-auditmod22 \ tst-auditmod23 \ tst-audit23mod \ + tst-auditmod24a \ + tst-audit24amod1 \ + tst-audit24amod2 \ + tst-auditmod24b \ + tst-audit24bmod1 \ + tst-audit24bmod2 \ + tst-auditmod24c \ + tst-auditmod24d \ + tst-audit24dmod1 \ + tst-audit24dmod2 \ + tst-audit24dmod3 \ + tst-audit24dmod4 \ + tst-auditmod25 \ + tst-audit25mod1 \ + tst-audit25mod2 \ + tst-audit25mod3 \ + tst-audit25mod4 \ tst-dl_find_object-mod1 \ tst-dl_find_object-mod2 \ tst-dl_find_object-mod3 \ @@ -466,7 +489,8 @@ extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) # filtmod1.so, tst-big-note-lib.so, tst-ro-dynamic-mod.so have special # rules. -modules-names-nobuild := filtmod1 tst-big-note-lib tst-ro-dynamic-mod +modules-names-nobuild := filtmod1 tst-big-note-lib tst-ro-dynamic-mod \ + tst-audit24bmod1 tst-audit24bmod2.so tests += $(tests-static) @@ -1634,6 +1658,69 @@ $(objpfx)tst-audit23.out: $(objpfx)tst-auditmod23.so \ $(objpfx)tst-audit23mod.so tst-audit23-ARGS = -- $(host-test-program-cmd) +$(objpfx)tst-audit24a.out: $(objpfx)tst-auditmod24a.so +$(objpfx)tst-audit24a: $(objpfx)tst-audit24amod1.so \ + $(objpfx)tst-audit24amod2.so +tst-audit24a-ENV = LD_AUDIT=$(objpfx)tst-auditmod24a.so +LDFLAGS-tst-audit24a = -Wl,-z,now + +$(objpfx)tst-audit24b.out: $(objpfx)tst-auditmod24b.so +$(objpfx)tst-audit24b: $(objpfx)tst-audit24bmod1.so \ + $(objpfx)tst-audit24bmod2.so +$(objpfx)tst-audit24bmod1: $(objpfx)tst-audit24bmod2.so +# The test check if a library without .gnu.version correctly calls the +# audit callbacks. So it uses an explicit link rule to avoid linking +# against libc.so. +$(objpfx)tst-audit24bmod1.so: $(objpfx)tst-audit24bmod1.os + $(CC) -nostdlib -nostartfiles -shared -o $@.new $(objpfx)tst-audit24bmod1.os \ + -Wl,-z,now + $(call after-link,$@.new) + mv -f $@.new $@ +CFLAGS-.os += $(call elide-stack-protector,.os,tst-audit24bmod1) +$(objpfx)tst-audit24bmod2.so: $(objpfx)tst-audit24bmod2.os + $(CC) -nostdlib -nostartfiles -shared -o $@.new $(objpfx)tst-audit24bmod2.os + $(call after-link,$@.new) + mv -f $@.new $@ +CFLAGS-.os += $(call elide-stack-protector,.os,tst-audit24bmod2) +tst-audit24b-ENV = LD_AUDIT=$(objpfx)tst-auditmod24b.so +LDFLAGS-tst-audit24b = -Wl,-z,now + +# Same as tst-audit24a, but tests LD_BIND_NOW +$(objpfx)tst-audit24c.out: $(objpfx)tst-auditmod24c.so +$(objpfx)tst-audit24c: $(objpfx)tst-audit24amod1.so \ + $(objpfx)tst-audit24amod2.so +tst-audit24c-ENV = LD_BIND_NOW=1 LD_AUDIT=$(objpfx)tst-auditmod24c.so +LDFLAGS-tst-audit24b = -Wl,-z,lazy + +$(objpfx)tst-audit24d.out: $(objpfx)tst-auditmod24d.so +$(objpfx)tst-audit24d: $(objpfx)tst-audit24dmod1.so \ + $(objpfx)tst-audit24dmod2.so +$(objpfx)tst-audit24dmod1.so: $(objpfx)tst-audit24dmod3.so +LDFLAGS-tst-audit24dmod1.so = -Wl,-z,now +$(objpfx)tst-audit24dmod2.so: $(objpfx)tst-audit24dmod4.so +LDFLAGS-tst-audit24dmod2.so = -Wl,-z,lazy +tst-audit24d-ENV = LD_AUDIT=$(objpfx)tst-auditmod24d.so +LDFLAGS-tst-audit24d = -Wl,-z,lazy + +$(objpfx)tst-audit25a.out: $(objpfx)tst-auditmod25.so +$(objpfx)tst-audit25a: $(objpfx)tst-audit25mod1.so \ + $(objpfx)tst-audit25mod2.so \ + $(objpfx)tst-audit25mod3.so \ + $(objpfx)tst-audit25mod4.so +$(objpfx)tst-audit25mod1.so: $(objpfx)tst-audit25mod3.so +LDFLAGS-tst-audit25mod1.so = -Wl,-z,now +$(objpfx)tst-audit25mod2.so: $(objpfx)tst-audit25mod4.so +LDFLAGS-tst-audit25mod2.so = -Wl,-z,lazy +tst-audit25a-ARGS = -- $(host-test-program-cmd) + +$(objpfx)tst-audit25b.out: $(objpfx)tst-auditmod25.so +$(objpfx)tst-audit25b: $(objpfx)tst-audit25mod1.so \ + $(objpfx)tst-audit25mod2.so \ + $(objpfx)tst-audit25mod3.so \ + $(objpfx)tst-audit25mod4.so +LDFLAGS-tst-audit25b = -Wl,-z,now +tst-audit25b-ARGS = -- $(host-test-program-cmd) + # tst-sonamemove links against an older implementation of the library. LDFLAGS-tst-sonamemove-linkmod1.so = \ -Wl,--version-script=tst-sonamemove-linkmod1.map \ diff --git a/elf/dl-audit.c b/elf/dl-audit.c index 715de53272..794bfd45cd 100644 --- a/elf/dl-audit.c +++ b/elf/dl-audit.c @@ -178,16 +178,23 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value, lookup_t result) { - reloc_result->bound = result; - /* Compute index of the symbol entry in the symbol table of the DSO with the - definition. */ - reloc_result->boundndx = (defsym - (ElfW(Sym) *) D_PTR (result, - l_info[DT_SYMTAB])); + bool for_jmp_slot = reloc_result == NULL; + + /* Compute index of the symbol entry in the symbol table of the DSO + with the definition. */ + unsigned int boundndx = defsym - (ElfW(Sym) *) D_PTR (result, + l_info[DT_SYMTAB]); + if (!for_jmp_slot) + { + reloc_result->bound = result; + reloc_result->boundndx = boundndx; + } if ((l->l_audit_any_plt | result->l_audit_any_plt) == 0) { /* Set all bits since this symbol binding is not interesting. */ - reloc_result->enterexit = (1u << DL_NNS) - 1; + if (!for_jmp_slot) + reloc_result->enterexit = (1u << DL_NNS) - 1; return; } @@ -199,12 +206,13 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, two bits. */ assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8); assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3); - reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT; + uint32_t enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT; const char *strtab2 = (const void *) D_PTR (result, l_info[DT_STRTAB]); unsigned int flags = 0; struct audit_ifaces *afct = GLRO(dl_audit); + uintptr_t new_value = (uintptr_t) sym.st_value; for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) { /* XXX Check whether both DSOs must request action or only one */ @@ -215,37 +223,41 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, { if (afct->symbind != NULL) { - uintptr_t new_value = afct->symbind (&sym, - reloc_result->boundndx, - &l_state->cookie, - &result_state->cookie, - &flags, - strtab2 + defsym->st_name); + flags |= for_jmp_slot ? LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT + : 0; + new_value = afct->symbind (&sym, boundndx, + &l_state->cookie, + &result_state->cookie, &flags, + strtab2 + defsym->st_name); if (new_value != (uintptr_t) sym.st_value) { flags |= LA_SYMB_ALTVALUE; - sym.st_value = new_value; + sym.st_value = for_jmp_slot + ? DL_FIXUP_BINDNOW_ADDR_VALUE (new_value) : new_value; } } /* Remember the results for every audit library and store a summary in the first two bits. */ - reloc_result->enterexit &= flags & (LA_SYMB_NOPLTENTER - | LA_SYMB_NOPLTEXIT); - reloc_result->enterexit |= ((flags & (LA_SYMB_NOPLTENTER - | LA_SYMB_NOPLTEXIT)) - << ((cnt + 1) * 2)); + enterexit &= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT); + enterexit |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) + << ((cnt + 1) * 2)); } else /* If the bind flags say this auditor is not interested, set the bits manually. */ - reloc_result->enterexit |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) - << ((cnt + 1) * 2)); + enterexit |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) + << ((cnt + 1) * 2)); afct = afct->next; } - reloc_result->flags = flags; - *value = DL_FIXUP_ADDR_VALUE (sym.st_value); + if (!for_jmp_slot) + { + reloc_result->enterexit = enterexit; + reloc_result->flags = flags; + } + + DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value); } void diff --git a/elf/do-rel.h b/elf/do-rel.h index 0718badf83..60d5dce8f2 100644 --- a/elf/do-rel.h +++ b/elf/do-rel.h @@ -16,6 +16,8 @@ License along with the GNU C Library; if not, see . */ +#include + /* This file may be included twice, to define both `elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */ @@ -123,6 +125,10 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[], for (; r < end; ++r) { + ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff; + const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)]; + void *const r_addr_arg = (void *) (l_addr + r->r_offset); + const struct r_found_version *rversion = &map->l_versions[ndx]; #if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE) { @@ -133,10 +139,19 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[], } #endif - ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff; - elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)], - &map->l_versions[ndx], - (void *) (l_addr + r->r_offset), skip_ifunc); + elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg, + skip_ifunc); +#if defined SHARED && !defined RTLD_BOOTSTRAP + if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT + && GLRO(dl_naudit) > 0) + { + struct link_map *sym_map + = RESOLVE_MAP (map, scope, &sym, rversion, + ELF_MACHINE_JMP_SLOT); + if (sym != NULL) + _dl_audit_symbind (map, NULL, sym, r_addr_arg, sym_map); + } +#endif } #if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP @@ -158,17 +173,33 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[], else { for (; r < end; ++r) + { + const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)]; + void *const r_addr_arg = (void *) (l_addr + r->r_offset); # ifdef ELF_MACHINE_IRELATIVE - if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE) - { - if (r2 == NULL) - r2 = r; - end2 = r; - } - else + if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE) + { + if (r2 == NULL) + r2 = r; + end2 = r; + continue; + } # endif - elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, - (void *) (l_addr + r->r_offset), skip_ifunc); + elf_machine_rel (map, scope, r, sym, NULL, r_addr_arg, + skip_ifunc); +# if defined SHARED && !defined RTLD_BOOTSTRAP + if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT + && GLRO(dl_naudit) > 0) + { + struct link_map *sym_map + = RESOLVE_MAP (map, scope, &sym, + (struct r_found_version *) NULL, + ELF_MACHINE_JMP_SLOT); + if (sym != NULL) + _dl_audit_symbind (map, NULL , sym,r_addr_arg, sym_map); + } +# endif + } # ifdef ELF_MACHINE_IRELATIVE if (r2 != NULL) diff --git a/elf/sotruss-lib.c b/elf/sotruss-lib.c index 1077458c9d..a5edd438f9 100644 --- a/elf/sotruss-lib.c +++ b/elf/sotruss-lib.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -231,6 +232,12 @@ uintptr_t la_symbind (Elf_Sym *sym, unsigned int ndx, uintptr_t *refcook, uintptr_t *defcook, unsigned int *flags, const char *symname) { + if (*flags & LA_SYMB_NOPLTENTER) + warnx ("cannot trace PLT enter (bind-now enabled)"); + + if (do_exit && *flags & LA_SYMB_NOPLTEXIT) + warnx ("cannot trace PLT exit (bind-now enabled)"); + if (!do_exit) *flags = LA_SYMB_NOPLTEXIT; diff --git a/elf/tst-audit24a.c b/elf/tst-audit24a.c new file mode 100644 index 0000000000..134c3e7b5b --- /dev/null +++ b/elf/tst-audit24a.c @@ -0,0 +1,36 @@ +/* DL_AUDIT test for la_symbind and bind-now. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +int tst_audit24amod1_func1 (void); +int tst_audit24amod1_func2 (void); +int tst_audit24amod2_func1 (void); + +int +do_test (void) +{ + TEST_COMPARE (tst_audit24amod1_func1 (), 1); + TEST_COMPARE (tst_audit24amod1_func2 (), 2); + TEST_COMPARE (tst_audit24amod2_func1 (), 10); + + return 0; +} + +#include diff --git a/elf/tst-audit24amod1.c b/elf/tst-audit24amod1.c new file mode 100644 index 0000000000..43d3831677 --- /dev/null +++ b/elf/tst-audit24amod1.c @@ -0,0 +1,31 @@ +/* Modules used by tst-audit24a. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +_Noreturn int +tst_audit24amod1_func1 (void) +{ + abort (); +} + +int +tst_audit24amod1_func2 (void) +{ + return 2; +} diff --git a/elf/tst-audit24amod2.c b/elf/tst-audit24amod2.c new file mode 100644 index 0000000000..c995827855 --- /dev/null +++ b/elf/tst-audit24amod2.c @@ -0,0 +1,25 @@ +/* Modules used by tst-audit24a. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +_Noreturn int +tst_audit24amod2_func1 (void) +{ + abort (); +} diff --git a/elf/tst-audit24b.c b/elf/tst-audit24b.c new file mode 100644 index 0000000000..69bf71b4c9 --- /dev/null +++ b/elf/tst-audit24b.c @@ -0,0 +1,37 @@ +/* DL_AUDIT test for la_symbind and bind-now. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* This is similar to tst-audit24a, with the difference this modules + does not have the .gnu.version section header. */ + +#include +#include + +int tst_audit24bmod1_func1 (void); +int tst_audit24bmod1_func2 (void); + +int +do_test (void) +{ + TEST_COMPARE (tst_audit24bmod1_func1 (), 1); + TEST_COMPARE (tst_audit24bmod1_func2 (), 2); + + return 0; +} + +#include diff --git a/elf/tst-audit24bmod1.c b/elf/tst-audit24bmod1.c new file mode 100644 index 0000000000..91c6fa0251 --- /dev/null +++ b/elf/tst-audit24bmod1.c @@ -0,0 +1,31 @@ +/* Modules used by tst-audit24c. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +int tst_audit24bmod2_func1 (void); + +int +tst_audit24bmod1_func1 (void) +{ + return -1; +} + +int +tst_audit24bmod1_func2 (void) +{ + return tst_audit24bmod2_func1 (); +} diff --git a/elf/tst-audit24bmod2.c b/elf/tst-audit24bmod2.c new file mode 100644 index 0000000000..3baf9e8bd4 --- /dev/null +++ b/elf/tst-audit24bmod2.c @@ -0,0 +1,23 @@ +/* Modules used by tst-audit24b. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +int +tst_audit24bmod2_func1 (void) +{ + return -1; +} diff --git a/elf/tst-audit24c.c b/elf/tst-audit24c.c new file mode 100644 index 0000000000..46ed328756 --- /dev/null +++ b/elf/tst-audit24c.c @@ -0,0 +1,2 @@ +/* It tests LD_BIND_NOW=1 instead of linking with -Wl,-z,now */ +#include "tst-audit24a.c" diff --git a/elf/tst-audit24d.c b/elf/tst-audit24d.c new file mode 100644 index 0000000000..821e5a2051 --- /dev/null +++ b/elf/tst-audit24d.c @@ -0,0 +1,36 @@ +/* DL_AUDIT test for la_symbind and bind-now. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +int tst_audit24dmod1_func1 (void); +int tst_audit24dmod1_func2 (void); +int tst_audit24dmod2_func1 (void); + +int +do_test (void) +{ + TEST_COMPARE (tst_audit24dmod1_func1 (), 1); + TEST_COMPARE (tst_audit24dmod1_func2 (), 32); + TEST_COMPARE (tst_audit24dmod2_func1 (), 10); + + return 0; +} + +#include diff --git a/elf/tst-audit24dmod1.c b/elf/tst-audit24dmod1.c new file mode 100644 index 0000000000..792da3b581 --- /dev/null +++ b/elf/tst-audit24dmod1.c @@ -0,0 +1,33 @@ +/* Modules used by tst-audit24d. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +int tst_audit24dmod3_func1 (void); + +_Noreturn int +tst_audit24dmod1_func1 (void) +{ + abort (); +} + +int +tst_audit24dmod1_func2 (void) +{ + return 2 + tst_audit24dmod3_func1 ();; +} diff --git a/elf/tst-audit24dmod2.c b/elf/tst-audit24dmod2.c new file mode 100644 index 0000000000..8c76257885 --- /dev/null +++ b/elf/tst-audit24dmod2.c @@ -0,0 +1,28 @@ +/* Module for tst-audit24d. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +int tst_audit24dmod4_func1 (void); + +_Noreturn int +tst_audit24dmod2_func1 (void) +{ + tst_audit24dmod4_func1 (); + abort (); +} diff --git a/elf/tst-audit24dmod3.c b/elf/tst-audit24dmod3.c new file mode 100644 index 0000000000..367c776eb5 --- /dev/null +++ b/elf/tst-audit24dmod3.c @@ -0,0 +1,31 @@ +/* Module for tst-audit24d. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +_Noreturn int +tst_audit24dmod3_func1 (void) +{ + abort (); +} + +int +tst_audit24dmod3_func2 (void) +{ + return 4; +} diff --git a/elf/tst-audit24dmod4.c b/elf/tst-audit24dmod4.c new file mode 100644 index 0000000000..c994c7cf03 --- /dev/null +++ b/elf/tst-audit24dmod4.c @@ -0,0 +1,25 @@ +/* Module for tst-audit24d. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +_Noreturn int +tst_audit24dmod4_func1 (void) +{ + abort (); +} diff --git a/elf/tst-audit25a.c b/elf/tst-audit25a.c new file mode 100644 index 0000000000..8d08371abd --- /dev/null +++ b/elf/tst-audit25a.c @@ -0,0 +1,127 @@ +/* Check DT_AUDIT and LD_BIND_NOW. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int restart; +#define CMDLINE_OPTIONS \ + { "restart", no_argument, &restart, 1 }, + +void tst_audit25mod1_func1 (void); +void tst_audit25mod1_func2 (void); +void tst_audit25mod2_func1 (void); +void tst_audit25mod2_func2 (void); + +static int +handle_restart (void) +{ + tst_audit25mod1_func1 (); + tst_audit25mod1_func2 (); + tst_audit25mod2_func1 (); + tst_audit25mod2_func2 (); + + return 0; +} + +static inline bool +startswith (const char *str, const char *pre) +{ + size_t lenpre = strlen (pre); + size_t lenstr = strlen (str); + return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0; +} + +static int +do_test (int argc, char *argv[]) +{ + /* We must have either: + - One our fource parameters left if called initially: + + path to ld.so optional + + "--library-path" optional + + the library path optional + + the application name */ + + if (restart) + return handle_restart (); + + setenv ("LD_AUDIT", "tst-auditmod25.so", 0); + + char *spargv[9]; + int i = 0; + for (; i < argc - 1; i++) + spargv[i] = argv[i + 1]; + spargv[i++] = (char *) "--direct"; + spargv[i++] = (char *) "--restart"; + spargv[i] = NULL; + + { + struct support_capture_subprocess result + = support_capture_subprogram (spargv[0], spargv); + support_capture_subprocess_check (&result, "tst-audit25a", 0, + sc_allow_stderr); + + /* tst-audit25a is build with -Wl,-z,lazy and tst-audit25mod1 with + -Wl,-z,now; so only tst_audit25mod3_func1 should be expected to + have LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. */ + TEST_COMPARE_STRING (result.err.buffer, + "la_symbind: tst_audit25mod3_func1 1\n" + "la_symbind: tst_audit25mod1_func1 0\n" + "la_symbind: tst_audit25mod1_func2 0\n" + "la_symbind: tst_audit25mod2_func1 0\n" + "la_symbind: tst_audit25mod4_func1 0\n" + "la_symbind: tst_audit25mod2_func2 0\n"); + + support_capture_subprocess_free (&result); + } + + { + setenv ("LD_BIND_NOW", "1", 0); + struct support_capture_subprocess result + = support_capture_subprogram (spargv[0], spargv); + support_capture_subprocess_check (&result, "tst-audit25a", 0, + sc_allow_stderr); + + /* With LD_BIND_NOW all symbols are expected to have + LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. Also the resolution + order is done in breadth-first order. */ + TEST_COMPARE_STRING (result.err.buffer, + "la_symbind: tst_audit25mod4_func1 1\n" + "la_symbind: tst_audit25mod3_func1 1\n" + "la_symbind: tst_audit25mod1_func1 1\n" + "la_symbind: tst_audit25mod2_func1 1\n" + "la_symbind: tst_audit25mod1_func2 1\n" + "la_symbind: tst_audit25mod2_func2 1\n"); + + support_capture_subprocess_free (&result); + } + + return 0; +} + +#define TEST_FUNCTION_ARGV do_test +#include diff --git a/elf/tst-audit25b.c b/elf/tst-audit25b.c new file mode 100644 index 0000000000..1d748b7068 --- /dev/null +++ b/elf/tst-audit25b.c @@ -0,0 +1,128 @@ +/* Check DT_AUDIT and LD_BIND_NOW. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int restart; +#define CMDLINE_OPTIONS \ + { "restart", no_argument, &restart, 1 }, + +void tst_audit25mod1_func1 (void); +void tst_audit25mod1_func2 (void); +void tst_audit25mod2_func1 (void); +void tst_audit25mod2_func2 (void); + +static int +handle_restart (void) +{ + tst_audit25mod1_func1 (); + tst_audit25mod1_func2 (); + tst_audit25mod2_func1 (); + tst_audit25mod2_func2 (); + + return 0; +} + +static inline bool +startswith (const char *str, const char *pre) +{ + size_t lenpre = strlen (pre); + size_t lenstr = strlen (str); + return lenstr >= lenpre && memcmp (pre, str, lenpre) == 0; +} + +static int +do_test (int argc, char *argv[]) +{ + /* We must have either: + - One our fource parameters left if called initially: + + path to ld.so optional + + "--library-path" optional + + the library path optional + + the application name */ + + if (restart) + return handle_restart (); + + setenv ("LD_AUDIT", "tst-auditmod25.so", 0); + + char *spargv[9]; + int i = 0; + for (; i < argc - 1; i++) + spargv[i] = argv[i + 1]; + spargv[i++] = (char *) "--direct"; + spargv[i++] = (char *) "--restart"; + spargv[i] = NULL; + + { + struct support_capture_subprocess result + = support_capture_subprogram (spargv[0], spargv); + support_capture_subprocess_check (&result, "tst-audit25a", 0, + sc_allow_stderr); + + /* tst-audit25a and tst-audit25mod1 are built with -Wl,-z,now, but + tst-audit25mod2 is built with -Wl,z,lazy. So only + tst_audit25mod4_func1 (called by tst_audit25mod2_func1) should not + have LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. */ + TEST_COMPARE_STRING (result.err.buffer, + "la_symbind: tst_audit25mod3_func1 1\n" + "la_symbind: tst_audit25mod1_func1 1\n" + "la_symbind: tst_audit25mod2_func1 1\n" + "la_symbind: tst_audit25mod1_func2 1\n" + "la_symbind: tst_audit25mod2_func2 1\n" + "la_symbind: tst_audit25mod4_func1 0\n"); + + support_capture_subprocess_free (&result); + } + + { + setenv ("LD_BIND_NOW", "1", 0); + struct support_capture_subprocess result + = support_capture_subprogram (spargv[0], spargv); + support_capture_subprocess_check (&result, "tst-audit25a", 0, + sc_allow_stderr); + + /* With LD_BIND_NOW all symbols are expected to have + LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. Also the resolution + order is done in breadth-first order. */ + TEST_COMPARE_STRING (result.err.buffer, + "la_symbind: tst_audit25mod4_func1 1\n" + "la_symbind: tst_audit25mod3_func1 1\n" + "la_symbind: tst_audit25mod1_func1 1\n" + "la_symbind: tst_audit25mod2_func1 1\n" + "la_symbind: tst_audit25mod1_func2 1\n" + "la_symbind: tst_audit25mod2_func2 1\n"); + + support_capture_subprocess_free (&result); + } + + return 0; +} + +#define TEST_FUNCTION_ARGV do_test +#include diff --git a/elf/tst-audit25mod1.c b/elf/tst-audit25mod1.c new file mode 100644 index 0000000000..9aa39ed325 --- /dev/null +++ b/elf/tst-audit25mod1.c @@ -0,0 +1,30 @@ +/* Modules used by tst-audit25. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +void tst_audit25mod3_func1 (void); + +void +tst_audit25mod1_func1 (void) +{ + tst_audit25mod3_func1 (); +} + +void +tst_audit25mod1_func2 (void) +{ +} diff --git a/elf/tst-audit25mod2.c b/elf/tst-audit25mod2.c new file mode 100644 index 0000000000..6d8e225fcc --- /dev/null +++ b/elf/tst-audit25mod2.c @@ -0,0 +1,30 @@ +/* Modules used by tst-audit25. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +void tst_audit25mod4_func1 (void); + +void +tst_audit25mod2_func1 (void) +{ + tst_audit25mod4_func1 (); +} + +void +tst_audit25mod2_func2 (void) +{ +} diff --git a/elf/tst-audit25mod3.c b/elf/tst-audit25mod3.c new file mode 100644 index 0000000000..c0d5977fd8 --- /dev/null +++ b/elf/tst-audit25mod3.c @@ -0,0 +1,22 @@ +/* Modules used by tst-audit25. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +void +tst_audit25mod3_func1 (void) +{ +} diff --git a/elf/tst-audit25mod4.c b/elf/tst-audit25mod4.c new file mode 100644 index 0000000000..689ee5138f --- /dev/null +++ b/elf/tst-audit25mod4.c @@ -0,0 +1,22 @@ +/* Modules used by tst-audit25. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +void +tst_audit25mod4_func1 (void) +{ +} diff --git a/elf/tst-auditmod24.h b/elf/tst-auditmod24.h new file mode 100644 index 0000000000..621fd50364 --- /dev/null +++ b/elf/tst-auditmod24.h @@ -0,0 +1,29 @@ +/* Auxiliary functions for tst-audit24x. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _TST_AUDITMOD24_H +#define _TST_AUDITMOD24_H + +static void +check_symbind_flags (unsigned int flags) +{ + if ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) == 0) + abort (); +} + +#endif diff --git a/elf/tst-auditmod24a.c b/elf/tst-auditmod24a.c new file mode 100644 index 0000000000..ce8be9c22f --- /dev/null +++ b/elf/tst-auditmod24a.c @@ -0,0 +1,114 @@ +/* Audit modules for tst-audit24a. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include + +#define AUDIT24_COOKIE 0x1 +#define AUDIT24MOD1_COOKIE 0x2 +#define AUDIT24MOD2_COOKIE 0x3 + +#ifndef TEST_NAME +# define TEST_NAME "tst-audit24a" +#endif +#ifndef TEST_MOD +# define TEST_MOD TEST_NAME +#endif +#ifndef TEST_FUNC +# define TEST_FUNC "tst_audit24a" +#endif + +unsigned int +la_version (unsigned int version) +{ + return LAV_CURRENT; +} + +unsigned int +la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) +{ + const char *p = strrchr (map->l_name, '/'); + const char *l_name = p == NULL ? TEST_NAME : p + 1; + + uintptr_t ck = -1; + if (strcmp (l_name, TEST_MOD "mod1.so") == 0) + ck = AUDIT24MOD1_COOKIE; + else if (strcmp (l_name, TEST_MOD "mod2.so") == 0) + ck = AUDIT24MOD2_COOKIE; + else if (strcmp (l_name, TEST_NAME) == 0) + ck = AUDIT24_COOKIE; + + *cookie = ck; + return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO; +} + +static int +tst_func1 (void) +{ + return 1; +} + +static int +tst_func2 (void) +{ + return 10; +} + +#if __ELF_NATIVE_CLASS == 64 +uintptr_t +la_symbind64 (Elf64_Sym *sym, unsigned int ndx, + uintptr_t *refcook, uintptr_t *defcook, + unsigned int *flags, const char *symname) +#else +uintptr_t +la_symbind32 (Elf32_Sym *sym, unsigned int ndx, + uintptr_t *refcook, uintptr_t *defcook, + unsigned int *flags, const char *symname) +#endif +{ + if (*refcook == AUDIT24_COOKIE) + { + if (*defcook == AUDIT24MOD1_COOKIE) + { + /* Check if bind-now symbols are advertised to not call the PLT + hooks. */ + check_symbind_flags (*flags); + + if (strcmp (symname, TEST_FUNC "mod1_func1") == 0) + return (uintptr_t) tst_func1; + else if (strcmp (symname, TEST_FUNC "mod1_func2") == 0) + return sym->st_value; + abort (); + } + if (*defcook == AUDIT24MOD2_COOKIE + && (strcmp (symname, TEST_FUNC "mod2_func1") == 0)) + { + check_symbind_flags (*flags); + + return (uintptr_t) tst_func2; + } + + /* malloc functions. */ + return sym->st_value; + } + + abort (); +} diff --git a/elf/tst-auditmod24b.c b/elf/tst-auditmod24b.c new file mode 100644 index 0000000000..d41c5adc6b --- /dev/null +++ b/elf/tst-auditmod24b.c @@ -0,0 +1,104 @@ +/* Audit modules for tst-audit24b. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include + +#define TEST_NAME "tst-audit24b" +#define TEST_FUNC "tst_audit24b" + +#define AUDIT24_COOKIE 0x1 +#define AUDIT24MOD1_COOKIE 0x2 +#define AUDIT24MOD2_COOKIE 0x3 + +unsigned int +la_version (unsigned int version) +{ + return LAV_CURRENT; +} + +unsigned int +la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) +{ + const char *p = strrchr (map->l_name, '/'); + const char *l_name = p == NULL ? TEST_NAME : p + 1; + + uintptr_t ck = -1; + if (strcmp (l_name, TEST_NAME "mod1.so") == 0) + ck = AUDIT24MOD1_COOKIE; + else if (strcmp (l_name, TEST_NAME "mod2.so") == 0) + ck = AUDIT24MOD2_COOKIE; + else if (strcmp (l_name, TEST_NAME) == 0) + ck = AUDIT24_COOKIE; + + *cookie = ck; + return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO; +} + +static int +tst_func1 (void) +{ + return 1; +} + +static int +tst_func2 (void) +{ + return 2; +} + +#if __ELF_NATIVE_CLASS == 64 +uintptr_t +la_symbind64 (Elf64_Sym *sym, unsigned int ndx, + uintptr_t *refcook, uintptr_t *defcook, + unsigned int *flags, const char *symname) +#else +uintptr_t +la_symbind32 (Elf32_Sym *sym, unsigned int ndx, + uintptr_t *refcook, uintptr_t *defcook, + unsigned int *flags, const char *symname) +#endif +{ + if (*refcook == AUDIT24_COOKIE) + { + if (*defcook == AUDIT24MOD1_COOKIE) + { + if (strcmp (symname, TEST_FUNC "mod1_func1") == 0) + return (uintptr_t) tst_func1; + else if (strcmp (symname, TEST_FUNC "mod1_func2") == 0) + return sym->st_value; + abort (); + } + /* malloc functions. */ + return sym->st_value; + } + else if (*refcook == AUDIT24MOD1_COOKIE) + { + if (*defcook == AUDIT24MOD2_COOKIE + && (strcmp (symname, TEST_FUNC "mod2_func1") == 0)) + { + check_symbind_flags (*flags); + return (uintptr_t) tst_func2; + } + } + + abort (); +} diff --git a/elf/tst-auditmod24c.c b/elf/tst-auditmod24c.c new file mode 100644 index 0000000000..67e62c9d33 --- /dev/null +++ b/elf/tst-auditmod24c.c @@ -0,0 +1,3 @@ +#define TEST_NAME "tst-audit24c" +#define TEST_MOD "tst-audit24a" +#include "tst-auditmod24a.c" diff --git a/elf/tst-auditmod24d.c b/elf/tst-auditmod24d.c new file mode 100644 index 0000000000..24cae42cb8 --- /dev/null +++ b/elf/tst-auditmod24d.c @@ -0,0 +1,120 @@ +/* Audit module for tst-audit24d. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include + +#define AUDIT24_COOKIE 0x0 +#define AUDIT24MOD1_COOKIE 0x1 +#define AUDIT24MOD2_COOKIE 0x2 +#define AUDIT24MOD3_COOKIE 0x3 +#define AUDIT24MOD4_COOKIE 0x4 + +unsigned int +la_version (unsigned int version) +{ + return LAV_CURRENT; +} + +unsigned int +la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) +{ + const char *p = strrchr (map->l_name, '/'); + const char *l_name = p == NULL ? "tst-audit24d" : p + 1; + + uintptr_t ck = -1; + if (strcmp (l_name, "tst-audit24dmod1.so") == 0) + ck = AUDIT24MOD1_COOKIE; + else if (strcmp (l_name, "tst-audit24dmod2.so") == 0) + ck = AUDIT24MOD2_COOKIE; + else if (strcmp (l_name, "tst-audit24dmod3.so") == 0) + ck = AUDIT24MOD3_COOKIE; + else if (strcmp (l_name, "tst-audit24dmod.so") == 0) + ck = AUDIT24MOD4_COOKIE; + else if (strcmp (l_name, "tst-audit24d") == 0) + ck = AUDIT24_COOKIE; + + *cookie = ck; + return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO; +} + +static int +tst_audit24dmod1_func1 (void) +{ + return 1; +} + +static int +tst_audit24dmod2_func1 (void) +{ + return 10; +} + +static int +tst_audit24dmod3_func1 (void) +{ + return 30; +} + +#include + +#if __ELF_NATIVE_CLASS == 64 +uintptr_t +la_symbind64 (Elf64_Sym *sym, unsigned int ndx, + uintptr_t *refcook, uintptr_t *defcook, + unsigned int *flags, const char *symname) +#else +uintptr_t +la_symbind32 (Elf32_Sym *sym, unsigned int ndx, + uintptr_t *refcook, uintptr_t *defcook, + unsigned int *flags, const char *symname) +#endif +{ + if (*refcook == AUDIT24_COOKIE) + { + if (*defcook == AUDIT24MOD1_COOKIE) + { + if (strcmp (symname, "tst_audit24dmod1_func1") == 0) + return (uintptr_t) tst_audit24dmod1_func1; + else if (strcmp (symname, "tst_audit24dmod1_func2") == 0) + return sym->st_value; + abort (); + } + if (*defcook == AUDIT24MOD2_COOKIE + && (strcmp (symname, "tst_audit24dmod2_func1") == 0)) + return (uintptr_t) tst_audit24dmod2_func1; + + /* malloc functions. */ + return sym->st_value; + } + else if (*refcook == AUDIT24MOD1_COOKIE) + { + if (*defcook == AUDIT24MOD3_COOKIE + && strcmp (symname, "tst_audit24dmod3_func1") == 0) + { + check_symbind_flags (*flags); + + return (uintptr_t) tst_audit24dmod3_func1; + } + } + + abort (); +} diff --git a/elf/tst-auditmod25.c b/elf/tst-auditmod25.c new file mode 100644 index 0000000000..ea4d5fe542 --- /dev/null +++ b/elf/tst-auditmod25.c @@ -0,0 +1,79 @@ +/* Audit modules for tst-audit25a. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include + +#define AUDIT25_COOKIE 0x1 +#define AUDIT25MOD1_COOKIE 0x2 +#define AUDIT25MOD2_COOKIE 0x3 +#define AUDIT25MOD3_COOKIE 0x2 +#define AUDIT25MOD4_COOKIE 0x3 + +#define TEST_NAME "tst-audit25" +#define TEST_MOD "tst-audit25" +#define TEST_FUNC "tst_audit25" + +unsigned int +la_version (unsigned int version) +{ + return LAV_CURRENT; +} + +unsigned int +la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) +{ + const char *p = strrchr (map->l_name, '/'); + const char *l_name = p == NULL ? TEST_NAME : p + 1; + + uintptr_t ck = -1; + if (strcmp (l_name, TEST_MOD "mod1.so") == 0) + ck = AUDIT25MOD1_COOKIE; + else if (strcmp (l_name, TEST_MOD "mod2.so") == 0) + ck = AUDIT25MOD2_COOKIE; + else if (strcmp (l_name, TEST_MOD "mod3.so") == 0) + ck = AUDIT25MOD3_COOKIE; + else if (strcmp (l_name, TEST_MOD "mod4.so") == 0) + ck = AUDIT25MOD4_COOKIE; + else if (strncmp (l_name, TEST_NAME, strlen (TEST_NAME)) == 0) + ck = AUDIT25_COOKIE; + + *cookie = ck; + return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO; +} + +#if __ELF_NATIVE_CLASS == 64 +uintptr_t +la_symbind64 (Elf64_Sym *sym, unsigned int ndx, + uintptr_t *refcook, uintptr_t *defcook, + unsigned int *flags, const char *symname) +#else +uintptr_t +la_symbind32 (Elf32_Sym *sym, unsigned int ndx, + uintptr_t *refcook, uintptr_t *defcook, + unsigned int *flags, const char *symname) +#endif +{ + if (*refcook != -1 && *defcook != -1) + fprintf (stderr, "la_symbind: %s %u\n", symname, + *flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) ? 1 : 0); + return sym->st_value; +} diff --git a/sysdeps/generic/dl-lookupcfg.h b/sysdeps/generic/dl-lookupcfg.h index 7460c0596a..95bcfc1cc1 100644 --- a/sysdeps/generic/dl-lookupcfg.h +++ b/sysdeps/generic/dl-lookupcfg.h @@ -26,3 +26,6 @@ #define DL_FIXUP_VALUE_CODE_ADDR(value) (value) #define DL_FIXUP_VALUE_ADDR(value) (value) #define DL_FIXUP_ADDR_VALUE(addr) (addr) +#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr) +#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ + (*value) = st_value; diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 97061bdf9f..2ebe7901c0 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1431,7 +1431,10 @@ void _dl_audit_objclose (struct link_map *l) /* Call the la_preinit from the audit modules for the link_map L. */ void _dl_audit_preinit (struct link_map *l); -/* Call the la_symbind{32,64} from the audit modules for the link_map L. */ +/* Call the la_symbind{32,64} from the audit modules for the link_map L. If + RELOC_RESULT is NULL it assumes the symbol to be bind-now and will set + the flags with LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT prior calling + la_symbind{32,64}. */ void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value, lookup_t result) diff --git a/sysdeps/hppa/dl-lookupcfg.h b/sysdeps/hppa/dl-lookupcfg.h index 5d381147c0..8da2412fea 100644 --- a/sysdeps/hppa/dl-lookupcfg.h +++ b/sysdeps/hppa/dl-lookupcfg.h @@ -80,3 +80,6 @@ void attribute_hidden _dl_unmap (struct link_map *map); #define DL_FIXUP_VALUE_CODE_ADDR(value) ((value).ip) #define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value)) #define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr)) +#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr) +#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ + (*value) = *(struct fdesc *) (st_value) diff --git a/sysdeps/ia64/dl-lookupcfg.h b/sysdeps/ia64/dl-lookupcfg.h index b8ab1bba15..3df3116b31 100644 --- a/sysdeps/ia64/dl-lookupcfg.h +++ b/sysdeps/ia64/dl-lookupcfg.h @@ -74,3 +74,6 @@ extern void attribute_hidden _dl_unmap (struct link_map *map); #define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value)) #define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr)) +#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr) +#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ + (*value) = *(struct fdesc *) (st_value) diff --git a/sysdeps/powerpc/dl-lookupcfg.h b/sysdeps/powerpc/dl-lookupcfg.h new file mode 100644 index 0000000000..43fc94a7f6 --- /dev/null +++ b/sysdeps/powerpc/dl-lookupcfg.h @@ -0,0 +1,39 @@ +/* Configuration of lookup functions. PowerPC version. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#define DL_FIXUP_VALUE_TYPE ElfW(Addr) +#define DL_FIXUP_MAKE_VALUE(map, addr) (addr) +#define DL_FIXUP_VALUE_CODE_ADDR(value) (value) +#define DL_FIXUP_VALUE_ADDR(value) (value) +#define DL_FIXUP_ADDR_VALUE(addr) (addr) +#if __WORDSIZE == 64 && _CALL_ELF == 1 +/* We need to correctly set the audit modules value for bind-now. */ +# define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) \ + (((Elf64_FuncDesc *)(addr))->fd_func) +# define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ + ({ \ + Elf64_FuncDesc *opd = (Elf64_FuncDesc *) (value); \ + opd->fd_func = (st_value); \ + if ((new_value) != (uintptr_t) (st_value)) \ + opd->fd_toc = ((Elf64_FuncDesc *)(new_value))->fd_toc; \ + }) +#else +# define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr) +# define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ + (*value) = st_value; +#endif