From patchwork Thu Oct 14 17:47:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 46237 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 AF1593857C52 for ; Thu, 14 Oct 2021 17:58:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AF1593857C52 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1634234315; bh=TuWdNtVgNYJ2UHiGm8E10XhjCUPgUdCcGfxuSYYZynA=; 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=GoRLnFIQstxFsQYwOZ5AbDb0OAz85NHTR0NzeINmQPKw62DOO6efCO0de75nnyNPa MBkhYFGU4o2aOHGHy3OZdpNtDWAmiwve5JvQhrLit0gbD1g2UH3ti3LXCMikGpJ+G6 UUA/Z2umglEbVqb2M6aPouCXz7Qb/e9q+ZXJp9fo= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-ua1-x930.google.com (mail-ua1-x930.google.com [IPv6:2607:f8b0:4864:20::930]) by sourceware.org (Postfix) with ESMTPS id BD2EF385802D for ; Thu, 14 Oct 2021 17:48:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org BD2EF385802D Received: by mail-ua1-x930.google.com with SMTP id i15so13028969uap.0 for ; Thu, 14 Oct 2021 10:48:20 -0700 (PDT) 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=TuWdNtVgNYJ2UHiGm8E10XhjCUPgUdCcGfxuSYYZynA=; b=MgwIVl0UsNmJxij1xPXmYDV6aexKabMObeuDuZHo5At4vgcufk/ecMefbYEerBwiKw DQPq/sa9qzLL6PZa4wZgW132fx+LTe9ZWFAhCNstbCfJSHnJyAS5FHIivHap3TfivXmk 4NbDnnP7+On2dKjgReBRHz9E1xqocCGSaTBL3JaVH9iMsx1q9NSslUmRXJyJevoGf0b9 JTIUyr1l4T6pXMBBKwB4O379/dddCE8O9VqenhzWrbApbCej8eNlT5vVxUa+VT0n+GWp XPkyLa1x08oTPzHErcJmpdZlLDEMjJZZ94Nkea5zumBcUnBrdYAenwAnRs87w7Fe9FVq NoFg== X-Gm-Message-State: AOAM533UgdADALwcWLWT8kQTQo7FQCcRyReS3sghjxJ/oaCM+Yg9TRpa AMfENUMmw4a2QJFAAjUVltXZkBgy7ksh9w== X-Google-Smtp-Source: ABdhPJwHRk8ziyMxwGiovYD3VF5lvyWznVqRQi8OzqdAnBulCS2FVTg2NB7ITeV7Bx2KjLsn1/UU+g== X-Received: by 2002:a67:ee88:: with SMTP id n8mr8400521vsp.58.1634233700047; Thu, 14 Oct 2021 10:48:20 -0700 (PDT) Received: from birita.. ([2804:431:c7ca:c6c7:3c65:db0e:6fcc:a8e9]) by smtp.gmail.com with ESMTPSA id q26sm2107237vkn.40.2021.10.14.10.48.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Oct 2021 10:48:19 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v4 14/21] elf: Issue audit la_objopen() for vDSO Date: Thu, 14 Oct 2021 14:47:45 -0300 Message-Id: <20211014174752.1651347-15-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211014174752.1651347-1-adhemerval.zanella@linaro.org> References: <20211014174752.1651347-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Reply-To: Adhemerval Zanella Cc: John Mellor-Crummey Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" The vDSO is is listed in the link_map chain, but is never the subject of an la_objopen call. A new internal flag __RTLD_VDSO is added that acts as __RTLD_OPENEXEC to allocate the required 'struct auditstate' extra space for the 'struct link_map'. The return value from the callback() is currently ignored, since there is no PLT call involved by glibc when using the vDSO, neither the vDSO are exported directly. Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. --- elf/Makefile | 5 ++ elf/dl-object.c | 17 ++++--- elf/rtld.c | 7 +++ elf/setup-vdso.h | 2 +- elf/tst-audit22.c | 119 +++++++++++++++++++++++++++++++++++++++++++ elf/tst-auditmod22.c | 37 ++++++++++++++ include/dlfcn.h | 1 + 7 files changed, 180 insertions(+), 8 deletions(-) create mode 100644 elf/tst-audit22.c create mode 100644 elf/tst-auditmod22.c diff --git a/elf/Makefile b/elf/Makefile index bf18fbc2a4..3c3f5cd37a 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -225,6 +225,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-audit19 \ tst-audit20 \ tst-audit21 \ + tst-audit22 \ tst-single_threaded tst-single_threaded-pthread \ tst-tls-ie tst-tls-ie-dlmopen argv0test \ tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \ @@ -317,6 +318,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-auditmod19 \ tst-auditmod20 tst-audit20mod \ tst-auditmod21 \ + tst-auditmod22 \ $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \ tst-nodelete-uniquemod tst-nodelete-rtldmod \ tst-nodelete-zmod \ @@ -1546,6 +1548,9 @@ tst-audit20-ARGS = -- $(host-test-program-cmd) $(objpfx)tst-audit21.out: $(objpfx)tst-auditmod21.so tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21.so +$(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so +tst-audit22-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-object.c b/elf/dl-object.c index eb2158a84b..6f26da4310 100644 --- a/elf/dl-object.c +++ b/elf/dl-object.c @@ -59,16 +59,19 @@ _dl_new_object (char *realname, const char *libname, int type, { #ifdef SHARED unsigned int naudit; - if (__glibc_unlikely ((mode & __RTLD_OPENEXEC) != 0)) + if (__glibc_unlikely ((mode & (__RTLD_OPENEXEC | __RTLD_VDSO)) != 0)) { - assert (type == lt_executable); - assert (nsid == LM_ID_BASE); + if (mode & __RTLD_OPENEXEC) + { + assert (type == lt_executable); + assert (nsid == LM_ID_BASE); - /* Ignore the specified libname for the main executable. It is - only known with an explicit loader invocation. */ - libname = ""; + /* Ignore the specified libname for the main executable. It is + only known with an explicit loader invocation. */ + libname = ""; + } - /* We create the map for the executable before we know whether + /* We create the map for the executable and vDSO before we know whether we have auditing libraries and if yes, how many. Assume the worst. */ naudit = DL_NNS; diff --git a/elf/rtld.c b/elf/rtld.c index 13bb1ba4cd..7f559b1aa7 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1875,6 +1875,13 @@ dl_main (const ElfW(Phdr) *phdr, assert (i == npreloads); } +#ifdef NEED_DL_SYSINFO_DSO + /* Now that the audit modules are opened, call la_objopen() for the + vDSO. */ + if (GLRO(dl_sysinfo_map) != NULL) + _dl_audit_objopen (GLRO(dl_sysinfo_map), LM_ID_BASE, true); +#endif + /* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD specified some libraries to load, these are inserted before the actual dependencies in the executable's searchlist for symbol resolution. */ diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h index f44748bc98..9e5410d613 100644 --- a/elf/setup-vdso.h +++ b/elf/setup-vdso.h @@ -30,7 +30,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)), We just want our data structures to describe it as if we had just mapped and relocated it normally. */ struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL, - 0, LM_ID_BASE); + __RTLD_VDSO, LM_ID_BASE); if (__glibc_likely (l != NULL)) { l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso) diff --git a/elf/tst-audit22.c b/elf/tst-audit22.c new file mode 100644 index 0000000000..c1b301c4cc --- /dev/null +++ b/elf/tst-audit22.c @@ -0,0 +1,119 @@ +/* Check DTAUDIT and vDSO interaction. + 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 }, + +static uintptr_t vdso_addr; + +static int +handle_restart (void) +{ + fprintf (stderr, "vdso: %" PRIxPTR "\n", vdso_addr); + return 0; +} + +static unsigned long int +parse_address (const char *str) +{ + char *endptr; + long int ret; + errno = 0; + ret = strtol (str, &endptr, 10); + TEST_COMPARE (errno, 0); + TEST_VERIFY (ret >= 0 && ret <= INT_MAX); + return ret; +} + +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[]) +{ + vdso_addr = getauxval (AT_SYSINFO_EHDR); + if (vdso_addr == 0) + FAIL_UNSUPPORTED ("getauxval (AT_SYSINFO_EHDR) returned 0"); + + /* 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-auditmod22.so", 0); + struct support_capture_subprocess result + = support_capture_subprogram (spargv[0], spargv); + support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr); + + unsigned long vdso_process = 0; + unsigned long vdso_audit = 0; + + 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)) + { + if (startswith (buffer, "vdso: ")) + vdso_process = parse_address (buffer + strlen ("vdso: ")); + else if (startswith (buffer, "vdso found: ")) + vdso_audit = parse_address (buffer + strlen ("vdso found: ")); + } + + TEST_COMPARE (vdso_process, vdso_audit); + + free (buffer); + xfclose (out); + + return 0; +} + +#define TEST_FUNCTION_ARGV do_test +#include diff --git a/elf/tst-auditmod22.c b/elf/tst-auditmod22.c new file mode 100644 index 0000000000..02275bed57 --- /dev/null +++ b/elf/tst-auditmod22.c @@ -0,0 +1,37 @@ +/* Check DTAUDIT and vDSO interaction. + 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 + +unsigned int +la_version (unsigned int version) +{ + return LAV_CURRENT; +} + +unsigned int +la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) +{ + if (map->l_addr == getauxval (AT_SYSINFO_EHDR)) + fprintf (stderr, "vdso found: %" PRIxPTR "\n", (uintptr_t) map->l_addr); + + return 0; +} diff --git a/include/dlfcn.h b/include/dlfcn.h index a4c283728f..66bcf2dff9 100644 --- a/include/dlfcn.h +++ b/include/dlfcn.h @@ -12,6 +12,7 @@ #define __RTLD_AUDIT 0x08000000 #define __RTLD_SECURE 0x04000000 /* Apply additional security checks. */ #define __RTLD_NOIFUNC 0x02000000 /* Suppress calling ifunc functions. */ +#define __RTLD_VDSO 0x01000000 #define __LM_ID_CALLER -2