1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/buildid.h>
5 #include <linux/pagemap.h>
9 * Parse build id from the note segment. This logic can be shared between
10 * 32-bit and 64-bit system, because Elf32_Nhdr and Elf64_Nhdr are
13 static inline int parse_build_id(void *page_addr,
14 unsigned char *build_id,
18 Elf32_Word note_offs = 0, new_offs;
20 /* check for overflow */
21 if (note_start < page_addr || note_start + note_size < note_start)
24 /* only supports note that fits in the first page */
25 if (note_start + note_size > page_addr + PAGE_SIZE)
28 while (note_offs + sizeof(Elf32_Nhdr) < note_size) {
29 Elf32_Nhdr *nhdr = (Elf32_Nhdr *)(note_start + note_offs);
31 if (nhdr->n_type == BUILD_ID &&
32 nhdr->n_namesz == sizeof("GNU") &&
34 nhdr->n_descsz <= BUILD_ID_SIZE_MAX) {
36 note_start + note_offs +
37 ALIGN(sizeof("GNU"), 4) + sizeof(Elf32_Nhdr),
39 memset(build_id + nhdr->n_descsz, 0,
40 BUILD_ID_SIZE_MAX - nhdr->n_descsz);
43 new_offs = note_offs + sizeof(Elf32_Nhdr) +
44 ALIGN(nhdr->n_namesz, 4) + ALIGN(nhdr->n_descsz, 4);
45 if (new_offs <= note_offs) /* overflow */
52 /* Parse build ID from 32-bit ELF */
53 static int get_build_id_32(void *page_addr, unsigned char *build_id)
55 Elf32_Ehdr *ehdr = (Elf32_Ehdr *)page_addr;
59 /* only supports phdr that fits in one page */
61 (PAGE_SIZE - sizeof(Elf32_Ehdr)) / sizeof(Elf32_Phdr))
64 phdr = (Elf32_Phdr *)(page_addr + sizeof(Elf32_Ehdr));
66 for (i = 0; i < ehdr->e_phnum; ++i) {
67 if (phdr[i].p_type == PT_NOTE &&
68 !parse_build_id(page_addr, build_id,
69 page_addr + phdr[i].p_offset,
76 /* Parse build ID from 64-bit ELF */
77 static int get_build_id_64(void *page_addr, unsigned char *build_id)
79 Elf64_Ehdr *ehdr = (Elf64_Ehdr *)page_addr;
83 /* only supports phdr that fits in one page */
85 (PAGE_SIZE - sizeof(Elf64_Ehdr)) / sizeof(Elf64_Phdr))
88 phdr = (Elf64_Phdr *)(page_addr + sizeof(Elf64_Ehdr));
90 for (i = 0; i < ehdr->e_phnum; ++i) {
91 if (phdr[i].p_type == PT_NOTE &&
92 !parse_build_id(page_addr, build_id,
93 page_addr + phdr[i].p_offset,
100 /* Parse build ID of ELF file mapped to vma */
101 int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id)
108 /* only works for page backed storage */
112 page = find_get_page(vma->vm_file->f_mapping, 0);
114 return -EFAULT; /* page not mapped */
117 page_addr = kmap_atomic(page);
118 ehdr = (Elf32_Ehdr *)page_addr;
120 /* compare magic x7f "ELF" */
121 if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0)
124 /* only support executable file and shared object file */
125 if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
128 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
129 ret = get_build_id_32(page_addr, build_id);
130 else if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
131 ret = get_build_id_64(page_addr, build_id);
133 kunmap_atomic(page_addr);