b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From 8707194a9f2f0b13e53041b03ebfdbdbd2942e43 Mon Sep 17 00:00:00 2001 |
| 2 | From: Mark Wielaard <mark@klomp.org> |
| 3 | Date: Tue, 5 Nov 2024 23:31:14 +0100 |
| 4 | Subject: [PATCH 1/1] libelf: Only fetch shdr once in elf_compress[_gnu] |
| 5 | |
| 6 | Some compilers assume the second call to elf[32|64]_getshdr can fail |
| 7 | and produce error: potential null pointer dereference. Just store the |
| 8 | result of the first call and reuse (when not NULL). |
| 9 | |
| 10 | * libelf/elf_compress.c (elf_compress): Store getshdr result in |
| 11 | a shdr union var. |
| 12 | * libelf/elf_compress_gnu.c (): Likewise |
| 13 | |
| 14 | https://sourceware.org/bugzilla/show_bug.cgi?id=32311 |
| 15 | |
| 16 | Signed-off-by: Mark Wielaard <mark@klomp.org> |
| 17 | --- |
| 18 | libelf/elf_compress.c | 55 +++++++++++++++++++++------------------ |
| 19 | libelf/elf_compress_gnu.c | 45 ++++++++++++++------------------ |
| 20 | 2 files changed, 48 insertions(+), 52 deletions(-) |
| 21 | |
| 22 | --- a/libelf/elf_compress.c |
| 23 | +++ b/libelf/elf_compress.c |
| 24 | @@ -584,25 +584,30 @@ elf_compress (Elf_Scn *scn, int type, un |
| 25 | Elf64_Xword sh_flags; |
| 26 | Elf64_Word sh_type; |
| 27 | Elf64_Xword sh_addralign; |
| 28 | + union shdr |
| 29 | + { |
| 30 | + Elf32_Shdr *s32; |
| 31 | + Elf64_Shdr *s64; |
| 32 | + } shdr; |
| 33 | if (elfclass == ELFCLASS32) |
| 34 | { |
| 35 | - Elf32_Shdr *shdr = elf32_getshdr (scn); |
| 36 | - if (shdr == NULL) |
| 37 | + shdr.s32 = elf32_getshdr (scn); |
| 38 | + if (shdr.s32 == NULL) |
| 39 | return -1; |
| 40 | |
| 41 | - sh_flags = shdr->sh_flags; |
| 42 | - sh_type = shdr->sh_type; |
| 43 | - sh_addralign = shdr->sh_addralign; |
| 44 | + sh_flags = shdr.s32->sh_flags; |
| 45 | + sh_type = shdr.s32->sh_type; |
| 46 | + sh_addralign = shdr.s32->sh_addralign; |
| 47 | } |
| 48 | else |
| 49 | { |
| 50 | - Elf64_Shdr *shdr = elf64_getshdr (scn); |
| 51 | - if (shdr == NULL) |
| 52 | + shdr.s64 = elf64_getshdr (scn); |
| 53 | + if (shdr.s64 == NULL) |
| 54 | return -1; |
| 55 | |
| 56 | - sh_flags = shdr->sh_flags; |
| 57 | - sh_type = shdr->sh_type; |
| 58 | - sh_addralign = shdr->sh_addralign; |
| 59 | + sh_flags = shdr.s64->sh_flags; |
| 60 | + sh_type = shdr.s64->sh_type; |
| 61 | + sh_addralign = shdr.s64->sh_addralign; |
| 62 | } |
| 63 | |
| 64 | if ((sh_flags & SHF_ALLOC) != 0) |
| 65 | @@ -679,17 +684,17 @@ elf_compress (Elf_Scn *scn, int type, un |
| 66 | correctly and ignored when SHF_COMPRESSED is set. */ |
| 67 | if (elfclass == ELFCLASS32) |
| 68 | { |
| 69 | - Elf32_Shdr *shdr = elf32_getshdr (scn); |
| 70 | - shdr->sh_size = new_size; |
| 71 | - shdr->sh_addralign = __libelf_type_align (ELFCLASS32, ELF_T_CHDR); |
| 72 | - shdr->sh_flags |= SHF_COMPRESSED; |
| 73 | + shdr.s32->sh_size = new_size; |
| 74 | + shdr.s32->sh_addralign = __libelf_type_align (ELFCLASS32, |
| 75 | + ELF_T_CHDR); |
| 76 | + shdr.s32->sh_flags |= SHF_COMPRESSED; |
| 77 | } |
| 78 | else |
| 79 | { |
| 80 | - Elf64_Shdr *shdr = elf64_getshdr (scn); |
| 81 | - shdr->sh_size = new_size; |
| 82 | - shdr->sh_addralign = __libelf_type_align (ELFCLASS64, ELF_T_CHDR); |
| 83 | - shdr->sh_flags |= SHF_COMPRESSED; |
| 84 | + shdr.s64->sh_size = new_size; |
| 85 | + shdr.s64->sh_addralign = __libelf_type_align (ELFCLASS64, |
| 86 | + ELF_T_CHDR); |
| 87 | + shdr.s64->sh_flags |= SHF_COMPRESSED; |
| 88 | } |
| 89 | |
| 90 | __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_CHDR); |
| 91 | @@ -731,17 +736,15 @@ elf_compress (Elf_Scn *scn, int type, un |
| 92 | correctly and ignored when SHF_COMPRESSED is set. */ |
| 93 | if (elfclass == ELFCLASS32) |
| 94 | { |
| 95 | - Elf32_Shdr *shdr = elf32_getshdr (scn); |
| 96 | - shdr->sh_size = scn->zdata_size; |
| 97 | - shdr->sh_addralign = scn->zdata_align; |
| 98 | - shdr->sh_flags &= ~SHF_COMPRESSED; |
| 99 | + shdr.s32->sh_size = scn->zdata_size; |
| 100 | + shdr.s32->sh_addralign = scn->zdata_align; |
| 101 | + shdr.s32->sh_flags &= ~SHF_COMPRESSED; |
| 102 | } |
| 103 | else |
| 104 | { |
| 105 | - Elf64_Shdr *shdr = elf64_getshdr (scn); |
| 106 | - shdr->sh_size = scn->zdata_size; |
| 107 | - shdr->sh_addralign = scn->zdata_align; |
| 108 | - shdr->sh_flags &= ~SHF_COMPRESSED; |
| 109 | + shdr.s64->sh_size = scn->zdata_size; |
| 110 | + shdr.s64->sh_addralign = scn->zdata_align; |
| 111 | + shdr.s64->sh_flags &= ~SHF_COMPRESSED; |
| 112 | } |
| 113 | |
| 114 | __libelf_reset_rawdata (scn, scn->zdata_base, |
| 115 | --- a/libelf/elf_compress_gnu.c |
| 116 | +++ b/libelf/elf_compress_gnu.c |
| 117 | @@ -59,25 +59,30 @@ elf_compress_gnu (Elf_Scn *scn, int infl |
| 118 | Elf64_Xword sh_flags; |
| 119 | Elf64_Word sh_type; |
| 120 | Elf64_Xword sh_addralign; |
| 121 | + union shdr |
| 122 | + { |
| 123 | + Elf32_Shdr *s32; |
| 124 | + Elf64_Shdr *s64; |
| 125 | + } shdr; |
| 126 | if (elfclass == ELFCLASS32) |
| 127 | { |
| 128 | - Elf32_Shdr *shdr = elf32_getshdr (scn); |
| 129 | - if (shdr == NULL) |
| 130 | + shdr.s32 = elf32_getshdr (scn); |
| 131 | + if (shdr.s32 == NULL) |
| 132 | return -1; |
| 133 | |
| 134 | - sh_flags = shdr->sh_flags; |
| 135 | - sh_type = shdr->sh_type; |
| 136 | - sh_addralign = shdr->sh_addralign; |
| 137 | + sh_flags = shdr.s32->sh_flags; |
| 138 | + sh_type = shdr.s32->sh_type; |
| 139 | + sh_addralign = shdr.s32->sh_addralign; |
| 140 | } |
| 141 | else |
| 142 | { |
| 143 | - Elf64_Shdr *shdr = elf64_getshdr (scn); |
| 144 | - if (shdr == NULL) |
| 145 | + shdr.s64 = elf64_getshdr (scn); |
| 146 | + if (shdr.s64 == NULL) |
| 147 | return -1; |
| 148 | |
| 149 | - sh_flags = shdr->sh_flags; |
| 150 | - sh_type = shdr->sh_type; |
| 151 | - sh_addralign = shdr->sh_addralign; |
| 152 | + sh_flags = shdr.s64->sh_flags; |
| 153 | + sh_type = shdr.s64->sh_type; |
| 154 | + sh_addralign = shdr.s64->sh_addralign; |
| 155 | } |
| 156 | |
| 157 | /* Allocated sections, or sections that are already are compressed |
| 158 | @@ -122,15 +127,9 @@ elf_compress_gnu (Elf_Scn *scn, int infl |
| 159 | sh_flags won't have a SHF_COMPRESSED hint in the GNU format. |
| 160 | Just adjust the sh_size. */ |
| 161 | if (elfclass == ELFCLASS32) |
| 162 | - { |
| 163 | - Elf32_Shdr *shdr = elf32_getshdr (scn); |
| 164 | - shdr->sh_size = new_size; |
| 165 | - } |
| 166 | + shdr.s32->sh_size = new_size; |
| 167 | else |
| 168 | - { |
| 169 | - Elf64_Shdr *shdr = elf64_getshdr (scn); |
| 170 | - shdr->sh_size = new_size; |
| 171 | - } |
| 172 | + shdr.s64->sh_size = new_size; |
| 173 | |
| 174 | __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_BYTE); |
| 175 | |
| 176 | @@ -187,15 +186,9 @@ elf_compress_gnu (Elf_Scn *scn, int infl |
| 177 | sh_flags won't have a SHF_COMPRESSED hint in the GNU format. |
| 178 | Just adjust the sh_size. */ |
| 179 | if (elfclass == ELFCLASS32) |
| 180 | - { |
| 181 | - Elf32_Shdr *shdr = elf32_getshdr (scn); |
| 182 | - shdr->sh_size = size; |
| 183 | - } |
| 184 | + shdr.s32->sh_size = size; |
| 185 | else |
| 186 | - { |
| 187 | - Elf64_Shdr *shdr = elf64_getshdr (scn); |
| 188 | - shdr->sh_size = size; |
| 189 | - } |
| 190 | + shdr.s64->sh_size = size; |
| 191 | |
| 192 | __libelf_reset_rawdata (scn, buf_out, size, sh_addralign, |
| 193 | __libelf_data_type (&ehdr, sh_type, |