Commit b5374396 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'modules-5.19-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux

Pull module fixes from Luis Chamberlain:
 "Although most of the move of code in in v5.19-rc1 should have not
  introduced a regression patch review on one of the file changes
  captured a checkpatch warning which advised to use strscpy() and it
  caused a buffer overflow when an incorrect length is passed.

  Another change which checkpatch complained about was an odd RCU usage,
  but that was properly addressed in a separate patch to the move by
  Aaron. That caused a regression with PREEMPT_RT=y due to an unbounded
  latency.

  This series fixes both and adjusts documentation which we forgot to do
  for the move"

* tag 'modules-5.19-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux:
  module: kallsyms: Ensure preemption in add_kallsyms() with PREEMPT_RT
  doc: module: update file references
  module: Fix "warning: variable 'exit' set but not used"
  module: Fix selfAssignment cppcheck warning
  modules: Fix corruption of /proc/kallsyms
parents 816e51df e69a6614
...@@ -223,7 +223,7 @@ Module Loading ...@@ -223,7 +223,7 @@ Module Loading
Inter Module support Inter Module support
-------------------- --------------------
Refer to the file kernel/module.c for more information. Refer to the files in kernel/module/ for more information.
Hardware Interfaces Hardware Interfaces
=================== ===================
......
...@@ -51,8 +51,8 @@ namespace ``USB_STORAGE``, use:: ...@@ -51,8 +51,8 @@ namespace ``USB_STORAGE``, use::
The corresponding ksymtab entry struct ``kernel_symbol`` will have the member The corresponding ksymtab entry struct ``kernel_symbol`` will have the member
``namespace`` set accordingly. A symbol that is exported without a namespace will ``namespace`` set accordingly. A symbol that is exported without a namespace will
refer to ``NULL``. There is no default namespace if none is defined. ``modpost`` refer to ``NULL``. There is no default namespace if none is defined. ``modpost``
and kernel/module.c make use the namespace at build time or module load time, and kernel/module/main.c make use the namespace at build time or module load
respectively. time, respectively.
2.2 Using the DEFAULT_SYMBOL_NAMESPACE define 2.2 Using the DEFAULT_SYMBOL_NAMESPACE define
============================================= =============================================
......
...@@ -210,11 +210,11 @@ module->symtab. ...@@ -210,11 +210,11 @@ module->symtab.
===================================== =====================================
Normally, a stripped down copy of a module's symbol table (containing only Normally, a stripped down copy of a module's symbol table (containing only
"core" symbols) is made available through module->symtab (See layout_symtab() "core" symbols) is made available through module->symtab (See layout_symtab()
in kernel/module.c). For livepatch modules, the symbol table copied into memory in kernel/module/kallsyms.c). For livepatch modules, the symbol table copied
on module load must be exactly the same as the symbol table produced when the into memory on module load must be exactly the same as the symbol table produced
patch module was compiled. This is because the relocations in each livepatch when the patch module was compiled. This is because the relocations in each
relocation section refer to their respective symbols with their symbol indices, livepatch relocation section refer to their respective symbols with their symbol
and the original symbol indices (and thus the symtab ordering) must be indices, and the original symbol indices (and thus the symtab ordering) must be
preserved in order for apply_relocate_add() to find the right symbol. preserved in order for apply_relocate_add() to find the right symbol.
For example, take this particular rela from a livepatch module::: For example, take this particular rela from a livepatch module:::
......
...@@ -50,9 +50,9 @@ Di conseguenza, nella tabella dei simboli del kernel ci sarà una voce ...@@ -50,9 +50,9 @@ Di conseguenza, nella tabella dei simboli del kernel ci sarà una voce
rappresentata dalla struttura ``kernel_symbol`` che avrà il campo rappresentata dalla struttura ``kernel_symbol`` che avrà il campo
``namespace`` (spazio dei nomi) impostato. Un simbolo esportato senza uno spazio ``namespace`` (spazio dei nomi) impostato. Un simbolo esportato senza uno spazio
dei nomi avrà questo campo impostato a ``NULL``. Non esiste uno spazio dei nomi dei nomi avrà questo campo impostato a ``NULL``. Non esiste uno spazio dei nomi
di base. Il programma ``modpost`` e il codice in kernel/module.c usano lo spazio di base. Il programma ``modpost`` e il codice in kernel/module/main.c usano lo
dei nomi, rispettivamente, durante la compilazione e durante il caricamento spazio dei nomi, rispettivamente, durante la compilazione e durante il
di un modulo. caricamento di un modulo.
2.2 Usare il simbolo di preprocessore DEFAULT_SYMBOL_NAMESPACE 2.2 Usare il simbolo di preprocessore DEFAULT_SYMBOL_NAMESPACE
============================================================== ==============================================================
......
...@@ -224,7 +224,7 @@ kernel/kmod.c ...@@ -224,7 +224,7 @@ kernel/kmod.c
模块接口支持 模块接口支持
------------ ------------
更多信息请参考文件kernel/module.c 更多信息请参阅kernel/module/目录下的文件
硬件接口 硬件接口
======== ========
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
相应的 ksymtab 条目结构体 ``kernel_symbol`` 将有相应的成员 ``命名空间`` 集。 相应的 ksymtab 条目结构体 ``kernel_symbol`` 将有相应的成员 ``命名空间`` 集。
导出时未指明命名空间的符号将指向 ``NULL`` 。如果没有定义命名空间,则默认没有。 导出时未指明命名空间的符号将指向 ``NULL`` 。如果没有定义命名空间,则默认没有。
``modpost`` 和kernel/module.c分别在构建时或模块加载时使用名称空间。 ``modpost`` 和kernel/module/main.c分别在构建时或模块加载时使用名称空间。
2.2 使用DEFAULT_SYMBOL_NAMESPACE定义 2.2 使用DEFAULT_SYMBOL_NAMESPACE定义
==================================== ====================================
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/rculist.h> #include <linux/rculist.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/mm.h>
#ifndef ARCH_SHF_SMALL #ifndef ARCH_SHF_SMALL
#define ARCH_SHF_SMALL 0 #define ARCH_SHF_SMALL 0
...@@ -30,11 +31,13 @@ ...@@ -30,11 +31,13 @@
* to ensure complete separation of code and data, but * to ensure complete separation of code and data, but
* only when CONFIG_STRICT_MODULE_RWX=y * only when CONFIG_STRICT_MODULE_RWX=y
*/ */
#ifdef CONFIG_STRICT_MODULE_RWX static inline unsigned int strict_align(unsigned int size)
# define strict_align(X) PAGE_ALIGN(X) {
#else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
# define strict_align(X) (X) return PAGE_ALIGN(size);
#endif else
return size;
}
extern struct mutex module_mutex; extern struct mutex module_mutex;
extern struct list_head modules; extern struct list_head modules;
......
...@@ -137,6 +137,7 @@ void layout_symtab(struct module *mod, struct load_info *info) ...@@ -137,6 +137,7 @@ void layout_symtab(struct module *mod, struct load_info *info)
info->symoffs = ALIGN(mod->data_layout.size, symsect->sh_addralign ?: 1); info->symoffs = ALIGN(mod->data_layout.size, symsect->sh_addralign ?: 1);
info->stroffs = mod->data_layout.size = info->symoffs + ndst * sizeof(Elf_Sym); info->stroffs = mod->data_layout.size = info->symoffs + ndst * sizeof(Elf_Sym);
mod->data_layout.size += strtab_size; mod->data_layout.size += strtab_size;
/* Note add_kallsyms() computes strtab_size as core_typeoffs - stroffs */
info->core_typeoffs = mod->data_layout.size; info->core_typeoffs = mod->data_layout.size;
mod->data_layout.size += ndst * sizeof(char); mod->data_layout.size += ndst * sizeof(char);
mod->data_layout.size = strict_align(mod->data_layout.size); mod->data_layout.size = strict_align(mod->data_layout.size);
...@@ -169,19 +170,20 @@ void add_kallsyms(struct module *mod, const struct load_info *info) ...@@ -169,19 +170,20 @@ void add_kallsyms(struct module *mod, const struct load_info *info)
Elf_Sym *dst; Elf_Sym *dst;
char *s; char *s;
Elf_Shdr *symsec = &info->sechdrs[info->index.sym]; Elf_Shdr *symsec = &info->sechdrs[info->index.sym];
unsigned long strtab_size;
/* Set up to point into init section. */ /* Set up to point into init section. */
mod->kallsyms = (void __rcu *)mod->init_layout.base + mod->kallsyms = (void __rcu *)mod->init_layout.base +
info->mod_kallsyms_init_off; info->mod_kallsyms_init_off;
preempt_disable(); rcu_read_lock();
/* The following is safe since this pointer cannot change */ /* The following is safe since this pointer cannot change */
rcu_dereference_sched(mod->kallsyms)->symtab = (void *)symsec->sh_addr; rcu_dereference(mod->kallsyms)->symtab = (void *)symsec->sh_addr;
rcu_dereference_sched(mod->kallsyms)->num_symtab = symsec->sh_size / sizeof(Elf_Sym); rcu_dereference(mod->kallsyms)->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
/* Make sure we get permanent strtab: don't use info->strtab. */ /* Make sure we get permanent strtab: don't use info->strtab. */
rcu_dereference_sched(mod->kallsyms)->strtab = rcu_dereference(mod->kallsyms)->strtab =
(void *)info->sechdrs[info->index.str].sh_addr; (void *)info->sechdrs[info->index.str].sh_addr;
rcu_dereference_sched(mod->kallsyms)->typetab = mod->init_layout.base + info->init_typeoffs; rcu_dereference(mod->kallsyms)->typetab = mod->init_layout.base + info->init_typeoffs;
/* /*
* Now populate the cut down core kallsyms for after init * Now populate the cut down core kallsyms for after init
...@@ -190,22 +192,29 @@ void add_kallsyms(struct module *mod, const struct load_info *info) ...@@ -190,22 +192,29 @@ void add_kallsyms(struct module *mod, const struct load_info *info)
mod->core_kallsyms.symtab = dst = mod->data_layout.base + info->symoffs; mod->core_kallsyms.symtab = dst = mod->data_layout.base + info->symoffs;
mod->core_kallsyms.strtab = s = mod->data_layout.base + info->stroffs; mod->core_kallsyms.strtab = s = mod->data_layout.base + info->stroffs;
mod->core_kallsyms.typetab = mod->data_layout.base + info->core_typeoffs; mod->core_kallsyms.typetab = mod->data_layout.base + info->core_typeoffs;
src = rcu_dereference_sched(mod->kallsyms)->symtab; strtab_size = info->core_typeoffs - info->stroffs;
for (ndst = i = 0; i < rcu_dereference_sched(mod->kallsyms)->num_symtab; i++) { src = rcu_dereference(mod->kallsyms)->symtab;
rcu_dereference_sched(mod->kallsyms)->typetab[i] = elf_type(src + i, info); for (ndst = i = 0; i < rcu_dereference(mod->kallsyms)->num_symtab; i++) {
rcu_dereference(mod->kallsyms)->typetab[i] = elf_type(src + i, info);
if (i == 0 || is_livepatch_module(mod) || if (i == 0 || is_livepatch_module(mod) ||
is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum, is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
info->index.pcpu)) { info->index.pcpu)) {
ssize_t ret;
mod->core_kallsyms.typetab[ndst] = mod->core_kallsyms.typetab[ndst] =
rcu_dereference_sched(mod->kallsyms)->typetab[i]; rcu_dereference(mod->kallsyms)->typetab[i];
dst[ndst] = src[i]; dst[ndst] = src[i];
dst[ndst++].st_name = s - mod->core_kallsyms.strtab; dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
s += strscpy(s, ret = strscpy(s,
&rcu_dereference_sched(mod->kallsyms)->strtab[src[i].st_name], &rcu_dereference(mod->kallsyms)->strtab[src[i].st_name],
KSYM_NAME_LEN) + 1; strtab_size);
if (ret < 0)
break;
s += ret + 1;
strtab_size -= ret + 1;
} }
} }
preempt_enable(); rcu_read_unlock();
mod->core_kallsyms.num_symtab = ndst; mod->core_kallsyms.num_symtab = ndst;
} }
......
...@@ -2939,24 +2939,25 @@ static void cfi_init(struct module *mod) ...@@ -2939,24 +2939,25 @@ static void cfi_init(struct module *mod)
{ {
#ifdef CONFIG_CFI_CLANG #ifdef CONFIG_CFI_CLANG
initcall_t *init; initcall_t *init;
#ifdef CONFIG_MODULE_UNLOAD
exitcall_t *exit; exitcall_t *exit;
#endif
rcu_read_lock_sched(); rcu_read_lock_sched();
mod->cfi_check = (cfi_check_fn) mod->cfi_check = (cfi_check_fn)
find_kallsyms_symbol_value(mod, "__cfi_check"); find_kallsyms_symbol_value(mod, "__cfi_check");
init = (initcall_t *) init = (initcall_t *)
find_kallsyms_symbol_value(mod, "__cfi_jt_init_module"); find_kallsyms_symbol_value(mod, "__cfi_jt_init_module");
exit = (exitcall_t *)
find_kallsyms_symbol_value(mod, "__cfi_jt_cleanup_module");
rcu_read_unlock_sched();
/* Fix init/exit functions to point to the CFI jump table */ /* Fix init/exit functions to point to the CFI jump table */
if (init) if (init)
mod->init = *init; mod->init = *init;
#ifdef CONFIG_MODULE_UNLOAD #ifdef CONFIG_MODULE_UNLOAD
exit = (exitcall_t *)
find_kallsyms_symbol_value(mod, "__cfi_jt_cleanup_module");
if (exit) if (exit)
mod->exit = *exit; mod->exit = *exit;
#endif #endif
rcu_read_unlock_sched();
cfi_module_add(mod, mod_tree.addr_min); cfi_module_add(mod, mod_tree.addr_min);
#endif #endif
......
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