Modules changes for v7.0-rc1

Module signing:
 
   - Remove SHA-1 support for signing modules. SHA-1 is no longer
     considered secure for signatures due to vulnerabilities that can
     lead to hash collisions. None of the major distributions use
     SHA-1 anymore, and the kernel has defaulted to SHA-512 since
     v6.11. Note that loading SHA-1 signed modules is still supported.
 
   - Update scripts/sign-file to use only the OpenSSL CMS API for
     signing. As SHA-1 support is gone, we can drop the legacy PKCS#7
     API which was limited to SHA-1. This also cleans up support for
     legacy OpenSSL versions.
 
 Cleanups and fixes:
 
   - Use system_dfl_wq instead of the per-cpu system_wq following the
     ongoing workqueue API refactoring.
 
   - Avoid open-coded kvrealloc() in module decompression logic by
     using the standard helper.
 
   - Improve section annotations by replacing the custom __modinit
     with __init_or_module and removing several unused __INIT*_OR_MODULE
     macros.
 
   - Fix kernel-doc warnings in include/linux/moduleparam.h.
 
   - Ensure set_module_sig_enforced is only declared when module
     signing is enabled.
 
   - Fix gendwarfksyms build failures on 32-bit hosts.
 
 MAINTAINERS:
 
   - Update the module subsystem entry to reflect the maintainer
     rotation and update the git repository link.
 
 The changes have been soaking in linux-next since -rc2.
 
 Note that like Daniel mentioned in the previous pull request [1], we
 rotate maintainership every 6 months, and I will be handling the module
 subsystem pull requests for the first half of this year.
 
 Link: https://lore.kernel.org/r/20251203234840.3720-1-da.gomez@kernel.org [1]
 Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQSE9au1u/dCZerzchhaByWrOaGnegUCaYYeeAAKCRBaByWrOaGn
 epIxAQDU/VSAC491S9/5dAUeGbOis9/p6QJKQlNgEqU4oTlOsgEA0p8BZ9Spkwzd
 v9BfIl3j9qVt7wUdlLdbHfdvPgtUVgc=
 =at6w
 -----END PGP SIGNATURE-----

Merge tag 'modules-7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/modules/linux

Pull module updates from Sami Tolvanen:
 "Module signing:

   - Remove SHA-1 support for signing modules.

     SHA-1 is no longer considered secure for signatures due to
     vulnerabilities that can lead to hash collisions. None of the major
     distributions use SHA-1 anymore, and the kernel has defaulted to
     SHA-512 since v6.11.

     Note that loading SHA-1 signed modules is still supported.

   - Update scripts/sign-file to use only the OpenSSL CMS API for
     signing.

     As SHA-1 support is gone, we can drop the legacy PKCS#7 API which
     was limited to SHA-1. This also cleans up support for legacy
     OpenSSL versions.

  Cleanups and fixes:

   - Use system_dfl_wq instead of the per-cpu system_wq following the
     ongoing workqueue API refactoring.

   - Avoid open-coded kvrealloc() in module decompression logic by using
     the standard helper.

   - Improve section annotations by replacing the custom __modinit with
     __init_or_module and removing several unused __INIT*_OR_MODULE
     macros.

   - Fix kernel-doc warnings in include/linux/moduleparam.h.

   - Ensure set_module_sig_enforced is only declared when module signing
     is enabled.

   - Fix gendwarfksyms build failures on 32-bit hosts.

  MAINTAINERS:

   - Update the module subsystem entry to reflect the maintainer
     rotation and update the git repository link"

* tag 'modules-7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/modules/linux:
  modules: moduleparam.h: fix kernel-doc comments
  module: Only declare set_module_sig_enforced when CONFIG_MODULE_SIG=y
  module/decompress: Avoid open-coded kvrealloc()
  gendwarfksyms: Fix build on 32-bit hosts
  sign-file: Use only the OpenSSL CMS API for signing
  module: Remove SHA-1 support for module signing
  module: replace use of system_wq with system_dfl_wq
  params: Replace __modinit with __init_or_module
  module: Remove unused __INIT*_OR_MODULE macros
  MAINTAINERS: Update module subsystem maintainers and repository
This commit is contained in:
Linus Torvalds 2026-02-10 09:49:18 -08:00
commit a7423e6ea2
10 changed files with 35 additions and 106 deletions

View file

