From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1039) id 0E9F73858C2A; Mon, 11 Dec 2023 19:06:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0E9F73858C2A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1702321566; bh=et6aol1tcsDgimM4Br7iExjWA+XeR8t93DFkzPy0xQ0=; h=From:To:Subject:Date:From; b=YX5dArltkhkg9Dqh3AtvNigHBu/pMH1zCrsdoBPUPcApkRHY+TNbKFXU1p6URPpak Kqbd+3bDFtNk4xFsKJEjyBSSih8MtTKOJXJowsClvtbEOMVvXaM1i+ze7/LK7LnTtN stTiM3P5ZbL5GFPItKto/RoIzDEE4RWXi5WI1N3Y= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: H.J. Lu To: glibc-cvs@sourceware.org Subject: [glibc] x86: Check PT_GNU_PROPERTY early X-Act-Checkin: glibc X-Git-Author: H.J. Lu X-Git-Refname: refs/heads/master X-Git-Oldrev: 7e03e0de7e7c2de975b5c5e18f5a4b0c75816674 X-Git-Newrev: 4753e9286858a61d5fbe8742d48d8c9166143354 Message-Id: <20231211190606.0E9F73858C2A@sourceware.org> Date: Mon, 11 Dec 2023 19:06:06 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=4753e9286858a61d5fbe8742d48d8c9166143354 commit 4753e9286858a61d5fbe8742d48d8c9166143354 Author: H.J. Lu Date: Thu Dec 7 13:05:39 2023 -0800 x86: Check PT_GNU_PROPERTY early The PT_GNU_PROPERTY segment is scanned before PT_NOTE. For binaries with the PT_GNU_PROPERTY segment, we can check it to avoid scan of the PT_NOTE segment. Reviewed-by: Noah Goldstein Diff: --- sysdeps/x86/dl-prop.h | 120 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 80 insertions(+), 40 deletions(-) diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h index b2836f3009..d2c53c2182 100644 --- a/sysdeps/x86/dl-prop.h +++ b/sysdeps/x86/dl-prop.h @@ -81,6 +81,60 @@ _dl_open_check (struct link_map *m) #endif } +/* Check the GNU property and return its value. It returns: + -1: Skip this note. + 0: Stop checking. + 1: Continue to check. + */ +static inline int +_dl_check_gnu_property (unsigned int type, unsigned int datasz, + void *ptr, unsigned int *feature_1_and, + unsigned int *needed_1, + unsigned int *isa_1_needed) +{ + if (type == GNU_PROPERTY_X86_FEATURE_1_AND + || type == GNU_PROPERTY_X86_ISA_1_NEEDED + || type == GNU_PROPERTY_1_NEEDED) + { + /* The sizes of types which we are searching for are + 4 bytes. There is no point to continue if this + note is ill-formed. */ + if (datasz != 4) + return -1; + + /* NB: Stop the scan only after seeing all types which + we are searching for. */ + _Static_assert (((GNU_PROPERTY_X86_ISA_1_NEEDED + > GNU_PROPERTY_X86_FEATURE_1_AND) + && (GNU_PROPERTY_X86_FEATURE_1_AND + > GNU_PROPERTY_1_NEEDED)), + "GNU_PROPERTY_X86_ISA_1_NEEDED > " + "GNU_PROPERTY_X86_FEATURE_1_AND && " + "GNU_PROPERTY_X86_FEATURE_1_AND > " + "GNU_PROPERTY_1_NEEDED"); + if (type == GNU_PROPERTY_X86_FEATURE_1_AND) + *feature_1_and = *(unsigned int *) ptr; + else if (type == GNU_PROPERTY_1_NEEDED) + *needed_1 = *(unsigned int *) ptr; + else + { + *isa_1_needed = *(unsigned int *) ptr; + + /* Keep searching for the next GNU property note + generated by the older linker. */ + return 0; + } + } + else if (type > GNU_PROPERTY_X86_ISA_1_NEEDED) + { + /* Stop the scan since property type is in ascending + order. */ + return 0; + } + + return 1; +} + static inline void __attribute__ ((unused)) _dl_process_property_note (struct link_map *l, const ElfW(Nhdr) *note, const ElfW(Addr) size, const ElfW(Addr) align) @@ -141,45 +195,14 @@ _dl_process_property_note (struct link_map *l, const ElfW(Nhdr) *note, last_type = type; - if (type == GNU_PROPERTY_X86_FEATURE_1_AND - || type == GNU_PROPERTY_X86_ISA_1_NEEDED - || type == GNU_PROPERTY_1_NEEDED) - { - /* The sizes of types which we are searching for are - 4 bytes. There is no point to continue if this - note is ill-formed. */ - if (datasz != 4) - return; - - /* NB: Stop the scan only after seeing all types which - we are searching for. */ - _Static_assert (((GNU_PROPERTY_X86_ISA_1_NEEDED - > GNU_PROPERTY_X86_FEATURE_1_AND) - && (GNU_PROPERTY_X86_FEATURE_1_AND - > GNU_PROPERTY_1_NEEDED)), - "GNU_PROPERTY_X86_ISA_1_NEEDED > " - "GNU_PROPERTY_X86_FEATURE_1_AND && " - "GNU_PROPERTY_X86_FEATURE_1_AND > " - "GNU_PROPERTY_1_NEEDED"); - if (type == GNU_PROPERTY_X86_FEATURE_1_AND) - feature_1_and = *(unsigned int *) ptr; - else if (type == GNU_PROPERTY_1_NEEDED) - needed_1 = *(unsigned int *) ptr; - else - { - isa_1_needed = *(unsigned int *) ptr; - - /* Keep searching for the next GNU property note - generated by the older linker. */ - break; - } - } - else if (type > GNU_PROPERTY_X86_ISA_1_NEEDED) - { - /* Stop the scan since property type is in ascending - order. */ - break; - } + int result = _dl_check_gnu_property (type, datasz, ptr, + &feature_1_and, + &needed_1, + &isa_1_needed); + if (result == -1) + return; /* Skip this note. */ + else if (result == 0) + break; /* Stop checking. */ /* Check the next property item. */ ptr += ALIGN_UP (datasz, sizeof (ElfW(Addr))); @@ -217,7 +240,24 @@ static inline int __attribute__ ((always_inline)) _dl_process_gnu_property (struct link_map *l, int fd, uint32_t type, uint32_t datasz, void *data) { - return 0; + /* This is called on each GNU property. */ + unsigned int needed_1 = 0; + unsigned int feature_1_and = 0; + unsigned int isa_1_needed = 0; + int result = _dl_check_gnu_property (type, datasz, data, + &feature_1_and, &needed_1, + &isa_1_needed); + if (needed_1 != 0) + l->l_1_needed = needed_1; + if (isa_1_needed != 0) + l->l_x86_isa_1_needed = isa_1_needed; + if (feature_1_and != 0) + l->l_x86_feature_1_and = feature_1_and; + if ((needed_1 | isa_1_needed | feature_1_and) != 0) + l->l_property = lc_property_valid; + else if (l->l_property == lc_property_unknown) + l->l_property = lc_property_none; + return result <= 0 ? 0 : result; } #endif /* _DL_PROP_H */