From nobody Fri Sep 25 21:40:13 2026 Received: from mta0.migadu.com (out-34.mta0.migadu.com [91.218.175.34]) (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 6217D51121B for ; Tue, 8 Sep 2026 09:25:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.34 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788859504; cv=none; b=ddVOao50tcznhUzJOEozQweZVCbpAsP5vEj9FPNsIodFqf1qlyQf0Z33epd7Y5mkc8sHzyYFyJpw3VtkR3/Dah0LjTo9GqrONa4PRyMicufOgBsPnxwfNEoKUAQVP8kaCxNVWpCTbjYTsTRjit0AcFZz5FU3OE9Mxi5ogdy6gH8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788859504; c=relaxed/simple; bh=V8xaXgzY9XllyFlk89eNgFUoQBothzQGCS5P6ix37Rs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=a4iia36x3o0uyH8Qtc6e22aY1NMCpKf8JMWv+2zwjek4ISHCUk6K/+o4z/5luHXdeq6wEFUdn6Ae1wio/8o1XDNAIP1HXwG9pzal1RsQMKJ0J0s/D5ruIdNzhu8/O+104+2Mq0OpQACKoYyB0AhG8p4MkJIzwa/jgy33HzMW6nE= 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=ZXrStVWc; arc=none smtp.client-ip=91.218.175.34 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="ZXrStVWc" 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=1788859500; v=1; x=1789464300; b=ZXrStVWcA3ndDiMkvoP1jRCdp6khiCSvLxqJQtV0bJSJXkDh7dplec02Hh3J74eirFw9qVTX Fr+I/qtdJokdbU6KeuRo+ARA5whnojtoFuT39dL4j6CF9iYGRc1no8E646e6rYWoOrCTLdqkzFe kleMGcbeSGp2aQtOJ7vhkcMg= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id 73556141def5d3fb; Tue, 08 Sep 2026 09:25:00 +0000 X-Mizu-Trace-ID: 73556141def5d3fb 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 v9 1/4] alloc_tag: move release_module_tags() above reserve_module_tags() Date: Tue, 8 Sep 2026 17:24:09 +0800 Message-Id: <20260908092412.115953-2-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260908092412.115953-1-hao.ge@linux.dev> References: <20260908092412.115953-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 Fri Sep 25 21:40:13 2026 Received: from mta0.migadu.com (out-48.mta0.migadu.com [91.218.175.48]) (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 58DEE51E439 for ; Tue, 8 Sep 2026 09:25:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788859529; cv=none; b=Vj43mffSe2VbYRXrsNB7QMwWOfQcnkBXSoOutFKv6R124+w2madfN/dAFKmgU4JMdbOgj6sbDyaYiZLtoqQ0Rt3TkiSdzprFgW3sdrvVyAIn5UwCsiBI6iCDwwCMAaRHH2/l1xV0zc/hoj+AxPRC0ohHP1m4X2oFFZ9STlHMfg0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788859529; c=relaxed/simple; bh=LBg+sSLJXtOw4WEz6FbemiKRacEtP0xCjkkrVUCvXnY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rC50ZD92L+9turg28z4+tT/HMIxXMUWkADiBJnxPcvmMhWFu4Ma1emq6SZ08cKwQaX+UsKqAHjKEejt0LRsoVNTVyVREk/6GeKCEqFs+Bshj+4ZTLoV3os9CBJEFaIovGNL7eD64RZs6tFZ4NzveVIvroWCf97Ut+U11ntMRorA= 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=xkjjv8Qk; arc=none smtp.client-ip=91.218.175.48 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="xkjjv8Qk" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=LBg+sSLJXtOw4WEz6FbemiKRacEtP0xCjkkrVUCvXnY=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1788859526; v=1; x=1789464326; b=xkjjv8QkGbLFxmumUWQo4JmgAxkQdSsD3poo1JVJvohVH54wQYpRVSmscrnbe3XBjOUUoZQE hQBRbWe66aujOa/v3EIf+Vw0P2EtRZ3WwlJywiexqmvjcmHx1KlvS9HJo9eDnk0iJTMsLMAkCAw gkWmDBKkN2Vydw4zjcWzGHNU= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id 7cf99981dc3c1c49; Tue, 08 Sep 2026 09:25:07 +0000 X-Mizu-Trace-ID: 7cf99981dc3c1c49 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 v9 2/4] alloc_tag: clean up the populate failure path Date: Tue, 8 Sep 2026 17:24:10 +0800 Message-Id: <20260908092412.115953-3-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260908092412.115953-1-hao.ge@linux.dev> References: <20260908092412.115953-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 e7a79116ad81..e7a40a276ed9 100644 --- a/mm/alloc_tag.c +++ b/mm/alloc_tag.c @@ -812,6 +812,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; @@ -955,6 +962,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; @@ -969,6 +977,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 21:40:13 2026 Received: from mta0.migadu.com (out-58.mta0.migadu.com [91.218.175.58]) (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 7DC7E51E443 for ; Tue, 8 Sep 2026 09:25:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.58 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788859535; cv=none; b=Eja4/oHWms3yX93yibyeUr+8t29rXl+LOTYORs4tEBxhsx4lgCjeDrPsU86mfy/Ndi+l7lAUYyM0nmmrZYGlwMAG90JzjAai9MNQOpxOv1sy72ErMD18VUk+WyZR03Ucb67NpPK6E2uSPQw3cMO4HE6rRmTz1kkM1vh2lsN1ZEc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788859535; c=relaxed/simple; bh=w/KB1SsQSsoWxYDHp1kzPPFPoeIu4Zqs63a0uQsIsZg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pgso7tus/vcgIYUoOUCti8fT/oVb+07HRepEhb3gAvr9u/QsQROlnJDyFhKP4NXAUbgZmoZDCrKtyGudILgtGuWg0g3swqFt5t0DoJo/knaTM2577yUHaKyyjXc9ah0yZJaAH/b/7dKOdSWaNQ5ZwEeVFOw/K6BU+WfI2c/dqBE= 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=rYkOBLKi; arc=none smtp.client-ip=91.218.175.58 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="rYkOBLKi" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=w/KB1SsQSsoWxYDHp1kzPPFPoeIu4Zqs63a0uQsIsZg=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1788859530; v=1; x=1789464330; b=rYkOBLKivt11g3GSTJpmD8ijpu5fzzP6KMxIoAORyd/Od/5CtVQPIPr5/IcgJHjZs/MWd/+Q 5lpD07jtO3x8uqYQckc/y7wn7TxPbE7UUyB32MvVVbNgTc0XG4aPLQsGyOeB58DFp1hKPFtMTIr 6Mi6lMFIe3hNAx+pFDULnaM4= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id da906c699fed78dd; Tue, 08 Sep 2026 09:25:30 +0000 X-Mizu-Trace-ID: da906c699fed78dd 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 v9 3/4] module: introduce SH_ENTSIZE_STANDALONE for separately allocated sections Date: Tue, 8 Sep 2026 17:24:11 +0800 Message-Id: <20260908092412.115953-4-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260908092412.115953-1-hao.ge@linux.dev> References: <20260908092412.115953-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 Cc: stable@vger.kernel.org Signed-off-by: Hao Ge Reviewed-by: Petr Pavlu --- include/linux/module.h | 2 ++ kernel/module/internal.h | 8 ++++++++ kernel/module/kallsyms.c | 13 +++---------- kernel/module/main.c | 32 +++++++++++++++++--------------- kernel/module/sysfs.c | 15 ++++++++++++--- 5 files changed, 42 insertions(+), 28 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, =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..fc577c01dfd2 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 diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c index 01c65d608873..f64170344e69 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 @@ -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 21:40:13 2026 Received: from mta0.migadu.com (out-66.mta0.migadu.com [91.218.175.66]) (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 DD05F4F4739 for ; Tue, 8 Sep 2026 09:25:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.66 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788859538; cv=none; b=VEz/fm+/iTmuokoUMEyQ8c1cKo/KwPBHVUdIdJ3DS4BxgwqZxiQsvd+gg3EroyTFUkMnRfOA3g6K8QqCYbV+COmYxCOphvyuuqRUEG8cddf00RpksGoaXLH6OG2OZPaxOxnalYosBb9kekx0aK5r7tZGTDVh4a07zm89n8rrFtk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788859538; c=relaxed/simple; bh=KRpwdv0Ik6eghF0NQ+wLMkFshij8x/0D3GA8MdrghsA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Cd29UFOPyKse9U4reJUNr6tkzDwaVNU3bMK2xXvB0Quuu4BwDnLSqrV02nWaxlb4AsaTMECoA5V92r1UwdOAs+45LqBoagxAHAQMs6z8zJTgeqR8cT6ATHZwerqjZlUs319z13+UvqlsVlCJUlvOaiGkZqF1lvbmnTaE1iiF/4I= 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=PEZ8PJjb; arc=none smtp.client-ip=91.218.175.66 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="PEZ8PJjb" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=KRpwdv0Ik6eghF0NQ+wLMkFshij8x/0D3GA8MdrghsA=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1788859533; v=1; x=1789464333; b=PEZ8PJjbmnbstFzOJjdVnR4na8OjjuWVCzLOYTpiG8KyUKqTIToi/nQrIEKZWmYnd0OPse2c DZSZUePIYHxRP6cUaE2hBtl2LMxNnGvQaOO1uxcn/4LQBj1bqhqXlA3pOPbrXGLibNc7CQIcNKn NstLvxXfITPX4tipEVwz/qJk= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id de3ac1b114ad648f; Tue, 08 Sep 2026 09:25:33 +0000 X-Mizu-Trace-ID: de3ac1b114ad648f 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 v9 4/4] module: allocate codetag sections before the regular module layout Date: Tue, 8 Sep 2026 17:24:12 +0800 Message-Id: <20260908092412.115953-5-hao.ge@linux.dev> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260908092412.115953-1-hao.ge@linux.dev> References: <20260908092412.115953-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] Cc: stable@vger.kernel.org Signed-off-by: Hao Ge Reviewed-by: Petr Pavlu --- 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 fc577c01dfd2..af8880d430fb 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 e7a40a276ed9..76942f2e3905 100644 --- a/mm/alloc_tag.c +++ b/mm/alloc_tag.c @@ -966,10 +966,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