From nobody Sat Sep 26 01:03:37 2026 Received: from mta1.migadu.com (out-57.mta1.migadu.com [95.215.58.57]) (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 45E12396561 for ; Mon, 7 Sep 2026 06:23:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.57 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788762216; cv=none; b=ZKeFGpMGuu3hIbh1PATSNZtqMpbCqDn7NNnmTYl59UoSw0MUoKQ+6I6OE25l26yC9dGBmY9qH0Xj3GQ4Vb60ykczj2+t6fCZkUSlG8rKgy5e4J4LvV6zex/c+YyDzHfSxwTPZ+d3iocTANs0pc3tRMmn5ygfsDeI0nAinxWET8c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788762216; c=relaxed/simple; bh=V8xaXgzY9XllyFlk89eNgFUoQBothzQGCS5P6ix37Rs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=PvlYzbNMHU33gMNjIz7ohBD/q56Obrz1yVB1abGlNoWEIT+Vn0Kie/ykzz8Ysb4SU2lMYofPzJwFby99nX8i/Qe8jvjsFXu8fzNd1IlGR509LB6Y7G8BkodWQ9umfsdiBOy6smmF79rtUpQ0SUHLJjBQfO8yyREq9qcCKgzPHj4= 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=OC/zIDew; arc=none smtp.client-ip=95.215.58.57 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="OC/zIDew" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=V8xaXgzY9XllyFlk89eNgFUoQBothzQGCS5P6ix37Rs=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1788762209; v=1; x=1789367009; b=OC/zIDewivDGk5D/c2JMi+LTo2WKd7KhSdjJ7tDuc7BrSGSKXj/q1UZJ7gM9Uohur7TZqF4i OaA19RRN733XQ5y0Mi5jrHu9E/Vq56iCXSlU203pOFrG+snKnppv0Mkd1JVcsAr7mN5x81iXjlz VW2k56RylWsEPTPxVBP5fEdM= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id 985a0dad0ac24b89; Mon, 07 Sep 2026 06:23:29 +0000 X-Mizu-Trace-ID: 985a0dad0ac24b89 X-Migadu-Flow: FLOW_OUT From: Hao Ge To: Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , Aaron Tomlin , Suren Baghdasaryan , Hao Ge , Andrew Morton Cc: linux-modules@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, Sashiko , stable@vger.kernel.org Subject: [PATCH v8 1/4] alloc_tag: move release_module_tags() above reserve_module_tags() Date: Mon, 7 Sep 2026 14:24:10 +0800 Message-Id: <20260907062414.106873-2-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260907062414.106873-1-hao.ge@linux.dev> References: <20260907062414.106873-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 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; } =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) { @@ -930,52 +976,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 Sat Sep 26 01:03:37 2026 Received: from mta1.migadu.com (out-60.mta1.migadu.com [95.215.58.60]) (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 EA8F8396567 for ; Mon, 7 Sep 2026 06:23:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.60 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788762221; cv=none; b=Pv6z12vDhPELtf1nC0u/acW4cXKaRNnHv0//X+UQjvTiCeHUD5n2PrBte21V552VBhlbl6igOoPBcD9Sh240gikIKh6n7j5UOzJIsANtP9e5IPujB8Jo2cCjHVSvubrSiCQqFGjdlpVbR/OFJUHdod77eYGgO9ktMh+/5lRDgP8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788762221; c=relaxed/simple; bh=W54UFCGSSmwPyS5+O/eCDyT8i2/f/U9GJTv7sexmrHE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=MMtYT8Ltvf9dSwRbMr3EQsPvgbtlsjsIuYgjNK5hAvIuPvM8mtwfkudMNzybwzw1FcnG6kWJCI7NlIo4x6aw7ZS5kRN2pyujGI5cWGYccyShOZGfsEo78gu2j503r+TDdDVnaA/R2YFKP1B8OcqUv7OpPxWqWx+YSRw52VKRgfU= 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=q2z26p0J; arc=none smtp.client-ip=95.215.58.60 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="q2z26p0J" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=W54UFCGSSmwPyS5+O/eCDyT8i2/f/U9GJTv7sexmrHE=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1788762214; v=1; x=1789367014; b=q2z26p0Jf3bjp3A6wUJs8UbU99dI8imvyofo+dNgfSw9/t6l7sabLv3F5vyBKe4FyuP602so zdZXDxLPOfbkAxp2SW/YiYWpF5FSTZOjN8BpCV4xkEOJsi+pNU2GRVhaf1n59dwYY3AHBsuZByA beiBQW1gGpB8OxYe8DhELbtg= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id 20bcc22c11472e28; Mon, 07 Sep 2026 06:23:34 +0000 X-Mizu-Trace-ID: 20bcc22c11472e28 X-Migadu-Flow: FLOW_OUT From: Hao Ge To: Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , Aaron Tomlin , Suren Baghdasaryan , Hao Ge , Andrew Morton Cc: linux-modules@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, Sashiko , stable@vger.kernel.org Subject: [PATCH v8 2/4] module: introduce SH_ENTSIZE_STANDALONE for separately allocated sections Date: Mon, 7 Sep 2026 14:24:11 +0800 Message-Id: <20260907062414.106873-3-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260907062414.106873-1-hao.ge@linux.dev> References: <20260907062414.106873-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 is now exported under /sys/module/*/sections/. Report the boot CPU instance of the module's per-CPU area there, as __is_module_percpu_address() does. 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] Cc: stable@vger.kernel.org Signed-off-by: Hao Ge --- Documentation/ABI/testing/sysfs-module | 8 ++++++ include/linux/module.h | 2 ++ kernel/module/internal.h | 8 ++++++ kernel/module/kallsyms.c | 13 +++------ kernel/module/main.c | 37 +++++++++++++++----------- 5 files changed, 43 insertions(+), 25 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-module b/Documentation/ABI/tes= ting/sysfs-module index d5b7d19bd310..65e152c6fa58 100644 --- a/Documentation/ABI/testing/sysfs-module +++ b/Documentation/ABI/testing/sysfs-module @@ -57,6 +57,14 @@ Description: List of symbol namespaces imported by this = module via This file only exists for modules that import at least one namespace. =20 +What: /sys/module/*/sections/
+Date: June 2005 +KernelVersion: 2.6.12 +Contact: linux-modules@vger.kernel.org +Description: The memory address of the given loaded section of the + module. .data..percpu has one instance per CPU; the + address reported is the instance of the boot CPU. + What: /sys/module/*/taint Date: Jan 2012 KernelVersion: 3.3 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, =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 0fc11e45df9b..49190deae61e 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 c32f1d370b73..20b85148ad72 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -1620,12 +1620,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) @@ -1716,7 +1717,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 @@ -1746,16 +1747,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 @@ -2811,7 +2806,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; @@ -2943,6 +2939,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. */ @@ -2956,8 +2953,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 @@ -3520,6 +3522,11 @@ static int load_module(struct load_info *info, const= char __user *uargs, if (err < 0) goto free_modinfo; =20 + /* The percpu ELF section is a template; report the boot CPU instance. */ + if (info->index.pcpu) + info->sechdrs[info->index.pcpu].sh_addr =3D + (unsigned long)per_cpu_ptr(mod->percpu, get_boot_cpu_id()); + flush_module_icache(mod); =20 /* Now copy in args */ --=20 2.25.1 From nobody Sat Sep 26 01:03:37 2026 Received: from mta0.migadu.com (out-80.mta0.migadu.com [91.218.175.80]) (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 B7EF439902B for ; Mon, 7 Sep 2026 06:23:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.80 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788762228; cv=none; b=o0hapoImF0zLJ4UN8lIEKW/zgy/I7//BUqXO3GU401KowhNEtfwVf3WxhtbXnBfnfi2ZsJby4SRz+4gzHyXNRjABpfpYWyRCPdlUsqpvT5R1YhGqcbmDWifrD5Clug+l5V5swLIpoi4iUTlSm6LO9Uu4el83LQjYPxEsi0T2FJ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788762228; c=relaxed/simple; bh=ZC7KtKLUN5VQuY7xOf0M7JnuJe+C9bnmljuxLn9sX8g=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=N04M1O+xOY7a6PLZYexERAlou3bcB8f94aVtW5IzdXK1RstwUiv3WOsax+002RNdAn14bklEKB9pLkX+DRuRefHyA7u5rBq4W79sY5YKqcjH/Vnp6bWt0ebpGnqtIU8XIX/gsWhMReWR6Aj+hvSn4Kqulg41Ef+6UJUuiXYanmE= 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=tXNY0+GU; arc=none smtp.client-ip=91.218.175.80 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="tXNY0+GU" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=ZC7KtKLUN5VQuY7xOf0M7JnuJe+C9bnmljuxLn9sX8g=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1788762220; v=1; x=1789367020; b=tXNY0+GU0SJM6JXoUvJ1LkPJTPmJS18ZlQNbB99ovOHTe7bez+cb5y8mrQhqHdI/RsLsNtPl QqM81FWBKNQFLFFtHK88jzpZZ40pE8csfkhL6WZIxP67pwiVbOPUdUXTAEHXP7dTLJYZBmY73Fw u7YP2IXSRR0FsVitVASARuvQ= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id e3dafb86706da778; Mon, 07 Sep 2026 06:23:39 +0000 X-Mizu-Trace-ID: e3dafb86706da778 X-Migadu-Flow: FLOW_OUT From: Hao Ge To: Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , Aaron Tomlin , Suren Baghdasaryan , Hao Ge , Andrew Morton Cc: linux-modules@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, Sashiko , stable@vger.kernel.org Subject: [PATCH v8 3/4] module: allocate codetag sections before the regular module layout Date: Mon, 7 Sep 2026 14:24:12 +0800 Message-Id: <20260907062414.106873-4-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260907062414.106873-1-hao.ge@linux.dev> References: <20260907062414.106873-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. 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] Cc: stable@vger.kernel.org Signed-off-by: Hao Ge --- kernel/module/main.c | 101 +++++++++++++++++++++++-------------------- mm/alloc_tag.c | 8 ++-- 2 files changed, 59 insertions(+), 50 deletions(-) diff --git a/kernel/module/main.c b/kernel/module/main.c index 20b85148ad72..612facc51214 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -1724,20 +1724,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); } @@ -2784,7 +2770,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) { @@ -2804,35 +2789,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) { /* @@ -2864,8 +2827,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; } @@ -2936,6 +2897,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; @@ -2968,18 +2972,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 e7a79116ad81..248496470904 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; =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); + return ERR_PTR(-EAGAIN); } =20 grow_res =3D vm_module_tags_populate(); --=20 2.25.1 From nobody Sat Sep 26 01:03:37 2026 Received: from mta0.migadu.com (out-88.mta0.migadu.com [91.218.175.88]) (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 1351839CD10 for ; Mon, 7 Sep 2026 06:23:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.88 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788762231; cv=none; b=WSuWKv7L6bfwNckVD/0ZqYb6FTdIGqVWyowe93feN8svE5NEeb5oh2B/WF2TbyeFNq7CSKVflftcgUFWvGXh05a//uHrDZGUt4ibZ1nYi/oYZ1vkhJyyCaxQo2Q2NQKOzwE2CZDLH6upCNTN2jdbw6cEDnuOvJESXNh+4jUTAHQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788762231; c=relaxed/simple; bh=dWk9y7b0drDaUlfFd/9bCLMEQv7pdwsvhjNQU3mPn70=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=RDNsQLX52oOPeU6tPR9EQHutI9eUd6tZrJREAUTypwGncEcK5dnfQd5WTP9lWON36IclXqvXVgu2tAspZbhu6sSL+vtMSyA4j1q4fimaUnQ5mbQmZHYgxbYe+VX3gFPR/vYrIhpalPmX6i9ef/+yY3rP1tqtxiAoviVqYk9aB84= 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=gPv2xR5W; arc=none smtp.client-ip=91.218.175.88 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="gPv2xR5W" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=dWk9y7b0drDaUlfFd/9bCLMEQv7pdwsvhjNQU3mPn70=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1788762224; v=1; x=1789367024; b=gPv2xR5WCmei2BlE4GtflZefmNDXluoiWnU5rajvt4Vt+b8SjL04YH5GEufPNfr4AQ3x4XUL GnC/KWy2lHyfNi1h705t1T+61VQl+3W26EPM2Bcvi2mpt42cFoVjiLMjqyOp3xVze1u5RszBVo8 maAzF46K7inKvMUK+Yy8psUs= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id bbad7cc037fa0143; Mon, 07 Sep 2026 06:23:44 +0000 X-Mizu-Trace-ID: bbad7cc037fa0143 X-Migadu-Flow: FLOW_OUT From: Hao Ge To: Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , Aaron Tomlin , Suren Baghdasaryan , Hao Ge , Andrew Morton Cc: linux-modules@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, Sashiko , stable@vger.kernel.org Subject: [PATCH v8 4/4] alloc_tag: release the reservation when populate fails Date: Mon, 7 Sep 2026 14:24:13 +0800 Message-Id: <20260907062414.106873-5-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260907062414.106873-1-hao.ge@linux.dev> References: <20260907062414.106873-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" vm_module_tags_populate() can fail after the reservation was stored in the maple tree, and the error return leaks the entry, since a failed load never unloads the module. Release it. 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 | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/alloc_tag.c b/mm/alloc_tag.c index 248496470904..3c25475becbc 100644 --- a/mm/alloc_tag.c +++ b/mm/alloc_tag.c @@ -971,6 +971,7 @@ 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); return ERR_PTR(grow_res); } } --=20 2.25.1