@ -17636,12 +17636,12 @@ MODULE SUPPORT
M: Luis Chamberlain <mcgrof@kernel.org>
M: Petr Pavlu <petr.pavlu@suse.com>
M: Daniel Gomez <da.gomez@kernel.org>
R: Sami Tolvanen <samitolvanen@google.com>
M: Sami Tolvanen <samitolvanen@google.com>
R: Aaron Tomlin <atomlin@atomlin.com>
L: linux-modules@vger.kernel.org
L: linux-kernel@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git modules-next
T: git git://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git modules-next
F: include/linux/kmod.h
F: include/linux/module*.h
F: kernel/module/

View file

@ -151,16 +151,10 @@ extern void cleanup_module(void);
#define __init_or_module
#define __initdata_or_module
#define __initconst_or_module
#define __INIT_OR_MODULE .text
#define __INITDATA_OR_MODULE .data
#define __INITRODATA_OR_MODULE .section ".rodata","a",%progbits
#else
#define __init_or_module __init
#define __initdata_or_module __initdata
#define __initconst_or_module __initconst
#define __INIT_OR_MODULE __INIT
#define __INITDATA_OR_MODULE __INITDATA
#define __INITRODATA_OR_MODULE __INITRODATA
#endif /*CONFIG_MODULES*/
struct module_kobject *lookup_or_create_module_kobject(const char *name);
@ -770,8 +764,6 @@ static inline bool is_livepatch_module(struct module *mod)
#endif
}
void set_module_sig_enforced(void);
void module_for_each_mod(int(*func)(struct module *mod, void *data), void *data);
#else /* !CONFIG_MODULES... */
@ -866,10 +858,6 @@ static inline bool module_requested_async_probing(struct module *module)
}
static inline void set_module_sig_enforced(void)
{
}
/* Dereference module function descriptor */
static inline
void *dereference_module_function_descriptor(struct module *mod, void *ptr)
@ -925,6 +913,8 @@ static inline bool retpoline_module_ok(bool has_retpoline)
#ifdef CONFIG_MODULE_SIG
bool is_module_sig_enforced(void);
void set_module_sig_enforced(void);
static inline bool module_sig_ok(struct module *module)
{
return module->sig_ok;
@ -935,6 +925,10 @@ static inline bool is_module_sig_enforced(void)
return false;
}
static inline void set_module_sig_enforced(void)
{
}
static inline bool module_sig_ok(struct module *module)
{
return true;

View file

@ -355,8 +355,8 @@ static inline void kernel_param_unlock(struct module *mod)
/**
* __core_param_cb - similar like core_param, with a set/get ops instead of type.
* @name: the name of the cmdline and sysfs parameter (often the same as var)
* @var: the variable
* @ops: the set & get operations for this parameter.
* @arg: the variable
* @perm: visibility in sysfs
*
* Ideally this should be called 'core_param_cb', but the name has been
@ -390,7 +390,7 @@ static inline void kernel_param_unlock(struct module *mod)
* @name1: parameter name 1
* @name2: parameter name 2
*
* Returns true if the two parameter names are equal.
* Returns: true if the two parameter names are equal.
* Dashes (-) are considered equal to underscores (_).
*/
extern bool parameq(const char *name1, const char *name2);
@ -402,6 +402,10 @@ extern bool parameq(const char *name1, const char *name2);
* @n: the length to compare
*
* Similar to parameq(), except it compares @n characters.
*
* Returns: true if the first @n characters of the two parameter names
* are equal.
* Dashes (-) are considered equal to underscores (_).
*/
extern bool parameqn(const char *name1, const char *name2, size_t n);

View file

@ -299,10 +299,6 @@ choice
possible to load a signed module containing the algorithm to check
the signature on that module.
config MODULE_SIG_SHA1
bool "SHA-1"
select CRYPTO_SHA1
config MODULE_SIG_SHA256
bool "SHA-256"
select CRYPTO_SHA256
@ -332,7 +328,6 @@ endchoice
config MODULE_SIG_HASH
string
depends on MODULE_SIG || IMA_APPRAISE_MODSIG
default "sha1" if MODULE_SIG_SHA1
default "sha256" if MODULE_SIG_SHA256
default "sha384" if MODULE_SIG_SHA384
default "sha512" if MODULE_SIG_SHA512

View file

@ -17,16 +17,16 @@
static int module_extend_max_pages(struct load_info *info, unsigned int extent)
{
struct page **new_pages;
unsigned int new_max = info->max_pages + extent;
new_pages = kvmalloc_array(info->max_pages + extent,
sizeof(info->pages), GFP_KERNEL);
new_pages = kvrealloc(info->pages,
size_mul(new_max, sizeof(*info->pages)),
GFP_KERNEL);
if (!new_pages)
return -ENOMEM;
memcpy(new_pages, info->pages, info->max_pages * sizeof(info->pages));
kvfree(info->pages);
info->pages = new_pages;
info->max_pages += extent;
info->max_pages = new_max;
return 0;
}

View file

@ -113,7 +113,7 @@ static void kmod_dup_request_complete(struct work_struct *work)
* let this linger forever as this is just a boot optimization for
* possible abuses of vmalloc() incurred by finit_module() thrashing.
*/
queue_delayed_work(system_wq, &kmod_req->delete_work, 60 * HZ);
queue_delayed_work(system_dfl_wq, &kmod_req->delete_work, 60 * HZ);
}
bool kmod_dup_request_exists_wait(char *module_name, bool wait, int *dup_ret)
@ -240,7 +240,7 @@ void kmod_dup_request_announce(char *module_name, int ret)
* There is no rush. But we also don't want to hold the
* caller up forever or introduce any boot delays.
*/
queue_work(system_wq, &kmod_req->complete_work);
queue_work(system_dfl_wq, &kmod_req->complete_work);
out:
mutex_unlock(&kmod_dup_mutex);

