From patchwork Mon Jan 3 13:25:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 49470 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 1BED5385841F for ; Mon, 3 Jan 2022 13:29:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1BED5385841F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1641216540; 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=ID4zW+1Nvgg+Dv4Jlw65fOt9XVDT+0CxS3evJUR59qwYId1vSUmVtKT3MM1268fuD Fv/gaTTumjXJI5uokZgVzyK8wQQULEdZk0AzrkWPJvLKlyXh8kyMih+JFYFtbP+okd P5tBVBOYfkMujBqdDR9esUYWwyEpz/BUjr67M+qs= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-ua1-x932.google.com (mail-ua1-x932.google.com [IPv6:2607:f8b0:4864:20::932]) by sourceware.org (Postfix) with ESMTPS id 038AD385842A for ; Mon, 3 Jan 2022 13:25:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 038AD385842A Received: by mail-ua1-x932.google.com with SMTP id az37so36812538uab.12 for ; Mon, 03 Jan 2022 05:25:36 -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=YvaJH2REWzo0n8/9PePpPC6G7rvzOFQFfN90d8Q1T8czIBSZ3yUPAS0whwgsANBx37 Zg99Wq4L8dc8Kym9aWPQXryGmTGqJHCoGCUeSjsdFU5bHTnfQulHC+zJUDThgtYaJ2U5 Q9Dg+FYNogoVurEN4fliv60FTgsBBbJpc8rYg38Ej95aiAyktyoHAxAA8a9o8viS/CPt V95QqKLdgHsdxm77T1yMujxbR9EKot1UxPJvJJGN5LStKqkwYYQIO/lxOe2R6XUwQs18 Q2+SYJloyHTJqvenTmmb7cmQ5mSdhsKZEzc8bvarXWewnFXfj/4ZGvDOI0whwoJbRQVv vIYA== X-Gm-Message-State: AOAM532jDZ7bPsIEGQaCyB+N3//piRNsL1DohgtvXjD1VYrpkiFe8zfN OUex/U+wwIE3W/UK1bhsQkbb3jJVWPqDWg== X-Google-Smtp-Source: ABdhPJz6ABotM2oxtA77NPVfXpoZSKxVY/MJGi+tTKaCZvWbt4zZlXEr4tPHg/+gHFVATxZfONIrQA== X-Received: by 2002:a67:ee1a:: with SMTP id f26mr12309491vsp.51.1641216336281; Mon, 03 Jan 2022 05:25:36 -0800 (PST) Received: from birita.. ([2804:431:c7ca:a350:6969:50a8:eab8:8f2f]) by smtp.gmail.com with ESMTPSA id r9sm3840530vke.20.2022.01.03.05.25.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Jan 2022 05:25:36 -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 10:25:27 -0300 Message-Id: <20220103132530.1149542-2-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220103132530.1149542-1-adhemerval.zanella@linaro.org> References: <20220103132530.1149542-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-11.5 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 Netto 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 13:25:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 49471 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 30FC03858424 for ; Mon, 3 Jan 2022 13:29:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 30FC03858424 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1641216587; 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=keefUSGlTfzdDOQjkdrARi9aXbc4uco81XkJeSXz4WW9HRB1qXaZ1DUOJStIyzo8s 8wEPg/SgtVzvvfsNapwgPa/PS0bFE+TkRsytkArgvsri8eByHPK81j4MAz8cbUSTho BWD05RrI/B12mslY7mLsSzfFanBj7gFhKJmMufAw= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-ua1-x932.google.com (mail-ua1-x932.google.com [IPv6:2607:f8b0:4864:20::932]) by sourceware.org (Postfix) with ESMTPS id 692F03858414 for ; Mon, 3 Jan 2022 13:25:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 692F03858414 Received: by mail-ua1-x932.google.com with SMTP id c36so32153233uae.13 for ; Mon, 03 Jan 2022 05:25:38 -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=Uoh3pyTBovZL13jYGKkHEDHY2LfJb7t8+Uyv+T6Nejl/HS8b7dtblQp/uB9a4UAb70 2CCb/t+sfMZd1WWl2gLFwwnDZGaRImre3cZudKhu3WtQrj0so5eVQBFKk+407m4gnzUS RPtzk0yhbD7UisTJKMG+BhoAQIrs4iPEYJGRT2ark72GNkIZeVFBU0eVs3g28Jb4d/Qr EswUeUeCO8e9FHF5TvIJ+7RPP18JuJXB4tsL/oHh/nWqhkXSuHJNM8p5HpvL1cB2vz3b zGLjkooHZIdGuvlAxi2qXAz1vYTJeDxF0RzvWbniZ+OpnZiHOFGwfzkI0C53fdzrzTw/ 3i4g== X-Gm-Message-State: AOAM5308tKj2aQARmJx6vuChXvb+8aUE+d8BxiV5DgmHPO+pFKAo0zbQ M+DpNfkxhzzmp8dtmTIJBjBJbDNhxKlvzg== X-Google-Smtp-Source: ABdhPJwEIyqPkFpZKRPU5DKuUbcujW5C+2O7arNrT5Gppm6lSyYiIyG8mudVrqA2zv+U7ATk3WYSnQ== X-Received: by 2002:a67:fd6d:: with SMTP id h13mr13648167vsa.0.1641216337701; Mon, 03 Jan 2022 05:25:37 -0800 (PST) Received: from birita.. ([2804:431:c7ca:a350:6969:50a8:eab8:8f2f]) by smtp.gmail.com with ESMTPSA id r9sm3840530vke.20.2022.01.03.05.25.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Jan 2022 05:25:37 -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 10:25:28 -0300 Message-Id: <20220103132530.1149542-3-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220103132530.1149542-1-adhemerval.zanella@linaro.org> References: <20220103132530.1149542-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.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 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 Netto 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 13:25:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 49472 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 9090D385841D for ; Mon, 3 Jan 2022 13:30:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9090D385841D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1641216631; bh=WCkfrV62Vo7lVplVbu3o7UxvHFgfdCdnBJG97YOsYlI=; 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=I+Lt/1YKEourcLvgtC4BQ7ovA8KR5iQrfAx5J8xjhpaJPfg3eMwoWrRahnizr8EWo qauHNtJLSqpLwF1KGmhubTE3G6n7Trat9qtlIfFukVy2yEAI3EbDCiyoThtEasfToE 8Nkud5Au02UWFBWV9JgXBsCN9mCVxMsrWcnQSrX0= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-ua1-x934.google.com (mail-ua1-x934.google.com [IPv6:2607:f8b0:4864:20::934]) by sourceware.org (Postfix) with ESMTPS id 592E13858408 for ; Mon, 3 Jan 2022 13:25:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 592E13858408 Received: by mail-ua1-x934.google.com with SMTP id e19so11794292uaa.11 for ; Mon, 03 Jan 2022 05:25:41 -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=WCkfrV62Vo7lVplVbu3o7UxvHFgfdCdnBJG97YOsYlI=; b=6MRyqEGo7ICx+vyoJlnlUwgPXpwZ7f0cUwVMnVE0WxG/ey9ahsoFq9Z+QrxCfuQbf5 l/jDBwl8DWz6ONRUngB5uGgxUgWZPA9nF1aKdql9Q6yycB3WdoJbwiYzn1+dSoBSQLwB 0uJSz2USaqRWHxA5tLuAtB3jKUdWqoBCAtZPD5j28OUtGS8B10wZbmUsEVynns8sRQ8d twRe2ZeItKpJ+zw7catfCNp8LXPHofPUOazEc/OveTetWFK+5F6p6GgZdIpCiac0ymJ0 OcFay+rCtg94DEGkIUAuGNESnizG9SaFUi4EkOxzYkSaO02TGkPaaYp7Y7MuVtDUWZxK FvSA== X-Gm-Message-State: AOAM530VkX7YCLQ+MGp8LCdHMolc4d7/8mNIsRoXEEgEAH0qrl7RW4SO n48HBAgTB7yzGaCBf5BKhV86znGvfIETKg== X-Google-Smtp-Source: ABdhPJxFRJxepABysxIC8LbajuH40mEjjyi0VYH8pla5OATZ1eZiH8+VUa2HXFQOZUUs8CaC3Yn0TQ== X-Received: by 2002:a67:f284:: with SMTP id m4mr10722082vsk.11.1641216339306; Mon, 03 Jan 2022 05:25:39 -0800 (PST) Received: from birita.. ([2804:431:c7ca:a350:6969:50a8:eab8:8f2f]) by smtp.gmail.com with ESMTPSA id r9sm3840530vke.20.2022.01.03.05.25.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Jan 2022 05:25:39 -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 10:25:29 -0300 Message-Id: <20220103132530.1149542-4-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220103132530.1149542-1-adhemerval.zanella@linaro.org> References: <20220103132530.1149542-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 Netto 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..b2999e4881 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 advertises 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 From patchwork Mon Jan 3 13:25:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 49473 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 305FE3858403 for ; Mon, 3 Jan 2022 13:31:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 305FE3858403 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1641216682; bh=uToezubI00o0j+gwtYhlEj3eTvr0OKXhkHHVjXJUMIw=; 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=F7LiRMdrNeBk+Y7ZYoFG8JgvwtW9xCkF2OtnH/+XdjsVRammOfozp4qBUCZHTu6fk EhlEzKXM8Iu4diyipgJs17uY9/3lDHLImF8Mmm+q0e47um/WKM79rIdtDDN5bgYah1 js2mZRcZubStiTZ9VsnVgiBUO50D+LhGFAWf9Nes= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-ua1-x936.google.com (mail-ua1-x936.google.com [IPv6:2607:f8b0:4864:20::936]) by sourceware.org (Postfix) with ESMTPS id 772143858423 for ; Mon, 3 Jan 2022 13:25:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 772143858423 Received: by mail-ua1-x936.google.com with SMTP id p37so57525053uae.8 for ; Mon, 03 Jan 2022 05:25:44 -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=uToezubI00o0j+gwtYhlEj3eTvr0OKXhkHHVjXJUMIw=; b=oEE65RM4f3XNHOJnU1HbXZdsoHpvYbmC4u7Ims33IgctDvLgblW0lw6EN6qL0r/5VY llVOCbHQ9uJ5CLVNrB6gDpoZ5XjVvHg5uGXngFSfDta/EgA+0PY1VT8H+VG2M8Wbhx8U /kXcGhdyFLvCW7sskq5lDK96e54HRvFJ/zo6c5o/JGuRYuBL53X4sntr7DEnqsR7cGmn 1b/YJzOtJcfZgqu5O0ca94iFrO+UNrGsPswamoZr6NmXDm5ADl4Jj/6Q/DUjo32Te7L+ Oa/51zsTqLfC/EvE+nIe6T6dxfTqw6Qz0GFF0kzCBCDnasyRPKahGodbSjUUb017OO1P onrQ== X-Gm-Message-State: AOAM53388gnZruPIXrcH31rRASm3XEaY50Jjh2vcVueKRrEYV93zke3p Uvzksu+hNlS1vXUubupTfBNGMvNYtA7Jrw== X-Google-Smtp-Source: ABdhPJwp/HwfoE5sqp763FRgcuw8Rw/lUnkB6Xt8h/cOj19QLM47XL+UemDk48lf2/Lp+NjPhMQnYA== X-Received: by 2002:a67:f8ca:: with SMTP id c10mr13407405vsp.43.1641216343399; Mon, 03 Jan 2022 05:25:43 -0800 (PST) Received: from birita.. ([2804:431:c7ca:a350:6969:50a8:eab8:8f2f]) by smtp.gmail.com with ESMTPSA id r9sm3840530vke.20.2022.01.03.05.25.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Jan 2022 05:25:43 -0800 (PST) To: libc-alpha@sourceware.org, jma14 Subject: [PATCH v9 4/4] elf: Fix runtime linker auditing on aarch64 (BZ #26643) Date: Mon, 3 Jan 2022 10:25:30 -0300 Message-Id: <20220103132530.1149542-5-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220103132530.1149542-1-adhemerval.zanella@linaro.org> References: <20220103132530.1149542-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 Netto Reply-To: Adhemerval Zanella Cc: John Mellor-Crummey Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" From: Ben Woodard The rtld audit support show two problems on aarch64: 1. _dl_runtime_resolve does not preserve x8, the indirect result location register, which might generate wrong result calls depending of the function signature. 2. The NEON Q registers pushed onto the stack by _dl_runtime_resolve were twice the size of D registers extracted from the stack frame by _dl_runtime_profile. While 2. might result in wrong information passed on the PLT tracing, 1. generates wrong runtime behaviour. The aarch64 rtld audit support is change to: * Both La_aarch64_regs and La_aarch64_retval are expanded to include both x8 and the full sized NEON V registers, as defined by the ABI. * dl_runtime_profile needed to extract registers saved by _dl_runtime_resolve and put them into the new correctly sized La_aarch64_regs structure. * The LAV_CURRENT check is change to only accept new audit modules to avoid the undefined behavior of not save/restore x8. * Different than other architectures, audit modules older than LAV_CURRENT are rejected (both La_aarch64_regs and La_aarch64_retval changes layout and it does not work the complexity to support multiple audit interfaces). Similar to x86, a new La_aarch64_vector type to represent the NEON register is added on the La_aarch64_regs (so each type can be accessed directly). Since LAV_CURRENT was already bumped to support bind-now, there is no need to increase it again. Checked on aarch64-linux-gnu. Co-authored-by: Adhemerval Zanella --- NEWS | 4 + elf/rtld.c | 3 +- sysdeps/aarch64/Makefile | 20 ++++ sysdeps/aarch64/bits/link.h | 26 +++-- sysdeps/aarch64/dl-audit-check.h | 28 +++++ sysdeps/aarch64/dl-link.sym | 6 +- sysdeps/aarch64/dl-trampoline.S | 97 +++++++++++------ sysdeps/aarch64/tst-audit26.c | 37 +++++++ sysdeps/aarch64/tst-audit26mod.c | 33 ++++++ sysdeps/aarch64/tst-audit26mod.h | 50 +++++++++ sysdeps/aarch64/tst-audit27.c | 64 +++++++++++ sysdeps/aarch64/tst-audit27mod.c | 95 ++++++++++++++++ sysdeps/aarch64/tst-audit27mod.h | 67 ++++++++++++ sysdeps/aarch64/tst-auditmod26.c | 103 ++++++++++++++++++ sysdeps/aarch64/tst-auditmod27.c | 180 +++++++++++++++++++++++++++++++ sysdeps/generic/dl-audit-check.h | 23 ++++ 16 files changed, 789 insertions(+), 47 deletions(-) create mode 100644 sysdeps/aarch64/dl-audit-check.h create mode 100644 sysdeps/aarch64/tst-audit26.c create mode 100644 sysdeps/aarch64/tst-audit26mod.c create mode 100644 sysdeps/aarch64/tst-audit26mod.h create mode 100644 sysdeps/aarch64/tst-audit27.c create mode 100644 sysdeps/aarch64/tst-audit27mod.c create mode 100644 sysdeps/aarch64/tst-audit27mod.h create mode 100644 sysdeps/aarch64/tst-auditmod26.c create mode 100644 sysdeps/aarch64/tst-auditmod27.c create mode 100644 sysdeps/generic/dl-audit-check.h diff --git a/NEWS b/NEWS index b2999e4881..b0272ae464 100644 --- a/NEWS +++ b/NEWS @@ -130,6 +130,10 @@ Deprecated and removed features, and other changes affecting compatibility: proper bind-now support. The loader now advertises on the la_symbind flags that PLT trace is not possible. +* The audit interface on aarch64 is extended to support both the indirect + result location register (x8) and NEON Q register. This makes old audit + modules to be rejected by the loader. + Changes to build and runtime requirements: [Add changes to build and runtime requirements here] diff --git a/elf/rtld.c b/elf/rtld.c index 75583db2f2..3d583d5632 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -52,6 +52,7 @@ #include #include #include +#include #include @@ -997,7 +998,7 @@ file=%s [%lu]; audit interface function la_version returned zero; ignored.\n", return; } - if (lav > LAV_CURRENT) + if (!_dl_audit_check_version (lav)) { _dl_debug_printf ("\ ERROR: audit interface '%s' requires version %d (maximum supported version %d); ignored.\n", diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile index 7c66fb97aa..7183895d04 100644 --- a/sysdeps/aarch64/Makefile +++ b/sysdeps/aarch64/Makefile @@ -10,6 +10,26 @@ endif ifeq ($(subdir),elf) sysdep-dl-routines += dl-bti + +tests += tst-audit26 \ + tst-audit27 + +modules-names += \ + tst-audit26mod \ + tst-auditmod26 \ + tst-audit27mod \ + tst-auditmod27 + +$(objpfx)tst-audit26: $(objpfx)tst-audit26mod.so \ + $(objpfx)tst-auditmod26.so +LDFLAGS-tst-audit26 += -Wl,-z,lazy +tst-audit26-ENV = LD_AUDIT=$(objpfx)tst-auditmod26.so + +$(objpfx)tst-audit27: $(objpfx)tst-audit27mod.so \ + $(objpfx)tst-auditmod27.so +$(objpfx)tst-audit27mod.so: $(libsupport) +LDFLAGS-tst-audit27 += -Wl,-z,lazy +tst-audit27-ENV = LD_AUDIT=$(objpfx)tst-auditmod27.so endif ifeq ($(subdir),elf) diff --git a/sysdeps/aarch64/bits/link.h b/sysdeps/aarch64/bits/link.h index e64f36d3f3..2479abc4fb 100644 --- a/sysdeps/aarch64/bits/link.h +++ b/sysdeps/aarch64/bits/link.h @@ -20,23 +20,31 @@ # error "Never include directly; use instead." #endif +typedef union +{ + float s; + double d; + long double q; +} La_aarch64_vector; + /* Registers for entry into PLT on AArch64. */ typedef struct La_aarch64_regs { - uint64_t lr_xreg[8]; - uint64_t lr_dreg[8]; - uint64_t lr_sp; - uint64_t lr_lr; + uint64_t lr_xreg[9]; + La_aarch64_vector lr_vreg[8]; + uint64_t lr_sp; + uint64_t lr_lr; + void *lr_vpcs; } La_aarch64_regs; /* Return values for calls from PLT on AArch64. */ typedef struct La_aarch64_retval { - /* Up to two integer registers can be used for a return value. */ - uint64_t lrv_xreg[2]; - /* Up to four D registers can be used for a return value. */ - uint64_t lrv_dreg[4]; - + /* Up to eight integer registers can be used for a return value. */ + uint64_t lrv_xreg[8]; + /* Up to eight V registers can be used for a return value. */ + La_aarch64_vector lrv_vreg[8]; + void *lrv_vpcs; } La_aarch64_retval; __BEGIN_DECLS diff --git a/sysdeps/aarch64/dl-audit-check.h b/sysdeps/aarch64/dl-audit-check.h new file mode 100644 index 0000000000..0efb5de6b3 --- /dev/null +++ b/sysdeps/aarch64/dl-audit-check.h @@ -0,0 +1,28 @@ +/* rtld-audit version check. AArch64 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 + . */ + +static inline bool +_dl_audit_check_version (unsigned int lav) +{ + /* Audit version 1 do not save neither x8 nor NEON register, which required + change La_aarch64_regs and La_aarch64_retval layout (BZ#26643). The + missing indirect result save/restore makes _dl_runtime_profile + potentially trigger undefined behavior if function returns a large + struct (even when PLT trace is not requested). */ + return lav == LAV_CURRENT; +} diff --git a/sysdeps/aarch64/dl-link.sym b/sysdeps/aarch64/dl-link.sym index d67d28b40c..cb4dcdcbed 100644 --- a/sysdeps/aarch64/dl-link.sym +++ b/sysdeps/aarch64/dl-link.sym @@ -7,9 +7,11 @@ DL_SIZEOF_RG sizeof(struct La_aarch64_regs) DL_SIZEOF_RV sizeof(struct La_aarch64_retval) DL_OFFSET_RG_X0 offsetof(struct La_aarch64_regs, lr_xreg) -DL_OFFSET_RG_D0 offsetof(struct La_aarch64_regs, lr_dreg) +DL_OFFSET_RG_V0 offsetof(struct La_aarch64_regs, lr_vreg) DL_OFFSET_RG_SP offsetof(struct La_aarch64_regs, lr_sp) DL_OFFSET_RG_LR offsetof(struct La_aarch64_regs, lr_lr) +DL_OFFSET_RG_VPCS offsetof(struct La_aarch64_regs, lr_vpcs) DL_OFFSET_RV_X0 offsetof(struct La_aarch64_retval, lrv_xreg) -DL_OFFSET_RV_D0 offsetof(struct La_aarch64_retval, lrv_dreg) +DL_OFFSET_RV_V0 offsetof(struct La_aarch64_retval, lrv_vreg) +DL_OFFSET_RV_VPCS offsetof(struct La_aarch64_retval, lrv_vpcs) diff --git a/sysdeps/aarch64/dl-trampoline.S b/sysdeps/aarch64/dl-trampoline.S index a403863ef9..692611341d 100644 --- a/sysdeps/aarch64/dl-trampoline.S +++ b/sysdeps/aarch64/dl-trampoline.S @@ -45,7 +45,8 @@ _dl_runtime_resolve: cfi_rel_offset (lr, 8) - /* Save arguments. */ + /* Note: Saving x9 is not required by the ABI but the assember requires + the immediate values of operand 3 to be a multiple of 16 */ stp x8, x9, [sp, #-(80+8*16)]! cfi_adjust_cfa_offset (80+8*16) cfi_rel_offset (x8, 0) @@ -142,13 +143,17 @@ _dl_runtime_profile: Stack frame layout: [sp, #...] lr [sp, #...] &PLTGOT[n] - [sp, #96] La_aarch64_regs - [sp, #48] La_aarch64_retval - [sp, #40] frame size return from pltenter - [sp, #32] dl_profile_call saved x1 - [sp, #24] dl_profile_call saved x0 - [sp, #16] t1 - [sp, #0] x29, lr <- x29 + ----------------------- + [sp, #384] La_aarch64_regs::lr_xreg (x0-x8) + [sp, #256] La_aarch64_regs::lr_vreg (q0-q7) + [sp, #240] La_aarch64_regs::sp and La_aarch64_regs::lr + [sp, #176] La_aarch64_retval::lrv_xreg (x0-x7) + [sp, # 48] La_aarch64_retval::lrv_vreg (q0-q7) + [sp, # 40] frame size return from pltenter + [sp, # 32] dl_profile_call saved x1 + [sp, # 24] dl_profile_call saved x0 + [sp, # 16] t1 + [sp, # 0] x29, lr <- x29 */ # define OFFSET_T1 16 @@ -183,19 +188,25 @@ _dl_runtime_profile: stp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3] cfi_rel_offset (x6, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 0) cfi_rel_offset (x7, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 8) - - stp d0, d1, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0] - cfi_rel_offset (d0, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0) - cfi_rel_offset (d1, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0 + 8) - stp d2, d3, [X29, #OFFSET_RG+ DL_OFFSET_RG_D0 + 16*1] - cfi_rel_offset (d2, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 0) - cfi_rel_offset (d3, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 8) - stp d4, d5, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2] - cfi_rel_offset (d4, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 0) - cfi_rel_offset (d5, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 8) - stp d6, d7, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3] - cfi_rel_offset (d6, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 0) - cfi_rel_offset (d7, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 8) + str x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4 + 0] + cfi_rel_offset (x8, OFFSET_RG + DL_OFFSET_RG_X0 + 16*4 + 0) + /* Note 8 bytes of padding is in the stack frame for alignment */ + + stp q0, q1, [X29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*0] + cfi_rel_offset (q0, OFFSET_RG + DL_OFFSET_RG_V0 + 32*0) + cfi_rel_offset (q1, OFFSET_RG + DL_OFFSET_RG_V0 + 32*0 + 16) + stp q2, q3, [X29, #OFFSET_RG+ DL_OFFSET_RG_V0 + 32*1] + cfi_rel_offset (q2, OFFSET_RG + DL_OFFSET_RG_V0 + 32*1 + 0) + cfi_rel_offset (q3, OFFSET_RG + DL_OFFSET_RG_V0 + 32*1 + 16) + stp q4, q5, [X29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*2] + cfi_rel_offset (q4, OFFSET_RG + DL_OFFSET_RG_V0 + 32*2 + 0) + cfi_rel_offset (q5, OFFSET_RG + DL_OFFSET_RG_V0 + 32*2 + 16) + stp q6, q7, [X29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*3] + cfi_rel_offset (q6, OFFSET_RG + DL_OFFSET_RG_V0 + 32*3 + 0) + cfi_rel_offset (q7, OFFSET_RG + DL_OFFSET_RG_V0 + 32*3 + 16) + + /* No APCS extension supported. */ + str xzr, [X29, #OFFSET_RG + DL_OFFSET_RG_VPCS] add x0, x29, #SF_SIZE + 16 ldr x1, [x29, #OFFSET_LR] @@ -234,10 +245,11 @@ _dl_runtime_profile: ldp x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1] ldp x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2] ldp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3] - ldp d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0] - ldp d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1] - ldp d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2] - ldp d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3] + ldr x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4] + ldp q0, q1, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*0] + ldp q2, q3, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*1] + ldp q4, q5, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*2] + ldp q6, q7, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*3] cfi_def_cfa_register (sp) ldp x29, x30, [x29, #0] @@ -280,14 +292,22 @@ _dl_runtime_profile: ldp x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1] ldp x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2] ldp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3] - ldp d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0] - ldp d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1] - ldp d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2] - ldp d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3] + ldr x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4] + ldp q0, q1, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*0] + ldp q2, q3, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*1] + ldp q4, q5, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*2] + ldp q6, q7, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*3] blr ip0 - stp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0] - stp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0] - stp d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1] + stp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*0] + stp x2, x3, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*1] + stp x4, x5, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*2] + stp x6, x7, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*3] + str x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4] + stp q0, q1, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*0] + stp q2, q3, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*1] + stp q4, q5, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*2] + stp q6, q7, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*3] + str xzr, [X29, #OFFSET_RV + DL_OFFSET_RG_VPCS] /* Setup call to pltexit */ ldp x0, x1, [x29, #OFFSET_SAVED_CALL_X0] @@ -295,9 +315,16 @@ _dl_runtime_profile: add x3, x29, #OFFSET_RV bl _dl_audit_pltexit - ldp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0] - ldp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0] - ldp d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1] + ldp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*0] + ldp x2, x3, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*1] + ldp x4, x5, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*2] + ldp x6, x7, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*3] + ldr x8, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*4] + ldp q0, q1, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*0] + ldp q2, q3, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*1] + ldp q4, q5, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*2] + ldp q6, q7, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*3] + /* LR from within La_aarch64_reg */ ldr lr, [x29, #OFFSET_RG + DL_OFFSET_RG_LR] cfi_restore(lr) diff --git a/sysdeps/aarch64/tst-audit26.c b/sysdeps/aarch64/tst-audit26.c new file mode 100644 index 0000000000..44d2479e08 --- /dev/null +++ b/sysdeps/aarch64/tst-audit26.c @@ -0,0 +1,37 @@ +/* Check DT_AUDIT for aarch64 ABI specifics. + 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 "tst-audit26mod.h" + +int +do_test (void) +{ + /* Returning a large struct uses 'x8' as indirect result location. */ + struct large_struct r = tst_audit26_func (ARG1, ARG2, ARG3); + + struct large_struct e = set_large_struct (ARG1, ARG2, ARG3); + + TEST_COMPARE_BLOB (r.a, sizeof (r.a), e.a, sizeof (e.a)); + + return 0; +} + +#include diff --git a/sysdeps/aarch64/tst-audit26mod.c b/sysdeps/aarch64/tst-audit26mod.c new file mode 100644 index 0000000000..f8d9270898 --- /dev/null +++ b/sysdeps/aarch64/tst-audit26mod.c @@ -0,0 +1,33 @@ +/* Check DT_AUDIT for aarch64 ABI specifics. + 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 "tst-audit26mod.h" + +struct large_struct +tst_audit26_func (char a, short b, long int c) +{ + if (a != ARG1) + abort (); + if (b != ARG2) + abort (); + if (c != ARG3) + abort (); + + return set_large_struct (a, b, c); +} diff --git a/sysdeps/aarch64/tst-audit26mod.h b/sysdeps/aarch64/tst-audit26mod.h new file mode 100644 index 0000000000..dd9ddcdada --- /dev/null +++ b/sysdeps/aarch64/tst-audit26mod.h @@ -0,0 +1,50 @@ +/* Check DT_AUDIT for aarch64 specific ABI. + 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_AUDIT27MOD_H +#define _TST_AUDIT27MOD_H 1 + +#include + +struct large_struct +{ + char a[16]; + short b[8]; + long int c[4]; +}; + +static inline struct large_struct +set_large_struct (char a, short b, long int c) +{ + struct large_struct r; + for (int i = 0; i < array_length (r.a); i++) + r.a[i] = a; + for (int i = 0; i < array_length (r.b); i++) + r.b[i] = b; + for (int i = 0; i < array_length (r.c); i++) + r.c[i] = c; + return r; +} + +#define ARG1 0x12 +#define ARG2 0x1234 +#define ARG3 0x12345678 + +struct large_struct tst_audit26_func (char a, short b, long int c); + +#endif diff --git a/sysdeps/aarch64/tst-audit27.c b/sysdeps/aarch64/tst-audit27.c new file mode 100644 index 0000000000..e19b58bc3b --- /dev/null +++ b/sysdeps/aarch64/tst-audit27.c @@ -0,0 +1,64 @@ +/* Check DT_AUDIT for aarch64 ABI specifics. + 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 "tst-audit27mod.h" + +int +do_test (void) +{ + { + float r = tst_audit27_func_float (FUNC_FLOAT_ARG0, FUNC_FLOAT_ARG1, + FUNC_FLOAT_ARG2, FUNC_FLOAT_ARG3, + FUNC_FLOAT_ARG4, FUNC_FLOAT_ARG5, + FUNC_FLOAT_ARG6, FUNC_FLOAT_ARG7); + if (r != FUNC_FLOAT_RET) + FAIL_EXIT1 ("tst_audit27_func_float() returned %a, expected %a", + r, FUNC_FLOAT_RET); + } + + { + double r = tst_audit27_func_double (FUNC_DOUBLE_ARG0, FUNC_DOUBLE_ARG1, + FUNC_DOUBLE_ARG2, FUNC_DOUBLE_ARG3, + FUNC_DOUBLE_ARG4, FUNC_DOUBLE_ARG5, + FUNC_DOUBLE_ARG6, FUNC_DOUBLE_ARG7); + if (r != FUNC_DOUBLE_RET) + FAIL_EXIT1 ("tst_audit27_func_double() returned %la, expected %la", + r, FUNC_DOUBLE_RET); + } + + { + long double r = tst_audit27_func_ldouble (FUNC_LDOUBLE_ARG0, + FUNC_LDOUBLE_ARG1, + FUNC_LDOUBLE_ARG2, + FUNC_LDOUBLE_ARG3, + FUNC_LDOUBLE_ARG4, + FUNC_LDOUBLE_ARG5, + FUNC_LDOUBLE_ARG6, + FUNC_LDOUBLE_ARG7); + if (r != FUNC_LDOUBLE_RET) + FAIL_EXIT1 ("tst_audit27_func_ldouble() returned %La, expected %La", + r, FUNC_LDOUBLE_RET); + } + + return 0; +} + +#include diff --git a/sysdeps/aarch64/tst-audit27mod.c b/sysdeps/aarch64/tst-audit27mod.c new file mode 100644 index 0000000000..a8e8b28523 --- /dev/null +++ b/sysdeps/aarch64/tst-audit27mod.c @@ -0,0 +1,95 @@ +/* Check DT_AUDIT for aarch64 ABI specifics. + 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 "tst-audit27mod.h" + +float +tst_audit27_func_float (float a0, float a1, float a2, float a3, float a4, + float a5, float a6, float a7) +{ + if (a0 != FUNC_FLOAT_ARG0) + FAIL_EXIT1 ("a0: %a != %a", a0, FUNC_FLOAT_ARG0); + if (a1 != FUNC_FLOAT_ARG1) + FAIL_EXIT1 ("a1: %a != %a", a1, FUNC_FLOAT_ARG1); + if (a2 != FUNC_FLOAT_ARG2) + FAIL_EXIT1 ("a2: %a != %a", a2, FUNC_FLOAT_ARG2); + if (a3 != FUNC_FLOAT_ARG3) + FAIL_EXIT1 ("a3: %a != %a", a3, FUNC_FLOAT_ARG3); + if (a4 != FUNC_FLOAT_ARG4) + FAIL_EXIT1 ("a4: %a != %a", a4, FUNC_FLOAT_ARG4); + if (a5 != FUNC_FLOAT_ARG5) + FAIL_EXIT1 ("a5: %a != %a", a5, FUNC_FLOAT_ARG5); + if (a6 != FUNC_FLOAT_ARG6) + FAIL_EXIT1 ("a6: %a != %a", a6, FUNC_FLOAT_ARG6); + if (a7 != FUNC_FLOAT_ARG7) + FAIL_EXIT1 ("a7: %a != %a", a7, FUNC_FLOAT_ARG7); + + return FUNC_FLOAT_RET; +} + +double +tst_audit27_func_double (double a0, double a1, double a2, double a3, double a4, + double a5, double a6, double a7) +{ + if (a0 != FUNC_DOUBLE_ARG0) + FAIL_EXIT1 ("a0: %la != %la", a0, FUNC_DOUBLE_ARG0); + if (a1 != FUNC_DOUBLE_ARG1) + FAIL_EXIT1 ("a1: %la != %la", a1, FUNC_DOUBLE_ARG1); + if (a2 != FUNC_DOUBLE_ARG2) + FAIL_EXIT1 ("a2: %la != %la", a2, FUNC_DOUBLE_ARG2); + if (a3 != FUNC_DOUBLE_ARG3) + FAIL_EXIT1 ("a3: %la != %la", a3, FUNC_DOUBLE_ARG3); + if (a4 != FUNC_DOUBLE_ARG4) + FAIL_EXIT1 ("a4: %la != %la", a4, FUNC_DOUBLE_ARG4); + if (a5 != FUNC_DOUBLE_ARG5) + FAIL_EXIT1 ("a5: %la != %la", a5, FUNC_DOUBLE_ARG5); + if (a6 != FUNC_DOUBLE_ARG6) + FAIL_EXIT1 ("a6: %la != %la", a6, FUNC_DOUBLE_ARG6); + if (a7 != FUNC_DOUBLE_ARG7) + FAIL_EXIT1 ("a7: %la != %la", a7, FUNC_DOUBLE_ARG7); + + return FUNC_DOUBLE_RET; +} + +long double +tst_audit27_func_ldouble (long double a0, long double a1, long double a2, + long double a3, long double a4, long double a5, + long double a6, long double a7) +{ + if (a0 != FUNC_LDOUBLE_ARG0) + FAIL_EXIT1 ("a0: %La != %La", a0, FUNC_LDOUBLE_ARG0); + if (a1 != FUNC_LDOUBLE_ARG1) + FAIL_EXIT1 ("a1: %La != %La", a1, FUNC_LDOUBLE_ARG1); + if (a2 != FUNC_LDOUBLE_ARG2) + FAIL_EXIT1 ("a2: %La != %La", a2, FUNC_LDOUBLE_ARG2); + if (a3 != FUNC_LDOUBLE_ARG3) + FAIL_EXIT1 ("a3: %La != %La", a3, FUNC_LDOUBLE_ARG3); + if (a4 != FUNC_LDOUBLE_ARG4) + FAIL_EXIT1 ("a4: %La != %La", a4, FUNC_LDOUBLE_ARG4); + if (a5 != FUNC_LDOUBLE_ARG5) + FAIL_EXIT1 ("a5: %La != %La", a5, FUNC_LDOUBLE_ARG5); + if (a6 != FUNC_LDOUBLE_ARG6) + FAIL_EXIT1 ("a6: %La != %La", a6, FUNC_LDOUBLE_ARG6); + if (a7 != FUNC_LDOUBLE_ARG7) + FAIL_EXIT1 ("a7: %La != %La", a7, FUNC_LDOUBLE_ARG7); + + return FUNC_LDOUBLE_RET; +} diff --git a/sysdeps/aarch64/tst-audit27mod.h b/sysdeps/aarch64/tst-audit27mod.h new file mode 100644 index 0000000000..cbd44c4bdf --- /dev/null +++ b/sysdeps/aarch64/tst-audit27mod.h @@ -0,0 +1,67 @@ +/* Check DT_AUDIT for aarch64 specific ABI. + 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_AUDIT27MOD_H +#define _TST_AUDIT27MOD_H 1 + +#include + +#define FUNC_FLOAT_ARG0 FLT_MIN +#define FUNC_FLOAT_ARG1 FLT_MAX +#define FUNC_FLOAT_ARG2 FLT_EPSILON +#define FUNC_FLOAT_ARG3 FLT_TRUE_MIN +#define FUNC_FLOAT_ARG4 0.0f +#define FUNC_FLOAT_ARG5 1.0f +#define FUNC_FLOAT_ARG6 2.0f +#define FUNC_FLOAT_ARG7 3.0f +#define FUNC_FLOAT_RET 4.0f + +float +tst_audit27_func_float (float a0, float a1, float a2, float a3, float a4, + float a5, float a6, float a7); + +#define FUNC_DOUBLE_ARG0 DBL_MIN +#define FUNC_DOUBLE_ARG1 DBL_MAX +#define FUNC_DOUBLE_ARG2 DBL_EPSILON +#define FUNC_DOUBLE_ARG3 DBL_TRUE_MIN +#define FUNC_DOUBLE_ARG4 0.0 +#define FUNC_DOUBLE_ARG5 1.0 +#define FUNC_DOUBLE_ARG6 2.0 +#define FUNC_DOUBLE_ARG7 3.0 +#define FUNC_DOUBLE_RET 0x1.fffffe0000001p+127 + +double +tst_audit27_func_double (double a0, double a1, double a2, double a3, double a4, + double a5, double a6, double a7); + +#define FUNC_LDOUBLE_ARG0 DBL_MAX + 1.0L +#define FUNC_LDOUBLE_ARG1 DBL_MAX + 2.0L +#define FUNC_LDOUBLE_ARG2 DBL_MAX + 3.0L +#define FUNC_LDOUBLE_ARG3 DBL_MAX + 4.0L +#define FUNC_LDOUBLE_ARG4 DBL_MAX + 5.0L +#define FUNC_LDOUBLE_ARG5 DBL_MAX + 6.0L +#define FUNC_LDOUBLE_ARG6 DBL_MAX + 7.0L +#define FUNC_LDOUBLE_ARG7 DBL_MAX + 8.0L +#define FUNC_LDOUBLE_RET 0x1.fffffffffffff000000000000001p+1023L + +long double +tst_audit27_func_ldouble (long double a0, long double a1, long double a2, + long double a3, long double a4, long double a5, + long double a6, long double a7); + +#endif diff --git a/sysdeps/aarch64/tst-auditmod26.c b/sysdeps/aarch64/tst-auditmod26.c new file mode 100644 index 0000000000..e9d9ced331 --- /dev/null +++ b/sysdeps/aarch64/tst-auditmod26.c @@ -0,0 +1,103 @@ +/* Check DT_AUDIT for aarch64 specific ABI. + 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 "tst-audit26mod.h" + +#define TEST_NAME "tst-audit26" + +#define AUDIT26_COOKIE 0 + +unsigned int +la_version (unsigned int v) +{ + return v; +} + +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 ? map->l_name : p + 1; + uintptr_t ck = -1; + if (strncmp (l_name, TEST_NAME, strlen (TEST_NAME)) == 0) + ck = AUDIT26_COOKIE; + *cookie = ck; + printf ("objopen: %ld, %s [cookie=%ld]\n", lmid, l_name, ck); + return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO; +} + +ElfW(Addr) +la_aarch64_gnu_pltenter (ElfW(Sym) *sym __attribute__ ((unused)), + unsigned int ndx __attribute__ ((unused)), + uintptr_t *refcook, uintptr_t *defcook, + La_aarch64_regs *regs, unsigned int *flags, + const char *symname, long int *framesizep) +{ + printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n", + symname, (long int) sym->st_value, ndx, *flags); + + if (strcmp (symname, "tst_audit26_func") == 0) + { + assert (regs->lr_xreg[0] == ARG1); + assert (regs->lr_xreg[1] == ARG2); + assert (regs->lr_xreg[2] == ARG3); + } + else + abort (); + + assert (regs->lr_vpcs == 0); + + /* Clobber 'x8'. */ + asm volatile ("mov x8, -1" : : : "x8"); + + *framesizep = 1024; + + return sym->st_value; +} + +unsigned int +la_aarch64_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, + uintptr_t *defcook, + const struct La_aarch64_regs *inregs, + struct La_aarch64_retval *outregs, const char *symname) +{ + printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u\n", + symname, (long int) sym->st_value, ndx); + + if (strcmp (symname, "tst_audit26_func") == 0) + { + assert (inregs->lr_xreg[0] == ARG1); + assert (inregs->lr_xreg[1] == ARG2); + assert (inregs->lr_xreg[2] == ARG3); + } + else + abort (); + + assert (inregs->lr_vpcs == 0); + assert (outregs->lrv_vpcs == 0); + + /* Clobber 'x8'. */ + asm volatile ("mov x8, -1" : : : "x8"); + + return 0; +} diff --git a/sysdeps/aarch64/tst-auditmod27.c b/sysdeps/aarch64/tst-auditmod27.c new file mode 100644 index 0000000000..c453775996 --- /dev/null +++ b/sysdeps/aarch64/tst-auditmod27.c @@ -0,0 +1,180 @@ +/* Check DT_AUDIT for aarch64 specific ABI. + 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 "tst-audit27mod.h" + +#define TEST_NAME "tst-audit27" + +#define AUDIT27_COOKIE 0 + +unsigned int +la_version (unsigned int v) +{ + return v; +} + +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 ? map->l_name : p + 1; + uintptr_t ck = -1; + if (strncmp (l_name, TEST_NAME, strlen (TEST_NAME)) == 0) + ck = AUDIT27_COOKIE; + *cookie = ck; + printf ("objopen: %ld, %s [%ld]\n", lmid, l_name, ck); + return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO; +} + +ElfW(Addr) +la_aarch64_gnu_pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, + uintptr_t *defcook, La_aarch64_regs *regs, + unsigned int *flags, const char *symname, + long int *framesizep) +{ + printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n", + symname, (long int) sym->st_value, ndx, *flags); + + if (strcmp (symname, "tst_audit27_func_float") == 0) + { + assert (regs->lr_vreg[0].s == FUNC_FLOAT_ARG0); + assert (regs->lr_vreg[1].s == FUNC_FLOAT_ARG1); + assert (regs->lr_vreg[2].s == FUNC_FLOAT_ARG2); + assert (regs->lr_vreg[3].s == FUNC_FLOAT_ARG3); + assert (regs->lr_vreg[4].s == FUNC_FLOAT_ARG4); + assert (regs->lr_vreg[5].s == FUNC_FLOAT_ARG5); + assert (regs->lr_vreg[6].s == FUNC_FLOAT_ARG6); + assert (regs->lr_vreg[7].s == FUNC_FLOAT_ARG7); + } + else if (strcmp (symname, "tst_audit27_func_double") == 0) + { + assert (regs->lr_vreg[0].d == FUNC_DOUBLE_ARG0); + assert (regs->lr_vreg[1].d == FUNC_DOUBLE_ARG1); + assert (regs->lr_vreg[2].d == FUNC_DOUBLE_ARG2); + assert (regs->lr_vreg[3].d == FUNC_DOUBLE_ARG3); + assert (regs->lr_vreg[4].d == FUNC_DOUBLE_ARG4); + assert (regs->lr_vreg[5].d == FUNC_DOUBLE_ARG5); + assert (regs->lr_vreg[6].d == FUNC_DOUBLE_ARG6); + assert (regs->lr_vreg[7].d == FUNC_DOUBLE_ARG7); + } + else if (strcmp (symname, "tst_audit27_func_ldouble") == 0) + { + assert (regs->lr_vreg[0].q == FUNC_LDOUBLE_ARG0); + assert (regs->lr_vreg[1].q == FUNC_LDOUBLE_ARG1); + assert (regs->lr_vreg[2].q == FUNC_LDOUBLE_ARG2); + assert (regs->lr_vreg[3].q == FUNC_LDOUBLE_ARG3); + assert (regs->lr_vreg[4].q == FUNC_LDOUBLE_ARG4); + assert (regs->lr_vreg[5].q == FUNC_LDOUBLE_ARG5); + assert (regs->lr_vreg[6].q == FUNC_LDOUBLE_ARG6); + assert (regs->lr_vreg[7].q == FUNC_LDOUBLE_ARG7); + } + else + abort (); + + assert (regs->lr_vpcs == 0); + + /* Clobber the q registers on exit. */ + uint8_t v = 0xff; + asm volatile ("dup v0.8b, %w0" : : "r" (v) : "v0"); + asm volatile ("dup v1.8b, %w0" : : "r" (v) : "v1"); + asm volatile ("dup v2.8b, %w0" : : "r" (v) : "v2"); + asm volatile ("dup v3.8b, %w0" : : "r" (v) : "v3"); + asm volatile ("dup v4.8b, %w0" : : "r" (v) : "v4"); + asm volatile ("dup v5.8b, %w0" : : "r" (v) : "v5"); + asm volatile ("dup v6.8b, %w0" : : "r" (v) : "v6"); + asm volatile ("dup v7.8b, %w0" : : "r" (v) : "v7"); + + *framesizep = 1024; + + return sym->st_value; +} + +unsigned int +la_aarch64_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, + uintptr_t *defcook, + const struct La_aarch64_regs *inregs, + struct La_aarch64_retval *outregs, + const char *symname) +{ + printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u\n", + symname, (long int) sym->st_value, ndx); + + if (strcmp (symname, "tst_audit27_func_float") == 0) + { + assert (inregs->lr_vreg[0].s == FUNC_FLOAT_ARG0); + assert (inregs->lr_vreg[1].s == FUNC_FLOAT_ARG1); + assert (inregs->lr_vreg[2].s == FUNC_FLOAT_ARG2); + assert (inregs->lr_vreg[3].s == FUNC_FLOAT_ARG3); + assert (inregs->lr_vreg[4].s == FUNC_FLOAT_ARG4); + assert (inregs->lr_vreg[5].s == FUNC_FLOAT_ARG5); + assert (inregs->lr_vreg[6].s == FUNC_FLOAT_ARG6); + assert (inregs->lr_vreg[7].s == FUNC_FLOAT_ARG7); + + assert (outregs->lrv_vreg[0].s == FUNC_FLOAT_RET); + } + else if (strcmp (symname, "tst_audit27_func_double") == 0) + { + assert (inregs->lr_vreg[0].d == FUNC_DOUBLE_ARG0); + assert (inregs->lr_vreg[1].d == FUNC_DOUBLE_ARG1); + assert (inregs->lr_vreg[2].d == FUNC_DOUBLE_ARG2); + assert (inregs->lr_vreg[3].d == FUNC_DOUBLE_ARG3); + assert (inregs->lr_vreg[4].d == FUNC_DOUBLE_ARG4); + assert (inregs->lr_vreg[5].d == FUNC_DOUBLE_ARG5); + assert (inregs->lr_vreg[6].d == FUNC_DOUBLE_ARG6); + assert (inregs->lr_vreg[7].d == FUNC_DOUBLE_ARG7); + + assert (outregs->lrv_vreg[0].d == FUNC_DOUBLE_RET); + } + else if (strcmp (symname, "tst_audit27_func_ldouble") == 0) + { + assert (inregs->lr_vreg[0].q == FUNC_LDOUBLE_ARG0); + assert (inregs->lr_vreg[1].q == FUNC_LDOUBLE_ARG1); + assert (inregs->lr_vreg[2].q == FUNC_LDOUBLE_ARG2); + assert (inregs->lr_vreg[3].q == FUNC_LDOUBLE_ARG3); + assert (inregs->lr_vreg[4].q == FUNC_LDOUBLE_ARG4); + assert (inregs->lr_vreg[5].q == FUNC_LDOUBLE_ARG5); + assert (inregs->lr_vreg[6].q == FUNC_LDOUBLE_ARG6); + assert (inregs->lr_vreg[7].q == FUNC_LDOUBLE_ARG7); + + assert (outregs->lrv_vreg[0].q == FUNC_LDOUBLE_RET); + } + else + abort (); + + assert (inregs->lr_vpcs == 0); + assert (outregs->lrv_vpcs == 0); + + /* Clobber the q registers on exit. */ + uint8_t v = 0xff; + asm volatile ("dup v0.8b, %w0" : : "r" (v) : "v0"); + asm volatile ("dup v1.8b, %w0" : : "r" (v) : "v1"); + asm volatile ("dup v2.8b, %w0" : : "r" (v) : "v2"); + asm volatile ("dup v3.8b, %w0" : : "r" (v) : "v3"); + asm volatile ("dup v4.8b, %w0" : : "r" (v) : "v4"); + asm volatile ("dup v5.8b, %w0" : : "r" (v) : "v5"); + asm volatile ("dup v6.8b, %w0" : : "r" (v) : "v6"); + asm volatile ("dup v7.8b, %w0" : : "r" (v) : "v7"); + + return 0; +} diff --git a/sysdeps/generic/dl-audit-check.h b/sysdeps/generic/dl-audit-check.h new file mode 100644 index 0000000000..f284382093 --- /dev/null +++ b/sysdeps/generic/dl-audit-check.h @@ -0,0 +1,23 @@ +/* rtld-audit version check. Generic 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 + . */ + +static inline bool +_dl_audit_check_version (unsigned int lav) +{ + return lav <= LAV_CURRENT; +}