Yes, the actual fix is 0020-CVE-2023-22608-3.patch. The other two files are the dependent patch files required for this patch to apply. If these are excluded, the build gives errors in do_compile task due to missing code dependencies.
Regards, Yash From: MacLeod, Randy<mailto:[email protected]> Sent: 28 February 2023 07:30 To: Yash Shinde<mailto:[email protected]>; [email protected]<mailto:[email protected]>; [email protected]<mailto:[email protected]> Cc: Kallapa, Umesh<mailto:[email protected]>; Gowda, Naveen<mailto:[email protected]>; Kokkonda, Sundeep<mailto:[email protected]>; Moodalappa, Shivaprasad<mailto:[email protected]>; Shinde, Yash<mailto:[email protected]> Subject: Re: [kirkstone][PATCH] binutils : Fix CVE-2023-22608 On 2023-02-26 04:11, Yash Shinde wrote: From: Yash Shinde <[email protected]><mailto:[email protected]> Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=8af23b30edbaedf009bc9b243cd4dfa10ae1ac09] Signed-off-by: Yash Shinde <[email protected]><mailto:[email protected]> --- .../binutils/binutils-2.38.inc | 3 + .../binutils/0020-CVE-2023-22608-1.patch | 502 ++++++++++++++++++ .../binutils/0020-CVE-2023-22608-2.patch | 211 ++++++++ .../binutils/0020-CVE-2023-22608-3.patch | 33 ++ This is a large patch so I took a look at it. The actual fix is: 0020-CVE-2023-22608-3.patch https://sourceware.org/git/?p=binutils-gdb.git;a=blobdiff;f=bfd/dwarf2.c;h=88335cb4fb0dddc3b1ca8a1d76c32b88ff85aa89;hp=b608afbc0cf260e98e2f87ab6d55c935937b2810;hb=8af23b30edbaedf009bc9b243cd4dfa10ae1ac09;hpb=8fbad19958c9b9c06a710bf7d6589d52f1ed8a64 which is just a few lines. Unfortunately we do need the other two, rather large patches to make that apply it seems. The patch that adds a trie seems like a feature but the code is all (I think) file scope local structs with static functions so as far as the ABI stability, it seems fine to backport. It will change the memory footprint: commit b43771b045fb5616da3964f2994eefbe8ae70d32 Author: Steinar H. Gunderson <[email protected]><mailto:[email protected]> Date: Fri May 20 10:10:34 2022 add a trie to map quickly from address range to compilation unit When using perf to profile large binaries, _bfd_dwarf2_find_nearest_line() becomes a hotspot, as perf wants to get line number information (for inline-detection purposes) for each and every sample. In Chromium in particular (the content_shell binary), this entails going through 475k address ranges, which takes a long time when done repeatedly. Add a radix-256 trie over the address space to quickly map address to compilation unit spaces; for content_shell, which is 1.6 GB when some (but not full) debug information turned is on, we go from 6 ms to 0.006 ms (6 µs) for each lookup from address to compilation unit, a 1000x speedup. There is a modest RAM increase of 180 MB in this binary (the existing linked list over ranges uses about 10 MB, and the entire perf job uses between 2–3 GB for a medium-size profile); for smaller binaries with few ranges, there should be hardly any extra RAM usage at all. ../Randy 4 files changed, 749 insertions(+) create mode 100644 meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-1.patch create mode 100644 meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-2.patch create mode 100644 meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-3.patch diff --git a/meta/recipes-devtools/binutils/binutils-2.38.inc b/meta/recipes-devtools/binutils/binutils-2.38.inc index 0a4a0d7bc1..30a34d7ba4 100644 --- a/meta/recipes-devtools/binutils/binutils-2.38.inc +++ b/meta/recipes-devtools/binutils/binutils-2.38.inc @@ -43,5 +43,8 @@ SRC_URI = "\ file://0018-CVE-2022-38128-2.patch \ file://0018-CVE-2022-38128-3.patch \ file://0019-CVE-2022-4285.patch \ + file://0020-CVE-2023-22608-1.patch \ + file://0020-CVE-2023-22608-2.patch \ + file://0020-CVE-2023-22608-3.patch \ " S = "${WORKDIR}/git" diff --git a/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-1.patch b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-1.patch new file mode 100644 index 0000000000..dd3d533d0d --- /dev/null +++ b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-1.patch @@ -0,0 +1,502 @@ +From a79c274dad99863f58b9ed627b38908daadb6d7e Mon Sep 17 00:00:00 2001 +From: "Steinar H. Gunderson" <[email protected]><mailto:[email protected]> +Date: Fri, 20 May 2022 16:10:34 +0200 +Subject: [PATCH] add a trie to map quickly from address range to compilation + unit +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When using perf to profile large binaries, _bfd_dwarf2_find_nearest_line() +becomes a hotspot, as perf wants to get line number information +(for inline-detection purposes) for each and every sample. In Chromium +in particular (the content_shell binary), this entails going through +475k address ranges, which takes a long time when done repeatedly. + +Add a radix-256 trie over the address space to quickly map address to +compilation unit spaces; for content_shell, which is 1.6 GB when some +(but not full) debug information turned is on, we go from 6 ms to +0.006 ms (6 µs) for each lookup from address to compilation unit, a 1000x +speedup. + +There is a modest RAM increase of 180 MB in this binary (the existing +linked list over ranges uses about 10 MB, and the entire perf job uses +between 2-3 GB for a medium-size profile); for smaller binaries with few +ranges, there should be hardly any extra RAM usage at all. + +Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=b43771b045fb5616da3964f2994eefbe8ae70d32] + +CVE: CVE-2023-22608 + +Signed-off-by: Yash Shinde <[email protected]><mailto:[email protected]> + +--- + bfd/dwarf2.c | 326 ++++++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 312 insertions(+), 14 deletions(-) + +diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c +index fdf071c3..0ae50a37 100644 +--- a/bfd/dwarf2.c ++++ b/bfd/dwarf2.c +@@ -82,6 +82,77 @@ struct adjusted_section + bfd_vma adj_vma; + }; + ++/* A trie to map quickly from address range to compilation unit. ++ ++ This is a fairly standard radix-256 trie, used to quickly locate which ++ compilation unit any given address belongs to. Given that each compilation ++ unit may register hundreds of very small and unaligned ranges (which may ++ potentially overlap, due to inlining and other concerns), and a large ++ program may end up containing hundreds of thousands of such ranges, we cannot ++ scan through them linearly without undue slowdown. ++ ++ We use a hybrid trie to avoid memory explosion: There are two types of trie ++ nodes, leaves and interior nodes. (Almost all nodes are leaves, so they ++ take up the bulk of the memory usage.) Leaves contain a simple array of ++ ranges (high/low address) and which compilation unit contains those ranges, ++ and when we get to a leaf, we scan through it linearly. Interior nodes ++ contain pointers to 256 other nodes, keyed by the next byte of the address. ++ So for a 64-bit address like 0x1234567abcd, we would start at the root and go ++ down child[0x00]->child[0x00]->child[0x01]->child[0x23]->child[0x45] etc., ++ until we hit a leaf. (Nodes are, in general, leaves until they exceed the ++ default allocation of 16 elements, at which point they are converted to ++ interior node if possible.) This gives us near-constant lookup times; ++ the only thing that can be costly is if there are lots of overlapping ranges ++ within a single 256-byte segment of the binary, in which case we have to ++ scan through them all to find the best match. ++ ++ For a binary with few ranges, we will in practice only have a single leaf ++ node at the root, containing a simple array. Thus, the scheme is efficient ++ for both small and large binaries. ++ */ ++ ++/* Experiments have shown 16 to be a memory-efficient default leaf size. ++ The only case where a leaf will hold more memory than this, is at the ++ bottomost level (covering 256 bytes in the binary), where we'll expand ++ the leaf to be able to hold more ranges if needed. ++ */ ++#define TRIE_LEAF_SIZE 16 ++ ++/* All trie_node pointers will really be trie_leaf or trie_interior, ++ but they have this common head. */ ++struct trie_node ++{ ++ /* If zero, we are an interior node. ++ Otherwise, how many ranges we have room for in this leaf. */ ++ unsigned int num_room_in_leaf; ++}; ++ ++struct trie_leaf ++{ ++ struct trie_node head; ++ unsigned int num_stored_in_leaf; ++ struct { ++ struct comp_unit *unit; ++ bfd_vma low_pc, high_pc; ++ } ranges[TRIE_LEAF_SIZE]; ++}; ++ ++struct trie_interior ++{ ++ struct trie_node head; ++ struct trie_node *children[256]; ++}; ++ ++static struct trie_node *alloc_trie_leaf (bfd *abfd) ++{ ++ struct trie_leaf *leaf = ++ bfd_zalloc (abfd, sizeof (struct trie_leaf)); ++ if (leaf == NULL) ++ return NULL; ++ leaf->head.num_room_in_leaf = TRIE_LEAF_SIZE; ++ return &leaf->head; ++} ++ + struct dwarf2_debug_file + { + /* The actual bfd from which debug info was loaded. Might be +@@ -139,6 +210,9 @@ struct dwarf2_debug_file + /* A list of all previously read comp_units. */ + struct comp_unit *all_comp_units; + ++ /* A list of all previously read comp_units with no ranges (yet). */ ++ struct comp_unit *all_comp_units_without_ranges; ++ + /* Last comp unit in list above. */ + struct comp_unit *last_comp_unit; + +@@ -147,6 +221,9 @@ struct dwarf2_debug_file + + /* Hash table to map offsets to decoded abbrevs. */ + htab_t abbrev_offsets; ++ ++ /* Root of a trie to map addresses to compilation units. */ ++ struct trie_node *trie_root; + }; + + struct dwarf2_debug +@@ -220,6 +297,11 @@ struct comp_unit + /* Chain the previously read compilation units. */ + struct comp_unit *next_unit; + ++ /* Chain the previously read compilation units that have no ranges yet. ++ We scan these separately when we have a trie over the ranges. ++ Unused if arange.high != 0. */ ++ struct comp_unit *next_unit_without_ranges; ++ + /* Likewise, chain the compilation unit read after this one. + The comp units are stored in reversed reading order. */ + struct comp_unit *prev_unit; +@@ -296,6 +378,10 @@ struct comp_unit + + /* TRUE if symbols are cached in hash table for faster lookup by name. */ + bool cached; ++ ++ /* Used when iterating over trie leaves to know which units we have ++ already seen in this iteration. */ ++ bool mark; + }; + + /* This data structure holds the information of an abbrev. */ +@@ -1766,9 +1852,189 @@ concat_filename (struct line_info_table *table, unsigned int file) + return strdup (filename); + } + ++/* Number of bits in a bfd_vma. */ ++#define VMA_BITS (8 * sizeof (bfd_vma)) ++ ++/* Check whether [low1, high1) can be combined with [low2, high2), ++ i.e., they touch or overlap. */ ++static bool ranges_overlap (bfd_vma low1, ++ bfd_vma high1, ++ bfd_vma low2, ++ bfd_vma high2) ++{ ++ if (low1 == low2 || high1 == high2) ++ return true; ++ ++ /* Sort so that low1 is below low2. */ ++ if (low1 > low2) ++ { ++ bfd_vma tmp; ++ ++ tmp = low1; ++ low1 = low2; ++ low2 = tmp; ++ ++ tmp = high1; ++ high1 = high2; ++ high2 = tmp; ++ } ++ ++ /* We touch iff low2 == high1. ++ We overlap iff low2 is within [low1, high1). */ ++ return (low2 <= high1); ++} ++ ++/* Insert an address range in the trie mapping addresses to compilation units. ++ Will return the new trie node (usually the same as is being sent in, but ++ in case of a leaf-to-interior conversion, or expansion of a leaf, it may be ++ different), or NULL on failure. ++ */ ++static struct trie_node *insert_arange_in_trie(bfd *abfd, ++ struct trie_node *trie, ++ bfd_vma trie_pc, ++ unsigned int trie_pc_bits, ++ struct comp_unit *unit, ++ bfd_vma low_pc, ++ bfd_vma high_pc) ++{ ++ bfd_vma clamped_low_pc, clamped_high_pc; ++ int ch, from_ch, to_ch; ++ bool is_full_leaf = false; ++ ++ /* See if we can extend any of the existing ranges. This merging ++ isn't perfect (if merging opens up the possibility of merging two existing ++ ranges, we won't find them), but it takes the majority of the cases. */ ++ if (trie->num_room_in_leaf > 0) ++ { ++ struct trie_leaf *leaf = (struct trie_leaf *) trie; ++ unsigned int i; ++ ++ for (i = 0; i < leaf->num_stored_in_leaf; ++i) ++ { ++ if (leaf->ranges[i].unit == unit && ++ ranges_overlap(low_pc, high_pc, ++ leaf->ranges[i].low_pc, leaf->ranges[i].high_pc)) ++ { ++ if (low_pc < leaf->ranges[i].low_pc) ++ leaf->ranges[i].low_pc = low_pc; ++ if (high_pc > leaf->ranges[i].high_pc) ++ leaf->ranges[i].high_pc = high_pc; ++ return trie; ++ } ++ } ++ ++ is_full_leaf = leaf->num_stored_in_leaf == trie->num_room_in_leaf; ++ } ++ ++ /* If we're a leaf with no more room and we're _not_ at the bottom, ++ convert to an interior node. */ ++ if (is_full_leaf && trie_pc_bits < VMA_BITS) ++ { ++ const struct trie_leaf *leaf = (struct trie_leaf *) trie; ++ unsigned int i; ++ ++ trie = bfd_zalloc (abfd, sizeof (struct trie_interior)); ++ if (!trie) ++ return NULL; ++ is_full_leaf = false; ++ ++ /* TODO: If we wanted to save a little more memory at the cost of ++ complexity, we could have reused the old leaf node as one of the ++ children of the new interior node, instead of throwing it away. */ ++ for (i = 0; i < leaf->num_stored_in_leaf; ++i) ++ { ++ if (!insert_arange_in_trie (abfd, trie, trie_pc, trie_pc_bits, ++ leaf->ranges[i].unit, leaf->ranges[i].low_pc, ++ leaf->ranges[i].high_pc)) ++ return NULL; ++ } ++ } ++ ++ /* If we're a leaf with no more room and we _are_ at the bottom, ++ we have no choice but to just make it larger. */ ++ if (is_full_leaf) ++ { ++ const struct trie_leaf *leaf = (struct trie_leaf *) trie; ++ unsigned int new_room_in_leaf = trie->num_room_in_leaf * 2; ++ struct trie_leaf *new_leaf; ++ ++ new_leaf = bfd_zalloc (abfd, ++ sizeof (struct trie_leaf) + ++ (new_room_in_leaf - TRIE_LEAF_SIZE) * sizeof (leaf->ranges[0])); ++ new_leaf->head.num_room_in_leaf = new_room_in_leaf; ++ new_leaf->num_stored_in_leaf = leaf->num_stored_in_leaf; ++ ++ memcpy (new_leaf->ranges, ++ leaf->ranges, ++ leaf->num_stored_in_leaf * sizeof (leaf->ranges[0])); ++ trie = &new_leaf->head; ++ is_full_leaf = false; ++ ++ /* Now the insert below will go through. */ ++ } ++ ++ /* If we're a leaf (now with room), we can just insert at the end. */ ++ if (trie->num_room_in_leaf > 0) ++ { ++ struct trie_leaf *leaf = (struct trie_leaf *) trie; ++ ++ unsigned int i = leaf->num_stored_in_leaf++; ++ leaf->ranges[i].unit = unit; ++ leaf->ranges[i].low_pc = low_pc; ++ leaf->ranges[i].high_pc = high_pc; ++ return trie; ++ } ++ ++ /* Now we are definitely an interior node, so recurse into all ++ the relevant buckets. */ ++ ++ /* Clamp the range to the current trie bucket. */ ++ clamped_low_pc = low_pc; ++ clamped_high_pc = high_pc; ++ if (trie_pc_bits > 0) ++ { ++ bfd_vma bucket_high_pc = ++ trie_pc + ((bfd_vma)-1 >> trie_pc_bits); /* Inclusive. */ ++ if (clamped_low_pc < trie_pc) ++ clamped_low_pc = trie_pc; ++ if (clamped_high_pc > bucket_high_pc) ++ clamped_high_pc = bucket_high_pc; ++ } ++ ++ /* Insert the ranges in all buckets that it spans. */ ++ from_ch = (clamped_low_pc >> (VMA_BITS - trie_pc_bits - 8)) & 0xff; ++ to_ch = ((clamped_high_pc - 1) >> (VMA_BITS - trie_pc_bits - 8)) & 0xff; ++ for (ch = from_ch; ch <= to_ch; ++ch) ++ { ++ struct trie_interior *interior = (struct trie_interior *) trie; ++ struct trie_node *child = interior->children[ch]; ++ ++ if (child == NULL) ++ { ++ child = alloc_trie_leaf (abfd); ++ if (!child) ++ return NULL; ++ } ++ child = insert_arange_in_trie (abfd, ++ child, ++ trie_pc + ((bfd_vma)ch << (VMA_BITS - trie_pc_bits - 8)), ++ trie_pc_bits + 8, ++ unit, ++ low_pc, ++ high_pc); ++ if (!child) ++ return NULL; ++ ++ interior->children[ch] = child; ++ } ++ ++ return trie; ++} ++ ++ + static bool +-arange_add (const struct comp_unit *unit, struct arange *first_arange, +- bfd_vma low_pc, bfd_vma high_pc) ++arange_add (struct comp_unit *unit, struct arange *first_arange, ++ struct trie_node **trie_root, bfd_vma low_pc, bfd_vma high_pc) + { + struct arange *arange; + +@@ -1776,6 +2042,19 @@ arange_add (const struct comp_unit *unit, struct arange *first_arange, + if (low_pc == high_pc) + return true; + ++ if (trie_root != NULL) ++ { ++ *trie_root = insert_arange_in_trie (unit->file->bfd_ptr, ++ *trie_root, ++ 0, ++ 0, ++ unit, ++ low_pc, ++ high_pc); ++ if (*trie_root == NULL) ++ return false; ++ } ++ + /* If the first arange is empty, use it. */ + if (first_arange->high == 0) + { +@@ -2410,7 +2689,8 @@ decode_line_info (struct comp_unit *unit) + low_pc = address; + if (address > high_pc) + high_pc = address; +- if (!arange_add (unit, &unit->arange, low_pc, high_pc)) ++ if (!arange_add (unit, &unit->arange, &unit->file->trie_root, ++ low_pc, high_pc)) + goto line_fail; + break; + case DW_LNE_set_address: +@@ -3134,7 +3414,7 @@ find_abstract_instance (struct comp_unit *unit, + + static bool + read_ranges (struct comp_unit *unit, struct arange *arange, +- bfd_uint64_t offset) ++ struct trie_node **trie_root, bfd_uint64_t offset) + { + bfd_byte *ranges_ptr; + bfd_byte *ranges_end; +@@ -3169,7 +3449,7 @@ read_ranges (struct comp_unit *unit, struct arange *arange, + base_address = high_pc; + else + { +- if (!arange_add (unit, arange, ++ if (!arange_add (unit, arange, trie_root, + base_address + low_pc, base_address + high_pc)) + return false; + } +@@ -3179,7 +3459,7 @@ read_ranges (struct comp_unit *unit, struct arange *arange, + + static bool + read_rnglists (struct comp_unit *unit, struct arange *arange, +- bfd_uint64_t offset) ++ struct trie_node **trie_root, bfd_uint64_t offset) + { + bfd_byte *rngs_ptr; + bfd_byte *rngs_end; +@@ -3253,19 +3533,19 @@ read_rnglists (struct comp_unit *unit, struct arange *arange, + return false; + } + +- if (!arange_add (unit, arange, low_pc, high_pc)) ++ if (!arange_add (unit, arange, trie_root, low_pc, high_pc)) + return false; + } + } + + static bool + read_rangelist (struct comp_unit *unit, struct arange *arange, +- bfd_uint64_t offset) ++ struct trie_node **trie_root, bfd_uint64_t offset) + { + if (unit->version <= 4) +- return read_ranges (unit, arange, offset); ++ return read_ranges (unit, arange, trie_root, offset); + else +- return read_rnglists (unit, arange, offset); ++ return read_rnglists (unit, arange, trie_root, offset); + } + + static struct funcinfo * +@@ -3563,7 +3843,8 @@ scan_unit_for_symbols (struct comp_unit *unit) + + case DW_AT_ranges: + if (is_int_form (&attr) +- && !read_rangelist (unit, &func->arange, attr.u.val)) ++ && !read_rangelist (unit, &func->arange, ++ &unit->file->trie_root, attr.u.val)) + goto fail; + break; + +@@ -3679,7 +3960,8 @@ scan_unit_for_symbols (struct comp_unit *unit) + + if (func && high_pc != 0) + { +- if (!arange_add (unit, &func->arange, low_pc, high_pc)) ++ if (!arange_add (unit, &func->arange, &unit->file->trie_root, ++ low_pc, high_pc)) + goto fail; + } + } +@@ -3874,7 +4156,8 @@ parse_comp_unit (struct dwarf2_debug *stash, + + case DW_AT_ranges: + if (is_int_form (&attr) +- && !read_rangelist (unit, &unit->arange, attr.u.val)) ++ && !read_rangelist (unit, &unit->arange, ++ &unit->file->trie_root, attr.u.val)) + return NULL; + break; + +@@ -3916,7 +4199,8 @@ parse_comp_unit (struct dwarf2_debug *stash, + high_pc += low_pc; + if (high_pc != 0) + { +- if (!arange_add (unit, &unit->arange, low_pc, high_pc)) ++ if (!arange_add (unit, &unit->arange, &unit->file->trie_root, ++ low_pc, high_pc)) + return NULL; + } + +@@ -4747,6 +5031,14 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, + if (!stash->alt.abbrev_offsets) + return false; + ++ stash->f.trie_root = alloc_trie_leaf (abfd); ++ if (!stash->f.trie_root) ++ return false; ++ ++ stash->alt.trie_root = alloc_trie_leaf (abfd); ++ if (!stash->alt.trie_root) ++ return false; ++ + *pinfo = stash; + + if (debug_bfd == NULL) +@@ -4918,6 +5210,12 @@ stash_comp_unit (struct dwarf2_debug *stash, struct dwarf2_debug_file *file) + each->next_unit = file->all_comp_units; + file->all_comp_units = each; + ++ if (each->arange.high == 0) ++ { ++ each->next_unit_without_ranges = file->all_comp_units_without_ranges; ++ file->all_comp_units_without_ranges = each->next_unit_without_ranges; ++ } ++ + file->info_ptr += length; + return each; + } diff --git a/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-2.patch b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-2.patch new file mode 100644 index 0000000000..8ffb500c1d --- /dev/null +++ b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-2.patch @@ -0,0 +1,211 @@ +From 73e97e32e1428d63d81d971176772ae69397a1a0 Mon Sep 17 00:00:00 2001 +From: Nick Clifton <[email protected]><mailto:[email protected]> +Date: Tue, 30 Aug 2022 16:01:20 +0100 +Subject: [PATCH] BFD library: Use entry 0 in directory and filename tables of + DWARF-5 debug info. + + PR 29529 + * dwarf2.c (struct line_info_table): Add new field: + use_dir_and_file_0. + (concat_filename): Use new field to help select the correct table + slot. + (read_formatted_entries): Do not skip entry 0. + (decode_line_info): Set new field depending upon the version of + DWARF being parsed. Initialise filename based upon the setting of + the new field. + +Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=37833b966576c5d25e797ea3b6c33d0459a71892] +CVE: CVE-2023-22608 + +Signed-off-by: Yash Shinde <[email protected]><mailto:[email protected]> + +--- + bfd/ChangeLog | 12 +++++ + bfd/dwarf2.c | 86 ++++++++++++++++++++---------- + ld/ChangeLog | 5 ++ + ld/testsuite/ld-x86-64/pr27587.err | 2 +- + 4 files changed, 76 insertions(+), 29 deletions(-) + +diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c +index 0ae50a37..b7839ad6 100644 +--- a/bfd/dwarf2.c ++++ b/bfd/dwarf2.c +@@ -1571,6 +1571,7 @@ struct line_info_table + unsigned int num_files; + unsigned int num_dirs; + unsigned int num_sequences; ++ bool use_dir_and_file_0; + char * comp_dir; + char ** dirs; + struct fileinfo* files; +@@ -1791,16 +1792,30 @@ concat_filename (struct line_info_table *table, unsigned int file) + { + char *filename; + +- if (table == NULL || file - 1 >= table->num_files) ++ /* Pre DWARF-5 entry 0 in the directory and filename tables was not used. ++ So in order to save space in the tables used here the info for, eg ++ directory 1 is stored in slot 0 of the directory table, directory 2 ++ in slot 1 and so on. ++ ++ Starting with DWARF-5 the 0'th entry is used so there is a one to one ++ mapping between DWARF slots and internal table entries. */ ++ if (! table->use_dir_and_file_0) + { +- /* FILE == 0 means unknown. */ +- if (file) +- _bfd_error_handler +- (_("DWARF error: mangled line number section (bad file number)")); ++ /* Pre DWARF-5, FILE == 0 means unknown. */ ++ if (file == 0) ++ return strdup ("<unknown>"); ++ -- file; ++ } ++ ++ if (table == NULL || file >= table->num_files) ++ { ++ _bfd_error_handler ++ (_("DWARF error: mangled line number section (bad file number)")); + return strdup ("<unknown>"); + } + +- filename = table->files[file - 1].name; ++ filename = table->files[file].name; ++ + if (filename == NULL) + return strdup ("<unknown>"); + +@@ -1811,12 +1826,17 @@ concat_filename (struct line_info_table *table, unsigned int file) + char *name; + size_t len; + +- if (table->files[file - 1].dir ++ if (table->files[file].dir + /* PR 17512: file: 0317e960. */ +- && table->files[file - 1].dir <= table->num_dirs ++ && table->files[file].dir <= table->num_dirs + /* PR 17512: file: 7f3d2e4b. */ + && table->dirs != NULL) +- subdir_name = table->dirs[table->files[file - 1].dir - 1]; ++ { ++ if (table->use_dir_and_file_0) ++ subdir_name = table->dirs[table->files[file].dir]; ++ else ++ subdir_name = table->dirs[table->files[file].dir - 1]; ++ } + + if (!subdir_name || !IS_ABSOLUTE_PATH (subdir_name)) + dir_name = table->comp_dir; +@@ -1857,10 +1877,12 @@ concat_filename (struct line_info_table *table, unsigned int file) + + /* Check whether [low1, high1) can be combined with [low2, high2), + i.e., they touch or overlap. */ +-static bool ranges_overlap (bfd_vma low1, +- bfd_vma high1, +- bfd_vma low2, +- bfd_vma high2) ++ ++static bool ++ranges_overlap (bfd_vma low1, ++ bfd_vma high1, ++ bfd_vma low2, ++ bfd_vma high2) + { + if (low1 == low2 || high1 == high2) + return true; +@@ -1887,15 +1909,16 @@ static bool ranges_overlap (bfd_vma low1, + /* Insert an address range in the trie mapping addresses to compilation units. + Will return the new trie node (usually the same as is being sent in, but + in case of a leaf-to-interior conversion, or expansion of a leaf, it may be +- different), or NULL on failure. +- */ +-static struct trie_node *insert_arange_in_trie(bfd *abfd, +- struct trie_node *trie, +- bfd_vma trie_pc, +- unsigned int trie_pc_bits, +- struct comp_unit *unit, +- bfd_vma low_pc, +- bfd_vma high_pc) ++ different), or NULL on failure. */ ++ ++static struct trie_node * ++insert_arange_in_trie (bfd *abfd, ++ struct trie_node *trie, ++ bfd_vma trie_pc, ++ unsigned int trie_pc_bits, ++ struct comp_unit *unit, ++ bfd_vma low_pc, ++ bfd_vma high_pc) + { + bfd_vma clamped_low_pc, clamped_high_pc; + int ch, from_ch, to_ch; +@@ -2031,7 +2054,6 @@ static struct trie_node *insert_arange_in_trie(bfd *abfd, + return trie; + } + +- + static bool + arange_add (struct comp_unit *unit, struct arange *first_arange, + struct trie_node **trie_root, bfd_vma low_pc, bfd_vma high_pc) +@@ -2412,10 +2434,8 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp, + } + } + +- /* Skip the first "zero entry", which is the compilation dir/file. */ +- if (datai != 0) +- if (!callback (table, fe.name, fe.dir, fe.time, fe.size)) +- return false; ++ if (!callback (table, fe.name, fe.dir, fe.time, fe.size)) ++ return false; + } + + *bufp = buf; +@@ -2592,6 +2612,7 @@ decode_line_info (struct comp_unit *unit) + if (!read_formatted_entries (unit, &line_ptr, line_end, table, + line_info_add_file_name)) + goto fail; ++ table->use_dir_and_file_0 = true; + } + else + { +@@ -2614,6 +2635,7 @@ decode_line_info (struct comp_unit *unit) + if (!line_info_add_file_name (table, cur_file, dir, xtime, size)) + goto fail; + } ++ table->use_dir_and_file_0 = false; + } + + /* Read the statement sequences until there's nothing left. */ +@@ -2622,7 +2644,7 @@ decode_line_info (struct comp_unit *unit) + /* State machine registers. */ + bfd_vma address = 0; + unsigned char op_index = 0; +- char * filename = table->num_files ? concat_filename (table, 1) : NULL; ++ char * filename = NULL; + unsigned int line = 1; + unsigned int column = 0; + unsigned int discriminator = 0; +@@ -2637,6 +2659,14 @@ decode_line_info (struct comp_unit *unit) + bfd_vma low_pc = (bfd_vma) -1; + bfd_vma high_pc = 0; + ++ if (table->num_files) ++ { ++ if (table->use_dir_and_file_0) ++ filename = concat_filename (table, 0); ++ else ++ filename = concat_filename (table, 1); ++ } ++ + /* Decode the table. */ + while (!end_sequence && line_ptr < line_end) + { +diff --git a/ld/testsuite/ld-x86-64/pr27587.err b/ld/testsuite/ld-x86-64/pr27587.err +index fa870790..807750ca 100644 +--- a/ld/testsuite/ld-x86-64/pr27587.err ++++ b/ld/testsuite/ld-x86-64/pr27587.err +@@ -1,3 +1,3 @@ + #... +-.*pr27587.i:4: undefined reference to `stack_size' ++.*pr27587/<artificial>:4: undefined reference to `stack_size' + #... diff --git a/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-3.patch b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-3.patch new file mode 100644 index 0000000000..603824155b --- /dev/null +++ b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-3.patch @@ -0,0 +1,33 @@ +From 20c75f063a999f9e849a77613a82b15de78ea45f Mon Sep 17 00:00:00 2001 +From: Nick Clifton <[email protected]><mailto:[email protected]> +Date: Fri, 23 Dec 2022 13:02:04 +0000 +Subject: [PATCH] Fix illegal memory access parsing corrupt DWARF information. + + PR 29936 + * dwarf2.c (concat_filename): Fix check for a directory index off + the end of the directory table. + +Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=8af23b30edbaedf009bc9b243cd4dfa10ae1ac09] +CVE: CVE-2023-22608 + +Signed-off-by: Yash Shinde <[email protected]><mailto:[email protected]> + +--- + bfd/ChangeLog | 6 ++++++ + bfd/dwarf2.c | 3 ++- + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c +index b7839ad6..8b07a24c 100644 +--- a/bfd/dwarf2.c ++++ b/bfd/dwarf2.c +@@ -1828,7 +1828,8 @@ concat_filename (struct line_info_table *table, unsigned int file) + + if (table->files[file].dir + /* PR 17512: file: 0317e960. */ +- && table->files[file].dir <= table->num_dirs ++ && table->files[file].dir ++ <= (table->use_dir_and_file_0 ? table->num_dirs - 1 : table->num_dirs) + /* PR 17512: file: 7f3d2e4b. */ + && table->dirs != NULL) + { -- # Randy MacLeod # Wind River Linux
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#177818): https://lists.openembedded.org/g/openembedded-core/message/177818 Mute This Topic: https://lists.openembedded.org/mt/97242671/21656 Group Owner: [email protected] Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
