1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/buildid.h> 4 #include <linux/cache.h> 5 #include <linux/elf.h> 6 #include <linux/kernel.h> 7 #include <linux/pagemap.h> 8 #include <linux/fs.h> 9 #include <linux/secretmem.h> 10 11 #define BUILD_ID 3 12 13 #define MAX_PHDR_CNT 256 14 15 void freader_init_from_file(struct freader *r, void *buf, u32 buf_sz, 16 struct file *file, bool may_fault) 17 { 18 memset(r, 0, sizeof(*r)); 19 r->buf = buf; 20 r->buf_sz = buf_sz; 21 r->file = file; 22 r->may_fault = may_fault; 23 } 24 25 void freader_init_from_mem(struct freader *r, const char *data, u64 data_sz) 26 { 27 memset(r, 0, sizeof(*r)); 28 r->data = data; 29 r->data_sz = data_sz; 30 } 31 32 static void freader_put_folio(struct freader *r) 33 { 34 if (!r->folio) 35 return; 36 kunmap_local(r->addr); 37 folio_put(r->folio); 38 r->folio = NULL; 39 } 40 41 static int freader_get_folio(struct freader *r, loff_t file_off) 42 { 43 /* check if we can just reuse current folio */ 44 if (r->folio && file_off >= r->folio_off && 45 file_off < r->folio_off + folio_size(r->folio)) 46 return 0; 47 48 freader_put_folio(r); 49 50 /* the page index must fit in pgoff_t */ 51 if (file_off < 0 || file_off > MAX_LFS_FILESIZE) 52 return -EFAULT; 53 54 /* only use page cache lookup - fail if not already cached */ 55 r->folio = filemap_get_folio(r->file->f_mapping, file_off >> PAGE_SHIFT); 56 57 if (IS_ERR(r->folio) || !folio_test_uptodate(r->folio)) { 58 if (!IS_ERR(r->folio)) 59 folio_put(r->folio); 60 r->folio = NULL; 61 return -EFAULT; 62 } 63 64 r->folio_off = folio_pos(r->folio); 65 r->addr = kmap_local_folio(r->folio, 0); 66 67 return 0; 68 } 69 70 const void *freader_fetch(struct freader *r, loff_t file_off, size_t sz) 71 { 72 size_t folio_sz; 73 74 /* provided internal temporary buffer should be sized correctly */ 75 if (WARN_ON(r->buf && sz > r->buf_sz)) { 76 r->err = -E2BIG; 77 return NULL; 78 } 79 80 if (unlikely(file_off + sz < file_off)) { 81 r->err = -EOVERFLOW; 82 return NULL; 83 } 84 85 /* working with memory buffer is much more straightforward */ 86 if (!r->buf) { 87 if (file_off + sz > r->data_sz) { 88 r->err = -ERANGE; 89 return NULL; 90 } 91 return r->data + file_off; 92 } 93 94 /* reject secretmem folios created with memfd_secret() */ 95 if (secretmem_mapping(r->file->f_mapping)) { 96 r->err = -EFAULT; 97 return NULL; 98 } 99 100 /* use __kernel_read() for sleepable context */ 101 if (r->may_fault) { 102 ssize_t ret; 103 104 ret = __kernel_read(r->file, r->buf, sz, &file_off); 105 if (ret != sz) { 106 r->err = (ret < 0) ? ret : -EIO; 107 return NULL; 108 } 109 return r->buf; 110 } 111 112 /* fetch or reuse folio for given file offset */ 113 r->err = freader_get_folio(r, file_off); 114 if (r->err) 115 return NULL; 116 117 /* if requested data is crossing folio boundaries, we have to copy 118 * everything into our local buffer to keep a simple linear memory 119 * access interface 120 */ 121 folio_sz = folio_size(r->folio); 122 if (file_off + sz > r->folio_off + folio_sz) { 123 u64 part_sz = r->folio_off + folio_sz - file_off, off; 124 125 memcpy(r->buf, r->addr + file_off - r->folio_off, part_sz); 126 off = part_sz; 127 128 while (off < sz) { 129 /* fetch next folio */ 130 r->err = freader_get_folio(r, r->folio_off + folio_sz); 131 if (r->err) 132 return NULL; 133 folio_sz = folio_size(r->folio); 134 part_sz = min_t(u64, sz - off, folio_sz); 135 memcpy(r->buf + off, r->addr, part_sz); 136 off += part_sz; 137 } 138 139 return r->buf; 140 } 141 142 /* if data fits in a single folio, just return direct pointer */ 143 return r->addr + (file_off - r->folio_off); 144 } 145 146 void freader_cleanup(struct freader *r) 147 { 148 if (!r->buf) 149 return; /* non-file-backed mode */ 150 151 freader_put_folio(r); 152 } 153 154 /* 155 * Parse build id from the note segment. This logic can be shared between 156 * 32-bit and 64-bit system, because Elf32_Nhdr and Elf64_Nhdr are 157 * identical. 158 */ 159 static int parse_build_id(struct freader *r, unsigned char *build_id, __u32 *size, 160 loff_t note_off, Elf32_Word note_size) 161 { 162 const char note_name[] = "GNU"; 163 const size_t note_name_sz = sizeof(note_name); 164 u32 build_id_off, new_off, note_end, name_sz, desc_sz; 165 const Elf32_Nhdr *nhdr; 166 const char *data; 167 168 if (check_add_overflow(note_off, note_size, ¬e_end)) 169 return -EINVAL; 170 171 while (note_end - note_off > sizeof(Elf32_Nhdr) + note_name_sz) { 172 nhdr = freader_fetch(r, note_off, sizeof(Elf32_Nhdr) + note_name_sz); 173 if (!nhdr) 174 return r->err; 175 176 name_sz = READ_ONCE(nhdr->n_namesz); 177 desc_sz = READ_ONCE(nhdr->n_descsz); 178 179 new_off = note_off + sizeof(Elf32_Nhdr); 180 if (check_add_overflow(new_off, ALIGN(name_sz, 4), &new_off) || 181 check_add_overflow(new_off, ALIGN(desc_sz, 4), &new_off) || 182 new_off > note_end) 183 break; 184 185 if (nhdr->n_type == BUILD_ID && 186 name_sz == note_name_sz && 187 memcmp(nhdr + 1, note_name, note_name_sz) == 0 && 188 desc_sz > 0 && desc_sz <= BUILD_ID_SIZE_MAX) { 189 build_id_off = note_off + sizeof(Elf32_Nhdr) + ALIGN(note_name_sz, 4); 190 191 /* freader_fetch() will invalidate nhdr pointer */ 192 data = freader_fetch(r, build_id_off, desc_sz); 193 if (!data) 194 return r->err; 195 196 memcpy(build_id, data, desc_sz); 197 memset(build_id + desc_sz, 0, BUILD_ID_SIZE_MAX - desc_sz); 198 if (size) 199 *size = desc_sz; 200 return 0; 201 } 202 203 note_off = new_off; 204 } 205 206 return -EINVAL; 207 } 208 209 /* Parse build ID from 32-bit ELF */ 210 static int get_build_id_32(struct freader *r, unsigned char *build_id, __u32 *size) 211 { 212 const Elf32_Ehdr *ehdr; 213 const Elf32_Phdr *phdr; 214 __u32 phnum, phoff, i; 215 216 ehdr = freader_fetch(r, 0, sizeof(Elf32_Ehdr)); 217 if (!ehdr) 218 return r->err; 219 220 /* subsequent freader_fetch() calls invalidate pointers, so remember locally */ 221 phnum = READ_ONCE(ehdr->e_phnum); 222 phoff = READ_ONCE(ehdr->e_phoff); 223 224 /* set upper bound on amount of segments (phdrs) we iterate */ 225 if (phnum > MAX_PHDR_CNT) 226 phnum = MAX_PHDR_CNT; 227 228 /* check that phoff is not large enough to cause an overflow */ 229 if (phoff + phnum * sizeof(Elf32_Phdr) < phoff) 230 return -EINVAL; 231 232 for (i = 0; i < phnum; ++i) { 233 phdr = freader_fetch(r, phoff + i * sizeof(Elf32_Phdr), sizeof(Elf32_Phdr)); 234 if (!phdr) 235 return r->err; 236 237 if (phdr->p_type == PT_NOTE && 238 !parse_build_id(r, build_id, size, READ_ONCE(phdr->p_offset), 239 READ_ONCE(phdr->p_filesz))) 240 return 0; 241 } 242 return -EINVAL; 243 } 244 245 /* Parse build ID from 64-bit ELF */ 246 static int get_build_id_64(struct freader *r, unsigned char *build_id, __u32 *size) 247 { 248 const Elf64_Ehdr *ehdr; 249 const Elf64_Phdr *phdr; 250 __u32 phnum, i; 251 __u64 phoff; 252 253 ehdr = freader_fetch(r, 0, sizeof(Elf64_Ehdr)); 254 if (!ehdr) 255 return r->err; 256 257 /* subsequent freader_fetch() calls invalidate pointers, so remember locally */ 258 phnum = READ_ONCE(ehdr->e_phnum); 259 phoff = READ_ONCE(ehdr->e_phoff); 260 261 /* set upper bound on amount of segments (phdrs) we iterate */ 262 if (phnum > MAX_PHDR_CNT) 263 phnum = MAX_PHDR_CNT; 264 265 /* check that phoff is not large enough to cause an overflow */ 266 if (phoff + phnum * sizeof(Elf64_Phdr) < phoff) 267 return -EINVAL; 268 269 for (i = 0; i < phnum; ++i) { 270 phdr = freader_fetch(r, phoff + i * sizeof(Elf64_Phdr), sizeof(Elf64_Phdr)); 271 if (!phdr) 272 return r->err; 273 274 if (phdr->p_type == PT_NOTE && 275 !parse_build_id(r, build_id, size, READ_ONCE(phdr->p_offset), 276 READ_ONCE(phdr->p_filesz))) 277 return 0; 278 } 279 280 return -EINVAL; 281 } 282 283 /* enough for Elf64_Ehdr, Elf64_Phdr, and all the smaller requests */ 284 #define MAX_FREADER_BUF_SZ 64 285 286 static int __build_id_parse(struct file *file, unsigned char *build_id, 287 __u32 *size, bool may_fault) 288 { 289 const Elf32_Ehdr *ehdr; 290 struct freader r; 291 char buf[MAX_FREADER_BUF_SZ]; 292 int ret; 293 294 freader_init_from_file(&r, buf, sizeof(buf), file, may_fault); 295 296 /* fetch first 18 bytes of ELF header for checks */ 297 ehdr = freader_fetch(&r, 0, offsetofend(Elf32_Ehdr, e_type)); 298 if (!ehdr) { 299 ret = r.err; 300 goto out; 301 } 302 303 ret = -EINVAL; 304 305 /* compare magic x7f "ELF" */ 306 if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) 307 goto out; 308 309 /* only support executable file and shared object file */ 310 if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) 311 goto out; 312 313 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32) 314 ret = get_build_id_32(&r, build_id, size); 315 else if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) 316 ret = get_build_id_64(&r, build_id, size); 317 out: 318 freader_cleanup(&r); 319 return ret; 320 } 321 322 /** 323 * build_id_parse_nofault() - Parse build ID of ELF file mapped to vma 324 * @vma: vma object 325 * @build_id: buffer to store build id, at least BUILD_ID_SIZE long 326 * @size: returns actual build id size in case of success 327 * 328 * Assumes no page fault can be taken, so if relevant portions of ELF file are 329 * not already paged in, fetching of build ID fails. 330 * 331 * Return: 0 on success; negative error, otherwise 332 */ 333 int build_id_parse_nofault(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size) 334 { 335 if (!vma->vm_file) 336 return -EINVAL; 337 338 return __build_id_parse(vma->vm_file, build_id, size, false /* !may_fault */); 339 } 340 341 /** 342 * build_id_parse() - Parse build ID of ELF file mapped to VMA 343 * @vma: vma object 344 * @build_id: buffer to store build id, at least BUILD_ID_SIZE long 345 * @size: returns actual build id size in case of success 346 * 347 * Assumes faultable context and can cause page faults to bring in file data 348 * into page cache. 349 * 350 * Return: 0 on success; negative error, otherwise 351 */ 352 int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size) 353 { 354 if (!vma->vm_file) 355 return -EINVAL; 356 357 return __build_id_parse(vma->vm_file, build_id, size, true /* may_fault */); 358 } 359 360 /** 361 * build_id_parse_file() - Parse build ID of ELF file 362 * @file: file object 363 * @build_id: buffer to store build id, at least BUILD_ID_SIZE long 364 * @size: returns actual build id size in case of success 365 * 366 * Assumes faultable context and can cause page faults to bring in file data 367 * into page cache. 368 * 369 * Return: 0 on success; negative error, otherwise 370 */ 371 int build_id_parse_file(struct file *file, unsigned char *build_id, __u32 *size) 372 { 373 return __build_id_parse(file, build_id, size, true /* may_fault */); 374 } 375 376 /** 377 * build_id_parse_buf - Get build ID from a buffer 378 * @buf: ELF note section(s) to parse 379 * @buf_size: Size of @buf in bytes 380 * @build_id: Build ID parsed from @buf, at least BUILD_ID_SIZE_MAX long 381 * 382 * Return: 0 on success, -EINVAL otherwise 383 */ 384 int build_id_parse_buf(const void *buf, unsigned char *build_id, u32 buf_size) 385 { 386 struct freader r; 387 int err; 388 389 freader_init_from_mem(&r, buf, buf_size); 390 391 err = parse_build_id(&r, build_id, NULL, 0, buf_size); 392 393 freader_cleanup(&r); 394 return err; 395 } 396 397 #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) || IS_ENABLED(CONFIG_VMCORE_INFO) 398 unsigned char vmlinux_build_id[BUILD_ID_SIZE_MAX] __ro_after_init; 399 400 /** 401 * init_vmlinux_build_id - Compute and stash the running kernel's build ID 402 */ 403 void __init init_vmlinux_build_id(void) 404 { 405 extern const void __start_notes; 406 extern const void __stop_notes; 407 unsigned int size = &__stop_notes - &__start_notes; 408 409 build_id_parse_buf(&__start_notes, vmlinux_build_id, size); 410 } 411 #endif 412