Commit 7eaf3cf3 authored by Stephen Boyd's avatar Stephen Boyd Committed by Linus Torvalds

buildid: add API to parse build ID out of buffer

Add an API that can parse the build ID out of a buffer, instead of a vma,
to support printing a kernel module's build ID for stack traces.

Link: https://lkml.kernel.org/r/20210511003845.2429846-3-swboyd@chromium.orgSigned-off-by: default avatarStephen Boyd <swboyd@chromium.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Jessica Yu <jeyu@kernel.org>
Cc: Evan Green <evgreen@chromium.org>
Cc: Hsin-Yi Wang <hsinyi@chromium.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Young <dyoung@redhat.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Petr Mladek <pmladek@suse.com>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: Sasha Levin <sashal@kernel.org>
Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent a010d79b
...@@ -8,5 +8,6 @@ ...@@ -8,5 +8,6 @@
int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id, int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
__u32 *size); __u32 *size);
int build_id_parse_buf(const void *buf, unsigned char *build_id, u32 buf_size);
#endif #endif
...@@ -2,30 +2,23 @@ ...@@ -2,30 +2,23 @@
#include <linux/buildid.h> #include <linux/buildid.h>
#include <linux/elf.h> #include <linux/elf.h>
#include <linux/kernel.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#define BUILD_ID 3 #define BUILD_ID 3
/* /*
* Parse build id from the note segment. This logic can be shared between * Parse build id from the note segment. This logic can be shared between
* 32-bit and 64-bit system, because Elf32_Nhdr and Elf64_Nhdr are * 32-bit and 64-bit system, because Elf32_Nhdr and Elf64_Nhdr are
* identical. * identical.
*/ */
static inline int parse_build_id(void *page_addr, static int parse_build_id_buf(unsigned char *build_id,
unsigned char *build_id, __u32 *size,
__u32 *size, const void *note_start,
void *note_start, Elf32_Word note_size)
Elf32_Word note_size)
{ {
Elf32_Word note_offs = 0, new_offs; Elf32_Word note_offs = 0, new_offs;
/* check for overflow */
if (note_start < page_addr || note_start + note_size < note_start)
return -EINVAL;
/* only supports note that fits in the first page */
if (note_start + note_size > page_addr + PAGE_SIZE)
return -EINVAL;
while (note_offs + sizeof(Elf32_Nhdr) < note_size) { while (note_offs + sizeof(Elf32_Nhdr) < note_size) {
Elf32_Nhdr *nhdr = (Elf32_Nhdr *)(note_start + note_offs); Elf32_Nhdr *nhdr = (Elf32_Nhdr *)(note_start + note_offs);
...@@ -50,9 +43,27 @@ static inline int parse_build_id(void *page_addr, ...@@ -50,9 +43,27 @@ static inline int parse_build_id(void *page_addr,
break; break;
note_offs = new_offs; note_offs = new_offs;
} }
return -EINVAL; return -EINVAL;
} }
static inline int parse_build_id(void *page_addr,
unsigned char *build_id,
__u32 *size,
void *note_start,
Elf32_Word note_size)
{
/* check for overflow */
if (note_start < page_addr || note_start + note_size < note_start)
return -EINVAL;
/* only supports note that fits in the first page */
if (note_start + note_size > page_addr + PAGE_SIZE)
return -EINVAL;
return parse_build_id_buf(build_id, size, note_start, note_size);
}
/* Parse build ID from 32-bit ELF */ /* Parse build ID from 32-bit ELF */
static int get_build_id_32(void *page_addr, unsigned char *build_id, static int get_build_id_32(void *page_addr, unsigned char *build_id,
__u32 *size) __u32 *size)
...@@ -148,3 +159,16 @@ int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id, ...@@ -148,3 +159,16 @@ int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
put_page(page); put_page(page);
return ret; return ret;
} }
/**
* build_id_parse_buf - Get build ID from a buffer
* @buf: Elf note section(s) to parse
* @buf_size: Size of @buf in bytes
* @build_id: Build ID parsed from @buf, at least BUILD_ID_SIZE_MAX long
*
* Return: 0 on success, -EINVAL otherwise
*/
int build_id_parse_buf(const void *buf, unsigned char *build_id, u32 buf_size)
{
return parse_build_id_buf(build_id, NULL, buf, buf_size);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment