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