Skip to content

Commit 039de46

Browse files
Sebastian Andrzej Siewiorpetrpavlu
authored andcommitted
module: Use proper RCU assignment in add_kallsyms().
add_kallsyms() assigns the RCU pointer module::kallsyms and setups the structures behind it which point to init-data. The module was not published yet, nothing can see the kallsyms pointer and the data behind it. Also module's init function was not yet invoked. There is no need to use rcu_dereference() here, it is just to keep checkers quiet. The whole RCU read section is also not needed. Use a local kallsyms pointer and setup the data structures. Assign that pointer to the data structure at the end via rcu_assign_pointer(). Signed-off-by: Sebastian Andrzej Siewior <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Petr Pavlu <[email protected]>
1 parent 838e6dd commit 039de46

File tree

1 file changed

+14
-17
lines changed

1 file changed

+14
-17
lines changed

kernel/module/kallsyms.c

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -177,19 +177,15 @@ void add_kallsyms(struct module *mod, const struct load_info *info)
177177
unsigned long strtab_size;
178178
void *data_base = mod->mem[MOD_DATA].base;
179179
void *init_data_base = mod->mem[MOD_INIT_DATA].base;
180+
struct mod_kallsyms *kallsyms;
180181

181-
/* Set up to point into init section. */
182-
mod->kallsyms = (void __rcu *)init_data_base +
183-
info->mod_kallsyms_init_off;
182+
kallsyms = init_data_base + info->mod_kallsyms_init_off;
184183

185-
rcu_read_lock();
186-
/* The following is safe since this pointer cannot change */
187-
rcu_dereference(mod->kallsyms)->symtab = (void *)symsec->sh_addr;
188-
rcu_dereference(mod->kallsyms)->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
184+
kallsyms->symtab = (void *)symsec->sh_addr;
185+
kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
189186
/* Make sure we get permanent strtab: don't use info->strtab. */
190-
rcu_dereference(mod->kallsyms)->strtab =
191-
(void *)info->sechdrs[info->index.str].sh_addr;
192-
rcu_dereference(mod->kallsyms)->typetab = init_data_base + info->init_typeoffs;
187+
kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
188+
kallsyms->typetab = init_data_base + info->init_typeoffs;
193189

194190
/*
195191
* Now populate the cut down core kallsyms for after init
@@ -199,28 +195,29 @@ void add_kallsyms(struct module *mod, const struct load_info *info)
199195
mod->core_kallsyms.strtab = s = data_base + info->stroffs;
200196
mod->core_kallsyms.typetab = data_base + info->core_typeoffs;
201197
strtab_size = info->core_typeoffs - info->stroffs;
202-
src = rcu_dereference(mod->kallsyms)->symtab;
203-
for (ndst = i = 0; i < rcu_dereference(mod->kallsyms)->num_symtab; i++) {
204-
rcu_dereference(mod->kallsyms)->typetab[i] = elf_type(src + i, info);
198+
src = kallsyms->symtab;
199+
for (ndst = i = 0; i < kallsyms->num_symtab; i++) {
200+
kallsyms->typetab[i] = elf_type(src + i, info);
205201
if (i == 0 || is_livepatch_module(mod) ||
206202
is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
207203
info->index.pcpu)) {
208204
ssize_t ret;
209205

210206
mod->core_kallsyms.typetab[ndst] =
211-
rcu_dereference(mod->kallsyms)->typetab[i];
207+
kallsyms->typetab[i];
212208
dst[ndst] = src[i];
213209
dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
214-
ret = strscpy(s,
215-
&rcu_dereference(mod->kallsyms)->strtab[src[i].st_name],
210+
ret = strscpy(s, &kallsyms->strtab[src[i].st_name],
216211
strtab_size);
217212
if (ret < 0)
218213
break;
219214
s += ret + 1;
220215
strtab_size -= ret + 1;
221216
}
222217
}
223-
rcu_read_unlock();
218+
219+
/* Set up to point into init section. */
220+
rcu_assign_pointer(mod->kallsyms, kallsyms);
224221
mod->core_kallsyms.num_symtab = ndst;
225222
}
226223

0 commit comments

Comments
 (0)