* [RFC PATCH v6 0/2] module: allocate codetag sections before the regular module layout
@ 2026-08-31 7:21 Hao Ge
2026-08-31 7:21 ` [RFC PATCH v6 1/2] alloc_tag: move release_module_tags() above reserve_module_tags() Hao Ge
2026-08-31 7:21 ` [RFC PATCH v6 2/2] module: allocate codetag sections before the regular module layout Hao Ge
0 siblings, 2 replies; 8+ messages in thread
From: Hao Ge @ 2026-08-31 7:21 UTC (permalink / raw)
To: Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Suren Baghdasaryan, Andrew Morton
Cc: linux-modules, linux-kernel, Hao Ge
I ran into an overflow problem in the module tag area. With profiling
toggled off, the overflow check in reserve_module_tags() did not
run, a module could load with more tags than the page flags can
address, and re-enabling profiling then silently corrupted
/proc/allocinfo. After discussion with Suren and Andrew the fix went
for a graceful approach: on overflow shut profiling down, release the
reservation and return -EAGAIN, and retry the load with profiling
disabled, so the codetag section lands as regular module data and
the module loads without profiling.
Review of that series by Sashiko turned up two more problems.
One is a race. layout_sections() and move_module() both asked
codetag_needs_module_section() where a codetag section goes, and
mem_profiling_support can change between the two calls, for instance
when another module load overflows the tag index and shuts profiling
down. move_module() then copies the codetag section to offset 0 of
its regular destination and clobbers the first section placed in
that region.
The other is a maple tree entry leak. The failure paths of
reserve_module_tags() return with the reservation still stored, and
a failed load never unloads the module, so nothing releases it.
v6 fixes both by reworking where codetag sections are allocated, on
a prototype by Petr Pavlu [1]. The allocation now runs before
layout_sections() and the placement is decided in one step, so
nothing re-asks the question and the race is gone. The retry is gone
too, on -EAGAIN the section is laid out as regular module data right
in the same load, and both failure paths release the reservation.
[1] https://lore.kernel.org/all/499bb60c-c6e3-43a3-bd92-95a0567ece5e@suse.com/
Sending this as an RFC since 2/2 is a rework of Petr's prototype and
the approach changed quite a bit from v5, feedback on the direction
would be welcome.
Patch 1 moves release_module_tags() above reserve_module_tags(),
since the overflow path now has to call it and the helper sits below
it.
Patch 2 moves the codetag allocation out of move_module() in front
of layout_sections(). On overflow reserve_module_tags() shuts
profiling down, releases the reservation and returns -EAGAIN, and
the section is laid out as regular module data, so the module loads
without profiling instead of failing. Any other error fails the
load.
Tested on an x86_64 virtual machine:
Booted without sysctl.vm.mem_profiling=1,compressed:
# cat /proc/allocinfo is fine
Booted with sysctl.vm.mem_profiling=1,compressed:
# cat /proc/allocinfo is fine
# insmod overflow_tag.ko
# dmesg
With module overflow_tag there are too many tags to fit in 13 page
flag bits. Memory allocation profiling is disabled!
# rmmod overflow_tag
The module loads without profiling and unloads cleanly.
Changes in v6:
- rework 2/2 on Petr's prototype and allocate codetag sections
before layout_sections(), the retry and its state resets are gone
- fix the layout_sections()/move_module() race (Found by Sashiko)
- release the reservation on populate failure as well (Found by
Sashiko)
- only -EAGAIN keeps the fallback, other errors fail the load
Changes in v5:
- add Fixes: and Cc: stable to patch 1/2 as well, since 2/2 does not
compile without it (Andrew Morton)
- restore frob-adjusted mem[type].size on retry instead of zeroing,
as s390 and parisc add GOT/PLT space there in
module_frob_arch_sections() (Reported by Sashiko)
- drop the load_module() mem_profiling_support check; the percpu
counter leak is pre-existing and orthogonal to this fix
Changes in v4:
- add a new patch (1/2) to move release_module_tags() above
reserve_module_tags(); the overflow fix is 2/2
- release the reservation on the -EAGAIN path
- return -EAGAIN instead of -ENOMEM so the module can still load
without profiling (Suren)
- reset sh_addr, mem[type].size and sym/str SHF_ALLOC before retry
- skip percpu counters in load_module() when profiling is off
Changes in v3:
- use pr_warn_once() instead of pr_warn()
- return -ENOMEM instead of -ENOSPC (Suren)
- expand the commit message to describe the /proc/allocinfo impact
(Andrew)
Changes in v2:
- return an error after shutdown_mem_profiling() to skip
vm_module_tags_populate()
v1: https://lore.kernel.org/all/20260804064408.105033-1-hao.ge@linux.dev/
v2: https://lore.kernel.org/all/20260804122038.190270-1-hao.ge@linux.dev/
v3: https://lore.kernel.org/all/20260805090633.141001-1-hao.ge@linux.dev/
v4: https://lore.kernel.org/all/20260810093955.153015-1-hao.ge@linux.dev/
v5: https://lore.kernel.org/all/20260812054105.102637-1-hao.ge@linux.dev/
Hao Ge (2):
alloc_tag: move release_module_tags() above reserve_module_tags()
module: allocate codetag sections before the regular module layout
include/linux/module.h | 2 +
kernel/module/internal.h | 4 ++
kernel/module/main.c | 120 ++++++++++++++++++++-------------------
mm/alloc_tag.c | 101 ++++++++++++++++----------------
4 files changed, 121 insertions(+), 106 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC PATCH v6 1/2] alloc_tag: move release_module_tags() above reserve_module_tags()
2026-08-31 7:21 [RFC PATCH v6 0/2] module: allocate codetag sections before the regular module layout Hao Ge
@ 2026-08-31 7:21 ` Hao Ge
2026-08-31 7:21 ` [RFC PATCH v6 2/2] module: allocate codetag sections before the regular module layout Hao Ge
1 sibling, 0 replies; 8+ messages in thread
From: Hao Ge @ 2026-08-31 7:21 UTC (permalink / raw)
To: Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Suren Baghdasaryan, Andrew Morton
Cc: linux-modules, linux-kernel, Hao Ge, stable
release_module_tags() is a cleanup helper. reserve_module_tags() can
also fail after storing the reservation in the maple tree, in which
case it should call release_module_tags() to undo it. Move the helper
above reserve_module_tags() so no forward declaration is needed.
No functional change.
Fixes: 4835f747d3ed ("alloc_tag: support for page allocation tag compression")
Cc: stable@vger.kernel.org
Acked-by: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Hao Ge <hao.ge@linux.dev>
---
mm/alloc_tag.c | 92 +++++++++++++++++++++++++-------------------------
1 file changed, 46 insertions(+), 46 deletions(-)
diff --git a/mm/alloc_tag.c b/mm/alloc_tag.c
index b1d48532a25a..e7a79116ad81 100644
--- a/mm/alloc_tag.c
+++ b/mm/alloc_tag.c
@@ -843,6 +843,52 @@ static int vm_module_tags_populate(void)
return 0;
}
+static void release_module_tags(struct module *mod, bool used)
+{
+ MA_STATE(mas, &mod_area_mt, module_tags.size, module_tags.size);
+ struct alloc_tag *start_tag;
+ struct alloc_tag *end_tag;
+ struct module *val;
+
+ mas_lock(&mas);
+ mas_for_each_rev(&mas, val, 0)
+ if (val == mod)
+ break;
+
+ if (!val) /* module not found */
+ goto out;
+
+ if (!used)
+ goto release_area;
+
+ start_tag = (struct alloc_tag *)(module_tags.start_addr + mas.index);
+ end_tag = (struct alloc_tag *)(module_tags.start_addr + mas.last);
+ if (!clean_unused_counters(start_tag, end_tag)) {
+ struct alloc_tag *tag;
+
+ for (tag = start_tag; tag <= end_tag; tag++) {
+ struct alloc_tag_counters counter;
+
+ if (!tag->counters)
+ continue;
+
+ counter = alloc_tag_read(tag);
+ pr_info("%s:%u module %s func:%s has %llu allocated at module unload\n",
+ tag->ct.filename, tag->ct.lineno, tag->ct.modname,
+ tag->ct.function, counter.bytes);
+ }
+ } else {
+ used = false;
+ }
+release_area:
+ mas_store(&mas, used ? &unloaded_mod : NULL);
+ val = mas_prev_range(&mas, 0);
+ if (val == &prepend_mod)
+ mas_store(&mas, NULL);
+out:
+ mas_unlock(&mas);
+}
+
static void *reserve_module_tags(struct module *mod, unsigned long size,
unsigned int prepend, unsigned long align)
{
@@ -930,52 +976,6 @@ static void *reserve_module_tags(struct module *mod, unsigned long size,
return (struct alloc_tag *)(module_tags.start_addr + offset);
}
-static void release_module_tags(struct module *mod, bool used)
-{
- MA_STATE(mas, &mod_area_mt, module_tags.size, module_tags.size);
- struct alloc_tag *start_tag;
- struct alloc_tag *end_tag;
- struct module *val;
-
- mas_lock(&mas);
- mas_for_each_rev(&mas, val, 0)
- if (val == mod)
- break;
-
- if (!val) /* module not found */
- goto out;
-
- if (!used)
- goto release_area;
-
- start_tag = (struct alloc_tag *)(module_tags.start_addr + mas.index);
- end_tag = (struct alloc_tag *)(module_tags.start_addr + mas.last);
- if (!clean_unused_counters(start_tag, end_tag)) {
- struct alloc_tag *tag;
-
- for (tag = start_tag; tag <= end_tag; tag++) {
- struct alloc_tag_counters counter;
-
- if (!tag->counters)
- continue;
-
- counter = alloc_tag_read(tag);
- pr_info("%s:%u module %s func:%s has %llu allocated at module unload\n",
- tag->ct.filename, tag->ct.lineno, tag->ct.modname,
- tag->ct.function, counter.bytes);
- }
- } else {
- used = false;
- }
-release_area:
- mas_store(&mas, used ? &unloaded_mod : NULL);
- val = mas_prev_range(&mas, 0);
- if (val == &prepend_mod)
- mas_store(&mas, NULL);
-out:
- mas_unlock(&mas);
-}
-
static int load_module(struct module *mod, struct codetag *start, struct codetag *stop)
{
/* Allocate module alloc_tag percpu counters */
--
2.25.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [RFC PATCH v6 2/2] module: allocate codetag sections before the regular module layout
2026-08-31 7:21 [RFC PATCH v6 0/2] module: allocate codetag sections before the regular module layout Hao Ge
2026-08-31 7:21 ` [RFC PATCH v6 1/2] alloc_tag: move release_module_tags() above reserve_module_tags() Hao Ge
@ 2026-08-31 7:21 ` Hao Ge
2026-08-31 7:47 ` sashiko-bot
2026-09-01 15:04 ` Petr Pavlu
1 sibling, 2 replies; 8+ messages in thread
From: Hao Ge @ 2026-08-31 7:21 UTC (permalink / raw)
To: Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Suren Baghdasaryan, Andrew Morton
Cc: linux-modules, linux-kernel, Hao Ge, Sashiko
Whether a codetag section goes to the codetag region is decided by
layout_sections() and asked again in move_module(). A concurrent
load can shut profiling down in between, and move_module() then
copies the section to offset 0 of its regular destination,
overwriting whatever is there.
Decide and allocate in one pass, before the layout. Allocation
errors fail the load. On a tag area overflow profiling is already
disabled, so -EAGAIN makes the section fall back to regular module
data and the module still loads.
The overflow and populate failure paths of reserve_module_tags() now
release their reservation instead of leaking the maple tree entry.
When profiling was toggled off, the overflow check did not run, a
module could load with more tags than the page flags can address,
and re-enabling profiling then silently corrupted /proc/allocinfo.
The check no longer depends on mem_alloc_profiling_enabled().
Fixes: 4835f747d3ed ("alloc_tag: support for page allocation tag compression")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Based-on-a-patch-by: Petr Pavlu <petr.pavlu@suse.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Hao Ge <hao.ge@linux.dev>
---
Changes against Petr's prototype:
- allocate_codetag_sections() returns an error instead of void, and
only -EAGAIN falls back to a regular section. Any other error now
fails the load. The prototype fell back on everything, which can
leave live tags in module memory.
- reserve_module_tags() releases its reservation when populate fails
too, that path used to leak the maple tree entry.
- codetag_free_module_sections() on the move_module() error path uses
info->mod, the local mod is assigned only after a successful move.
- The percpu section is marked only when index.pcpu != 0, otherwise
sechdrs[0] gets marked.
- Dropped the SHF_ALLOC check, .codetag.* sections always have it.
---
include/linux/module.h | 2 +
kernel/module/internal.h | 4 ++
kernel/module/main.c | 120 ++++++++++++++++++++-------------------
mm/alloc_tag.c | 9 ++-
4 files changed, 75 insertions(+), 60 deletions(-)
diff --git a/include/linux/module.h b/include/linux/module.h
index 7566815fabbe..33548daa31a3 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -325,6 +325,8 @@ enum mod_mem_type {
MOD_INIT_RODATA,
MOD_MEM_NUM_TYPES,
+
+ MOD_STANDALONE = -2,
MOD_INVALID = -1,
};
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index 061161cc79d9..217bb540e361 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -29,6 +29,10 @@
#define SH_ENTSIZE_TYPE_MASK ((1UL << SH_ENTSIZE_TYPE_BITS) - 1)
#define SH_ENTSIZE_OFFSET_MASK ((1UL << (BITS_PER_LONG - SH_ENTSIZE_TYPE_BITS)) - 1)
+#define SH_ENTSIZE_STANDALONE \
+ (((unsigned long)MOD_STANDALONE & SH_ENTSIZE_TYPE_MASK) \
+ << SH_ENTSIZE_TYPE_SHIFT)
+
/* Maximum number of characters written by module_flags() */
#define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4)
diff --git a/kernel/module/main.c b/kernel/module/main.c
index c32f1d370b73..587df9103f0b 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -1625,7 +1625,7 @@ static int apply_relocations(struct module *mod, const struct load_info *info)
* ELF template and subsequently copy it to the per-CPU destinations.
*/
if (!(info->sechdrs[infosec].sh_flags & SHF_ALLOC) &&
- (!infosec || infosec != info->index.pcpu))
+ info->sechdrs[infosec].sh_entsize != SH_ENTSIZE_STANDALONE)
continue;
if (info->sechdrs[i].sh_flags & SHF_RELA_LIVEPATCH)
@@ -1723,20 +1723,6 @@ static void __layout_sections(struct module *mod, struct load_info *info, bool i
if (WARN_ON_ONCE(type == MOD_INVALID))
continue;
- /*
- * Do not allocate codetag memory as we load it into
- * preallocated contiguous memory.
- */
- if (codetag_needs_module_section(mod, sname, s->sh_size)) {
- /*
- * s->sh_entsize won't be used but populate the
- * type field to avoid confusion.
- */
- s->sh_entsize = ((unsigned long)(type) & SH_ENTSIZE_TYPE_MASK)
- << SH_ENTSIZE_TYPE_SHIFT;
- continue;
- }
-
s->sh_entsize = module_get_offset_and_type(mod, type, s, i);
pr_debug("\t%s\n", sname);
}
@@ -1746,16 +1732,10 @@ static void __layout_sections(struct module *mod, struct load_info *info, bool i
/*
* Lay out the SHF_ALLOC sections in a way not dissimilar to how ld
* might -- code, read-only data, read-write data, small data. Tally
- * sizes, and place the offsets into sh_entsize fields: high bit means it
- * belongs in init.
+ * sizes, and place the offsets into sh_entsize fields.
*/
static void layout_sections(struct module *mod, struct load_info *info)
{
- unsigned int i;
-
- for (i = 0; i < info->hdr->e_shnum; i++)
- info->sechdrs[i].sh_entsize = ~0UL;
-
pr_debug("Core section allocation order for %s:\n", mod->name);
__layout_sections(mod, info, false);
@@ -2789,7 +2769,6 @@ static int move_module(struct module *mod, struct load_info *info)
{
int i, ret;
enum mod_mem_type t = MOD_MEM_NUM_TYPES;
- bool codetag_section_found = false;
for_each_mod_mem_type(type) {
if (!mod->mem[type].size) {
@@ -2807,36 +2786,14 @@ static int move_module(struct module *mod, struct load_info *info)
/* Transfer each section which specifies SHF_ALLOC */
pr_debug("Final section addresses for %s:\n", mod->name);
for (i = 0; i < info->hdr->e_shnum; i++) {
- void *dest;
Elf_Shdr *shdr = &info->sechdrs[i];
- const char *sname;
+ void *dest;
if (!(shdr->sh_flags & SHF_ALLOC))
continue;
- sname = info->secstrings + shdr->sh_name;
- /*
- * Load codetag sections separately as they might still be used
- * after module unload.
- */
- if (codetag_needs_module_section(mod, sname, shdr->sh_size)) {
- dest = codetag_alloc_module_section(mod, sname, shdr->sh_size,
- arch_mod_section_prepend(mod, i), shdr->sh_addralign);
- if (WARN_ON(!dest)) {
- ret = -EINVAL;
- goto out_err;
- }
- if (IS_ERR(dest)) {
- ret = PTR_ERR(dest);
- goto out_err;
- }
- codetag_section_found = true;
- } else {
- enum mod_mem_type type = shdr->sh_entsize >> SH_ENTSIZE_TYPE_SHIFT;
- unsigned long offset = shdr->sh_entsize & SH_ENTSIZE_OFFSET_MASK;
-
- dest = mod->mem[type].base + offset;
- }
+ dest = mod->mem[shdr->sh_entsize >> SH_ENTSIZE_TYPE_SHIFT].base +
+ (shdr->sh_entsize & SH_ENTSIZE_OFFSET_MASK);
if (shdr->sh_type != SHT_NOBITS) {
/*
@@ -2868,8 +2825,6 @@ static int move_module(struct module *mod, struct load_info *info)
module_memory_restore_rox(mod);
while (t--)
module_memory_free(mod, t);
- if (codetag_section_found)
- codetag_free_module_sections(mod);
return ret;
}
@@ -2940,9 +2895,48 @@ static bool blacklisted(const char *module_name)
}
core_param(module_blacklist, module_blacklist, charp, 0400);
+/*
+ * Allocate codetag sections separately. They are loaded into preallocated
+ * contiguous memory because they may still be used after the module is
+ * unloaded.
+ *
+ * If the separate allocation overflows, allocate the section normally
+ * so that the module can still be loaded.
+ */
+static int allocate_codetag_sections(struct load_info *info)
+{
+ for (unsigned int i = 1; i < info->hdr->e_shnum; i++) {
+ Elf_Shdr *shdr = &info->sechdrs[i];
+ const char *sname = info->secstrings + shdr->sh_name;
+ void *dest;
+
+ if (!codetag_needs_module_section(info->mod, sname, shdr->sh_size))
+ continue;
+
+ dest = codetag_alloc_module_section(info->mod, sname, shdr->sh_size,
+ arch_mod_section_prepend(info->mod, i), shdr->sh_addralign);
+ if (WARN_ON(!dest))
+ return -EINVAL;
+ if (dest == ERR_PTR(-EAGAIN))
+ /* Allocate the section as a regular section. */
+ continue;
+ if (IS_ERR(dest))
+ return PTR_ERR(dest);
+
+ if (shdr->sh_type != SHT_NOBITS)
+ memcpy(dest, (void *)shdr->sh_addr, shdr->sh_size);
+ shdr->sh_addr = (unsigned long)dest;
+ shdr->sh_flags &= ~(unsigned long)SHF_ALLOC;
+ shdr->sh_entsize = SH_ENTSIZE_STANDALONE;
+ }
+
+ return 0;
+}
+
static struct module *layout_and_allocate(struct load_info *info, int flags)
{
struct module *mod;
+ unsigned int i;
int err;
/* Allow arches to frob section contents and sizes. */
@@ -2956,8 +2950,15 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
if (err < 0)
return ERR_PTR(err);
+ /* Repurpose sh_entsize to track where each section is allocated. */
+ for (i = 0; i < info->hdr->e_shnum; i++)
+ info->sechdrs[i].sh_entsize = ~0UL;
+
/* We will do a special allocation for per-cpu sections later. */
- info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC;
+ if (info->index.pcpu) {
+ info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC;
+ info->sechdrs[info->index.pcpu].sh_entsize = SH_ENTSIZE_STANDALONE;
+ }
/*
* Mark relevant sections as SHF_RO_AFTER_INIT so layout_sections() can
@@ -2966,18 +2967,23 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
*/
module_mark_ro_after_init(info->hdr, info->sechdrs, info->secstrings);
- /*
- * Determine total sizes, and put offsets in sh_entsize. For now
- * this is done generically; there doesn't appear to be any
- * special cases for the architectures.
- */
+ /* Allow codetag sections to be allocated separately first. */
+ err = allocate_codetag_sections(info);
+ if (err) {
+ codetag_free_module_sections(info->mod);
+ return ERR_PTR(err);
+ }
+
+ /* Determine total sizes and put offsets in sh_entsize. */
layout_sections(info->mod, info);
layout_symtab(info->mod, info);
/* Allocate and move to the final place */
err = move_module(info->mod, info);
- if (err)
+ if (err) {
+ codetag_free_module_sections(info->mod);
return ERR_PTR(err);
+ }
/* Module has been copied to its final place now: return it. */
mod = (void *)info->sechdrs[info->index.mod].sh_addr;
diff --git a/mm/alloc_tag.c b/mm/alloc_tag.c
index e7a79116ad81..3c25475becbc 100644
--- a/mm/alloc_tag.c
+++ b/mm/alloc_tag.c
@@ -958,10 +958,12 @@ static void *reserve_module_tags(struct module *mod, unsigned long size,
int grow_res;
module_tags.size = offset + size;
- if (mem_alloc_profiling_enabled() && !tags_addressable()) {
+ if (!tags_addressable()) {
shutdown_mem_profiling(true);
- pr_warn("With module %s there are too many tags to fit in %d page flag bits. Memory allocation profiling is disabled!\n",
- mod->name, NR_UNUSED_PAGEFLAG_BITS);
+ pr_warn_once("With module %s there are too many tags to fit in %d page flag bits. Memory allocation profiling is disabled!\n",
+ mod->name, NR_UNUSED_PAGEFLAG_BITS);
+ release_module_tags(mod, false);
+ return ERR_PTR(-EAGAIN);
}
grow_res = vm_module_tags_populate();
@@ -969,6 +971,7 @@ static void *reserve_module_tags(struct module *mod, unsigned long size,
shutdown_mem_profiling(true);
pr_err("Failed to allocate memory for allocation tags in the module %s. Memory allocation profiling is disabled!\n",
mod->name);
+ release_module_tags(mod, false);
return ERR_PTR(grow_res);
}
}
--
2.25.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [RFC PATCH v6 2/2] module: allocate codetag sections before the regular module layout
2026-08-31 7:21 ` [RFC PATCH v6 2/2] module: allocate codetag sections before the regular module layout Hao Ge
@ 2026-08-31 7:47 ` sashiko-bot
2026-09-01 15:04 ` Petr Pavlu
1 sibling, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-08-31 7:47 UTC (permalink / raw)
To: Hao Ge; +Cc: linux-modules
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Percpu counters are permanently leaked when a codetag section falls back to regular module memory.
--
commit 67e030141d036ccecf172380286b7317fac48a51
Author: Hao Ge <hao.ge@linux.dev>
module: allocate codetag sections before the regular module layout
This patch moves codetag section allocation to occur before the regular
module layout and fails the load on allocation errors. However, on tag
area overflow, it gracefully falls back to allocating the codetag section
in regular module memory instead.
> diff --git a/kernel/module/main.c b/kernel/module/main.c
> index d0e1e0bd2ad06..da80f7c187921 100644
> --- a/kernel/module/main.c
> +++ b/kernel/module/main.c
[ ... ]
> @@ -2951,9 +2906,48 @@ static bool blacklisted(const char *module_name)
> }
> core_param(module_blacklist, module_blacklist, charp, 0400);
>
> +/*
> + * Allocate codetag sections separately. They are loaded into preallocated
> + * contiguous memory because they may still be used after the module is
> + * unloaded.
> + *
> + * If the separate allocation overflows, allocate the section normally
> + * so that the module can still be loaded.
> + */
> +static int allocate_codetag_sections(struct load_info *info)
> +{
> + for (unsigned int i = 1; i < info->hdr->e_shnum; i++) {
> + Elf_Shdr *shdr = &info->sechdrs[i];
> + const char *sname = info->secstrings + shdr->sh_name;
> + void *dest;
> +
> + if (!codetag_needs_module_section(info->mod, sname, shdr->sh_size))
> + continue;
> +
> + dest = codetag_alloc_module_section(info->mod, sname, shdr->sh_size,
> + arch_mod_section_prepend(info->mod, i), shdr->sh_addralign);
> + if (WARN_ON(!dest))
> + return -EINVAL;
> + if (dest == ERR_PTR(-EAGAIN))
> + /* Allocate the section as a regular section. */
> + continue;
[Severity: High]
If reserve_module_tags() returns -EAGAIN due to reaching the tag addressable
limit, the module load proceeds by falling back to regular module memory.
However, does this cause a permanent percpu memory leak when the module is
eventually unloaded?
When the codetag section falls back to regular memory, the module is never
added to the mod_area_mt maple tree. Later, load_module() in mm/alloc_tag.c
unconditionally allocates percpu memory for all tags in the module:
mm/alloc_tag.c:load_module() {
...
for (tag = start_tag; tag < stop_tag; tag++) {
...
tag->counters = alloc_percpu(struct alloc_tag_counters);
}
}
During unload, release_module_tags() attempts to free these counters. But
since the module was never added to the maple tree, it exits early before
cleaning up the counters:
mm/alloc_tag.c:release_module_tags() {
...
mas_for_each_rev(&mas, val, 0)
if (val == mod)
break;
if (!val) /* module not found */
goto out;
...
}
Will this cause all percpu counters allocated for this module to be leaked,
potentially leading to percpu memory exhaustion over time?
> + if (IS_ERR(dest))
> + return PTR_ERR(dest);
> +
> + if (shdr->sh_type != SHT_NOBITS)
> + memcpy(dest, (void *)shdr->sh_addr, shdr->sh_size);
> + shdr->sh_addr = (unsigned long)dest;
> + shdr->sh_flags &= ~(unsigned long)SHF_ALLOC;
> + shdr->sh_entsize = SH_ENTSIZE_STANDALONE;
> + }
> +
> + return 0;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831072104.120197-1-hao.ge@linux.dev?part=2
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC PATCH v6 2/2] module: allocate codetag sections before the regular module layout
2026-08-31 7:21 ` [RFC PATCH v6 2/2] module: allocate codetag sections before the regular module layout Hao Ge
2026-08-31 7:47 ` sashiko-bot
@ 2026-09-01 15:04 ` Petr Pavlu
2026-09-01 18:36 ` Suren Baghdasaryan
2026-09-02 6:52 ` Hao Ge
1 sibling, 2 replies; 8+ messages in thread
From: Petr Pavlu @ 2026-09-01 15:04 UTC (permalink / raw)
To: Hao Ge
Cc: Luis Chamberlain, Daniel Gomez, Sami Tolvanen, Aaron Tomlin,
Suren Baghdasaryan, Andrew Morton, linux-modules, linux-kernel,
Sashiko
On 8/31/26 9:21 AM, Hao Ge wrote:
> Whether a codetag section goes to the codetag region is decided by
> layout_sections() and asked again in move_module(). A concurrent
> load can shut profiling down in between, and move_module() then
> copies the section to offset 0 of its regular destination,
> overwriting whatever is there.
>
> Decide and allocate in one pass, before the layout. Allocation
> errors fail the load. On a tag area overflow profiling is already
> disabled, so -EAGAIN makes the section fall back to regular module
> data and the module still loads.
>
> The overflow and populate failure paths of reserve_module_tags() now
> release their reservation instead of leaking the maple tree entry.
> When profiling was toggled off, the overflow check did not run, a
> module could load with more tags than the page flags can address,
> and re-enabling profiling then silently corrupted /proc/allocinfo.
> The check no longer depends on mem_alloc_profiling_enabled().
>
> Fixes: 4835f747d3ed ("alloc_tag: support for page allocation tag compression")
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Based-on-a-patch-by: Petr Pavlu <petr.pavlu@suse.com>
> Cc: Suren Baghdasaryan <surenb@google.com>
> Signed-off-by: Hao Ge <hao.ge@linux.dev>
> ---
> Changes against Petr's prototype:
> - allocate_codetag_sections() returns an error instead of void, and
> only -EAGAIN falls back to a regular section. Any other error now
> fails the load. The prototype fell back on everything, which can
> leave live tags in module memory.
> - reserve_module_tags() releases its reservation when populate fails
> too, that path used to leak the maple tree entry.
> - codetag_free_module_sections() on the move_module() error path uses
> info->mod, the local mod is assigned only after a successful move.
> - The percpu section is marked only when index.pcpu != 0, otherwise
> sechdrs[0] gets marked.
> - Dropped the SHF_ALLOC check, .codetag.* sections always have it.
> ---
> include/linux/module.h | 2 +
> kernel/module/internal.h | 4 ++
> kernel/module/main.c | 120 ++++++++++++++++++++-------------------
> mm/alloc_tag.c | 9 ++-
> 4 files changed, 75 insertions(+), 60 deletions(-)
>
> diff --git a/include/linux/module.h b/include/linux/module.h
> index 7566815fabbe..33548daa31a3 100644
> --- a/include/linux/module.h
> +++ b/include/linux/module.h
> @@ -325,6 +325,8 @@ enum mod_mem_type {
> MOD_INIT_RODATA,
>
> MOD_MEM_NUM_TYPES,
> +
> + MOD_STANDALONE = -2,
> MOD_INVALID = -1,
> };
>
It might be better to split this patch into two: the first to introduce
MOD_STANDALONE and use it only for the percpu section, and the second
with all the codetag-related changes.
The introduction of SH_ENTSIZE_STANDALONE should also allow us to clean
up the current resetting of SHF_ALLOC for the percpu section, and now
also for codetag sections. The problem is that find_sec(".data..percpu")
can currently return different results depending on whether it is called
before layout_and_allocate() or later. In addition, apply_relocations()
needs a special case for SH_ENTSIZE_STANDALONE, where it could otherwise
just test SHF_ALLOC.
Instead of resetting SHF_ALLOC for percpu/codetag sections, both
__layout_sections() and move_module() can check for
SH_ENTSIZE_STANDALONE to determine whether a section is handled
specially and should be skipped.
I think it would be useful to include this change in the first patch
introducing MOD_STANDALONE, but I'm also ok with the current version.
I can send a separate patch later to make more use of
SH_ENTSIZE_STANDALONE in this way.
> @@ -2966,18 +2967,23 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
> */
> module_mark_ro_after_init(info->hdr, info->sechdrs, info->secstrings);
>
> - /*
> - * Determine total sizes, and put offsets in sh_entsize. For now
> - * this is done generically; there doesn't appear to be any
> - * special cases for the architectures.
> - */
> + /* Allow codetag sections to be allocated separately first. */
> + err = allocate_codetag_sections(info);
> + if (err) {
> + codetag_free_module_sections(info->mod);
The usual convention is that functions clean up after themselves on
error. That means this codetag_free_module_sections() call should be
done ideally by allocate_codetag_sections().
--
Thanks,
Petr
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC PATCH v6 2/2] module: allocate codetag sections before the regular module layout
2026-09-01 15:04 ` Petr Pavlu
@ 2026-09-01 18:36 ` Suren Baghdasaryan
2026-09-02 7:28 ` Hao Ge
2026-09-02 6:52 ` Hao Ge
1 sibling, 1 reply; 8+ messages in thread
From: Suren Baghdasaryan @ 2026-09-01 18:36 UTC (permalink / raw)
To: Petr Pavlu
Cc: Hao Ge, Luis Chamberlain, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Andrew Morton, linux-modules, linux-kernel, Sashiko
On Tue, Sep 1, 2026 at 8:04 AM Petr Pavlu <petr.pavlu@suse.com> wrote:
>
> On 8/31/26 9:21 AM, Hao Ge wrote:
> > Whether a codetag section goes to the codetag region is decided by
> > layout_sections() and asked again in move_module(). A concurrent
> > load can shut profiling down in between, and move_module() then
> > copies the section to offset 0 of its regular destination,
> > overwriting whatever is there.
> >
> > Decide and allocate in one pass, before the layout. Allocation
> > errors fail the load. On a tag area overflow profiling is already
> > disabled, so -EAGAIN makes the section fall back to regular module
> > data and the module still loads.
> >
> > The overflow and populate failure paths of reserve_module_tags() now
> > release their reservation instead of leaking the maple tree entry.
> > When profiling was toggled off, the overflow check did not run, a
> > module could load with more tags than the page flags can address,
> > and re-enabling profiling then silently corrupted /proc/allocinfo.
> > The check no longer depends on mem_alloc_profiling_enabled().
> >
> > Fixes: 4835f747d3ed ("alloc_tag: support for page allocation tag compression")
> > Reported-by: Sashiko <sashiko-bot@kernel.org>
> > Based-on-a-patch-by: Petr Pavlu <petr.pavlu@suse.com>
> > Cc: Suren Baghdasaryan <surenb@google.com>
> > Signed-off-by: Hao Ge <hao.ge@linux.dev>
> > ---
> > Changes against Petr's prototype:
> > - allocate_codetag_sections() returns an error instead of void, and
> > only -EAGAIN falls back to a regular section. Any other error now
> > fails the load. The prototype fell back on everything, which can
> > leave live tags in module memory.
> > - reserve_module_tags() releases its reservation when populate fails
> > too, that path used to leak the maple tree entry.
> > - codetag_free_module_sections() on the move_module() error path uses
> > info->mod, the local mod is assigned only after a successful move.
> > - The percpu section is marked only when index.pcpu != 0, otherwise
> > sechdrs[0] gets marked.
> > - Dropped the SHF_ALLOC check, .codetag.* sections always have it.
> > ---
> > include/linux/module.h | 2 +
> > kernel/module/internal.h | 4 ++
> > kernel/module/main.c | 120 ++++++++++++++++++++-------------------
> > mm/alloc_tag.c | 9 ++-
> > 4 files changed, 75 insertions(+), 60 deletions(-)
> >
> > diff --git a/include/linux/module.h b/include/linux/module.h
> > index 7566815fabbe..33548daa31a3 100644
> > --- a/include/linux/module.h
> > +++ b/include/linux/module.h
> > @@ -325,6 +325,8 @@ enum mod_mem_type {
> > MOD_INIT_RODATA,
> >
> > MOD_MEM_NUM_TYPES,
> > +
> > + MOD_STANDALONE = -2,
> > MOD_INVALID = -1,
> > };
> >
>
> It might be better to split this patch into two: the first to introduce
> MOD_STANDALONE and use it only for the percpu section, and the second
> with all the codetag-related changes.
>
> The introduction of SH_ENTSIZE_STANDALONE should also allow us to clean
> up the current resetting of SHF_ALLOC for the percpu section, and now
> also for codetag sections. The problem is that find_sec(".data..percpu")
> can currently return different results depending on whether it is called
> before layout_and_allocate() or later. In addition, apply_relocations()
> needs a special case for SH_ENTSIZE_STANDALONE, where it could otherwise
> just test SHF_ALLOC.
>
> Instead of resetting SHF_ALLOC for percpu/codetag sections, both
> __layout_sections() and move_module() can check for
> SH_ENTSIZE_STANDALONE to determine whether a section is handled
> specially and should be skipped.
>
> I think it would be useful to include this change in the first patch
> introducing MOD_STANDALONE, but I'm also ok with the current version.
> I can send a separate patch later to make more use of
> SH_ENTSIZE_STANDALONE in this way.
I ran some tests on my side and nothing blew up.
Petr's suggestion to split the patch sounds good to me and
release_module_tags() change in alloc_tag.c could also be done in a
separate patch. It's the cleanup after we do shutdown_mem_profiling(),
so I think it would be correct on its own.
Thanks,
Suren.
>
> > @@ -2966,18 +2967,23 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
> > */
> > module_mark_ro_after_init(info->hdr, info->sechdrs, info->secstrings);
> >
> > - /*
> > - * Determine total sizes, and put offsets in sh_entsize. For now
> > - * this is done generically; there doesn't appear to be any
> > - * special cases for the architectures.
> > - */
> > + /* Allow codetag sections to be allocated separately first. */
> > + err = allocate_codetag_sections(info);
> > + if (err) {
> > + codetag_free_module_sections(info->mod);
>
> The usual convention is that functions clean up after themselves on
> error. That means this codetag_free_module_sections() call should be
> done ideally by allocate_codetag_sections().
>
> --
> Thanks,
> Petr
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC PATCH v6 2/2] module: allocate codetag sections before the regular module layout
2026-09-01 15:04 ` Petr Pavlu
2026-09-01 18:36 ` Suren Baghdasaryan
@ 2026-09-02 6:52 ` Hao Ge
1 sibling, 0 replies; 8+ messages in thread
From: Hao Ge @ 2026-09-02 6:52 UTC (permalink / raw)
To: Petr Pavlu
Cc: Luis Chamberlain, Daniel Gomez, Sami Tolvanen, Aaron Tomlin,
Suren Baghdasaryan, Andrew Morton, linux-modules, linux-kernel,
Sashiko
Hi Petr
Thanks for review.
On 2026/9/1 23:04, Petr Pavlu wrote:
> On 8/31/26 9:21 AM, Hao Ge wrote:
>> Whether a codetag section goes to the codetag region is decided by
>> layout_sections() and asked again in move_module(). A concurrent
>> load can shut profiling down in between, and move_module() then
>> copies the section to offset 0 of its regular destination,
>> overwriting whatever is there.
>>
>> Decide and allocate in one pass, before the layout. Allocation
>> errors fail the load. On a tag area overflow profiling is already
>> disabled, so -EAGAIN makes the section fall back to regular module
>> data and the module still loads.
>>
>> The overflow and populate failure paths of reserve_module_tags() now
>> release their reservation instead of leaking the maple tree entry.
>> When profiling was toggled off, the overflow check did not run, a
>> module could load with more tags than the page flags can address,
>> and re-enabling profiling then silently corrupted /proc/allocinfo.
>> The check no longer depends on mem_alloc_profiling_enabled().
>>
>> Fixes: 4835f747d3ed ("alloc_tag: support for page allocation tag compression")
>> Reported-by: Sashiko <sashiko-bot@kernel.org>
>> Based-on-a-patch-by: Petr Pavlu <petr.pavlu@suse.com>
>> Cc: Suren Baghdasaryan <surenb@google.com>
>> Signed-off-by: Hao Ge <hao.ge@linux.dev>
>> ---
>> Changes against Petr's prototype:
>> - allocate_codetag_sections() returns an error instead of void, and
>> only -EAGAIN falls back to a regular section. Any other error now
>> fails the load. The prototype fell back on everything, which can
>> leave live tags in module memory.
>> - reserve_module_tags() releases its reservation when populate fails
>> too, that path used to leak the maple tree entry.
>> - codetag_free_module_sections() on the move_module() error path uses
>> info->mod, the local mod is assigned only after a successful move.
>> - The percpu section is marked only when index.pcpu != 0, otherwise
>> sechdrs[0] gets marked.
>> - Dropped the SHF_ALLOC check, .codetag.* sections always have it.
>> ---
>> include/linux/module.h | 2 +
>> kernel/module/internal.h | 4 ++
>> kernel/module/main.c | 120 ++++++++++++++++++++-------------------
>> mm/alloc_tag.c | 9 ++-
>> 4 files changed, 75 insertions(+), 60 deletions(-)
>>
>> diff --git a/include/linux/module.h b/include/linux/module.h
>> index 7566815fabbe..33548daa31a3 100644
>> --- a/include/linux/module.h
>> +++ b/include/linux/module.h
>> @@ -325,6 +325,8 @@ enum mod_mem_type {
>> MOD_INIT_RODATA,
>>
>> MOD_MEM_NUM_TYPES,
>> +
>> + MOD_STANDALONE = -2,
>> MOD_INVALID = -1,
>> };
>>
>
> It might be better to split this patch into two: the first to introduce
> MOD_STANDALONE and use it only for the percpu section, and the second
> with all the codetag-related changes.
>
OK, will do for the next version.
> The introduction of SH_ENTSIZE_STANDALONE should also allow us to clean
> up the current resetting of SHF_ALLOC for the percpu section, and now
> also for codetag sections. The problem is that find_sec(".data..percpu")
I also like that this keeps SHF_ALLOC semantics closer to the ELF spec.
https://www.sco.com/developers/gabi/latest/ch4.sheader.html
SHF_ALLOC
The section occupies memory during process execution. Some control sections do
not reside in the memory image of an object file; this attribute is off for those sections.
(I spent some time reading up on this, so hopefully I've understood it correctly.)
So it feels like we were taking a bit of a shortcut before.
These sections really do satisfy the SHF_ALLOC property by definition.
There were probably other reasons for doing it that way back then, but either‑way
I think adding SH_ENTSIZE_STANDALONE is a much cleaner solution.
> can currently return different results depending on whether it is called
> before layout_and_allocate() or later. In addition, apply_relocations()
> needs a special case for SH_ENTSIZE_STANDALONE, where it could otherwise
> just test SHF_ALLOC.
>
Yeah, fair point.
> Instead of resetting SHF_ALLOC for percpu/codetag sections, both
> __layout_sections() and move_module() can check for
> SH_ENTSIZE_STANDALONE to determine whether a section is handled
> specially and should be skipped.
>
Right, While working on the code, I noticed that __layout_sections already has a check for
this.
if ((s->sh_flags & masks[m][0]) != masks[m][0]
|| (s->sh_flags & masks[m][1])
|| s->sh_entsize != ~0UL
|| is_init != module_init_layout_section(sname))
continue;
s->sh_entsize != ~0UL can be used to handle this.
I'll add a short comment here.
> I think it would be useful to include this change in the first patch
> introducing MOD_STANDALONE, but I'm also ok with the current version.
> I can send a separate patch later to make more use of
> SH_ENTSIZE_STANDALONE in this way.
So cool.
>
>> @@ -2966,18 +2967,23 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
>> */
>> module_mark_ro_after_init(info->hdr, info->sechdrs, info->secstrings);
>>
>> - /*
>> - * Determine total sizes, and put offsets in sh_entsize. For now
>> - * this is done generically; there doesn't appear to be any
>> - * special cases for the architectures.
>> - */
>> + /* Allow codetag sections to be allocated separately first. */
>> + err = allocate_codetag_sections(info);
>> + if (err) {
>> + codetag_free_module_sections(info->mod);
>
> The usual convention is that functions clean up after themselves on
> error. That means this codetag_free_module_sections() call should be
> done ideally by allocate_codetag_sections().
>
Ack.
Thanks
Best Regards
Hao
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC PATCH v6 2/2] module: allocate codetag sections before the regular module layout
2026-09-01 18:36 ` Suren Baghdasaryan
@ 2026-09-02 7:28 ` Hao Ge
0 siblings, 0 replies; 8+ messages in thread
From: Hao Ge @ 2026-09-02 7:28 UTC (permalink / raw)
To: Suren Baghdasaryan, Petr Pavlu
Cc: Luis Chamberlain, Daniel Gomez, Sami Tolvanen, Aaron Tomlin,
Andrew Morton, linux-modules, linux-kernel, Sashiko
Hi Suren
Thanks for your review.
On 2026/9/2 02:36, Suren Baghdasaryan wrote:
> On Tue, Sep 1, 2026 at 8:04 AM Petr Pavlu <petr.pavlu@suse.com> wrote:
>>
>> On 8/31/26 9:21 AM, Hao Ge wrote:
>>> Whether a codetag section goes to the codetag region is decided by
>>> layout_sections() and asked again in move_module(). A concurrent
>>> load can shut profiling down in between, and move_module() then
>>> copies the section to offset 0 of its regular destination,
>>> overwriting whatever is there.
>>>
>>> Decide and allocate in one pass, before the layout. Allocation
>>> errors fail the load. On a tag area overflow profiling is already
>>> disabled, so -EAGAIN makes the section fall back to regular module
>>> data and the module still loads.
>>>
>>> The overflow and populate failure paths of reserve_module_tags() now
>>> release their reservation instead of leaking the maple tree entry.
>>> When profiling was toggled off, the overflow check did not run, a
>>> module could load with more tags than the page flags can address,
>>> and re-enabling profiling then silently corrupted /proc/allocinfo.
>>> The check no longer depends on mem_alloc_profiling_enabled().
>>>
>>> Fixes: 4835f747d3ed ("alloc_tag: support for page allocation tag compression")
>>> Reported-by: Sashiko <sashiko-bot@kernel.org>
>>> Based-on-a-patch-by: Petr Pavlu <petr.pavlu@suse.com>
>>> Cc: Suren Baghdasaryan <surenb@google.com>
>>> Signed-off-by: Hao Ge <hao.ge@linux.dev>
>>> ---
>>> Changes against Petr's prototype:
>>> - allocate_codetag_sections() returns an error instead of void, and
>>> only -EAGAIN falls back to a regular section. Any other error now
>>> fails the load. The prototype fell back on everything, which can
>>> leave live tags in module memory.
>>> - reserve_module_tags() releases its reservation when populate fails
>>> too, that path used to leak the maple tree entry.
>>> - codetag_free_module_sections() on the move_module() error path uses
>>> info->mod, the local mod is assigned only after a successful move.
>>> - The percpu section is marked only when index.pcpu != 0, otherwise
>>> sechdrs[0] gets marked.
>>> - Dropped the SHF_ALLOC check, .codetag.* sections always have it.
>>> ---
>>> include/linux/module.h | 2 +
>>> kernel/module/internal.h | 4 ++
>>> kernel/module/main.c | 120 ++++++++++++++++++++-------------------
>>> mm/alloc_tag.c | 9 ++-
>>> 4 files changed, 75 insertions(+), 60 deletions(-)
>>>
>>> diff --git a/include/linux/module.h b/include/linux/module.h
>>> index 7566815fabbe..33548daa31a3 100644
>>> --- a/include/linux/module.h
>>> +++ b/include/linux/module.h
>>> @@ -325,6 +325,8 @@ enum mod_mem_type {
>>> MOD_INIT_RODATA,
>>>
>>> MOD_MEM_NUM_TYPES,
>>> +
>>> + MOD_STANDALONE = -2,
>>> MOD_INVALID = -1,
>>> };
>>>
>>
>> It might be better to split this patch into two: the first to introduce
>> MOD_STANDALONE and use it only for the percpu section, and the second
>> with all the codetag-related changes.
>>
>> The introduction of SH_ENTSIZE_STANDALONE should also allow us to clean
>> up the current resetting of SHF_ALLOC for the percpu section, and now
>> also for codetag sections. The problem is that find_sec(".data..percpu")
>> can currently return different results depending on whether it is called
>> before layout_and_allocate() or later. In addition, apply_relocations()
>> needs a special case for SH_ENTSIZE_STANDALONE, where it could otherwise
>> just test SHF_ALLOC.
>>
>> Instead of resetting SHF_ALLOC for percpu/codetag sections, both
>> __layout_sections() and move_module() can check for
>> SH_ENTSIZE_STANDALONE to determine whether a section is handled
>> specially and should be skipped.
>>
>> I think it would be useful to include this change in the first patch
>> introducing MOD_STANDALONE, but I'm also ok with the current version.
>> I can send a separate patch later to make more use of
>> SH_ENTSIZE_STANDALONE in this way.
>
> I ran some tests on my side and nothing blew up.
>
Thanks.
> Petr's suggestion to split the patch sounds good to me and
> release_module_tags() change in alloc_tag.c could also be done in a
> separate patch. It's the cleanup after we do shutdown_mem_profiling(),
> so I think it would be correct on its own.
OK, if I understand you correctly, you'd like the release_module_tags() call
on vm_module_tags_populate() failure to go into its own separate patch.
That's because our -EAGAIN fallback depends on the reserve_module_tags() change.
Without it the overflow entry stays in the maple tree, codetag_module_replaced()
retargets it at the live module, and rmmod then walks the never-populated tag area
and faults.
Thanks
Best Regards
Hao
> Thanks,
> Suren.
>
>>
>>> @@ -2966,18 +2967,23 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
>>> */
>>> module_mark_ro_after_init(info->hdr, info->sechdrs, info->secstrings);
>>>
>>> - /*
>>> - * Determine total sizes, and put offsets in sh_entsize. For now
>>> - * this is done generically; there doesn't appear to be any
>>> - * special cases for the architectures.
>>> - */
>>> + /* Allow codetag sections to be allocated separately first. */
>>> + err = allocate_codetag_sections(info);
>>> + if (err) {
>>> + codetag_free_module_sections(info->mod);
>>
>> The usual convention is that functions clean up after themselves on
>> error. That means this codetag_free_module_sections() call should be
>> done ideally by allocate_codetag_sections().
>>
>> --
>> Thanks,
>> Petr
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-09-02 7:27 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-31 7:21 [RFC PATCH v6 0/2] module: allocate codetag sections before the regular module layout Hao Ge
2026-08-31 7:21 ` [RFC PATCH v6 1/2] alloc_tag: move release_module_tags() above reserve_module_tags() Hao Ge
2026-08-31 7:21 ` [RFC PATCH v6 2/2] module: allocate codetag sections before the regular module layout Hao Ge
2026-08-31 7:47 ` sashiko-bot
2026-09-01 15:04 ` Petr Pavlu
2026-09-01 18:36 ` Suren Baghdasaryan
2026-09-02 7:28 ` Hao Ge
2026-09-02 6:52 ` Hao Ge
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox