From 9f81ddd80e05edbb08854c6cb6908fc8c039744f Mon Sep 17 00:00:00 2001 From: huyubiao Date: Fri, 11 Jul 2025 10:53:22 +0800 Subject: [PATCH] Fix leaks and instruction-related issues in aarch64 and x86 --- ...void-BTI-stub-for-a-PLT-that-has-BTI.patch | 74 +++++++++++++++ ...64-Fix-BTI-stub-optimization-PR30957.patch | 57 ++++++++++++ ...-aarch64-Fix-broken-BTI-stub-PR30930.patch | 91 +++++++++++++++++++ ...-Fix-leaks-in-case-of-BTI-stub-reuse.patch | 87 ++++++++++++++++++ ...eak-of-names-of-newly-inserted-non-r.patch | 47 ++++++++++ ...x-suffix-less-PUSH-of-symbol-address.patch | 74 +++++++++++++++ ...for-call-and-jmp-in-binutils-older-t.patch | 89 ++++++++++++++++++ ...t-prefix-use-with-.insn-VEX-XOP-EVEX.patch | 47 ++++++++++ binutils.spec | 22 ++++- 9 files changed, 587 insertions(+), 1 deletion(-) create mode 100644 backport-bfd-aarch64-Avoid-BTI-stub-for-a-PLT-that-has-BTI.patch create mode 100644 backport-bfd-aarch64-Fix-BTI-stub-optimization-PR30957.patch create mode 100644 backport-bfd-aarch64-Fix-broken-BTI-stub-PR30930.patch create mode 100644 backport-bfd-aarch64-Fix-leaks-in-case-of-BTI-stub-reuse.patch create mode 100644 backport-libctf-fix-ref-leak-of-names-of-newly-inserted-non-r.patch create mode 100644 backport-x86-64-fix-suffix-less-PUSH-of-symbol-address.patch create mode 100644 backport-x86-Check-MODRM-for-call-and-jmp-in-binutils-older-t.patch create mode 100644 backport-x86-restrict-prefix-use-with-.insn-VEX-XOP-EVEX.patch diff --git a/backport-bfd-aarch64-Avoid-BTI-stub-for-a-PLT-that-has-BTI.patch b/backport-bfd-aarch64-Avoid-BTI-stub-for-a-PLT-that-has-BTI.patch new file mode 100644 index 0000000..05da24d --- /dev/null +++ b/backport-bfd-aarch64-Avoid-BTI-stub-for-a-PLT-that-has-BTI.patch @@ -0,0 +1,74 @@ +From 0c0527d30bcb168691faa7a611a54cf68d1d1770 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy +Date: Wed, 18 Oct 2023 16:12:56 +0100 +Subject: [PATCH] bfd: aarch64: Avoid BTI stub for a PLT that has BTI + +We decide to emit BTI stubs based on the instruction at the target +location. But PLT code is generated later than the stubs so we always +read 0 which is not a valid BTI. + +Fix the logic to special case the PLT section: this is code the linker +generates so we know when it will have BTI. + +This avoids BTI stubs in large executables where the PLTs have them +already. An alternative is to never emit BTI stubs for PLTs, instead +use BTI in the PLT if a library gets too big, however that may be +more tricky given the ordering of PLT sizing and stub insertion. + +Related to bug 30957. + +(cherry picked from commit fc48504c7abe8eb9d9723632b2d53504927f46ff) +--- + bfd/elfnn-aarch64.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c +index 3adece302..4faf642b4 100644 +--- a/bfd/elfnn-aarch64.c ++++ b/bfd/elfnn-aarch64.c +@@ -3675,7 +3675,8 @@ group_sections (struct elf_aarch64_link_hash_table *htab, + /* True if the inserted stub does not break BTI compatibility. */ + + static bool +-aarch64_bti_stub_p (struct elf_aarch64_stub_hash_entry *stub_entry) ++aarch64_bti_stub_p (struct bfd_link_info *info, ++ struct elf_aarch64_stub_hash_entry *stub_entry) + { + /* Stubs without indirect branch are BTI compatible. */ + if (stub_entry->stub_type != aarch64_stub_adrp_branch +@@ -3684,12 +3685,22 @@ aarch64_bti_stub_p (struct elf_aarch64_stub_hash_entry *stub_entry) + + /* Return true if the target instruction is compatible with BR x16. */ + ++ struct elf_aarch64_link_hash_table *globals = elf_aarch64_hash_table (info); + asection *section = stub_entry->target_section; + bfd_byte loc[4]; + file_ptr off = stub_entry->target_value; + bfd_size_type count = sizeof (loc); + +- if (!bfd_get_section_contents (section->owner, section, loc, off, count)) ++ /* PLT code is not generated yet, so treat it specially. ++ Note: Checking elf_aarch64_obj_tdata.plt_type & PLT_BTI is not ++ enough because it only implies BTI in the PLT0 and tlsdesc PLT ++ entries. Normal PLT entries don't have BTI in a shared library ++ (because such PLT is normally not called indirectly and adding ++ the BTI when a stub targets a PLT would change the PLT layout ++ and it's too late for that here). */ ++ if (section == globals->root.splt) ++ memcpy (loc, globals->plt_entry, count); ++ else if (!bfd_get_section_contents (section->owner, section, loc, off, count)) + return false; + + uint32_t insn = bfd_getl32 (loc); +@@ -4636,7 +4647,7 @@ _bfd_aarch64_add_call_stub_entries (bool *stub_changed, bfd *output_bfd, + + /* A stub with indirect jump may break BTI compatibility, so + insert another stub with direct jump near the target then. */ +- if (need_bti && !aarch64_bti_stub_p (stub_entry)) ++ if (need_bti && !aarch64_bti_stub_p (info, stub_entry)) + { + id_sec_bti = htab->stub_group[sym_sec->id].link_sec; + +-- +2.43.0 + diff --git a/backport-bfd-aarch64-Fix-BTI-stub-optimization-PR30957.patch b/backport-bfd-aarch64-Fix-BTI-stub-optimization-PR30957.patch new file mode 100644 index 0000000..0119485 --- /dev/null +++ b/backport-bfd-aarch64-Fix-BTI-stub-optimization-PR30957.patch @@ -0,0 +1,57 @@ +From 8b9de994244a85f6d87564a798e00d5acefa75b7 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy +Date: Fri, 13 Oct 2023 17:51:15 +0100 +Subject: [PATCH] bfd: aarch64: Fix BTI stub optimization PR30957 + +The instruction was looked up in the wrong input file (file of branch +source instead of branch target) when optimizing away BTI stubs in + + commit 5834f36d93cabf1a8bcc7dd7654141aed3d296bc + bfd: aarch64: Optimize BTI stubs PR30076 + +This can cause adding BTI stubs when they are not necessary or removing +them when they are (the latter is a correctness issue but it is very +unlikely in practice). + +Fixes bug 30957. + +(cherry picked from commit 98b94ebb3ffe715fddde762bb3ee7fd6d972f233) +--- + bfd/elfnn-aarch64.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c +index 4592bd6da..a0dd17faa 100644 +--- a/bfd/elfnn-aarch64.c ++++ b/bfd/elfnn-aarch64.c +@@ -3675,8 +3675,7 @@ group_sections (struct elf_aarch64_link_hash_table *htab, + /* True if the inserted stub does not break BTI compatibility. */ + + static bool +-aarch64_bti_stub_p (bfd *input_bfd, +- struct elf_aarch64_stub_hash_entry *stub_entry) ++aarch64_bti_stub_p (struct elf_aarch64_stub_hash_entry *stub_entry) + { + /* Stubs without indirect branch are BTI compatible. */ + if (stub_entry->stub_type != aarch64_stub_adrp_branch +@@ -3690,7 +3689,7 @@ aarch64_bti_stub_p (bfd *input_bfd, + file_ptr off = stub_entry->target_value; + bfd_size_type count = sizeof (loc); + +- if (!bfd_get_section_contents (input_bfd, section, loc, off, count)) ++ if (!bfd_get_section_contents (section->owner, section, loc, off, count)) + return false; + + uint32_t insn = bfd_getl32 (loc); +@@ -4637,7 +4636,7 @@ _bfd_aarch64_add_call_stub_entries (bool *stub_changed, bfd *output_bfd, + + /* A stub with indirect jump may break BTI compatibility, so + insert another stub with direct jump near the target then. */ +- if (need_bti && !aarch64_bti_stub_p (input_bfd, stub_entry)) ++ if (need_bti && !aarch64_bti_stub_p (stub_entry)) + { + stub_entry->double_stub = true; + htab->has_double_stub = true; +-- +2.43.0 + diff --git a/backport-bfd-aarch64-Fix-broken-BTI-stub-PR30930.patch b/backport-bfd-aarch64-Fix-broken-BTI-stub-PR30930.patch new file mode 100644 index 0000000..8508abd --- /dev/null +++ b/backport-bfd-aarch64-Fix-broken-BTI-stub-PR30930.patch @@ -0,0 +1,91 @@ +From d00636070750a9be57eb5a24aca75a06efa93140 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy +Date: Mon, 16 Oct 2023 13:18:13 +0100 +Subject: [PATCH] bfd: aarch64: Fix broken BTI stub PR30930 + +Input sections are grouped together that can use the same stub area +(within reach) and these groups have a stable id. + +Stubs have a name generated from the stub group id and target symbol. +When a relocation requires a stub with a name that already exists, the +stub is reused instead of adding a new one. + +For an indirect branch stub another BTI stub may be inserted near the +target to provide a BTI landing pad. + +The BTI stub can end up with the same stub group id and thus the same +name as the indirect stub. This happens if the target symbol is within +reach of the indirect branch stub. Then, due to the name collision, +only a single stub was emmitted which branched to itself causing an +infinite loop at runtime. + +A possible solution is to just name the BTI stubs differently, but +since in the problematic case the indirect and BTI stub are in the +same stub area, a better solution is to emit a single stub with a +direct branch. The stub is still needed since the caller cannot reach +the target directly and we also want a BTI landing pad in the stub in +case other indirect stubs target the same symbol and thus need a BTI +stub. + +In short we convert an indirect branch stub into a BTI stub when the +target is within reach and has no BTI. It is a hassle to change the +symbol of the stub so a BTI stub may end up with *_veneer instead of +*_bti_veneer after the conversion, but this should not matter much. +(Refactoring some of _bfd_aarch64_add_call_stub_entries would be +useful but too much for this bug fix patch.) + +The same conversion to direct branch could be done even if the target +did not need a BTI. The stub groups are fixed in the current logic so +linking can fail if too many stubs are inserted and the section layout +is changed too much, but this only happens in extreme cases that can +be reasonably ignored. Because of this the target cannot go out of +reach during stub insertion so the optimization is valid, but not +implemented by this patch for the non-BTI case. + +Fixes bug 30930. + +(cherry picked from commit d3a8dfdef0797244d0f2f3a8ec5db8f1dcf1337b) +--- + bfd/elfnn-aarch64.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c +index a0dd17faa..798643ade 100644 +--- a/bfd/elfnn-aarch64.c ++++ b/bfd/elfnn-aarch64.c +@@ -4638,9 +4638,22 @@ _bfd_aarch64_add_call_stub_entries (bool *stub_changed, bfd *output_bfd, + insert another stub with direct jump near the target then. */ + if (need_bti && !aarch64_bti_stub_p (stub_entry)) + { ++ id_sec_bti = htab->stub_group[sym_sec->id].link_sec; ++ ++ /* If the stub with indirect jump and the BTI stub are in ++ the same stub group: change the indirect jump stub into ++ a BTI stub since a direct branch can reach the target. ++ The BTI landing pad is still needed in case another ++ stub indirectly jumps to it. */ ++ if (id_sec_bti == id_sec) ++ { ++ stub_entry->stub_type = aarch64_stub_bti_direct_branch; ++ goto skip_double_stub; ++ } ++ + stub_entry->double_stub = true; + htab->has_double_stub = true; +- id_sec_bti = htab->stub_group[sym_sec->id].link_sec; ++ + stub_name_bti = + elfNN_aarch64_stub_name (id_sec_bti, sym_sec, hash, irela); + if (!stub_name_bti) +@@ -4687,7 +4700,7 @@ _bfd_aarch64_add_call_stub_entries (bool *stub_changed, bfd *output_bfd, + stub_entry->h = NULL; + stub_entry->st_type = STT_FUNC; + } +- ++skip_double_stub: + *stub_changed = true; + } + +-- +2.43.0 + diff --git a/backport-bfd-aarch64-Fix-leaks-in-case-of-BTI-stub-reuse.patch b/backport-bfd-aarch64-Fix-leaks-in-case-of-BTI-stub-reuse.patch new file mode 100644 index 0000000..fcd526b --- /dev/null +++ b/backport-bfd-aarch64-Fix-leaks-in-case-of-BTI-stub-reuse.patch @@ -0,0 +1,87 @@ +From 95a26c1f3de31f82162dda78e571cf0e58d11833 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy +Date: Tue, 17 Oct 2023 14:13:00 +0100 +Subject: [PATCH] bfd: aarch64: Fix leaks in case of BTI stub reuse + +BTI stub parameters were recomputed even if those were already set up. +This is unnecessary work and leaks the symbol name that is allocated +for the stub. + +(cherry picked from commit a74ac8c41971682f687a8a5ce94f36a8054ecd0e) +--- + bfd/elfnn-aarch64.c | 56 ++++++++++++++++++++++++++------------------- + 1 file changed, 32 insertions(+), 24 deletions(-) + +diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c +index 798643ade..3adece302 100644 +--- a/bfd/elfnn-aarch64.c ++++ b/bfd/elfnn-aarch64.c +@@ -4665,33 +4665,41 @@ _bfd_aarch64_add_call_stub_entries (bool *stub_changed, bfd *output_bfd, + stub_entry_bti = + aarch64_stub_hash_lookup (&htab->stub_hash_table, + stub_name_bti, false, false); +- if (stub_entry_bti == NULL) +- stub_entry_bti = +- _bfd_aarch64_add_stub_entry_in_group (stub_name_bti, +- sym_sec, htab); +- if (stub_entry_bti == NULL) ++ if (stub_entry_bti != NULL) ++ BFD_ASSERT (stub_entry_bti->stub_type ++ == aarch64_stub_bti_direct_branch); ++ else + { +- free (stub_name); +- free (stub_name_bti); +- goto error_ret_free_internal; +- } +- +- stub_entry_bti->target_value = sym_value + irela->r_addend; +- stub_entry_bti->target_section = sym_sec; +- stub_entry_bti->stub_type = aarch64_stub_bti_direct_branch; +- stub_entry_bti->h = hash; +- stub_entry_bti->st_type = st_type; ++ stub_entry_bti = ++ _bfd_aarch64_add_stub_entry_in_group (stub_name_bti, ++ sym_sec, htab); ++ if (stub_entry_bti == NULL) ++ { ++ free (stub_name); ++ free (stub_name_bti); ++ goto error_ret_free_internal; ++ } + +- len = sizeof (BTI_STUB_ENTRY_NAME) + strlen (sym_name); +- stub_entry_bti->output_name = bfd_alloc (htab->stub_bfd, len); +- if (stub_entry_bti->output_name == NULL) +- { +- free (stub_name); +- free (stub_name_bti); +- goto error_ret_free_internal; ++ stub_entry_bti->target_value = ++ sym_value + irela->r_addend; ++ stub_entry_bti->target_section = sym_sec; ++ stub_entry_bti->stub_type = ++ aarch64_stub_bti_direct_branch; ++ stub_entry_bti->h = hash; ++ stub_entry_bti->st_type = st_type; ++ ++ len = sizeof (BTI_STUB_ENTRY_NAME) + strlen (sym_name); ++ stub_entry_bti->output_name = bfd_alloc (htab->stub_bfd, ++ len); ++ if (stub_entry_bti->output_name == NULL) ++ { ++ free (stub_name); ++ free (stub_name_bti); ++ goto error_ret_free_internal; ++ } ++ snprintf (stub_entry_bti->output_name, len, ++ BTI_STUB_ENTRY_NAME, sym_name); + } +- snprintf (stub_entry_bti->output_name, len, +- BTI_STUB_ENTRY_NAME, sym_name); + + /* Update the indirect call stub to target the BTI stub. */ + stub_entry->target_value = 0; +-- +2.43.0 + diff --git a/backport-libctf-fix-ref-leak-of-names-of-newly-inserted-non-r.patch b/backport-libctf-fix-ref-leak-of-names-of-newly-inserted-non-r.patch new file mode 100644 index 0000000..3b92907 --- /dev/null +++ b/backport-libctf-fix-ref-leak-of-names-of-newly-inserted-non-r.patch @@ -0,0 +1,47 @@ +From 682c71f4bbbe5dc25a0b9825879be796d7e7d279 Mon Sep 17 00:00:00 2001 +From: Nick Alcock +Date: Mon, 29 Jul 2024 12:45:09 +0100 +Subject: [PATCH] libctf: fix ref leak of names of newly-inserted + non-root-visible types + +A bug in ctf_dtd_delete led to refs in the string table to the +names of non-root-visible types not being removed when the DTD +was. This seems harmless, but actually it would lead to a write +down a pointer into freed memory if such a type was ctf_rollback()ed +over and then the dict was serialized (updating all the refs as the +strtab was serialized in turn). + +Bug introduced in commit fe4c2d55634c700ba527ac4183e05c66e9f93c62 +("libctf: create: non-root-visible types should not appear in name tables") +which is included in binutils 2.35. + +libctf/ + * ctf-create.c (ctf_dtd_delete): Remove refs for all types + with names, not just root-visible ones. +--- + libctf/ctf-create.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c +index 6b342dc64..2ddb3acb5 100644 +--- a/libctf/ctf-create.c ++++ b/libctf/ctf-create.c +@@ -288,11 +288,11 @@ ctf_dtd_delete (ctf_dict_t *fp, ctf_dtdef_t *dtd) + dtd->dtd_vlen_alloc = 0; + + if (dtd->dtd_data.ctt_name +- && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL +- && LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info)) ++ && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL) + { +- ctf_dynhash_remove (ctf_name_table (fp, name_kind)->ctn_writable, +- name); ++ if (LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info)) ++ ctf_dynhash_remove (ctf_name_table (fp, name_kind)->ctn_writable, ++ name); + ctf_str_remove_ref (fp, name, &dtd->dtd_data.ctt_name); + } + +-- +2.43.0 + diff --git a/backport-x86-64-fix-suffix-less-PUSH-of-symbol-address.patch b/backport-x86-64-fix-suffix-less-PUSH-of-symbol-address.patch new file mode 100644 index 0000000..31e0418 --- /dev/null +++ b/backport-x86-64-fix-suffix-less-PUSH-of-symbol-address.patch @@ -0,0 +1,74 @@ +From 7fe76f02413fff61566ae52ec80d581da1e264a2 Mon Sep 17 00:00:00 2001 +From: Jan Beulich +Date: Wed, 27 Sep 2023 10:53:38 +0200 +Subject: [PATCH] x86-64: fix suffix-less PUSH of symbol address + +PR gas/30856 + +In 5cc007751cdb ("x86: further adjust extend-to-32bit-address +conditions") I neglected the case of PUSH, which is the only insn +allowing (proper) symbol addresses to be used as immediates (not +displacements, like CALL/JMP) in the absence of any register operands. +Since it defaults to 64-bit operand size, guessing an L suffix is wrong +there. +--- + gas/config/tc-i386.c | 7 ++++++- + gas/testsuite/gas/i386/immed64.d | 6 ++++++ + gas/testsuite/gas/i386/immed64.s | 6 ++++++ + 3 files changed, 18 insertions(+), 1 deletion(-) + +diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c +index 4d85f8bcf..913e016a4 100644 +--- a/gas/config/tc-i386.c ++++ b/gas/config/tc-i386.c +@@ -6039,7 +6039,12 @@ optimize_imm (void) + } + else if ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0)) + guess_suffix = WORD_MNEM_SUFFIX; +- else if (flag_code != CODE_64BIT || !(i.prefix[REX_PREFIX] & REX_W)) ++ else if (flag_code != CODE_64BIT ++ || (!(i.prefix[REX_PREFIX] & REX_W) ++ /* A more generic (but also more involved) way of dealing ++ with the special case(s) would be to go look for ++ DefaultSize attributes on any of the templates. */ ++ && current_templates->start->mnem_off != MN_push)) + guess_suffix = LONG_MNEM_SUFFIX; + + for (op = i.operands; --op >= 0;) +diff --git a/gas/testsuite/gas/i386/immed64.d b/gas/testsuite/gas/i386/immed64.d +index 35492a5a4..a83ab2c6e 100644 +--- a/gas/testsuite/gas/i386/immed64.d ++++ b/gas/testsuite/gas/i386/immed64.d +@@ -24,6 +24,12 @@ Disassembly of section \.text: + [ ]*[0-9a-fA-F]+:[ ]+48 b8 04 00 00 00 00 00 00 00[ ]+movabsq? +\$0x4,%rax + [ ]*[0-9a-fA-F]+:[ ]+48 b8 08 00 00 00 00 00 00 00[ ]+movabsq? +\$0x8,%rax + [ ]*[0-9a-fA-F]+:[ ]+48 b8 00 00 00 00 00 00 00 00[ ]+movabsq? +\$0x0,%rax ++[ ]*[0-9a-fA-F]+:[ ]+6a 04[ ]+pushq? +\$0x4 ++[ ]*[0-9a-fA-F]+:[ ]+68 08 00 00 00[ ]+pushq? +\$0x8 ++[ ]*[0-9a-fA-F]+:[ ]+66 6a 04[ ]+pushw +\$0x4 ++[ ]*[0-9a-fA-F]+:[ ]+66 68 08 00[ ]+pushw +\$0x8 ++[ ]*[0-9a-fA-F]+:[ ]+6a 04[ ]+pushq? +\$0x4 ++[ ]*[0-9a-fA-F]+:[ ]+68 08 00 00 00[ ]+pushq? +\$0x8 + [ ]*[0-9a-fA-F]+:[ ]+04 04[ ]+addb? +\$0x4,%al + [ ]*[0-9a-fA-F]+:[ ]+04 08[ ]+addb? +\$0x8,%al + [ ]*[0-9a-fA-F]+:[ ]+04 00[ ]+addb? +\$0x0,%al +diff --git a/gas/testsuite/gas/i386/immed64.s b/gas/testsuite/gas/i386/immed64.s +index 265b41924..21c30ec48 100644 +--- a/gas/testsuite/gas/i386/immed64.s ++++ b/gas/testsuite/gas/i386/immed64.s +@@ -19,6 +19,12 @@ _start: + movabsq $early, %rax + movabsq $late, %rax + movabsq $xtrn, %rax ++ pushq $early ++ pushq $late ++ pushw $early ++ pushw $late ++ push $early ++ push $late + addb $early, %al + addb $late, %al + addb $xtrn, %al +-- +2.43.0 + diff --git a/backport-x86-Check-MODRM-for-call-and-jmp-in-binutils-older-t.patch b/backport-x86-Check-MODRM-for-call-and-jmp-in-binutils-older-t.patch new file mode 100644 index 0000000..c83f49f --- /dev/null +++ b/backport-x86-Check-MODRM-for-call-and-jmp-in-binutils-older-t.patch @@ -0,0 +1,89 @@ +From a4206092924aee25c62b8e4013960b1b158155a0 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Thu, 22 May 2025 11:29:49 +0800 +Subject: [PATCH] x86: Check MODRM for call and jmp in binutils older than 2.45 + +When i386 glibc was assembled with commit: + +commit 11c2852449825a5f486f63bc40aabed56b7c04c1 (HEAD) +Author: Jan Beulich +Date: Fri Feb 21 10:24:50 2025 +0100 + + x86: widen @got{,pcrel} support to PUSH and APX IMUL + + With us doing the transformation to an immediate operand for MOV and + various ALU insns, there's little reason to then not support the same + conversion for the other two insns which have respective immediate + operand forms. Unfortunately for IMUL (due to the 0F opcode prefix) + there's no suitable relocation, so the pre-APX forms cannot be marked + for relaxation in the assembler. + +"pushl main@GOT(%ebx)" in sysdeps/i386/start.S was assembled to + +1c: ff b3 00 00 00 00 push 0x0(%ebx) 1e: R_386_GOT32X main + +Linkers in binutils versions older than 2.45 treated it as jmp and relaxed +it to + +22c: e9 cf ff ff ff jmp 200
+231: 90 nop + +Update elf_i386_convert_load_reloc in binutils versions older than 2.45 +to check MODRM for call and jmp to work with i386 glibc assembled with +binutils 2.45 or newer. Do the same in elf_x86_64_convert_load_reloc. + + PR ld/32991 + * elf32-i386.c (elf_i386_convert_load_reloc): Check MODRM for + call and jmp. + * elf64-x86-64.c (elf_x86_64_convert_load_reloc): Likewise. + +Signed-off-by: H.J. Lu +(cherry picked from commit 452f5511154ca02095a271cf085e17f536587207) +--- + bfd/elf32-i386.c | 9 +++++++++ + bfd/elf64-x86-64.c | 9 +++++++++ + 2 files changed, 18 insertions(+) + +diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c +index 7e6823b40..d91aa2819 100644 +--- a/bfd/elf32-i386.c ++++ b/bfd/elf32-i386.c +@@ -1329,6 +1329,15 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, + + if (opcode == 0xff) + { ++ switch (modrm & 0x38) ++ { ++ case 0x10: /* CALL */ ++ case 0x20: /* JMP */ ++ break; ++ default: ++ return true; ++ } ++ + /* We have "call/jmp *foo@GOT[(%reg)]". */ + if ((h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) +diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c +index f926464d8..4e5e35157 100644 +--- a/bfd/elf64-x86-64.c ++++ b/bfd/elf64-x86-64.c +@@ -1752,6 +1752,15 @@ elf_x86_64_convert_load_reloc (bfd *abfd, + /* Convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX to + R_X86_64_PC32. */ + modrm = bfd_get_8 (abfd, contents + roff - 1); ++ switch (modrm & 0x38) ++ { ++ case 0x10: /* CALL */ ++ case 0x20: /* JMP */ ++ break; ++ default: ++ return true; ++ } ++ + if (modrm == 0x25) + { + /* Convert to "jmp foo nop". */ +-- +2.43.0 + diff --git a/backport-x86-restrict-prefix-use-with-.insn-VEX-XOP-EVEX.patch b/backport-x86-restrict-prefix-use-with-.insn-VEX-XOP-EVEX.patch new file mode 100644 index 0000000..ebbfa81 --- /dev/null +++ b/backport-x86-restrict-prefix-use-with-.insn-VEX-XOP-EVEX.patch @@ -0,0 +1,47 @@ +From b6f6a3ecd15f4c55a4652933f8478feb8b685788 Mon Sep 17 00:00:00 2001 +From: Jan Beulich +Date: Fri, 8 Sep 2023 08:45:11 +0200 +Subject: [PATCH] x86: restrict prefix use with .insn VEX/XOP/EVEX + +Avoid triggering the respective abort() in output_insn(). +--- + gas/config/tc-i386.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c +index de35ee2a2..4d85f8bcf 100644 +--- a/gas/config/tc-i386.c ++++ b/gas/config/tc-i386.c +@@ -10671,6 +10671,29 @@ s_insn (int dummy ATTRIBUTE_UNUSED) + if (line > end && i.vec_encoding == vex_encoding_default) + i.vec_encoding = evex ? vex_encoding_evex : vex_encoding_vex; + ++ if (i.vec_encoding != vex_encoding_default) ++ { ++ /* Only address size and segment override prefixes are permitted with ++ VEX/XOP/EVEX encodings. */ ++ const unsigned char *p = i.prefix; ++ ++ for (j = 0; j < ARRAY_SIZE (i.prefix); ++j, ++p) ++ { ++ if (!*p) ++ continue; ++ ++ switch (j) ++ { ++ case SEG_PREFIX: ++ case ADDR_PREFIX: ++ break; ++ default: ++ as_bad (_("illegal prefix used with VEX/XOP/EVEX")); ++ goto bad; ++ } ++ } ++ } ++ + if (line > end && *line == '.') + { + /* Length specifier (VEX.L, XOP.L, EVEX.L'L). */ +-- +2.43.0 + diff --git a/binutils.spec b/binutils.spec index 1434539..e73e030 100644 --- a/binutils.spec +++ b/binutils.spec @@ -2,7 +2,7 @@ Summary: A GNU collection of binary utilities Name: binutils%{?_with_debug:-debug} Version: 2.41 -Release: 19 +Release: 20 License: GPL-3.0-or-later AND (GPL-3.0-or-later WITH Bison-exception-2.2) AND (LGPL-2.0-or-later WITH GCC-exception-2.0) AND BSD-3-Clause AND GFDL-1.3-or-later AND GPL-2.0-or-later AND LGPL-2.1-or-later AND LGPL-2.0-or-later URL: https://sourceware.org/binutils @@ -392,6 +392,15 @@ Patch5017: backport-Re-PR32399-buffer-overflow-printing-core_file_failin.patch #---------------------------------------------------------------------------- Patch6001: aarch64-add-l4-instruction.patch +Patch6002: backport-bfd-aarch64-Fix-BTI-stub-optimization-PR30957.patch +Patch6003: backport-bfd-aarch64-Fix-broken-BTI-stub-PR30930.patch +Patch6004: backport-bfd-aarch64-Avoid-BTI-stub-for-a-PLT-that-has-BTI.patch +Patch6005: backport-bfd-aarch64-Fix-leaks-in-case-of-BTI-stub-reuse.patch +Patch6006: backport-libctf-fix-ref-leak-of-names-of-newly-inserted-non-r.patch +Patch6007: backport-x86-64-fix-suffix-less-PUSH-of-symbol-address.patch +Patch6008: backport-x86-Check-MODRM-for-call-and-jmp-in-binutils-older-t.patch +Patch6009: backport-x86-restrict-prefix-use-with-.insn-VEX-XOP-EVEX.patch + Provides: bundled(libiberty) @@ -1407,6 +1416,17 @@ exit 0 #---------------------------------------------------------------------------- %changelog +* Fri Jul 11 2025 huyubiao - 2.41-20 +- Fix leaks and instruction-related issues in aarch64 and x86. +- Add backport-bfd-aarch64-Avoid-BTI-stub-for-a-PLT-that-has-BTI.patch + backport-bfd-aarch64-Fix-BTI-stub-optimization-PR30957.patch + backport-bfd-aarch64-Fix-broken-BTI-stub-PR30930.patch + backport-bfd-aarch64-Fix-leaks-in-case-of-BTI-stub-reuse.patch + backport-libctf-fix-ref-leak-of-names-of-newly-inserted-non-r.patch + backport-x86-64-fix-suffix-less-PUSH-of-symbol-address.patch + backport-x86-Check-MODRM-for-call-and-jmp-in-binutils-older-t.patch + backport-x86-restrict-prefix-use-with-.insn-VEX-XOP-EVEX.patch + * Fri Apr 18 2025 eastb233 - 2.41-19 - Fix PR32399, buffer overflow printing core_file_failing_command -- Gitee