Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions include/linux/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -1362,12 +1362,18 @@ struct bpf_prog *bpf_prog_ksym_find(unsigned long addr);

static inline int
bpf_address_lookup(unsigned long addr, unsigned long *size,
unsigned long *off, char **modname, char *sym)
unsigned long *off, char **modname,
const unsigned char **modbuildid, char *sym)
{
int ret = __bpf_address_lookup(addr, size, off, sym);

if (ret && modname)
*modname = NULL;
if (ret) {
if (modname)
*modname = NULL;
if (modbuildid)
*modbuildid = NULL;
}

return ret;
}

Expand Down Expand Up @@ -1433,7 +1439,8 @@ static inline struct bpf_prog *bpf_prog_ksym_find(unsigned long addr)

static inline int
bpf_address_lookup(unsigned long addr, unsigned long *size,
unsigned long *off, char **modname, char *sym)
unsigned long *off, char **modname,
const unsigned char **modbuildid, char *sym)
{
return 0;
}
Expand Down
6 changes: 4 additions & 2 deletions include/linux/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,13 @@ struct ftrace_hash;
defined(CONFIG_DYNAMIC_FTRACE)
int
ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
unsigned long *off, char **modname, char *sym);
unsigned long *off, char **modname,
const unsigned char **modbuildid, char *sym);
#else
static inline int
ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
unsigned long *off, char **modname, char *sym)
unsigned long *off, char **modname,
const unsigned char **modbuildid, char *sym)
{
return 0;
}
Expand Down
9 changes: 9 additions & 0 deletions include/linux/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,15 @@ static inline void __module_get(struct module *module)
__mod ? __mod->name : "kernel"; \
})

static inline const unsigned char *module_buildid(struct module *mod)
{
#ifdef CONFIG_STACKTRACE_BUILD_ID
return mod->build_id;
#else
return NULL;
#endif
}

/* Dereference module function descriptor */
void *dereference_module_function_descriptor(struct module *mod, void *ptr);

Expand Down
60 changes: 46 additions & 14 deletions kernel/kallsyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,12 @@ static int kallsyms_lookup_buildid(unsigned long addr,
{
int ret;

namebuf[KSYM_NAME_LEN - 1] = 0;
/*
* kallsyms_lookus() returns pointer to namebuf on success and
* NULL on error. But some callers ignore the return value.
* Instead they expect @namebuf filled either with valid
* or empty string.
*/
namebuf[0] = 0;

if (is_ksym_addr(addr)) {
Expand All @@ -374,12 +379,12 @@ static int kallsyms_lookup_buildid(unsigned long addr,
ret = module_address_lookup(addr, symbolsize, offset,
modname, modbuildid, namebuf);
if (!ret)
ret = bpf_address_lookup(addr, symbolsize,
offset, modname, namebuf);
ret = bpf_address_lookup(addr, symbolsize, offset,
modname, modbuildid, namebuf);

if (!ret)
ret = ftrace_mod_address_lookup(addr, symbolsize,
offset, modname, namebuf);
ret = ftrace_mod_address_lookup(addr, symbolsize, offset,
modname, modbuildid, namebuf);

return ret;
}
Expand Down Expand Up @@ -423,6 +428,37 @@ int lookup_symbol_name(unsigned long addr, char *symname)
return lookup_module_symbol_name(addr, symname);
}

#ifdef CONFIG_STACKTRACE_BUILD_ID

static int append_buildid(char *buffer, const char *modname,
const unsigned char *buildid)
{
if (!modname)
return 0;

if (!buildid) {
pr_warn_once("Undefined buildid for the module %s\n", modname);
return 0;
}

/* build ID should match length of sprintf */
#ifdef CONFIG_MODULES
static_assert(sizeof(typeof_member(struct module, build_id)) == 20);
#endif

return sprintf(buffer, " %20phN", buildid);
}

#else /* CONFIG_STACKTRACE_BUILD_ID */

static int append_buildid(char *buffer, const char *modname,
const unsigned char *buildid)
{
return 0;
}

#endif /* CONFIG_STACKTRACE_BUILD_ID */

/* Look up a kernel symbol and return it in a text buffer. */
static int __sprint_symbol(char *buffer, unsigned long address,
int symbol_offset, int add_offset, int add_buildid)
Expand All @@ -432,6 +468,9 @@ static int __sprint_symbol(char *buffer, unsigned long address,
unsigned long offset, size;
int len;

/* Prevent module removal until modname and modbuildid are printed */
guard(rcu)();

address += symbol_offset;
len = kallsyms_lookup_buildid(address, &size, &offset, &modname, &buildid,
buffer);
Expand All @@ -445,15 +484,8 @@ static int __sprint_symbol(char *buffer, unsigned long address,

if (modname) {
len += sprintf(buffer + len, " [%s", modname);
#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)
if (add_buildid && buildid) {
/* build ID should match length of sprintf */
#if IS_ENABLED(CONFIG_MODULES)
static_assert(sizeof(typeof_member(struct module, build_id)) == 20);
#endif
len += sprintf(buffer + len, " %20phN", buildid);
}
#endif
if (add_buildid)
len += append_buildid(buffer + len, modname, buildid);
len += sprintf(buffer + len, "]");
}

Expand Down
9 changes: 2 additions & 7 deletions kernel/module/kallsyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,13 +334,8 @@ int module_address_lookup(unsigned long addr,
if (mod) {
if (modname)
*modname = mod->name;
if (modbuildid) {
#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)
*modbuildid = mod->build_id;
#else
*modbuildid = NULL;
#endif
}
if (modbuildid)
*modbuildid = module_buildid(mod);

sym = find_kallsyms_symbol(mod, addr, size, offset);

Expand Down
5 changes: 4 additions & 1 deletion kernel/trace/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -7678,7 +7678,8 @@ ftrace_func_address_lookup(struct ftrace_mod_map *mod_map,

int
ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
unsigned long *off, char **modname, char *sym)
unsigned long *off, char **modname,
const unsigned char **modbuildid, char *sym)
{
struct ftrace_mod_map *mod_map;
int ret = 0;
Expand All @@ -7690,6 +7691,8 @@ ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
if (ret) {
if (modname)
*modname = mod_map->mod->name;
if (modbuildid)
*modbuildid = module_buildid(mod_map->mod);
break;
}
}
Expand Down
Loading