[PATCH v4 0/2] alloc_tag: fix undetected compressed tag overflow when profiling is disabled

Hao Ge posted 2 patches 1 month, 2 weeks ago
There is a newer version of this series
kernel/module/main.c |  17 ++++++++-
mm/alloc_tag.c       | 103 +++++++++++++++++++++++++++------------------------
2 files changed, 69 insertions(+), 51 deletions(-)
[PATCH v4 0/2] alloc_tag: fix undetected compressed tag overflow when profiling is disabled
Posted by Hao Ge 1 month, 2 weeks ago
v3 was a single patch. After discussion with Suren and Andrew we went
for a more graceful approach: rather than failing the module load on
overflow, let it load without profiling. Once profiling is disabled,
codetag_needs_module_section() returns false, so on retry the codetag
section is placed as regular module data.

A new patch (1/2) is added to move release_module_tags() above
reserve_module_tags(), since the overflow path now has to call it and
the helper sits below it.

release_module_tags() is what module unload calls to drop a module's
reservation from the maple tree. By the time reserve_module_tags()
detects the overflow it has already stored that reservation, and the
-EAGAIN return skips vm_module_tags_populate(), so the backing pages
never get mapped. If reserve_module_tags() returns without calling
release_module_tags(), the stale entry keeps pointing at that unmapped
range; when the module is later unloaded, release_module_tags() walks
it and panics.

Tested on an x86_64 virtual machine:

# 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.

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/

Hao Ge (2):
  alloc_tag: move release_module_tags() above reserve_module_tags()
  alloc_tag: fix undetected compressed tag overflow when profiling is
    disabled

 kernel/module/main.c |  17 ++++++++-
 mm/alloc_tag.c       | 103 +++++++++++++++++++++++++++------------------------
 2 files changed, 69 insertions(+), 51 deletions(-)

-- 
2.25.1
Re: [PATCH v4 0/2] alloc_tag: fix undetected compressed tag overflow when profiling is disabled
Posted by Andrew Morton 1 month, 2 weeks ago
On Mon, 10 Aug 2026 17:39:53 +0800 Hao Ge <hao.ge@linux.dev> wrote:

> v3 was a single patch. After discussion with Suren and Andrew we went
> for a more graceful approach: rather than failing the module load on
> overflow, let it load without profiling. Once profiling is disabled,
> codetag_needs_module_section() returns false, so on retry the codetag
> section is placed as regular module data.
> 
> A new patch (1/2) is added to move release_module_tags() above
> reserve_module_tags(), since the overflow path now has to call it and
> the helper sits below it.

Thing is, [2/2] has cc:stable but it requires [1/2] to be able to be
compiled.  [1/2] doesn't have cc:stable so we're asking -stable folks
to backport a patch which doesn't compile.

Resolve this by using the same Fixes: and cc:stable in both patches.

> release_module_tags() is what module unload calls to drop a module's
> reservation from the maple tree. By the time reserve_module_tags()
> detects the overflow it has already stored that reservation, and the
> -EAGAIN return skips vm_module_tags_populate(), so the backing pages
> never get mapped. If reserve_module_tags() returns without calling
> release_module_tags(), the stale entry keeps pointing at that unmapped
> range; when the module is later unloaded, release_module_tags() walks
> it and panics.

AI review had a lot to say about this patchset.  Some pre-existing, some
not:
	https://sashiko.dev/#/patchset/20260810093955.153015-1-hao.ge@linux.dev



offtopic: alloc_tag isn't getting allmodconfig build coverage at this
time because:

1: MEM_ALLOC_PROFILING depends on !DEBUG_FORCE_WEAK_PER_CPU (why?  I
   can't figure that out)

2: x86_64 allmodconfig enables DEBUG_FORCE_WEAK_PER_CPU, despite it
   being for s390 and alpha.  In fact it might be alpha-only.

Adding

	depends on ALPHA || S390

in there fixes this.
Re: [PATCH v4 0/2] alloc_tag: fix undetected compressed tag overflow when profiling is disabled
Posted by Suren Baghdasaryan 1 month, 2 weeks ago
On Mon, Aug 10, 2026 at 8:52 PM Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Mon, 10 Aug 2026 17:39:53 +0800 Hao Ge <hao.ge@linux.dev> wrote:
>
> > v3 was a single patch. After discussion with Suren and Andrew we went
> > for a more graceful approach: rather than failing the module load on
> > overflow, let it load without profiling. Once profiling is disabled,
> > codetag_needs_module_section() returns false, so on retry the codetag
> > section is placed as regular module data.
> >
> > A new patch (1/2) is added to move release_module_tags() above
> > reserve_module_tags(), since the overflow path now has to call it and
> > the helper sits below it.
>
> Thing is, [2/2] has cc:stable but it requires [1/2] to be able to be
> compiled.  [1/2] doesn't have cc:stable so we're asking -stable folks
> to backport a patch which doesn't compile.
>
> Resolve this by using the same Fixes: and cc:stable in both patches.
>
> > release_module_tags() is what module unload calls to drop a module's
> > reservation from the maple tree. By the time reserve_module_tags()
> > detects the overflow it has already stored that reservation, and the
> > -EAGAIN return skips vm_module_tags_populate(), so the backing pages
> > never get mapped. If reserve_module_tags() returns without calling
> > release_module_tags(), the stale entry keeps pointing at that unmapped
> > range; when the module is later unloaded, release_module_tags() walks
> > it and panics.
>
> AI review had a lot to say about this patchset.  Some pre-existing, some
> not:
>         https://sashiko.dev/#/patchset/20260810093955.153015-1-hao.ge@linux.dev

Yeah, some of them are not related to this change but at least one does.
I need to address the unrelated ones. Will do that as a separate patchset.

>
>
>
> offtopic: alloc_tag isn't getting allmodconfig build coverage at this
> time because:
>
> 1: MEM_ALLOC_PROFILING depends on !DEBUG_FORCE_WEAK_PER_CPU (why?  I
>    can't figure that out)

DEBUG_FORCE_WEAK_PER_CPU forces weak percpu definitions everywhere,
even in the core kernel. This introduces the restriction of [1]:

2. Static percpu variables cannot be defined inside a function.

Memory allocation profiling relies on percpu variables inside a
function in DEFINE_ALLOC_TAG(). For
CONFIG_ARCH_MODULE_NEEDS_WEAK_PER_CPU we comporomise by accounting all
module allocations to a statically defined _shared_alloc_tag (see [2])
but we can't do that for all kernel allocations because profiling
becomes quite meaningless at that point (all allocations being
accounted in the same counter is not useful).

[1] https://elixir.bootlin.com/linux/v7.2-rc6/source/include/linux/percpu-defs.h#L64
[2]  https://elixir.bootlin.com/linux/v7.2-rc6/source/include/linux/alloc_tag.h#L91

>
> 2: x86_64 allmodconfig enables DEBUG_FORCE_WEAK_PER_CPU, despite it
>    being for s390 and alpha.  In fact it might be alpha-only.
>
> Adding
>
>         depends on ALPHA || S390
>
> in there fixes this.