diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-11-29 00:04:10 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-11-29 00:04:10 +0000 |
commit | 60d9c6b48bb8fbaeba791ee15b003f90b3ec1d64 (patch) | |
tree | 9e0f058a7450c9e97fc745899e6ee4fcd714dc63 | |
parent | 85643939a9161d14cfa1eb7fc1a03aa924372013 (diff) | |
parent | d6bbe48d7ec724c092979583fb9ae0879ac5b3aa (diff) | |
download | elfutils-60d9c6b48bb8fbaeba791ee15b003f90b3ec1d64.tar.gz |
Snap for 11152489 from d6bbe48d7ec724c092979583fb9ae0879ac5b3aa to sdk-release
Change-Id: I6608598da65170bee81f85e8efd58c858edac7b4
-rw-r--r-- | libdw/dwarf_formstring.c | 6 | ||||
-rw-r--r-- | libdwfl/dwfl_report_elf.c | 3 | ||||
-rw-r--r-- | libelf/elf_compress.c | 2 | ||||
-rw-r--r-- | patches/libdw-check-offset-dwarf_formstring-in-all-cases.patch | 36 | ||||
-rw-r--r-- | patches/libdwfl-handle-duplicate-ELFs-when-reporting-archive.patch | 56 | ||||
-rw-r--r-- | patches/libelf-check-decompressed-ZSTD-size.patch | 33 |
6 files changed, 131 insertions, 5 deletions
diff --git a/libdw/dwarf_formstring.c b/libdw/dwarf_formstring.c index 0ee42411..65f03a5e 100644 --- a/libdw/dwarf_formstring.c +++ b/libdw/dwarf_formstring.c @@ -173,11 +173,11 @@ dwarf_formstring (Dwarf_Attribute *attrp) off = read_4ubyte_unaligned (dbg, datap); else off = read_8ubyte_unaligned (dbg, datap); - - if (off >= data_size) - goto invalid_offset; } + if (off >= data_size) + goto invalid_offset; + return (const char *) data->d_buf + off; } INTDEF(dwarf_formstring) diff --git a/libdwfl/dwfl_report_elf.c b/libdwfl/dwfl_report_elf.c index 581f4079..a76d3681 100644 --- a/libdwfl/dwfl_report_elf.c +++ b/libdwfl/dwfl_report_elf.c @@ -276,10 +276,11 @@ __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name, } else { - elf_end (elf); if (m->main_bias != bias || m->main.vaddr != vaddr || m->main.address_sync != address_sync) goto overlap; + elf_end (m->main.elf); + m->main.elf = elf; } } return m; diff --git a/libelf/elf_compress.c b/libelf/elf_compress.c index f13b41ba..e3ecab32 100644 --- a/libelf/elf_compress.c +++ b/libelf/elf_compress.c @@ -421,7 +421,7 @@ __libelf_decompress_zstd (void *buf_in, size_t size_in, size_t size_out) } size_t ret = ZSTD_decompress (buf_out, size_out, buf_in, size_in); - if (ZSTD_isError (ret)) + if (unlikely (ZSTD_isError (ret)) || unlikely (ret != size_out)) { free (buf_out); __libelf_seterrno (ELF_E_DECOMPRESS_ERROR); diff --git a/patches/libdw-check-offset-dwarf_formstring-in-all-cases.patch b/patches/libdw-check-offset-dwarf_formstring-in-all-cases.patch new file mode 100644 index 00000000..7e30d2a3 --- /dev/null +++ b/patches/libdw-check-offset-dwarf_formstring-in-all-cases.patch @@ -0,0 +1,36 @@ +From 1bd9deb9aa19ac2e2fa9665009e0d5924adcf4d3 Mon Sep 17 00:00:00 2001 +From: Aleksei Vetrov <vvvvvv@google.com> +Date: Thu, 16 Nov 2023 21:29:22 +0000 +Subject: [PATCH] libdw: check offset dwarf_formstring in all cases + +This check was initially added to test if offset overflows the safe +prefix where any string will be null-terminated. However the check +was placed in a wrong place and didn't cover all `attrp->form` cases. + + * libdw/dwarf_formstring.c (dwarf_formstring): Move offset check + right before returning the result. + +Signed-off-by: Aleksei Vetrov <vvvvvv@google.com> + +diff --git a/libdw/dwarf_formstring.c b/libdw/dwarf_formstring.c +index 0ee42411..65f03a5e 100644 +--- a/libdw/dwarf_formstring.c ++++ b/libdw/dwarf_formstring.c +@@ -173,11 +173,11 @@ dwarf_formstring (Dwarf_Attribute *attrp) + off = read_4ubyte_unaligned (dbg, datap); + else + off = read_8ubyte_unaligned (dbg, datap); +- +- if (off >= data_size) +- goto invalid_offset; + } + ++ if (off >= data_size) ++ goto invalid_offset; ++ + return (const char *) data->d_buf + off; + } + INTDEF(dwarf_formstring) +-- +2.43.0.rc1.413.gea7ed67945-goog + diff --git a/patches/libdwfl-handle-duplicate-ELFs-when-reporting-archive.patch b/patches/libdwfl-handle-duplicate-ELFs-when-reporting-archive.patch new file mode 100644 index 00000000..021ecdcf --- /dev/null +++ b/patches/libdwfl-handle-duplicate-ELFs-when-reporting-archive.patch @@ -0,0 +1,56 @@ +From 0ab5a3eb4122f36cbaff259e7a0a3f9d014cb6f7 Mon Sep 17 00:00:00 2001 +From: Aleksei Vetrov <vvvvvv@google.com> +Date: Mon, 20 Nov 2023 17:44:47 +0000 +Subject: [PATCH] libdwfl: handle duplicate ELFs when reporting archives + +When archive is processed in process_archive (libdwfl/offline.c), it +creates an Elf object for each archive member. Then in +process_archive_member it calls process_file to create a Dwfl_Module +through __libdwfl_report_elf. + +The ownership of the Elf object is expected to be: + +* either transfered to the Dwfl_Module, if __libdwfl_report_elf returns + not NULL; + +* or handled at the end of process_archive_member by calling elf_end. + +Moreover, Elf object is expected to be alive, if __libdwfl_report_elf +returns not NULL, because at the end of process_archive_member it +advances to the next member through the elf_next call. + +The problem happens when __libdwfl_report_elf encounters Elf with the +same name and content as it seen before. In that case dwfl_report_module +will reuse existing Dwfl_Module object. This leads to a codepath that +calls elf_end on the Elf object, while returning not NULL, breaking the +elf_next call to the next member. + +The fix is to destroy m->main.elf instead and put the new Elf object in +the already existing Dwfl_Module. + + * libdwfl/dwfl_report_elf.c (__libdwfl_report_elf): Replace Elf in + the Dwfl_Module in case of duplicate modules to prolong its + lifetime for subsequent processing. + +Signed-off-by: Aleksei Vetrov <vvvvvv@google.com> + +diff --git a/libdwfl/dwfl_report_elf.c b/libdwfl/dwfl_report_elf.c +index 581f4079..a76d3681 100644 +--- a/libdwfl/dwfl_report_elf.c ++++ b/libdwfl/dwfl_report_elf.c +@@ -276,10 +276,11 @@ __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name, + } + else + { +- elf_end (elf); + if (m->main_bias != bias + || m->main.vaddr != vaddr || m->main.address_sync != address_sync) + goto overlap; ++ elf_end (m->main.elf); ++ m->main.elf = elf; + } + } + return m; +-- +2.43.0.rc1.413.gea7ed67945-goog + diff --git a/patches/libelf-check-decompressed-ZSTD-size.patch b/patches/libelf-check-decompressed-ZSTD-size.patch new file mode 100644 index 00000000..6c76fac1 --- /dev/null +++ b/patches/libelf-check-decompressed-ZSTD-size.patch @@ -0,0 +1,33 @@ +From 03c171947cc538b04957ac2222ce86e7c0170bd1 Mon Sep 17 00:00:00 2001 +From: Aleksei Vetrov <vvvvvv@google.com> +Date: Thu, 23 Nov 2023 15:31:47 +0000 +Subject: [PATCH] libelf: check decompressed ZSTD size + +Decompression functions like __libelf_decompress_zlib check that +decompressed data has the same size as it was declared in the header +(size_out argument). The same check is now added to +__libelf_decompress_zstd to make sure that the whole allocated buffer is +initialized. + + * libelf/elf_compress.c (__libelf_decompress_zstd): Use return value + of ZSTD_decompress to check that decompressed data size is the + same as size_out of the buffer that was allocated. + +Signed-off-by: Aleksei Vetrov <vvvvvv@google.com> + +diff --git a/libelf/elf_compress.c b/libelf/elf_compress.c +index c7283c6a..0ad6a32a 100644 +--- a/libelf/elf_compress.c ++++ b/libelf/elf_compress.c +@@ -422,7 +422,7 @@ __libelf_decompress_zstd (void *buf_in, size_t size_in, size_t size_out) + } + + size_t ret = ZSTD_decompress (buf_out, size_out, buf_in, size_in); +- if (ZSTD_isError (ret)) ++ if (unlikely (ZSTD_isError (ret)) || unlikely (ret != size_out)) + { + free (buf_out); + __libelf_seterrno (ELF_E_DECOMPRESS_ERROR); +-- +2.43.0.rc1.413.gea7ed67945-goog + |