Skip to content
Closed
2 changes: 1 addition & 1 deletion arch/arm64/net/bpf_jit_comp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2939,7 +2939,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
u64 plt_target = 0ULL;
bool poking_bpf_entry;

if (!__bpf_address_lookup((unsigned long)ip, &size, &offset, namebuf))
if (!bpf_address_lookup((unsigned long)ip, &size, &offset, namebuf))
/* Only poking bpf text is supported. Since kernel function
* entry is set up by ftrace, we reply on ftrace to poke kernel
* functions.
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/net/bpf_jit_comp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1122,7 +1122,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
branch_flags = poke_type == BPF_MOD_CALL ? BRANCH_SET_LINK : 0;

/* We currently only support poking bpf programs */
if (!__bpf_address_lookup(bpf_func, &size, &offset, name)) {
if (!bpf_address_lookup(bpf_func, &size, &offset, name)) {
pr_err("%s (0x%lx): kernel/modules are not supported\n", __func__, bpf_func);
return -EOPNOTSUPP;
}
Expand Down
26 changes: 4 additions & 22 deletions include/linux/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -1353,24 +1353,13 @@ static inline bool bpf_jit_kallsyms_enabled(void)
return false;
}

int __bpf_address_lookup(unsigned long addr, unsigned long *size,
unsigned long *off, char *sym);
int bpf_address_lookup(unsigned long addr, unsigned long *size,
unsigned long *off, char *sym);
bool is_bpf_text_address(unsigned long addr);
int bpf_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
char *sym);
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)
{
int ret = __bpf_address_lookup(addr, size, off, sym);

if (ret && modname)
*modname = NULL;
return ret;
}

void bpf_prog_kallsyms_add(struct bpf_prog *fp);
void bpf_prog_kallsyms_del(struct bpf_prog *fp);

Expand Down Expand Up @@ -1409,8 +1398,8 @@ static inline bool bpf_jit_kallsyms_enabled(void)
}

static inline int
__bpf_address_lookup(unsigned long addr, unsigned long *size,
unsigned long *off, char *sym)
bpf_address_lookup(unsigned long addr, unsigned long *size,
unsigned long *off, char *sym)
{
return 0;
}
Expand All @@ -1431,13 +1420,6 @@ static inline struct bpf_prog *bpf_prog_ksym_find(unsigned long addr)
return NULL;
}

static inline int
bpf_address_lookup(unsigned long addr, unsigned long *size,
unsigned long *off, char **modname, char *sym)
{
return 0;
}

static inline void bpf_prog_kallsyms_add(struct bpf_prog *fp)
{
}
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
4 changes: 2 additions & 2 deletions kernel/bpf/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,8 +713,8 @@ static struct bpf_ksym *bpf_ksym_find(unsigned long addr)
return n ? container_of(n, struct bpf_ksym, tnode) : NULL;
}

int __bpf_address_lookup(unsigned long addr, unsigned long *size,
unsigned long *off, char *sym)
int bpf_address_lookup(unsigned long addr, unsigned long *size,
unsigned long *off, char *sym)
{
struct bpf_ksym *ksym;
int ret = 0;
Expand Down
73 changes: 54 additions & 19 deletions kernel/kallsyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
return 1;
}
return !!module_address_lookup(addr, symbolsize, offset, NULL, NULL, namebuf) ||
!!__bpf_address_lookup(addr, symbolsize, offset, namebuf);
!!bpf_address_lookup(addr, symbolsize, offset, namebuf);
}

static int kallsyms_lookup_buildid(unsigned long addr,
Expand All @@ -352,8 +352,21 @@ 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;
/*
* Initialize the module-related return values. They are not set
* when the symbol is in vmlinux or it is a bpf address.
*/
if (modname)
*modname = NULL;
if (modbuildid)
*modbuildid = NULL;

if (is_ksym_addr(addr)) {
unsigned long pos;
Expand All @@ -362,10 +375,6 @@ static int kallsyms_lookup_buildid(unsigned long addr,
/* Grab name */
kallsyms_expand_symbol(get_symbol_offset(pos),
namebuf, KSYM_NAME_LEN);
if (modname)
*modname = NULL;
if (modbuildid)
*modbuildid = NULL;

return strlen(namebuf);
}
Expand All @@ -374,12 +383,11 @@ 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, 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 +431,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 +471,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 +487,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