Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <bigeasy@linutronix.de>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20250108090457.512198-4-bigeasy@linutronix.de
Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>

authored by

Sebastian Andrzej Siewior and committed by
Petr Pavlu
039de468 838e6dd8

+14 -17
+14 -17
kernel/module/kallsyms.c
··· 177 177 unsigned long strtab_size; 178 178 void *data_base = mod->mem[MOD_DATA].base; 179 179 void *init_data_base = mod->mem[MOD_INIT_DATA].base; 180 + struct mod_kallsyms *kallsyms; 180 181 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; 184 183 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); 189 186 /* 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; 193 189 194 190 /* 195 191 * Now populate the cut down core kallsyms for after init ··· 195 199 mod->core_kallsyms.strtab = s = data_base + info->stroffs; 196 200 mod->core_kallsyms.typetab = data_base + info->core_typeoffs; 197 201 strtab_size = info->core_typeoffs - info->stroffs; 198 - src = rcu_dereference(mod->kallsyms)->symtab; 199 - for (ndst = i = 0; i < rcu_dereference(mod->kallsyms)->num_symtab; i++) { 200 - rcu_dereference(mod->kallsyms)->typetab[i] = elf_type(src + i, info); 202 + src = kallsyms->symtab; 203 + for (ndst = i = 0; i < kallsyms->num_symtab; i++) { 204 + kallsyms->typetab[i] = elf_type(src + i, info); 201 205 if (i == 0 || is_livepatch_module(mod) || 202 206 is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum, 203 207 info->index.pcpu)) { 204 208 ssize_t ret; 205 209 206 210 mod->core_kallsyms.typetab[ndst] = 207 - rcu_dereference(mod->kallsyms)->typetab[i]; 211 + kallsyms->typetab[i]; 208 212 dst[ndst] = src[i]; 209 213 dst[ndst++].st_name = s - mod->core_kallsyms.strtab; 210 - ret = strscpy(s, 211 - &rcu_dereference(mod->kallsyms)->strtab[src[i].st_name], 214 + ret = strscpy(s, &kallsyms->strtab[src[i].st_name], 212 215 strtab_size); 213 216 if (ret < 0) 214 217 break; ··· 215 220 strtab_size -= ret + 1; 216 221 } 217 222 } 218 - rcu_read_unlock(); 223 + 224 + /* Set up to point into init section. */ 225 + rcu_assign_pointer(mod->kallsyms, kallsyms); 219 226 mod->core_kallsyms.num_symtab = ndst; 220 227 } 221 228