Hello Suren Baghdasaryan, Commit e88dfe467aa7 ("alloc_tag: load module tags into separate contiguous memory") from Oct 23, 2024 (linux-next), leads to the following Smatch static checker warning: kernel/module/main.c:2594 move_module() warn: 'dest' isn't an ERR_PTR kernel/module/main.c 2554 static int move_module(struct module *mod, struct load_info *info) 2555 { 2556 int i; 2557 enum mod_mem_type t = 0; 2558 int ret = -ENOMEM; 2559 bool codetag_section_found = false; 2560 2561 for_each_mod_mem_type(type) { 2562 if (!mod->mem[type].size) { 2563 mod->mem[type].base = NULL; 2564 mod->mem[type].rw_copy = NULL; 2565 continue; 2566 } 2567 2568 ret = module_memory_alloc(mod, type); 2569 if (ret) { 2570 t = type; 2571 goto out_err; 2572 } 2573 } 2574 2575 /* Transfer each section which specifies SHF_ALLOC */ 2576 pr_debug("Final section addresses for %s:\n", mod->name); 2577 for (i = 0; i < info->hdr->e_shnum; i++) { 2578 void *dest; 2579 Elf_Shdr *shdr = &info->sechdrs[i]; 2580 const char *sname; 2581 unsigned long addr; 2582 2583 if (!(shdr->sh_flags & SHF_ALLOC)) 2584 continue; 2585 2586 sname = info->secstrings + shdr->sh_name; 2587 /* 2588 * Load codetag sections separately as they might still be used 2589 * after module unload. 2590 */ 2591 if (codetag_needs_module_section(mod, sname, shdr->sh_size)) { 2592 dest = codetag_alloc_module_section(mod, sname, shdr->sh_size, 2593 arch_mod_section_prepend(mod, i), shdr->sh_addralign); --> 2594 if (IS_ERR(dest)) { 2595 ret = PTR_ERR(dest); 2596 goto out_err; 2597 } This is a false positive caused my specific kernel config. The codetag_alloc_module_section() function returns both error pointers and NULL. It can return NULL because of the .config, because the section isn't found, because the size is too small or because the desc.alloc_section_mem() function isn't implemented (which is a bug). 2598 addr = (unsigned long)dest; 2599 codetag_section_found = true; 2600 } else { 2601 enum mod_mem_type type = shdr->sh_entsize >> SH_ENTSIZE_TYPE_SHIFT; 2602 unsigned long offset = shdr->sh_entsize & SH_ENTSIZE_OFFSET_MASK; 2603 2604 addr = (unsigned long)mod->mem[type].base + offset; 2605 dest = mod->mem[type].rw_copy + offset; 2606 } 2607 2608 if (shdr->sh_type != SHT_NOBITS) { 2609 /* 2610 * Our ELF checker already validated this, but let's 2611 * be pedantic and make the goal clearer. We actually 2612 * end up copying over all modifications made to the 2613 * userspace copy of the entire struct module. 2614 */ 2615 if (i == info->index.mod && 2616 (WARN_ON_ONCE(shdr->sh_size != sizeof(struct module)))) { This handles the case where the size is too small. Why not return an error pointer if the section is not found or if there is a bug. We could also add a NULL check here. 2617 ret = -ENOEXEC; 2618 goto out_err; 2619 } 2620 memcpy(dest, (void *)shdr->sh_addr, shdr->sh_size); ^^^^^ Dereferenced without testing. 2621 } 2622 /* 2623 * Update the userspace copy's ELF section address to point to 2624 * our newly allocated memory as a pure convenience so that 2625 * users of info can keep taking advantage and using the newly 2626 * minted official memory area. 2627 */ 2628 shdr->sh_addr = addr; 2629 pr_debug("\t0x%lx 0x%.8lx %s\n", (long)shdr->sh_addr, 2630 (long)shdr->sh_size, info->secstrings + shdr->sh_name); 2631 } 2632 2633 return 0; 2634 out_err: 2635 for (t--; t >= 0; t--) 2636 module_memory_free(mod, t); 2637 if (codetag_section_found) 2638 codetag_free_module_sections(mod); 2639 2640 return ret; 2641 } regards, dan carpenter