From patchwork Thu Apr 14 23:21:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 52946 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 E9F21385737E for ; Thu, 14 Apr 2022 23:21:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E9F21385737E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1649978515; bh=7oxVsR2USvnvkZWtKxCjWsipqeXw67r/PgvBokBUWlI=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Zkriag4B2upHW0lfpA7J8EttWKI8VQRwoU5kYqSSCzhhXyQkrC8h5BsdlxPkTU4Vy 6tIYKyPVmqJF6zXvOcXN+syPNO517Tbyg293kNFmapasjt0ScjRuwoRyAXYDPPiIBo +b4n4HPrl5psjuiEJtgJBfcGNUJAbLbvAIBp+YqU= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pl1-x633.google.com (mail-pl1-x633.google.com [IPv6:2607:f8b0:4864:20::633]) by sourceware.org (Postfix) with ESMTPS id 3A01D385803E for ; Thu, 14 Apr 2022 23:21:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3A01D385803E Received: by mail-pl1-x633.google.com with SMTP id s14so5910155plk.8 for ; Thu, 14 Apr 2022 16:21:32 -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=7oxVsR2USvnvkZWtKxCjWsipqeXw67r/PgvBokBUWlI=; b=EYWNARsTvAXDV/DJ6ZH3JAJptmqZBOjTcM47KMzlhP4wR6H4MOx9ylaKtaYgWnfAZv rvi4ys3S1KqEFcGeDM4agDl0GG2wKC/H0A92Ad/VZEC2ippKll71yFZx3N71QrVy14Fx Ihsbs1AuGQya8BQqCM3B3yDXP9GkAleXJjXj2UI238dtrYRbpAeqdgf3w+9fEIULoVGB unVtSd8vNhi0KQ7gcH5KDGprBRGEu8wy5aQlqGPvuKS0Ky5m0MLhMDUKXgB3wniAxb2I xt0Leb4U6uA93CTeyGJmoNdRCcmbibBRyxSQO3NZ42LZitaZzgBq+AQf4OfZPXkPKkFK IugA== X-Gm-Message-State: AOAM531DjxJqAlJjWU/za+KNkozApK2hotBlDhJZ2tj8Qtgu2aw0CoF1 2eC0uK3pIJWfiVNAwVOCQ8c= X-Google-Smtp-Source: ABdhPJxO7gDRPR4yJ14PzbUajOEE7GZY6mnzcMb/TikqqZhQLFeGKsfm/Mcqy5Ym1gk4KHM4Z3/a4A== X-Received: by 2002:a17:90b:314b:b0:1cd:5ffc:ca95 with SMTP id ip11-20020a17090b314b00b001cd5ffcca95mr1020007pjb.148.1649978491229; Thu, 14 Apr 2022 16:21:31 -0700 (PDT) Received: from gnu-tgl-3.localdomain ([172.58.36.153]) by smtp.gmail.com with ESMTPSA id s20-20020aa78d54000000b004fac74c83b3sm869923pfe.186.2022.04.14.16.21.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Apr 2022 16:21:30 -0700 (PDT) Received: from gnu-tgl-3.. (localhost [IPv6:::1]) by gnu-tgl-3.localdomain (Postfix) with ESMTP id CC67CC0421; Thu, 14 Apr 2022 16:21:29 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v10 2/7] Add GLIBC_ABI_DT_RELR for DT_RELR support Date: Thu, 14 Apr 2022 16:21:24 -0700 Message-Id: <20220414232129.1886210-3-hjl.tools@gmail.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220414232129.1886210-1-hjl.tools@gmail.com> References: <20220414232129.1886210-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3027.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, 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: "H.J. Lu via Libc-alpha" From: "H.J. Lu" Reply-To: "H.J. Lu" Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" The EI_ABIVERSION field of the ELF header in executables and shared libraries can be bumped to indicate the minimum ABI requirement on the dynamic linker. However, EI_ABIVERSION in executables isn't checked by the Linux kernel ELF loader nor the existing dynamic linker. Executables will crash mysteriously if the dynamic linker doesn't support the ABI features required by the EI_ABIVERSION field. The dynamic linker should be changed to check EI_ABIVERSION in executables. Add a glibc version, GLIBC_ABI_DT_RELR, to indicate DT_RELR support so that the existing dynamic linkers will issue an error on executables with GLIBC_ABI_DT_RELR dependency. When there is a DT_VERNEED entry with libc.so on DT_NEEDED, issue an error if there is a DT_RELR entry without GLIBC_ABI_DT_RELR dependency. Support __placeholder_only_for_empty_version_map as the placeholder symbol used only for empty version map to generate GLIBC_ABI_DT_RELR without any symbols. Reviewed-by: Adhemerval Zanella --- elf/Makefile | 14 ++++++++++++-- elf/Versions | 5 +++++ elf/dl-version.c | 35 +++++++++++++++++++++++++++++++++-- include/link.h | 2 ++ scripts/abilist.awk | 2 ++ scripts/versions.awk | 7 ++++++- 6 files changed, 60 insertions(+), 5 deletions(-) diff --git a/elf/Makefile b/elf/Makefile index d30d0ee917..ee8778c3a2 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -1110,8 +1110,12 @@ $(eval $(call include_dsosort_tests,dso-sort-tests-1.def)) $(eval $(call include_dsosort_tests,dso-sort-tests-2.def)) endif -check-abi: $(objpfx)check-abi-ld.out -tests-special += $(objpfx)check-abi-ld.out +check-abi: $(objpfx)check-abi-ld.out \ + $(objpfx)check-abi-version-libc.out +tests-special += \ + $(objpfx)check-abi-ld.out \ + $(objpfx)check-abi-version-libc.out \ +# tests-special update-abi: update-abi-ld update-all-abi: update-all-abi-ld @@ -2733,3 +2737,9 @@ $(objpfx)tst-p_align3: $(objpfx)tst-p_alignmod3.so $(objpfx)tst-p_align3.out: tst-p_align3.sh $(objpfx)tst-p_align3 $(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \ $(evaluate-test) + +$(objpfx)check-abi-version-libc.out: $(common-objpfx)libc.so + LC_ALL=C $(READELF) -V -W $< \ + | sed -ne '/.gnu.version_d/, /.gnu.version_r/ p' \ + | grep GLIBC_ABI_DT_RELR > $@; \ + $(evaluate-test) diff --git a/elf/Versions b/elf/Versions index 8bed855d8c..a9ff278de7 100644 --- a/elf/Versions +++ b/elf/Versions @@ -23,6 +23,11 @@ libc { GLIBC_2.35 { _dl_find_object; } + GLIBC_ABI_DT_RELR { + # This symbol is used only for empty version map and will be removed + # by scripts/versions.awk. + __placeholder_only_for_empty_version_map; + } GLIBC_PRIVATE { # functions used in other libraries __libc_early_init; diff --git a/elf/dl-version.c b/elf/dl-version.c index b47bd91727..cda0889209 100644 --- a/elf/dl-version.c +++ b/elf/dl-version.c @@ -214,12 +214,19 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode) while (1) { /* Match the symbol. */ + const char *string = strtab + aux->vna_name; result |= match_symbol (DSO_FILENAME (map->l_name), map->l_ns, aux->vna_hash, - strtab + aux->vna_name, - needed->l_real, verbose, + string, needed->l_real, verbose, aux->vna_flags & VER_FLG_WEAK); + /* 0xfd0e42: _dl_elf_hash ("GLIBC_ABI_DT_RELR"). */ + if (aux->vna_hash == 0xfd0e42 + && __glibc_likely (strcmp (string, + "GLIBC_ABI_DT_RELR") + == 0)) + map->l_dt_relr_ref = 1; + /* Compare the version index. */ if ((unsigned int) (aux->vna_other & 0x7fff) > ndx_high) ndx_high = aux->vna_other & 0x7fff; @@ -352,6 +359,30 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode) } } + /* When there is a DT_VERNEED entry with libc.so on DT_NEEDED, issue + an error if there is a DT_RELR entry without GLIBC_ABI_DT_RELR + dependency. */ + if (dyn != NULL + && map->l_info[DT_NEEDED] != NULL + && map->l_info[DT_RELR] != NULL + && __glibc_unlikely (!map->l_dt_relr_ref)) + { + const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); + const ElfW(Dyn) *d; + for (d = map->l_ld; d->d_tag != DT_NULL; ++d) + if (d->d_tag == DT_NEEDED) + { + const char *name = strtab + d->d_un.d_val; + if (strncmp (name, "libc.so.", 8) == 0) + { + _dl_exception_create + (&exception, DSO_FILENAME (map->l_name), + N_("DT_RELR without GLIBC_ABI_DT_RELR dependency")); + goto call_error; + } + } + } + return result; } diff --git a/include/link.h b/include/link.h index 03db14c7b0..0ac82d7c77 100644 --- a/include/link.h +++ b/include/link.h @@ -177,6 +177,8 @@ struct link_map lt_library, /* Library needed by main executable. */ lt_loaded /* Extra run-time loaded shared object. */ } l_type:2; + unsigned int l_dt_relr_ref:1; /* Nonzero if GLIBC_ABI_DT_RELR is + referenced. */ unsigned int l_relocated:1; /* Nonzero if object's relocations done. */ unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */ unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */ diff --git a/scripts/abilist.awk b/scripts/abilist.awk index 24a34ccbed..6cc7af6ac8 100644 --- a/scripts/abilist.awk +++ b/scripts/abilist.awk @@ -55,6 +55,8 @@ $2 == "g" || $2 == "w" && (NF == 7 || NF == 8) { # caused STV_HIDDEN symbols to appear in .dynsym, though that is useless. if (NF > 7 && $7 == ".hidden") next; + if (version ~ /^GLIBC_ABI_/ && !include_abi_version) next; + if (version == "GLIBC_PRIVATE" && !include_private) next; desc = ""; diff --git a/scripts/versions.awk b/scripts/versions.awk index 357ad1355e..d70b07bd1a 100644 --- a/scripts/versions.awk +++ b/scripts/versions.awk @@ -185,8 +185,13 @@ END { closeversion(oldver, veryoldver); veryoldver = oldver; } - printf("%s {\n global:\n", $2) > outfile; oldver = $2; + # Skip the placeholder symbol used only for empty version map. + if ($3 == "__placeholder_only_for_empty_version_map;") { + printf("%s {\n", $2) > outfile; + continue; + } + printf("%s {\n global:\n", $2) > outfile; } printf(" ") > outfile; for (n = 3; n <= NF; ++n) {