From nobody Fri Sep 25 08:45:42 2026 Received: from mta0.migadu.com (out-99.mta0.migadu.com [91.218.175.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 195DA1F5821 for ; Tue, 15 Sep 2026 06:59:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.99 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789455558; cv=none; b=TOWDdd8HUyUOAkI90MQX594fZYu9/dgbLOiMMJ2kN06dEaaGvl4eaW1FoAUhX64RECoIdRziTGNZUKDmPP+2d5dMl02f3A9G4aNZpLGHKcWMYubB9S5MPRHbsFMxcmzJIBKnG3KTkkim+pKaG79HmzUj1H9NqvRC6MidyJVYwJI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789455558; c=relaxed/simple; bh=1hrOUU2WscT9i12+q2dsMTJyNqNUXrCyPWNHR9ygX74=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=mLF7hQ+l3Y4oGRTsuLXXgo34FWS6P2Aisc0U+ZMTN/kWPKZvK4q9nB04xMSutlZKgFgNfay6sbPkrT9QuYs/DZTM1h3vKfQWUpVOoC+Pn2zcOyRGCQY6sGveF1mRaM9hXPiCGtO1BI8GvijTMOtH2hwmrWBRWUgf7ji5ud/6i2M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=Dz+c9LRn; arc=none smtp.client-ip=91.218.175.99 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="Dz+c9LRn" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=1hrOUU2WscT9i12+q2dsMTJyNqNUXrCyPWNHR9ygX74=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1789455553; v=1; x=1790060353; b=Dz+c9LRn+U4BKwUguORIFZqNQQxieg5o6zVodNBkoC2JEXt8UFf3IAGlY2Ygdn+0XcweaVfN RyzXkNvwdBOTnbJydG4u2KGY58++n+UcMBnQKR4CbLBnkhksvsIBdLOWisrIpXrFWhTKTay03rA jLB+iD4fMXYWigsmUd+sRAvg= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id 6a28f1219eb0585b; Tue, 15 Sep 2026 06:59:13 +0000 X-Mizu-Trace-ID: 6a28f1219eb0585b X-Migadu-Flow: FLOW_OUT From: Hao Ge To: Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , Aaron Tomlin , Suren Baghdasaryan , Kent Overstreet , Hao Ge , Andrew Morton Cc: linux-modules@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Sashiko , stable@vger.kernel.org Subject: [PATCH v10 1/6] alloc_tag: move release_module_tags() above reserve_module_tags() Date: Tue, 15 Sep 2026 14:59:56 +0800 Message-Id: <20260915070001.113559-2-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260915070001.113559-1-hao.ge@linux.dev> References: <20260915070001.113559-1-hao.ge@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 compressio= n") Fixes: 0f9b685626da ("alloc_tag: populate memory for module tags as needed") Reported-by: Sashiko Cc: stable@vger.kernel.org Acked-by: Suren Baghdasaryan Signed-off-by: Hao Ge --- 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 b33410310477..2070e682fe10 100644 --- a/mm/alloc_tag.c +++ b/mm/alloc_tag.c @@ -835,6 +835,52 @@ static int vm_module_tags_populate(void) return 0; } =20 +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 =3D=3D mod) + break; + + if (!val) /* module not found */ + goto out; + + if (!used) + goto release_area; + + start_tag =3D (struct alloc_tag *)(module_tags.start_addr + mas.index); + end_tag =3D (struct alloc_tag *)(module_tags.start_addr + mas.last); + if (!clean_unused_counters(start_tag, end_tag)) { + struct alloc_tag *tag; + + for (tag =3D start_tag; tag <=3D end_tag; tag++) { + struct alloc_tag_counters counter; + + if (!tag->counters) + continue; + + counter =3D 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 =3D false; + } +release_area: + mas_store(&mas, used ? &unloaded_mod : NULL); + val =3D mas_prev_range(&mas, 0); + if (val =3D=3D &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) { @@ -922,52 +968,6 @@ static void *reserve_module_tags(struct module *mod, u= nsigned long size, return (struct alloc_tag *)(module_tags.start_addr + offset); } =20 -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 =3D=3D mod) - break; - - if (!val) /* module not found */ - goto out; - - if (!used) - goto release_area; - - start_tag =3D (struct alloc_tag *)(module_tags.start_addr + mas.index); - end_tag =3D (struct alloc_tag *)(module_tags.start_addr + mas.last); - if (!clean_unused_counters(start_tag, end_tag)) { - struct alloc_tag *tag; - - for (tag =3D start_tag; tag <=3D end_tag; tag++) { - struct alloc_tag_counters counter; - - if (!tag->counters) - continue; - - counter =3D 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 =3D false; - } -release_area: - mas_store(&mas, used ? &unloaded_mod : NULL); - val =3D mas_prev_range(&mas, 0); - if (val =3D=3D &prepend_mod) - mas_store(&mas, NULL); -out: - mas_unlock(&mas); -} - static int load_module(struct module *mod, struct codetag *start, struct c= odetag *stop) { /* Allocate module alloc_tag percpu counters */ --=20 2.25.1 From nobody Fri Sep 25 08:45:42 2026 Received: from mta0.migadu.com (out-109.mta0.migadu.com [91.218.175.109]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E19AE443AB7 for ; Tue, 15 Sep 2026 06:59:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.109 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789455561; cv=none; b=BPUi7dmuJVbFcvSudC46BP7V06rNPtnyRc7EtdarhcbC62fOjF8qwRSoSvYCNOScr72z+MTKtCgxYiP/DIBKYXOaK+8eMbrBcM9khm2OAXrD3cR98gERSvqRG2HL6xSeHE/zdkZnY26IMAzkvfyhl+dJmF4VPHjLxNf90OvoS9E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789455561; c=relaxed/simple; bh=5Vw+v6tRRrP3hQtpFy1LEiukFTySuc0mxZr/k7GpH8M=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Fy1NuZMiTgHar9fEts8eD1nBb2fkQOoRgNNOgW1ky0IiMLBDr3zhcNNCQcdGCXGj8whEiAwmS0GGpNa9K1zvWVPEpCPOlS2Q+4VDc/J+H4jxRVx/qDIriyciwwzxU1cotiB18sf6Gd/xhC5Q20IEzv0+QlqGIcYbVRSIWHoy9iM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=XvH0H/gQ; arc=none smtp.client-ip=91.218.175.109 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="XvH0H/gQ" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=5Vw+v6tRRrP3hQtpFy1LEiukFTySuc0mxZr/k7GpH8M=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1789455557; v=1; x=1790060357; b=XvH0H/gQ5qZmazbWuhKBFp2+oUOmHjfpydsM0L5V/NgCCPIFe6vhmxRZGBaXpsOBgGDKmDtd zmbEMmdwUmy5/lFMm4b5JNGQF8A+ICmaNJs7q8QIbbToqFgD6TyKUsVV98xeMTThCSFOoi0PBhn LXSlF8qY6ajAsV+EVsusMMQ4= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id 332822dd31fa1db3; Tue, 15 Sep 2026 06:59:17 +0000 X-Mizu-Trace-ID: 332822dd31fa1db3 X-Migadu-Flow: FLOW_OUT From: Hao Ge To: Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , Aaron Tomlin , Suren Baghdasaryan , Kent Overstreet , Hao Ge , Andrew Morton Cc: linux-modules@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Sashiko , stable@vger.kernel.org Subject: [PATCH v10 2/6] alloc_tag: clean up the populate failure path Date: Tue, 15 Sep 2026 14:59:57 +0800 Message-Id: <20260915070001.113559-3-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260915070001.113559-1-hao.ge@linux.dev> References: <20260915070001.113559-1-hao.ge@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The reservation is already stored in the maple tree when vm_module_tags_populate() fails. A failed load never unloads the module, so nothing releases the entry. Release it and roll module_tags.size back. Without the rollback a concurrent load that already passed needs_section_mem() can reuse the freed gap, skip vm_module_tags_populate() and write to unmapped memory. vmap_pages_range() may have installed some PTEs before failing. A retry to populate the same range would BUG on them, so undo them, but only if vmap actually ran. Fixes: 4835f747d3ed ("alloc_tag: support for page allocation tag compressio= n") Fixes: 0f9b685626da ("alloc_tag: populate memory for module tags as needed") Reported-by: Sashiko Cc: stable@vger.kernel.org Signed-off-by: Hao Ge --- mm/alloc_tag.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mm/alloc_tag.c b/mm/alloc_tag.c index 2070e682fe10..95ddf5b743d0 100644 --- a/mm/alloc_tag.c +++ b/mm/alloc_tag.c @@ -804,6 +804,13 @@ static int vm_module_tags_populate(void) next_page, PAGE_SHIFT) < 0) { release_pages_arg arg =3D { .pages =3D next_page }; =20 + /* + * vmap_pages_range() only runs once all pages were + * allocated, and it may have installed some mappings + * before failing. Undo them. + */ + if (nr =3D=3D more_pages) + vunmap_range(phys_end, phys_end + (nr << PAGE_SHIFT)); /* Clean up and error out */ release_pages(arg, nr); return -ENOMEM; @@ -947,6 +954,7 @@ static void *reserve_module_tags(struct module *mod, un= signed long size, return ret; =20 if (module_tags.size < offset + size) { + unsigned long prev_size =3D module_tags.size; int grow_res; =20 module_tags.size =3D offset + size; @@ -961,6 +969,8 @@ static void *reserve_module_tags(struct module *mod, un= signed 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); + module_tags.size =3D prev_size; return ERR_PTR(grow_res); } } --=20 2.25.1 From nobody Fri Sep 25 08:45:42 2026 Received: from mta0.migadu.com (out-122.mta0.migadu.com [91.218.175.122]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 10C124457CF for ; Tue, 15 Sep 2026 06:59:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.122 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789455569; cv=none; b=XoMWchX77FSNBQdb0rsmvSI8PDzinnYuLA5tnpYzDdVaH2mBBf1tbTT35RB7LNULWc7sNzBDLvao75EQV6AFsV8pxTZRRCoOM6pR4hhAV+plcrLG+fEmVWbK7/tPrAXRUkgS3Rwh883Q1j2Dw5K3o77GzCYDNnfBY7FVs7g94nE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789455569; c=relaxed/simple; bh=JlOTHViXIUCNUHaVGMaJ96xltazLuZ70o/39P8cGYqY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=OzY7xlB7rzBQhxEzLoIMDzGGmmIUnb5qQj+SoIDDND9Yq17b+uCE1azPvCwuDE6aGVza8beEpIdIApb4pySmhQDkyMuoGKFGvRSVCgcdFloHuFn4m9+cEyorJ/4gmE/pfPmzI937pZCS0/NmefFQSwlQ1ZcQ+3DCcRbrHZx5j18= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=eX8qA/FQ; arc=none smtp.client-ip=91.218.175.122 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="eX8qA/FQ" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=JlOTHViXIUCNUHaVGMaJ96xltazLuZ70o/39P8cGYqY=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1789455565; v=1; x=1790060365; b=eX8qA/FQMAqQ1y9V0POhTCcGwZthmYQxTlnAsZJG+OaRuI4+ogmno1eG/AV6dDSEY4RyeKes lHjiOaxfYJlV5sAYxPByFS4RKMlAWHXhGl+P1cpNjm626+qshAIXbAsfQEqlvki4Yh6+yCc2TCl iqEQF3zM0n/R5iCVaBawJcoY= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id 5cc9afbad426c8d5; Tue, 15 Sep 2026 06:59:25 +0000 X-Mizu-Trace-ID: 5cc9afbad426c8d5 X-Migadu-Flow: FLOW_OUT From: Hao Ge To: Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , Aaron Tomlin , Suren Baghdasaryan , Kent Overstreet , Hao Ge , Andrew Morton Cc: linux-modules@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Sashiko , stable@vger.kernel.org Subject: [PATCH v10 3/6] module: introduce SH_ENTSIZE_STANDALONE for separately allocated sections Date: Tue, 15 Sep 2026 14:59:58 +0800 Message-Id: <20260915070001.113559-4-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260915070001.113559-1-hao.ge@linux.dev> References: <20260915070001.113559-1-hao.ge@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" SHF_ALLOC means, per the ELF spec, that a section occupies memory during process execution. Some module sections occupy memory outside the regular module layout, for example the percpu section with its per-CPU allocations. The loader currently excludes such a section from the layout by clearing its SHF_ALLOC, which overloads the flag with a loader-internal meaning. apply_relocations() needs a special case for the section, and find_sec(".data..percpu") returns different results before and after layout_and_allocate(). Introduce SH_ENTSIZE_STANDALONE to mark sections with a separate allocation. The percpu section is its first user. layout_sections() and move_module() skip marked sections, and apply_relocations() goes back to testing only SHF_ALLOC. Based on a patch by Petr Pavlu [1]. .data..percpu keeps SHF_ALLOC, so it would now show up under /sys/module/*/sections/. The section has one instance per CPU and no single address to report, and the entry never existed before, so skip it in add_sect_attrs(). add_notes_attrs() indexes its attrs[] array and skips it too. No functional change otherwise. Fixes: 4835f747d3ed ("alloc_tag: support for page allocation tag compressio= n") Reported-by: Sashiko Link: https://lore.kernel.org/all/499bb60c-c6e3-43a3-bd92-95a0567ece5e@suse= .com/ [1] Suggested-by: Petr Pavlu Reviewed-by: Petr Pavlu Cc: stable@vger.kernel.org Signed-off-by: Hao Ge Reviewed-by: Suren Baghdasaryan --- include/linux/module.h | 2 ++ kernel/module/internal.h | 8 ++++++++ kernel/module/kallsyms.c | 13 +++---------- kernel/module/main.c | 32 +++++++++++++++++--------------- kernel/module/sysfs.c | 17 +++++++++++++---- 5 files changed, 43 insertions(+), 29 deletions(-) diff --git a/include/linux/module.h b/include/linux/module.h index 96cc98568eea..0c6f32ddcbf2 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -325,6 +325,8 @@ enum mod_mem_type { MOD_INIT_RODATA, =20 MOD_MEM_NUM_TYPES, + + MOD_STANDALONE =3D -2, MOD_INVALID =3D -1, }; =20 diff --git a/kernel/module/internal.h b/kernel/module/internal.h index 061161cc79d9..4c738074a27b 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -29,6 +29,14 @@ #define SH_ENTSIZE_TYPE_MASK ((1UL << SH_ENTSIZE_TYPE_BITS) - 1) #define SH_ENTSIZE_OFFSET_MASK ((1UL << (BITS_PER_LONG - SH_ENTSIZE_TYPE_B= ITS)) - 1) =20 +/* + * Marker for sections with a separate allocation, which are not placed + * into mod->mem[]. + */ +#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) =20 diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c index f23126d804b2..0dca6d40160e 100644 --- a/kernel/module/kallsyms.c +++ b/kernel/module/kallsyms.c @@ -76,7 +76,7 @@ static char elf_type(const Elf_Sym *sym, const struct loa= d_info *info) } =20 static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs, - unsigned int shnum, unsigned int pcpundx) + unsigned int shnum) { const Elf_Shdr *sec; enum mod_mem_type type; @@ -86,11 +86,6 @@ static bool is_core_symbol(const Elf_Sym *src, const Elf= _Shdr *sechdrs, !src->st_name) return false; =20 -#ifdef CONFIG_KALLSYMS_ALL - if (src->st_shndx =3D=3D pcpundx) - return true; -#endif - sec =3D sechdrs + src->st_shndx; type =3D sec->sh_entsize >> SH_ENTSIZE_TYPE_SHIFT; if (!(sec->sh_flags & SHF_ALLOC) @@ -131,8 +126,7 @@ void layout_symtab(struct module *mod, struct load_info= *info) /* Compute total space required for the core symbols' strtab. */ for (ndst =3D i =3D 0; i < nsrc; i++) { if (i =3D=3D 0 || is_livepatch_module(mod) || - is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum, - info->index.pcpu)) { + is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum)) { strtab_size +=3D strlen(&info->strtab[src[i].st_name]) + 1; ndst++; } @@ -199,8 +193,7 @@ void add_kallsyms(struct module *mod, const struct load= _info *info) for (ndst =3D i =3D 0; i < kallsyms->num_symtab; i++) { kallsyms->typetab[i] =3D elf_type(src + i, info); if (i =3D=3D 0 || is_livepatch_module(mod) || - is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum, - info->index.pcpu)) { + is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum)) { ssize_t ret; =20 mod->core_kallsyms.typetab[ndst] =3D diff --git a/kernel/module/main.c b/kernel/module/main.c index c1b34dc1e89a..ae2678ac7840 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -1619,12 +1619,13 @@ static int apply_relocations(struct module *mod, co= nst struct load_info *info) =20 /* * Don't bother with non-allocated sections. - * An exception is the percpu section, which has separate allocations - * for individual CPUs. We relocate the percpu section in the initial - * ELF template and subsequently copy it to the per-CPU destinations. + * + * Note that .data..percpu has separate allocations for + * individual CPUs. We relocate the section in the + * initial ELF template and subsequently copy it to the + * per-CPU destinations. */ - if (!(info->sechdrs[infosec].sh_flags & SHF_ALLOC) && - (!infosec || infosec !=3D info->index.pcpu)) + if (!(info->sechdrs[infosec].sh_flags & SHF_ALLOC)) continue; =20 if (info->sechdrs[i].sh_flags & SHF_RELA_LIVEPATCH) @@ -1715,7 +1716,7 @@ static void __layout_sections(struct module *mod, str= uct load_info *info, bool i =20 if ((s->sh_flags & masks[m][0]) !=3D masks[m][0] || (s->sh_flags & masks[m][1]) - || s->sh_entsize !=3D ~0UL + || s->sh_entsize !=3D ~0UL /* offset or standalone */ || is_init !=3D module_init_layout_section(sname)) continue; =20 @@ -1745,16 +1746,10 @@ static void __layout_sections(struct module *mod, s= truct 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 =3D 0; i < info->hdr->e_shnum; i++) - info->sechdrs[i].sh_entsize =3D ~0UL; - pr_debug("Core section allocation order for %s:\n", mod->name); __layout_sections(mod, info, false); =20 @@ -2822,7 +2817,8 @@ static int move_module(struct module *mod, struct loa= d_info *info) Elf_Shdr *shdr =3D &info->sechdrs[i]; const char *sname; =20 - if (!(shdr->sh_flags & SHF_ALLOC)) + if (!(shdr->sh_flags & SHF_ALLOC) + || shdr->sh_entsize =3D=3D SH_ENTSIZE_STANDALONE) continue; =20 sname =3D info->secstrings + shdr->sh_name; @@ -2954,6 +2950,7 @@ core_param(module_blacklist, module_blacklist, charp,= 0400); static struct module *layout_and_allocate(struct load_info *info, int flag= s) { struct module *mod; + unsigned int i; int err; =20 /* Allow arches to frob section contents and sizes. */ @@ -2967,8 +2964,13 @@ static struct module *layout_and_allocate(struct loa= d_info *info, int flags) if (err < 0) return ERR_PTR(err); =20 + /* Repurpose sh_entsize to track where each section is allocated. */ + for (i =3D 0; i < info->hdr->e_shnum; i++) + info->sechdrs[i].sh_entsize =3D ~0UL; + /* We will do a special allocation for per-cpu sections later. */ - info->sechdrs[info->index.pcpu].sh_flags &=3D ~(unsigned long)SHF_ALLOC; + if (info->index.pcpu) + info->sechdrs[info->index.pcpu].sh_entsize =3D SH_ENTSIZE_STANDALONE; =20 /* * Mark relevant sections as SHF_RO_AFTER_INIT so layout_sections() can diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c index 01c65d608873..15c6baeb39c4 100644 --- a/kernel/module/sysfs.c +++ b/kernel/module/sysfs.c @@ -62,6 +62,15 @@ static void free_sect_attrs(struct module_sect_attrs *se= ct_attrs) kfree(sect_attrs); } =20 +/* + * .data..percpu has a separate allocation per CPU and no single + * address to report. + */ +static bool sect_visible(const struct load_info *info, unsigned int i) +{ + return !sect_empty(&info->sechdrs[i]) && i !=3D info->index.pcpu; +} + static int add_sect_attrs(struct module *mod, const struct load_info *info) { struct module_sect_attrs *sect_attrs; @@ -72,7 +81,7 @@ static int add_sect_attrs(struct module *mod, const struc= t load_info *info) =20 /* Count loaded sections and allocate structures */ for (i =3D 0; i < info->hdr->e_shnum; i++) - if (!sect_empty(&info->sechdrs[i])) + if (sect_visible(info, i)) nloaded++; sect_attrs =3D kzalloc_flex(*sect_attrs, attrs, nloaded); if (!sect_attrs) @@ -92,7 +101,7 @@ static int add_sect_attrs(struct module *mod, const stru= ct load_info *info) for (i =3D 0; i < info->hdr->e_shnum; i++) { Elf_Shdr *sec =3D &info->sechdrs[i]; =20 - if (sect_empty(sec)) + if (!sect_visible(info, i)) continue; sysfs_bin_attr_init(sattr); sattr->attr.name =3D @@ -159,7 +168,7 @@ static int add_notes_attrs(struct module *mod, const st= ruct load_info *info) /* Count notes sections and allocate structures. */ notes =3D 0; for (i =3D 0; i < info->hdr->e_shnum; i++) - if (!sect_empty(&info->sechdrs[i]) && + if (sect_visible(info, i) && info->sechdrs[i].sh_type =3D=3D SHT_NOTE) ++notes; =20 @@ -181,7 +190,7 @@ static int add_notes_attrs(struct module *mod, const st= ruct load_info *info) =20 nattr =3D ¬es_attrs->attrs[0]; for (loaded =3D i =3D 0; i < info->hdr->e_shnum; ++i) { - if (sect_empty(&info->sechdrs[i])) + if (!sect_visible(info, i)) continue; if (info->sechdrs[i].sh_type =3D=3D SHT_NOTE) { sysfs_bin_attr_init(nattr); --=20 2.25.1 From nobody Fri Sep 25 08:45:42 2026 Received: from mta0.migadu.com (out-137.mta0.migadu.com [91.218.175.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 64431446066 for ; Tue, 15 Sep 2026 06:59:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.137 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789455576; cv=none; b=tUUClG/HG1sA64p1Y+jAfgVFI/s7tG23I/vzuf6tIkETUyRYImxQ1JAfWwKCxfmj4gpKekz3CJCVeBs0yLASu0F0ExfxiV8QOB6O4RwqmZQ43exlN8TwEhNi6I+JLD0s66zJkNrbLDWjSzMZhUWtaX5jDXobC2ENVgo86fm1OJ0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789455576; c=relaxed/simple; bh=c4O0poOXDZAJ+dp5afuegzOnP6NuguXqyzv1RKQWySk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=hSPCNU+ISz1O6Y+es2JrHKqgYMXcLAHFDBT1fiHKAnWC23/rWSSBVIPbDARtZeHEipK1iiMuDKcXEBMNzqimBtGO94BW/6SwdgqUqSn65WuFFHgeemYkdN/nipBaA6wRmCCotrLpQgCRAGdXWo/yOPkBydzwR2vPLJ6pl9J8CZ8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=gZHJBhAW; arc=none smtp.client-ip=91.218.175.137 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="gZHJBhAW" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=c4O0poOXDZAJ+dp5afuegzOnP6NuguXqyzv1RKQWySk=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1789455572; v=1; x=1790060372; b=gZHJBhAW4Anv3v5A+AAu5ENXSA6gb6fCjUx7EWLCN4ZpK5wgXJWzjVFsYTZlRInWfG0Idl+D vg+oh8D+lhxUXylNf3UZzg3EkFiTBDwvTvEPYVR6pdCcBpB3eNe2yIVanbiF9qrt0LMoDbWR3xU qz6PTIXCMqoC5NWPwl8L3OjQ= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id 5b16f9d39e75a696; Tue, 15 Sep 2026 06:59:32 +0000 X-Mizu-Trace-ID: 5b16f9d39e75a696 X-Migadu-Flow: FLOW_OUT From: Hao Ge To: Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , Aaron Tomlin , Suren Baghdasaryan , Kent Overstreet , Hao Ge , Andrew Morton Cc: linux-modules@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Sashiko , stable@vger.kernel.org Subject: [PATCH v10 4/6] module: allocate codetag sections before the regular module layout Date: Tue, 15 Sep 2026 14:59:59 +0800 Message-Id: <20260915070001.113559-5-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260915070001.113559-1-hao.ge@linux.dev> References: <20260915070001.113559-1-hao.ge@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 reservation is released and module_tags.size rolled back, so a concurrent load which already passed needs_section_mem() does not skip vm_module_tags_populate(). An SHT_NOBITS codetag section is zeroed explicitly, the tag area pages are not zeroed on allocation. 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(). Based on a patch by Petr Pavlu [1]. Fixes: 4835f747d3ed ("alloc_tag: support for page allocation tag compressio= n") Reported-by: Sashiko Link: https://lore.kernel.org/all/499bb60c-c6e3-43a3-bd92-95a0567ece5e@suse= .com/ [1] Reviewed-by: Petr Pavlu Cc: stable@vger.kernel.org Signed-off-by: Hao Ge Reviewed-by: Suren Baghdasaryan --- kernel/module/main.c | 101 +++++++++++++++++++++++-------------------- mm/alloc_tag.c | 9 ++-- 2 files changed, 60 insertions(+), 50 deletions(-) diff --git a/kernel/module/main.c b/kernel/module/main.c index ae2678ac7840..b7ebcc40bdda 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -1723,20 +1723,6 @@ static void __layout_sections(struct module *mod, st= ruct load_info *info, bool i if (WARN_ON_ONCE(type =3D=3D MOD_INVALID)) continue; =20 - /* - * 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 =3D ((unsigned long)(type) & SH_ENTSIZE_TYPE_MASK) - << SH_ENTSIZE_TYPE_SHIFT; - continue; - } - s->sh_entsize =3D module_get_offset_and_type(mod, type, s, i); pr_debug("\t%s\n", sname); } @@ -2795,7 +2781,6 @@ static int move_module(struct module *mod, struct loa= d_info *info) { int i, ret; enum mod_mem_type t =3D MOD_MEM_NUM_TYPES; - bool codetag_section_found =3D false; =20 for_each_mod_mem_type(type) { if (!mod->mem[type].size) { @@ -2815,35 +2800,13 @@ static int move_module(struct module *mod, struct l= oad_info *info) for (i =3D 0; i < info->hdr->e_shnum; i++) { void *dest; Elf_Shdr *shdr =3D &info->sechdrs[i]; - const char *sname; =20 if (!(shdr->sh_flags & SHF_ALLOC) || shdr->sh_entsize =3D=3D SH_ENTSIZE_STANDALONE) continue; =20 - sname =3D 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 =3D codetag_alloc_module_section(mod, sname, shdr->sh_size, - arch_mod_section_prepend(mod, i), shdr->sh_addralign); - if (WARN_ON(!dest)) { - ret =3D -EINVAL; - goto out_err; - } - if (IS_ERR(dest)) { - ret =3D PTR_ERR(dest); - goto out_err; - } - codetag_section_found =3D true; - } else { - enum mod_mem_type type =3D shdr->sh_entsize >> SH_ENTSIZE_TYPE_SHIFT; - unsigned long offset =3D shdr->sh_entsize & SH_ENTSIZE_OFFSET_MASK; - - dest =3D mod->mem[type].base + offset; - } + dest =3D mod->mem[shdr->sh_entsize >> SH_ENTSIZE_TYPE_SHIFT].base + + (shdr->sh_entsize & SH_ENTSIZE_OFFSET_MASK); =20 if (shdr->sh_type !=3D SHT_NOBITS) { /* @@ -2875,8 +2838,6 @@ static int move_module(struct module *mod, struct loa= d_info *info) module_memory_restore_rox(mod); while (t--) module_memory_free(mod, t); - if (codetag_section_found) - codetag_free_module_sections(mod); =20 return ret; } @@ -2947,6 +2908,49 @@ static bool blacklisted(const char *module_name) } core_param(module_blacklist, module_blacklist, charp, 0400); =20 +/* + * 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 =3D 1; i < info->hdr->e_shnum; i++) { + Elf_Shdr *shdr =3D &info->sechdrs[i]; + const char *sname =3D info->secstrings + shdr->sh_name; + void *dest; + + if (!codetag_needs_module_section(info->mod, sname, shdr->sh_size)) + continue; + + dest =3D codetag_alloc_module_section(info->mod, sname, shdr->sh_size, + arch_mod_section_prepend(info->mod, i), shdr->sh_addralign); + if (WARN_ON(!dest)) { + codetag_free_module_sections(info->mod); + return -EINVAL; + } + if (dest =3D=3D ERR_PTR(-EAGAIN)) + /* Allocate the section as a regular section. */ + continue; + if (IS_ERR(dest)) { + codetag_free_module_sections(info->mod); + return PTR_ERR(dest); + } + + if (shdr->sh_type !=3D SHT_NOBITS) + memcpy(dest, (void *)shdr->sh_addr, shdr->sh_size); + else + memset(dest, 0, shdr->sh_size); + shdr->sh_addr =3D (unsigned long)dest; + shdr->sh_entsize =3D SH_ENTSIZE_STANDALONE; + } + + return 0; +} + static struct module *layout_and_allocate(struct load_info *info, int flag= s) { struct module *mod; @@ -2979,18 +2983,21 @@ static struct module *layout_and_allocate(struct lo= ad_info *info, int flags) */ module_mark_ro_after_init(info->hdr, info->sechdrs, info->secstrings); =20 - /* - * 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 =3D allocate_codetag_sections(info); + if (err) + return ERR_PTR(err); + + /* Determine total sizes and put offsets in sh_entsize. */ layout_sections(info->mod, info); layout_symtab(info->mod, info); =20 /* Allocate and move to the final place */ err =3D move_module(info->mod, info); - if (err) + if (err) { + codetag_free_module_sections(info->mod); return ERR_PTR(err); + } =20 /* Module has been copied to its final place now: return it. */ mod =3D (void *)info->sechdrs[info->index.mod].sh_addr; diff --git a/mm/alloc_tag.c b/mm/alloc_tag.c index 95ddf5b743d0..5836803898ad 100644 --- a/mm/alloc_tag.c +++ b/mm/alloc_tag.c @@ -958,10 +958,13 @@ static void *reserve_module_tags(struct module *mod, = unsigned long size, int grow_res; =20 module_tags.size =3D 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); + module_tags.size =3D prev_size; + return ERR_PTR(-EAGAIN); } =20 grow_res =3D vm_module_tags_populate(); --=20 2.25.1 From nobody Fri Sep 25 08:45:42 2026 Received: from mta0.migadu.com (out-142.mta0.migadu.com [91.218.175.142]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 917EB446C0C for ; Tue, 15 Sep 2026 06:59:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.142 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789455579; cv=none; b=ZfD2/FkhlMoOoSBRyUR8TsQul3Dh2ISeT4slLcf9uE9fDREFPUNvYdwli30YBBmi4KYPFF8Dcw8y/1s9eZngBZcId2rgzVddRL2PYw/Oi/jG89eLYFHeIsx9ZlkP8V9MyelSHD5wNGbHCm/JsTMW1SnDXkd19jvtuyLuG/Dwr7w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789455579; c=relaxed/simple; bh=j1q5lh6+pcNupQnOWdCoKiNEOrdrCXWiA588ffNXkqk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ls3L3FiRfu5H1kh1Bi7x+Mp+eB3J9GSx0INnv7oR0TjaVfuxMowy8OfhkemiG5RmzelStxAZH81olV3XIPrZxr92/TibygyhU8A3dW4F3dfMH73TUkNYnF01Z0KLYJtjj3aAqTg9PAE7gjvfJUqo2EQRyQO9l5wEmfzwxEHTI9M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=kcwewssJ; arc=none smtp.client-ip=91.218.175.142 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="kcwewssJ" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=j1q5lh6+pcNupQnOWdCoKiNEOrdrCXWiA588ffNXkqk=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1789455575; v=1; x=1790060375; b=kcwewssJoV9tjMvq8zA7F36JiK8XsZIx99HA4Hi5iMdA43G12vyPbV1ZVYHEEokVJwK7u2Rt ei+2BuSYhJdWwYhFP5Oxwg9tn2YuBTTaZ2w4Yta/OFq6ZPIylRd1vQVCI5BoSZuQ4uX4l/Q+AS1 OII+G2A3x2Iw5fyISiEg6HpM= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id 245cf166983b45cf; Tue, 15 Sep 2026 06:59:35 +0000 X-Mizu-Trace-ID: 245cf166983b45cf X-Migadu-Flow: FLOW_OUT From: Hao Ge To: Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , Aaron Tomlin , Suren Baghdasaryan , Kent Overstreet , Hao Ge , Andrew Morton Cc: linux-modules@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Sashiko , stable@vger.kernel.org Subject: [PATCH v10 5/6] alloc_tag: skip percpu counter allocation when profiling is disabled Date: Tue, 15 Sep 2026 15:00:00 +0800 Message-Id: <20260915070001.113559-6-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260915070001.113559-1-hao.ge@linux.dev> References: <20260915070001.113559-1-hao.ge@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" After shutdown_mem_profiling() clears mem_profiling_support, needs_section_mem() returns false, so later modules have their codetag section placed as regular data and never enter the alloc_tag maple tree. codetag_load_module() still called load_module(), which allocated a percpu counter for every tag; release_module_tags() could not find these modules on unload, so the counters leaked. Return -EOPNOTSUPP from load_module() when profiling is off: codetag_module_init() drops the module's cmod, no counters are allocated and the module loads without its tags. codetag_unload_module() now always calls free_section_mem(), since a module whose module_load() returned -EOPNOTSUPP is not in the idr but may still hold a reserved section. Reported-by: Sashiko Fixes: 4835f747d3ed ("alloc_tag: support for page allocation tag compressio= n") Cc: stable@vger.kernel.org Suggested-by: Suren Baghdasaryan Acked-by: Suren Baghdasaryan Signed-off-by: Hao Ge --- lib/codetag.c | 10 ++++++++-- mm/alloc_tag.c | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/codetag.c b/lib/codetag.c index a9cda4c962a3..a0b600720afc 100644 --- a/lib/codetag.c +++ b/lib/codetag.c @@ -240,7 +240,9 @@ static int codetag_module_init(struct codetag_type *ctt= ype, struct module *mod) =20 if (err < 0) { kfree(cmod); - return err; + /* -EOPNOTSUPP means we can load the module without its tag. */ + if (err !=3D -EOPNOTSUPP) + return err; } =20 return 0; @@ -388,7 +390,11 @@ void codetag_unload_module(struct module *mod) ++cttype->content_id; } up_write(&cttype->mod_lock); - if (found && cttype->desc.free_section_mem) + /* + * A module whose module_load() returned -EOPNOTSUPP is not + * in the idr but may still hold reserved section memory. + */ + if (cttype->desc.free_section_mem) cttype->desc.free_section_mem(mod, true); } mutex_unlock(&codetag_lock); diff --git a/mm/alloc_tag.c b/mm/alloc_tag.c index 5836803898ad..1ca0409b492b 100644 --- a/mm/alloc_tag.c +++ b/mm/alloc_tag.c @@ -988,6 +988,10 @@ static int load_module(struct module *mod, struct code= tag *start, struct codetag struct alloc_tag *stop_tag; struct alloc_tag *tag; =20 + /* Profiling disabled: load the module without its tags. */ + if (!mem_profiling_support) + return -EOPNOTSUPP; + /* percpu counters for core allocations are already statically allocated = */ if (!mod) return 0; --=20 2.25.1 From nobody Fri Sep 25 08:45:42 2026 Received: from mta0.migadu.com (out-153.mta0.migadu.com [91.218.175.153]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 99742447813 for ; Tue, 15 Sep 2026 06:59:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789455586; cv=none; b=sRVkZhx9Ws08eWYTnh54I172p+X9miUVVVwBcfpYvssBkaAOpiYQOfUrMCvp57aczbkA1/IdqJTItxRU+6lz2+OW0TwUsjz7KLWnP1e5rVEXJ3yFfJDTd8DSOU0rJdyhC0hXml5DP1xRzK8+qdG3Pz/Nb3k+iPTpNxOTg1DGaOI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789455586; c=relaxed/simple; bh=0gcszhOdin+bUpsUHNDDdcWh1NUbmDL4eeu4aqfKVU0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=qodIAJC4D5FgpKZbR0RC/iqmHJgCTePq9JxiLV21hNsjah+gfAqLJGVtmn86kguye9mptWijgvBGBHhVd4x1aXYrWaZ/D8edHR/h208u+0nJvzcMcCoWu/Zix8W3MpeaiIH8gFGqbh/VNJFU787rb2SrWD0gYyhz8uagdI85/EY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=ii7UKsEJ; arc=none smtp.client-ip=91.218.175.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="ii7UKsEJ" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=0gcszhOdin+bUpsUHNDDdcWh1NUbmDL4eeu4aqfKVU0=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1789455582; v=1; x=1790060382; b=ii7UKsEJcTBsF7caN5U1iFoEQgL0UqerqAbbcBOobpfHYqOXY5XOrkAR+NW+SfrUtm08NJgX wUnivqnee3uX/0YJZmuNIG0ypkh/Gd0p3OUsCYe9AN0OJ9uJwla9HSyQpjYPfieGPxJHVhKV39V kl65Ukv3OwOzPAtRWnLwwTng= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id efae1140c7a24bc8; Tue, 15 Sep 2026 06:59:42 +0000 X-Mizu-Trace-ID: efae1140c7a24bc8 X-Migadu-Flow: FLOW_OUT From: Hao Ge To: Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , Aaron Tomlin , Suren Baghdasaryan , Kent Overstreet , Hao Ge , Andrew Morton Cc: linux-modules@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Sashiko , stable@vger.kernel.org Subject: [PATCH v10 6/6] alloc_tag: Defer /proc/allocinfo removal to a workqueue Date: Tue, 15 Sep 2026 15:00:01 +0800 Message-Id: <20260915070001.113559-7-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260915070001.113559-1-hao.ge@linux.dev> References: <20260915070001.113559-1-hao.ge@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" shutdown_mem_profiling() calls remove_proc_entry() from reserve_module_tags(), which runs under mod_lock held for write. remove_proc_entry() waits for readers, and a reader takes mod_lock for read in allocinfo_start(): CPU0 (insmod) CPU1 (read /proc/allocinfo) ---------------- ---------------------------- reserve_module_tags() down_write(&mod_lock) [held] use_pde() [in_use++] allocinfo_start() down_read(&mod_lock) <- blocks shutdown_mem_profiling() remove_proc_entry() wait for in_use =3D=3D 0 <- blocks Move remove_proc_entry() to a workqueue. The file creation is moved to the end of alloc_tag_init() as well. If alloc_tag_init() fails with alloc_tag_cttype still NULL or an error pointer, a concurrent reader of the leftover file would dereference it in allocinfo_start() and panic. Reported-by: Sashiko Fixes: 4835f747d3ed ("alloc_tag: support for page allocation tag compressio= n") Cc: stable@vger.kernel.org Signed-off-by: Hao Ge --- mm/alloc_tag.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/mm/alloc_tag.c b/mm/alloc_tag.c index 1ca0409b492b..cfa0fc84b68f 100644 --- a/mm/alloc_tag.c +++ b/mm/alloc_tag.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include =20 @@ -591,6 +592,13 @@ void pgalloc_tag_swap(struct folio *new, struct folio = *old) put_page_tag_ref(handle_new); } =20 +static void remove_allocinfo_file(struct work_struct *work) +{ + remove_proc_entry(ALLOCINFO_FILE_NAME, NULL); +} + +static DECLARE_WORK(remove_allocinfo_work, remove_allocinfo_file); + static void shutdown_mem_profiling(bool remove_file) { if (mem_alloc_profiling_enabled()) @@ -600,7 +608,7 @@ static void shutdown_mem_profiling(bool remove_file) return; =20 if (remove_file) - remove_proc_entry(ALLOCINFO_FILE_NAME, NULL); + schedule_work(&remove_allocinfo_work); mem_profiling_support =3D false; } =20 @@ -1358,16 +1366,10 @@ static int __init alloc_tag_init(void) return 0; } =20 - if (!proc_create(ALLOCINFO_FILE_NAME, 0400, NULL, &allocinfo_proc_ops)) { - pr_err("Failed to create %s file\n", ALLOCINFO_FILE_NAME); - shutdown_mem_profiling(false); - return -ENOMEM; - } - res =3D alloc_mod_tags_mem(); if (res) { pr_err("Failed to reserve address space for module tags, errno =3D %d\n"= , res); - shutdown_mem_profiling(true); + shutdown_mem_profiling(false); return res; } =20 @@ -1375,10 +1377,16 @@ static int __init alloc_tag_init(void) if (IS_ERR(alloc_tag_cttype)) { pr_err("Allocation tags registration failed, errno =3D %pe\n", alloc_tag= _cttype); free_mod_tags_mem(); - shutdown_mem_profiling(true); + shutdown_mem_profiling(false); return PTR_ERR(alloc_tag_cttype); } =20 + if (!proc_create(ALLOCINFO_FILE_NAME, 0400, NULL, &allocinfo_proc_ops)) { + pr_err("Failed to create %s file\n", ALLOCINFO_FILE_NAME); + shutdown_mem_profiling(false); + return -ENOMEM; + } + return 0; } module_init(alloc_tag_init); --=20 2.25.1