Skip to content

Commit

Permalink
kernel: Add kallsyms_on_each_symbol variant for single module
Browse files Browse the repository at this point in the history
The module_kallsyms_on_each_symbol function iterates over symbols of all
modules. To implement BTF ID set processing in each module's BTF parsing
routine, we need a variant that can iterate over a single module's
symbols. To implement this, extract the single module functionality out
of module_kallsyms_on_each_symbol, and rename the old function to
module_kallsyms_on_each_symbol_all.

Then, the new module_kallsyms_on_each_symbol which iterates over a
single module's symbols uses this extracted helper with appropriate
locking.

Next commit will make use of it to implement BTF ID set concatentation
per hook and type.

Also, since we'll be using kallsyms_on_each_symbol for vmlinux BTF
parsing, remove its dependency on CONFIG_LIVEPATCH.

Cc: Luis Chamberlain <mcgrof@kernel.org>
Cc: Jessica Yu <jeyu@kernel.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Jiri Kosina <jikos@kernel.org>
Cc: Miroslav Benes <mbenes@suse.cz>
Cc: Petr Mladek <pmladek@suse.com>
Cc: Joe Lawrence <joe.lawrence@redhat.com>
Cc: live-patching@vger.kernel.org
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
  • Loading branch information
kkdwivedi authored and intel-lab-lkp committed Dec 30, 2021
1 parent 3ccdcee commit 25d6b43
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 21 deletions.
11 changes: 10 additions & 1 deletion include/linux/kallsyms.h
Expand Up @@ -65,11 +65,12 @@ static inline void *dereference_symbol_descriptor(void *ptr)
return ptr;
}

#ifdef CONFIG_KALLSYMS

int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
unsigned long),
void *data);

#ifdef CONFIG_KALLSYMS
/* Lookup the address for a symbol. Returns 0 if not found. */
unsigned long kallsyms_lookup_name(const char *name);

Expand Down Expand Up @@ -98,6 +99,14 @@ extern bool kallsyms_show_value(const struct cred *cred);

#else /* !CONFIG_KALLSYMS */

static inline int kallsyms_on_each_symbol(int (*fn)(void *, const char *,
struct module *,
unsigned long),
void *data)
{
return 0;
}

static inline unsigned long kallsyms_lookup_name(const char *name)
{
return 0;
Expand Down
37 changes: 36 additions & 1 deletion include/linux/module.h
Expand Up @@ -867,8 +867,43 @@ static inline bool module_sig_ok(struct module *module)
}
#endif /* CONFIG_MODULE_SIG */

int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
#if defined(CONFIG_MODULES) && defined(CONFIG_KALLSYMS)

#ifdef CONFIG_LIVEPATCH

int module_kallsyms_on_each_symbol_all(int (*fn)(void *, const char *,
struct module *,
unsigned long),
void *data);

#else /* !CONFIG_LIVEPATCH */

static inline int module_kallsyms_on_each_symbol_all(int (*fn)(void *, const char *,
struct module *,
unsigned long),
void *data)
{
return 0;
}

#endif /* CONFIG_LIVEPATCH */

int module_kallsyms_on_each_symbol(struct module *mod,
int (*fn)(void *, const char *,
struct module *, unsigned long),
void *data);

#else /* !(CONFIG_MODULES && CONFIG_KALLSYMS) */

static inline int module_kallsyms_on_each_symbol(struct module *mod,
int (*fn)(void *, const char *,
struct module *,
unsigned long),
void *data)
{
return 0;
}

#endif /* CONFIG_MODULES && CONFIG_KALLSYMS */

#endif /* _LINUX_MODULE_H */
4 changes: 1 addition & 3 deletions kernel/kallsyms.c
Expand Up @@ -224,10 +224,9 @@ unsigned long kallsyms_lookup_name(const char *name)
return module_kallsyms_lookup_name(name);
}

#ifdef CONFIG_LIVEPATCH
/*
* Iterate over all symbols in vmlinux. For symbols from modules use
* module_kallsyms_on_each_symbol instead.
* module_kallsyms_on_each_symbol_all instead.
*/
int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
unsigned long),
Expand All @@ -246,7 +245,6 @@ int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
}
return 0;
}
#endif /* CONFIG_LIVEPATCH */

static unsigned long get_symbol_pos(unsigned long addr,
unsigned long *symbolsize,
Expand Down
2 changes: 1 addition & 1 deletion kernel/livepatch/core.c
Expand Up @@ -165,7 +165,7 @@ static int klp_find_object_symbol(const char *objname, const char *name,
};

if (objname)
module_kallsyms_on_each_symbol(klp_find_callback, &args);
module_kallsyms_on_each_symbol_all(klp_find_callback, &args);
else
kallsyms_on_each_symbol(klp_find_callback, &args);

Expand Down
62 changes: 47 additions & 15 deletions kernel/module.c
Expand Up @@ -4473,13 +4473,54 @@ unsigned long module_kallsyms_lookup_name(const char *name)
return ret;
}

#ifdef CONFIG_LIVEPATCH
int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
static int __module_kallsyms_on_each_symbol(struct mod_kallsyms *kallsyms,
struct module *mod,
int (*fn)(void *, const char *,
struct module *, unsigned long),
void *data)
{
unsigned long i;
int ret = 0;

for (i = 0; i < kallsyms->num_symtab; i++) {
const Elf_Sym *sym = &kallsyms->symtab[i];

if (sym->st_shndx == SHN_UNDEF)
continue;

ret = fn(data, kallsyms_symbol_name(kallsyms, i),
mod, kallsyms_symbol_value(sym));
if (ret != 0)
break;
}

return ret;
}

int module_kallsyms_on_each_symbol(struct module *mod,
int (*fn)(void *, const char *,
struct module *, unsigned long),
void *data)
{
struct mod_kallsyms *kallsyms;
int ret = 0;

mutex_lock(&module_mutex);
/* We hold module_mutex: no need for rcu_dereference_sched */
kallsyms = mod->kallsyms;
if (mod->state != MODULE_STATE_UNFORMED)
ret = __module_kallsyms_on_each_symbol(kallsyms, mod, fn, data);
mutex_unlock(&module_mutex);

return ret;
}

#ifdef CONFIG_LIVEPATCH
int module_kallsyms_on_each_symbol_all(int (*fn)(void *, const char *,
struct module *, unsigned long),
void *data)
{
struct module *mod;
unsigned int i;
int ret = 0;

mutex_lock(&module_mutex);
Expand All @@ -4489,19 +4530,10 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,

if (mod->state == MODULE_STATE_UNFORMED)
continue;
for (i = 0; i < kallsyms->num_symtab; i++) {
const Elf_Sym *sym = &kallsyms->symtab[i];

if (sym->st_shndx == SHN_UNDEF)
continue;

ret = fn(data, kallsyms_symbol_name(kallsyms, i),
mod, kallsyms_symbol_value(sym));
if (ret != 0)
goto out;
}
ret = __module_kallsyms_on_each_symbol(kallsyms, mod, fn, data);
if (ret != 0)
break;
}
out:
mutex_unlock(&module_mutex);
return ret;
}
Expand Down

0 comments on commit 25d6b43

Please sign in to comment.