View file

@ -596,12 +596,6 @@ static ssize_t param_attr_store(const struct module_attribute *mattr,
}
#endif
#ifdef CONFIG_MODULES
#define __modinit
#else
#define __modinit __init
#endif
#ifdef CONFIG_SYSFS
void kernel_param_lock(struct module *mod)
{
@ -626,9 +620,9 @@ EXPORT_SYMBOL(kernel_param_unlock);
* create file in sysfs. Returns an error on out of memory. Always cleans up
* if there's an error.
*/
static __modinit int add_sysfs_param(struct module_kobject *mk,
const struct kernel_param *kp,
const char *name)
static __init_or_module int add_sysfs_param(struct module_kobject *mk,
const struct kernel_param *kp,
const char *name)
{
struct module_param_attrs *new_mp;
struct attribute **new_attrs;
@ -761,7 +755,8 @@ void destroy_params(const struct kernel_param *params, unsigned num)
params[i].ops->free(params[i].arg);
}
struct module_kobject __modinit * lookup_or_create_module_kobject(const char *name)
struct module_kobject * __init_or_module
lookup_or_create_module_kobject(const char *name)
{
struct module_kobject *mk;
struct kobject *kobj;

View file

@ -750,6 +750,7 @@ static void process_enumerator_type(struct state *state, struct die *cache,
Dwarf_Die *die)
{
bool overridden = false;
unsigned long override;
Dwarf_Word value;
if (stable) {
@ -761,7 +762,8 @@ static void process_enumerator_type(struct state *state, struct die *cache,
return;
overridden = kabi_get_enumerator_value(
state->expand.current_fqn, cache->fqn, &value);
state->expand.current_fqn, cache->fqn, &override);
value = override;
}
process_list_comma(state, cache);

View file

@ -3,6 +3,7 @@
* Copyright (C) 2024 Google LLC
*/
#include <inttypes.h>
#include "gendwarfksyms.h"
#define SYMBOL_HASH_BITS 12
@ -242,7 +243,7 @@ static void elf_for_each_global(int fd, elf_symbol_callback_t func, void *arg)
error("elf_getdata failed: %s", elf_errmsg(-1));
if (shdr->sh_entsize != sym_size)
error("expected sh_entsize (%lu) to be %zu",
error("expected sh_entsize (%" PRIu64 ") to be %zu",
shdr->sh_entsize, sym_size);
nsyms = shdr->sh_size / shdr->sh_entsize;
@ -292,7 +293,7 @@ static void set_symbol_addr(struct symbol *sym, void *arg)
hash_add(symbol_addrs, &sym->addr_hash,
symbol_addr_hash(&sym->addr));
debug("%s -> { %u, %lx }", sym->name, sym->addr.section,
debug("%s -> { %u, %" PRIx64 " }", sym->name, sym->addr.section,
sym->addr.address);
} else if (sym->addr.section != addr->section ||
sym->addr.address != addr->address) {

View file

@ -24,6 +24,7 @@
#include <arpa/inet.h>
#include <openssl/opensslv.h>
#include <openssl/bio.h>
#include <openssl/cms.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>
@ -39,29 +40,6 @@
#endif
#include "ssl-common.h"
/*
* Use CMS if we have openssl-1.0.0 or newer available - otherwise we have to
* assume that it's not available and its header file is missing and that we
* should use PKCS#7 instead. Switching to the older PKCS#7 format restricts
* the options we have on specifying the X.509 certificate we want.
*
* Further, older versions of OpenSSL don't support manually adding signers to
* the PKCS#7 message so have to accept that we get a certificate included in
* the signature message. Nor do such older versions of OpenSSL support
* signing with anything other than SHA1 - so we're stuck with that if such is
* the case.
*/
#if defined(LIBRESSL_VERSION_NUMBER) || \
OPENSSL_VERSION_NUMBER < 0x10000000L || \
defined(OPENSSL_NO_CMS)
#define USE_PKCS7
#endif
#ifndef USE_PKCS7
#include <openssl/cms.h>
#else
#include <openssl/pkcs7.h>
#endif
struct module_signature {
uint8_t algo; /* Public-key crypto algorithm [0] */
uint8_t hash; /* Digest algorithm [0] */
@ -228,15 +206,10 @@ int main(int argc, char **argv)
bool raw_sig = false;
unsigned char buf[4096];
unsigned long module_size, sig_size;
unsigned int use_signed_attrs;
const EVP_MD *digest_algo;
EVP_PKEY *private_key;
#ifndef USE_PKCS7
CMS_ContentInfo *cms = NULL;
unsigned int use_keyid = 0;
#else
PKCS7 *pkcs7 = NULL;
#endif
X509 *x509;
BIO *bd, *bm;
int opt, n;
@ -246,21 +219,13 @@ int main(int argc, char **argv)
key_pass = getenv("KBUILD_SIGN_PIN");
#ifndef USE_PKCS7
use_signed_attrs = CMS_NOATTR;
#else
use_signed_attrs = PKCS7_NOATTR;
#endif
do {
opt = getopt(argc, argv, "sdpk");
switch (opt) {
case 's': raw_sig = true; break;
case 'p': save_sig = true; break;
case 'd': sign_only = true; save_sig = true; break;
#ifndef USE_PKCS7
case 'k': use_keyid = CMS_USE_KEYID; break;
#endif
case -1: break;
default: format();
}
@ -289,14 +254,6 @@ int main(int argc, char **argv)
replace_orig = true;
}
#ifdef USE_PKCS7
if (strcmp(hash_algo, "sha1") != 0) {
fprintf(stderr, "sign-file: %s only supports SHA1 signing\n",
OPENSSL_VERSION_TEXT);
exit(3);
}
#endif
/* Open the module file */
bm = BIO_new_file(module_name, "rb");
ERR(!bm, "%s", module_name);
@ -314,10 +271,9 @@ int main(int argc, char **argv)
digest_algo = EVP_get_digestbyname(hash_algo);
ERR(!digest_algo, "EVP_get_digestbyname");
#ifndef USE_PKCS7
unsigned int flags =
CMS_NOCERTS |
CMS_NOATTR |
CMS_PARTIAL |
CMS_BINARY |
CMS_DETACHED |
@ -335,12 +291,10 @@ int main(int argc, char **argv)
/* ML-DSA + CMS_NOATTR is not supported in openssl-3.5
* and before.
*/
use_signed_attrs = 0;
flags &= ~CMS_NOATTR;
}
#endif
flags |= use_signed_attrs;
/* Load the signature message from the digest buffer. */
cms = CMS_sign(NULL, NULL, NULL, NULL, flags);
ERR(!cms, "CMS_sign");
@ -350,13 +304,6 @@ int main(int argc, char **argv)
ERR(CMS_final(cms, bm, NULL, flags) != 1,
"CMS_final");
#else
pkcs7 = PKCS7_sign(x509, private_key, NULL, bm,
PKCS7_NOCERTS | PKCS7_BINARY |
PKCS7_DETACHED | use_signed_attrs);
ERR(!pkcs7, "PKCS7_sign");
#endif
if (save_sig) {
char *sig_file_name;
BIO *b;
@ -365,13 +312,8 @@ int main(int argc, char **argv)
"asprintf");
b = BIO_new_file(sig_file_name, "wb");
ERR(!b, "%s", sig_file_name);
#ifndef USE_PKCS7
ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) != 1,
"%s", sig_file_name);
#else
ERR(i2d_PKCS7_bio(b, pkcs7) != 1,
"%s", sig_file_name);
#endif
BIO_free(b);
}
@ -398,11 +340,7 @@ int main(int argc, char **argv)
module_size = BIO_number_written(bd);
if (!raw_sig) {
#ifndef USE_PKCS7
ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) != 1, "%s", dest_name);
#else
ERR(i2d_PKCS7_bio(bd, pkcs7) != 1, "%s", dest_name);
#endif
} else {
BIO *b;