* Re: [PATCH v2] tpm: restore timeout for key creation commands
From: Jarkko Sakkinen @ 2026-05-04 15:13 UTC (permalink / raw)
To: Baoli Zhang
Cc: Peter Huewe, Jason Gunthorpe, Serge Hallyn, Lili Li,
linux-integrity, linux-kernel
In-Reply-To: <20260421005021.13765-1-baoli.zhang@linux.intel.com>
On Tue, Apr 21, 2026 at 08:50:20AM +0800, Baoli Zhang wrote:
> From: "Baoli Zhang" <baoli.zhang@linux.intel.com>
>
> Commit 207696b17f38 ("tpm: use a map for tpm2_calc_ordinal_duration()")
> inadvertently reduced the timeout for TPM2 key creation commands
> (`CREATE_PRIMARY`, `CREATE`, `CREATE_LOADED`) from 300 seconds to 30
> seconds.
>
> This causes intermittent timeout failures, with several failures observed
> across hundreds of test runs on some Intel platforms using Infineon
> SLB9670 and SLB9672 TPM modules. Restore the timeout to 300 seconds to
> avoid spurious failures.
Is this a production case?
I'm not sure if there is anything to fix tbh. I mean it is
pretty much the same as "maintaining compatibility to OTT driver"
to addresses issues on undisclosed hardware.
Please correct me if I'm wrong. Otherwise, I'd carry out internal patch
to tweak this for pre-production hardware (presumably).
>
> Fixes: 207696b17f38 ("tpm: use a map for tpm2_calc_ordinal_duration()")
> Co-developed-by: Lili Li <lili.li@intel.com>
> Signed-off-by: Lili Li <lili.li@intel.com>
> Signed-off-by: Baoli Zhang <baoli.zhang@linux.intel.com>
> ---
> Changes in v2:
> - Add description of intermittent nature of the timeout issue.
> - Fix Co-developed-by and Signed-off-by tag ordering.
>
> v1: https://patchwork.kernel.org/project/linux-integrity/patch/20260410014940.3557934-1-baoli.zhang@linux.intel.com/
>
> drivers/char/tpm/tpm2-cmd.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
> index 3a77be7ebf4aa..430022f695f24 100644
> --- a/drivers/char/tpm/tpm2-cmd.c
> +++ b/drivers/char/tpm/tpm2-cmd.c
> @@ -71,9 +71,9 @@ static const struct {
> {TPM2_CC_HIERARCHY_CHANGE_AUTH, 2000},
> {TPM2_CC_GET_CAPABILITY, 750},
> {TPM2_CC_NV_READ, 2000},
> - {TPM2_CC_CREATE_PRIMARY, 30000},
> - {TPM2_CC_CREATE, 30000},
> - {TPM2_CC_CREATE_LOADED, 30000},
> + {TPM2_CC_CREATE_PRIMARY, 300000},
> + {TPM2_CC_CREATE, 300000},
> + {TPM2_CC_CREATE_LOADED, 300000},
> };
>
> /**
> --
> 2.43.0
>
BR, Jarkko
^ permalink raw reply
* Re: [PATCH v2 00/10] Fix dm-ima bugs
From: Mikulas Patocka @ 2026-05-04 15:45 UTC (permalink / raw)
To: Benjamin Marzinski
Cc: Mike Snitzer, dm-devel, linux-integrity, Alasdair Kergon,
Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Lakshmi Ramasubramanian, steven chen
In-Reply-To: <20260429202108.2823261-1-bmarzins@redhat.com>
Applied, thanks.
Mikulas
On Wed, 29 Apr 2026, Benjamin Marzinski wrote:
> The dm-ima code does not guarantee that the dm_ima_measure_on_*
> functions will not be called at the same time. Since they modify and
> free shared memory, this can lead to Use-After-Free errors or garbage
> measurements. Further, they don't make sure that the state they measure
> corresponds to the actual device state. For instance if table_load()
> runs at the same time as do_resume() on a table swap,
> dm_ima_measure_on_device_resume() can end up thinking the wrong table is
> active. Or a concurrent dm_hash_rename() and a table swap, can end up
> with a the new active table still using the old name. This patchset
> makes sure the the dm-ima function are serialized and report the correct
> device state.
>
> However, the code is still messier that in could be. This is because
> it duplicates the current measurement events and format. I would really
> like to know if that is necessary. Specifically, it currently measures
> the following dm device and table actions:
>
> load
> clear
> rename
> resume
> remove
>
> I don't see the benefit of reporting changes to the inactive table, or
> resumes where the device does not change state. From the user's point of
> view, the device is still the same after these events. At the same
> time, it doesn't measure device creates if no table was loaded, so you
> can have situations where the the first measurement for a device is a
> rename or a remove. A more sensible set of actions to measure would be:
>
> create
> table_swap
> rename
> remove
>
> Also, the measurement format doesn't map well to how dm device's are
> actually set up, in a way that makes it harder for the code and records
> extraneous information. First, like I mentioned before, I don't see the
> benefit of measuring the inactive table. Second, the name, uuid, and
> major/minor numbers are properties of the device, not it's table (and dm
> devices can't have partitions, so the minor count will always be 1). I
> don't see a reason to store and occasinally log this information twice,
> if there is an active and incative table, and it forces extra
> coordination between the dm_ima_measure_on_* functions.
>
> I'm wondering it we are stuck with the current events and format, now
> that this has been released? Or could we bump the version, and change
> what events we measure, and how we format the output?
>
> Changes in v2:
> - 05/10: Switched from using atomics and barriers to using a spinlock to
> serialize the dm_ima_measure_on_* functions
> - 05/10: Fixed typos in comments and commit message
> - 06/10: changed no_data string from "table_rename" to "device_rename"
>
> If this patchset is going in largely as it is, I should point out that
> there are changes to the ima measurements in corner cases, where the
> data was previously incorrect (as mentioned in the patches). However
> it's possible, although I don't think very likely, that systems are
> expecting these incorrect measurements. We could bump the version number
> because of this possible change in the measurements, but IIUC, since
> this version number itself is part of the IMA measurements, that would
> guarantee that systems would get different measurements.
>
> Benjamin Marzinski (10):
> dm-ima: remove dm_ima_reset_data()
> dm-ima: remove broken last_target_measured logic
> dm-ima: Remove status_flags from dm_ima_measure_on_table_load()
> dm-ima: don't copy the active table to the inactive table
> dm-ima: Fix UAF errors and measuring incorrect context
> dm-ima: remove new_map from dm_ima_measure_on_device_clear
> dm-ima: Fix issues with dm_ima_measure_on_device_rename
> dm-ima: Handle race between rename and table swap
> dm-ima: Fail more gracefully in dm_ima_measure_on_*
> dm-ima: use active table's size if available
>
> drivers/md/dm-ima.c | 492 +++++++++++++++++++-----------------------
> drivers/md/dm-ima.h | 68 ++++--
> drivers/md/dm-ioctl.c | 146 +++++++++++--
> drivers/md/dm.c | 2 +-
> 4 files changed, 410 insertions(+), 298 deletions(-)
>
> --
> 2.53.0
>
^ permalink raw reply
* Re: tpm: spi: do not call blocking ops when !TASK_RUNNING; during shutdown
From: Stefan Wahren @ 2026-05-04 16:05 UTC (permalink / raw)
To: Jarkko Sakkinen
Cc: Peter Huewe, Jason Gunthorpe, linux-arm-kernel, linux-integrity,
kernel, Frank Li, Sascha Hauer, imx@lists.linux.dev
In-Reply-To: <afiiUdFv7p0fuK-5@kernel.org>
Am 04.05.26 um 15:42 schrieb Jarkko Sakkinen:
> Hi Stefan,
>
> On Mon, Apr 20, 2026 at 12:25:21PM +0200, Stefan Wahren wrote:
>> Hi,
>> we use a custom i.MX93 board, which based on Phytec Phycore i.MX93 with a
>> TPM connected via SPI. If I enable CONFIG_DEBUG_ATOMIC_SLEEP=y in our kernel
>> config with mainline kernel 6.18.23 and reboot our board, I will get the
>> following warning:
> Please provide results with the latest mainline kernel.
>
Here you are
[ 69.085410] do not call blocking ops when !TASK_RUNNING; state=1 set
at [<0000000090f4020f>] prepare_to_wait_event+0x54/0x14c
[ 69.097076] WARNING: kernel/sched/core.c:9086 at
__might_sleep+0x74/0x7c, CPU#0: systemd-shutdow/1
[ 69.106026] Modules linked in: flexcan can_dev rtc_rv3028 mse102x
phy_can_transceiver fuse autofs4
[ 69.114991] CPU: 0 UID: 0 PID: 1 Comm: systemd-shutdow Not tainted
7.1.0-rc2-00005-g6d35786de281-dirty #45 PREEMPT
[ 69.125405] Hardware name: chargebyte Charge SOM Evaluation Kit (DT)
[ 69.131741] pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS
BTYPE=--)
[ 69.138690] pc : __might_sleep+0x74/0x7c
[ 69.142608] lr : __might_sleep+0x74/0x7c
[ 69.146525] sp : ffff800081b7b710
[ 69.149827] x29: ffff800081b7b710 x28: 0000000000000080 x27:
ffff000002cafe80
[ 69.156951] x26: ffff800081965000 x25: 0000000000000018 x24:
0000000000000000
[ 69.164075] x23: ffff800081b7b8f7 x22: 0000000000000000 x21:
0000000000000080
[ 69.171199] x20: 000000000000013c x19: ffff8000813e2880 x18:
0000000000000000
[ 69.178323] x17: 003fffffffffffff x16: 000000000017d600 x15:
ffff00003fda1a00
[ 69.185447] x14: ffff000000132c00 x13: 00000000000002ce x12:
0000000000000000
[ 69.192571] x11: 00000000000000c0 x10: 00000000000009e0 x9 :
ffff800081b7b580
[ 69.199695] x8 : ffff0000001335c0 x7 : ffff00003fda1280 x6 :
0000000000000000
[ 69.206819] x5 : 000000001fffffff x4 : 0000000000000001 x3 :
0000000000000010
[ 69.213943] x2 : 0000000000000000 x1 : 0000000000000000 x0 :
ffff000000132b80
[ 69.221068] Call trace:
[ 69.223503] __might_sleep+0x74/0x7c (P)
[ 69.227420] mutex_lock+0x24/0x80
[ 69.230731] spi_bus_lock+0x20/0x50
[ 69.234214] tpm_tis_spi_transfer_full+0x70/0x2c4
[ 69.238912] tpm_tis_spi_read_bytes+0x3c/0x48
[ 69.243263] tpm_tis_status+0x58/0xf8
[ 69.246920] wait_for_tpm_stat_cond+0x30/0x90
[ 69.251271] wait_for_tpm_stat+0x1cc/0x2e0
[ 69.255361] tpm_tis_send_data+0xdc/0x35c
[ 69.259365] tpm_tis_send_main+0x74/0x18c
[ 69.263369] tpm_tis_send+0xd4/0x13c
[ 69.266940] tpm_transmit+0xc4/0x3c4
[ 69.270511] tpm_transmit_cmd+0x38/0xd4
[ 69.274341] tpm2_shutdown+0x6c/0xa4
[ 69.277912] tpm_class_shutdown+0x60/0x88
[ 69.281916] device_shutdown+0x130/0x258
[ 69.285833] kernel_restart+0x44/0xa4
[ 69.289491] __do_sys_reboot+0x114/0x244
[ 69.293408] __arm64_sys_reboot+0x24/0x30
[ 69.297412] invoke_syscall+0x54/0x10c
[ 69.301156] el0_svc_common.constprop.0+0x40/0xe0
[ 69.305853] do_el0_svc+0x1c/0x28
[ 69.309164] el0_svc+0x38/0x138
[ 69.312301] el0t_64_sync_handler+0xa0/0xe4
[ 69.316478] el0t_64_sync+0x198/0x19c
^ permalink raw reply
* Re: [PATCH v2 1/2] bpf: add bpf_init_inode_xattr kfunc for atomic inode labeling
From: Paul Moore @ 2026-05-04 20:14 UTC (permalink / raw)
To: David Windsor
Cc: Alexander Viro, Christian Brauner, Alexei Starovoitov,
Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman,
Kumar Kartikeya Dwivedi, KP Singh, Matt Bobrowski, James Morris,
Serge E. Hallyn, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Stephen Smalley, Casey Schaufler, Song Liu, Jan Kara,
John Fastabend, Martin KaFai Lau, Yonghong Song, Jiri Olsa,
Eric Snowberg, Ondrej Mosnacek, linux-fsdevel, linux-kernel, bpf,
linux-security-module, linux-integrity, selinux
In-Reply-To: <20260503211835.16103-2-dwindsor@gmail.com>
On Sun, May 3, 2026 at 5:18 PM David Windsor <dwindsor@gmail.com> wrote:
>
> Add bpf_init_inode_xattr() kfunc for BPF LSM programs to atomically set
> xattrs via the inode_init_security hook using lsm_get_xattr_slot().
>
> The inode_init_security hook previously took the xattr array and count
> as two separate output parameters (struct xattr *xattrs, int
> *xattr_count), which BPF programs cannot write to. Pass the xattr state
> as a single context object (struct lsm_xattr_ctx) instead, and have
> bpf_init_inode_xattr() take that context directly. Update the existing
> in-tree callers of inode_init_security to take and forward the new
> lsm_xattr_ctx.
>
> Because we rely on the hook-specific ctx layout, the kfunc is
> restricted to lsm/inode_init_security. Restrict the xattr names that
> may be set via this kfunc to the bpf.* namespace.
>
> Suggested-by: Song Liu <song@kernel.org>
> Signed-off-by: David Windsor <dwindsor@gmail.com>
> ---
> fs/bpf_fs_kfuncs.c | 106 +++++++++++++++++++++++++++++-
> include/linux/bpf_lsm.h | 3 +
> include/linux/evm.h | 9 +--
> include/linux/lsm_hook_defs.h | 4 +-
> include/linux/lsm_hooks.h | 16 ++---
> include/linux/security.h | 5 ++
> kernel/bpf/bpf_lsm.c | 1 +
> security/bpf/hooks.c | 1 +
> security/integrity/evm/evm_main.c | 8 ++-
> security/security.c | 7 +-
> security/selinux/hooks.c | 4 +-
> security/smack/smack_lsm.c | 13 ++--
> 12 files changed, 147 insertions(+), 30 deletions(-)
Comments below ...
> diff --git a/fs/bpf_fs_kfuncs.c b/fs/bpf_fs_kfuncs.c
> index 9d27be058494..193accc00796 100644
> --- a/fs/bpf_fs_kfuncs.c
> +++ b/fs/bpf_fs_kfuncs.c
> @@ -10,6 +10,7 @@
> #include <linux/fsnotify.h>
> #include <linux/file.h>
> #include <linux/kernfs.h>
> +#include <linux/lsm_hooks.h>
> #include <linux/mm.h>
> #include <linux/xattr.h>
>
> @@ -353,6 +354,97 @@ __bpf_kfunc int bpf_cgroup_read_xattr(struct cgroup *cgroup, const char *name__s
> }
> #endif /* CONFIG_CGROUPS */
>
> +static int bpf_xattrs_used(const struct lsm_xattr_ctx *ctx)
> +{
> + const size_t prefix_len = sizeof(XATTR_BPF_LSM_SUFFIX) - 1;
> + int i, n = 0;
> +
> + for (i = 0; i < *ctx->xattr_count; i++) {
> + const char *name = ctx->xattrs[i].name;
> +
> + if (name && !strncmp(name, XATTR_BPF_LSM_SUFFIX, prefix_len))
> + n++;
> + }
> + return n;
> +}
> +
> +static int __bpf_init_inode_xattr(struct lsm_xattr_ctx *xattr_ctx,
> + const char *name__str,
> + const struct bpf_dynptr *value_p)
> +{
> + struct bpf_dynptr_kern *value_ptr = (struct bpf_dynptr_kern *)value_p;
> + size_t name_len;
> + void *xattr_value;
> + struct xattr *xattr;
> + struct xattr *xattrs;
> + int *xattr_count;
> + const void *value;
> + u32 value_len;
> +
> + if (!xattr_ctx || !name__str)
> + return -EINVAL;
> +
> + xattrs = xattr_ctx->xattrs;
> + xattr_count = xattr_ctx->xattr_count;
> + if (!xattrs || !xattr_count)
> + return -EINVAL;
> + if (bpf_xattrs_used(xattr_ctx) >= BPF_LSM_INODE_INIT_XATTRS)
> + return -ENOSPC;
> +
> + name_len = strlen(name__str);
> + if (name_len == 0 || name_len > XATTR_NAME_MAX)
> + return -EINVAL;
> + if (strncmp(name__str, XATTR_BPF_LSM_SUFFIX,
> + sizeof(XATTR_BPF_LSM_SUFFIX) - 1))
> + return -EPERM;
> +
> + value_len = __bpf_dynptr_size(value_ptr);
> + if (value_len == 0 || value_len > XATTR_SIZE_MAX)
> + return -EINVAL;
> +
> + value = __bpf_dynptr_data(value_ptr, value_len);
> + if (!value)
> + return -EINVAL;
> +
> + /* Combine xattr value + name into one allocation. */
> + xattr_value = kmalloc(value_len + name_len + 1, GFP_KERNEL);
> + if (!xattr_value)
> + return -ENOMEM;
> +
> + memcpy(xattr_value, value, value_len);
> + memcpy(xattr_value + value_len, name__str, name_len);
> + ((char *)xattr_value)[value_len + name_len] = '\0';
> +
> + xattr = lsm_get_xattr_slot(xattr_ctx);
> + if (!xattr) {
> + kfree(xattr_value);
> + return -ENOSPC;
> + }
> +
> + xattr->value = xattr_value;
> + xattr->name = (const char *)xattr_value + value_len;
> + xattr->value_len = value_len;
> +
> + return 0;
> +}
> +
> +/**
> + * bpf_init_inode_xattr - set an xattr on a new inode from inode_init_security
> + * @xattr_ctx: inode_init_security xattr state from the hook context
> + * @name__str: xattr name (e.g., "bpf.file_label")
> + * @value_p: dynptr containing the xattr value
> + *
> + * Only callable from lsm/inode_init_security programs.
> + *
> + * Return: 0 on success, negative error on failure.
> + */
> +__bpf_kfunc int bpf_init_inode_xattr(struct lsm_xattr_ctx *xattr_ctx,
> + const char *name__str,
> + const struct bpf_dynptr *value_p)
> +{
> + return __bpf_init_inode_xattr(xattr_ctx, name__str, value_p);
> +}
> +
> __bpf_kfunc_end_defs();
>
> BTF_KFUNCS_START(bpf_fs_kfunc_set_ids)
> @@ -363,13 +455,25 @@ BTF_ID_FLAGS(func, bpf_get_dentry_xattr, KF_SLEEPABLE)
> BTF_ID_FLAGS(func, bpf_get_file_xattr, KF_SLEEPABLE)
> BTF_ID_FLAGS(func, bpf_set_dentry_xattr, KF_SLEEPABLE)
> BTF_ID_FLAGS(func, bpf_remove_dentry_xattr, KF_SLEEPABLE)
> +BTF_ID_FLAGS(func, bpf_init_inode_xattr, KF_SLEEPABLE)
> BTF_KFUNCS_END(bpf_fs_kfunc_set_ids)
>
> +BTF_ID_LIST(bpf_lsm_inode_init_security_btf_ids)
> +BTF_ID(func, bpf_lsm_inode_init_security)
> +
> +BTF_ID_LIST(bpf_init_inode_xattr_btf_ids)
> +BTF_ID(func, bpf_init_inode_xattr)
> +
> static int bpf_fs_kfuncs_filter(const struct bpf_prog *prog, u32 kfunc_id)
> {
> if (!btf_id_set8_contains(&bpf_fs_kfunc_set_ids, kfunc_id) ||
> - prog->type == BPF_PROG_TYPE_LSM)
> + prog->type == BPF_PROG_TYPE_LSM) {
> + /* bpf_init_inode_xattr only attaches to inode_init_security. */
> + if (kfunc_id == bpf_init_inode_xattr_btf_ids[0] &&
> + prog->aux->attach_btf_id != bpf_lsm_inode_init_security_btf_ids[0])
> + return -EACCES;
> return 0;
> + }
> return -EACCES;
> }
Perhaps I'm simply not seeing it, but is there a check to ensure that
there is only one BPF LSM calling into security_inode_init_security()
at any given time? With the BPF LSM only reserving a single xattr
slot, multiple loaded BPF LSM programs providing
security_inode_init_security() callbacks will be a problem.
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 41d7367cf403..a2fc72e63ada 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -68,6 +68,11 @@ struct watch;
> struct watch_notification;
> struct lsm_ctx;
>
> +struct lsm_xattr_ctx {
> + struct xattr *xattrs;
> + int *xattr_count;
> +};
I'd prefer this to be simply "struct lsm_xattrs" as "ctx" is an
overloaded term in the LSM space.
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 97801966bf32..dca81a22bf83 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -2962,11 +2962,11 @@ static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
>
> static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
> const struct qstr *qstr,
> - struct xattr *xattrs, int *xattr_count)
> + struct lsm_xattr_ctx *xattr_ctx)
> {
> const struct cred_security_struct *crsec = selinux_cred(current_cred());
> struct superblock_security_struct *sbsec;
> - struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
> + struct xattr *xattr = lsm_get_xattr_slot(xattr_ctx);
> u32 newsid, clen;
> u16 newsclass;
> int rc;
In case you didn't see it, your fix for the above lsm_get_xattr_slot()
usage is now in Linus' tree. It's a trivial bit of merge fuzz, but
you might want to rebase your next revision.
--
paul-moore.com
^ permalink raw reply
* Re: [PATCH] ima: debugging late_initcall_sync measurements
From: Paul Moore @ 2026-05-04 20:51 UTC (permalink / raw)
To: Mimi Zohar
Cc: Yeoreum Yun, Jonathan McDowell, linux-security-module,
linux-kernel, linux-integrity, linux-arm-kernel, kvmarm, jmorris,
serge, roberto.sassu, dmitry.kasatkin, eric.snowberg, jarkko, jgg,
sudeep.holla, maz, oupton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will, noodles, sebastianene
In-Reply-To: <ff28c6dcb60c357c752724927addaa8c4fd3bf2c.camel@linux.ibm.com>
On Mon, May 4, 2026 at 8:03 AM Mimi Zohar <zohar@linux.ibm.com> wrote:
> On Sun, 2026-05-03 at 12:46 -0400, Paul Moore wrote:
> > Regardless, assuming you always want IMA to leverage a TPMs when they
> > exist, your reply suggests that using an initcall based IMA init
> > scheme, even a late-sync initcall, may not be sufficient because
> > deferred TPM initialization could happen later, yes?
>
> Well yeah. The TPM could be configured as a module, but that scenario is not of
> interest. That's way too late. The case being addressed in this patch set is
> when the TPM driver tries to initialize at device_initcall, returns
> EPROBE_DEFER, and is retried at deferred_probe_initcall (late_initcall). Since
> ordering within an initcall is not supported, this patch attempts to initialize
> IMA at late_initcall and similarly retries, in this case, at late_initcall_sync.
Okay, so from a TPM initialization perspective you are satisfied with
a late-sync IMA initialization, yes?
--
paul-moore.com
^ permalink raw reply
* Re: [PATCH v2 1/2] bpf: add bpf_init_inode_xattr kfunc for atomic inode labeling
From: Song Liu @ 2026-05-04 21:40 UTC (permalink / raw)
To: Paul Moore
Cc: David Windsor, Alexander Viro, Christian Brauner,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, KP Singh,
Matt Bobrowski, James Morris, Serge E. Hallyn, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Stephen Smalley, Casey Schaufler,
Jan Kara, John Fastabend, Martin KaFai Lau, Yonghong Song,
Jiri Olsa, Eric Snowberg, Ondrej Mosnacek, linux-fsdevel,
linux-kernel, bpf, linux-security-module, linux-integrity,
selinux
In-Reply-To: <CAHC9VhSy5K5nQTtFUE4BScy1Ur61v7eZW067vTcUYDQeJb13Bw@mail.gmail.com>
On Mon, May 4, 2026 at 10:14 PM Paul Moore <paul@paul-moore.com> wrote:
[...]
> > diff --git a/fs/bpf_fs_kfuncs.c b/fs/bpf_fs_kfuncs.c
> > index 9d27be058494..193accc00796 100644
> > --- a/fs/bpf_fs_kfuncs.c
> > +++ b/fs/bpf_fs_kfuncs.c
> > @@ -10,6 +10,7 @@
> > #include <linux/fsnotify.h>
> > #include <linux/file.h>
> > #include <linux/kernfs.h>
> > +#include <linux/lsm_hooks.h>
> > #include <linux/mm.h>
> > #include <linux/xattr.h>
> >
> > @@ -353,6 +354,97 @@ __bpf_kfunc int bpf_cgroup_read_xattr(struct cgroup *cgroup, const char *name__s
> > }
> > #endif /* CONFIG_CGROUPS */
> >
> > +static int bpf_xattrs_used(const struct lsm_xattr_ctx *ctx)
> > +{
> > + const size_t prefix_len = sizeof(XATTR_BPF_LSM_SUFFIX) - 1;
> > + int i, n = 0;
> > +
> > + for (i = 0; i < *ctx->xattr_count; i++) {
> > + const char *name = ctx->xattrs[i].name;
> > +
> > + if (name && !strncmp(name, XATTR_BPF_LSM_SUFFIX, prefix_len))
> > + n++;
> > + }
> > + return n;
> > +}
[...]
> > +
> > static int bpf_fs_kfuncs_filter(const struct bpf_prog *prog, u32 kfunc_id)
> > {
> > if (!btf_id_set8_contains(&bpf_fs_kfunc_set_ids, kfunc_id) ||
> > - prog->type == BPF_PROG_TYPE_LSM)
> > + prog->type == BPF_PROG_TYPE_LSM) {
> > + /* bpf_init_inode_xattr only attaches to inode_init_security. */
> > + if (kfunc_id == bpf_init_inode_xattr_btf_ids[0] &&
> > + prog->aux->attach_btf_id != bpf_lsm_inode_init_security_btf_ids[0])
> > + return -EACCES;
We need to mark bpf_init_inode_xattr with KF_RCU (requires a trusted
pointer), then we can remove this check above.
> > return 0;
> > + }
> > return -EACCES;
> > }
>
> Perhaps I'm simply not seeing it, but is there a check to ensure that
> there is only one BPF LSM calling into security_inode_init_security()
> at any given time? With the BPF LSM only reserving a single xattr
> slot, multiple loaded BPF LSM programs providing
> security_inode_init_security() callbacks will be a problem.
I don't think there is such a check. Also, a single BPF LSM function
may call the kfunc multiple times, which is also problematic.
I think we will need to make the default bigger, and also introduce
some realloc mechanism for the worst case scenario. This should
work, but the code might be a bit messy.
Thanks,
Song
>
> > diff --git a/include/linux/security.h b/include/linux/security.h
> > index 41d7367cf403..a2fc72e63ada 100644
> > --- a/include/linux/security.h
> > +++ b/include/linux/security.h
> > @@ -68,6 +68,11 @@ struct watch;
> > struct watch_notification;
> > struct lsm_ctx;
> >
[...]
^ permalink raw reply
* Re: [PATCH v2 1/2] bpf: add bpf_init_inode_xattr kfunc for atomic inode labeling
From: Paul Moore @ 2026-05-04 22:42 UTC (permalink / raw)
To: Song Liu
Cc: David Windsor, Alexander Viro, Christian Brauner,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, KP Singh,
Matt Bobrowski, James Morris, Serge E. Hallyn, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Stephen Smalley, Casey Schaufler,
Jan Kara, John Fastabend, Martin KaFai Lau, Yonghong Song,
Jiri Olsa, Eric Snowberg, Ondrej Mosnacek, linux-fsdevel,
linux-kernel, bpf, linux-security-module, linux-integrity,
selinux
In-Reply-To: <CAPhsuW6sy2cdC4B7Z48-5A-yVX6fmVWxS_fWVjQxiX95KeUguw@mail.gmail.com>
On Mon, May 4, 2026 at 5:40 PM Song Liu <song@kernel.org> wrote:
> On Mon, May 4, 2026 at 10:14 PM Paul Moore <paul@paul-moore.com> wrote:
> [...]
> > > diff --git a/fs/bpf_fs_kfuncs.c b/fs/bpf_fs_kfuncs.c
> > > index 9d27be058494..193accc00796 100644
> > > --- a/fs/bpf_fs_kfuncs.c
> > > +++ b/fs/bpf_fs_kfuncs.c
> > > @@ -10,6 +10,7 @@
> > > #include <linux/fsnotify.h>
> > > #include <linux/file.h>
> > > #include <linux/kernfs.h>
> > > +#include <linux/lsm_hooks.h>
> > > #include <linux/mm.h>
> > > #include <linux/xattr.h>
> > >
> > > @@ -353,6 +354,97 @@ __bpf_kfunc int bpf_cgroup_read_xattr(struct cgroup *cgroup, const char *name__s
> > > }
> > > #endif /* CONFIG_CGROUPS */
> > >
> > > +static int bpf_xattrs_used(const struct lsm_xattr_ctx *ctx)
> > > +{
> > > + const size_t prefix_len = sizeof(XATTR_BPF_LSM_SUFFIX) - 1;
> > > + int i, n = 0;
> > > +
> > > + for (i = 0; i < *ctx->xattr_count; i++) {
> > > + const char *name = ctx->xattrs[i].name;
> > > +
> > > + if (name && !strncmp(name, XATTR_BPF_LSM_SUFFIX, prefix_len))
> > > + n++;
> > > + }
> > > + return n;
> > > +}
> [...]
> > > +
> > > static int bpf_fs_kfuncs_filter(const struct bpf_prog *prog, u32 kfunc_id)
> > > {
> > > if (!btf_id_set8_contains(&bpf_fs_kfunc_set_ids, kfunc_id) ||
> > > - prog->type == BPF_PROG_TYPE_LSM)
> > > + prog->type == BPF_PROG_TYPE_LSM) {
> > > + /* bpf_init_inode_xattr only attaches to inode_init_security. */
> > > + if (kfunc_id == bpf_init_inode_xattr_btf_ids[0] &&
> > > + prog->aux->attach_btf_id != bpf_lsm_inode_init_security_btf_ids[0])
> > > + return -EACCES;
>
> We need to mark bpf_init_inode_xattr with KF_RCU (requires a trusted
> pointer), then we can remove this check above.
>
> > > return 0;
> > > + }
> > > return -EACCES;
> > > }
> >
> > Perhaps I'm simply not seeing it, but is there a check to ensure that
> > there is only one BPF LSM calling into security_inode_init_security()
> > at any given time? With the BPF LSM only reserving a single xattr
> > slot, multiple loaded BPF LSM programs providing
> > security_inode_init_security() callbacks will be a problem.
>
> I don't think there is such a check. Also, a single BPF LSM function
> may call the kfunc multiple times, which is also problematic.
>
> I think we will need to make the default bigger, and also introduce
> some realloc mechanism for the worst case scenario. This should
> work, but the code might be a bit messy.
Thanks for the clarification, that is what I was afraid of when
looking at the code, but I was hoping I was just missing it.
Increasing the default is an option, but I don't think we want to
support a dynamic reallocation scheme for the xattr slots, that will
likely get extremely messy with synchronization between the LSM
framework and BPF LSM hook registrations as well as special code to
handle inodes with lifetimes that are disjoint from the BPF LSM
programs ... I suppose there may be a way to do it, but it will surely
be ugly and come at a cost.
--
paul-moore.com
^ permalink raw reply
* Re: [PATCH v2 1/2] bpf: add bpf_init_inode_xattr kfunc for atomic inode labeling
From: Song Liu @ 2026-05-04 23:09 UTC (permalink / raw)
To: Paul Moore
Cc: David Windsor, Alexander Viro, Christian Brauner,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, KP Singh,
Matt Bobrowski, James Morris, Serge E. Hallyn, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Stephen Smalley, Casey Schaufler,
Jan Kara, John Fastabend, Martin KaFai Lau, Yonghong Song,
Jiri Olsa, Eric Snowberg, Ondrej Mosnacek, linux-fsdevel,
linux-kernel, bpf, linux-security-module, linux-integrity,
selinux
In-Reply-To: <CAHC9VhQLN5NA_ZMMNyUdMCZVdwC3VM4PUnzka8xDK5rpR2a3sw@mail.gmail.com>
On Tue, May 5, 2026 at 12:42 AM Paul Moore <paul@paul-moore.com> wrote:
[...]
> > > Perhaps I'm simply not seeing it, but is there a check to ensure that
> > > there is only one BPF LSM calling into security_inode_init_security()
> > > at any given time? With the BPF LSM only reserving a single xattr
> > > slot, multiple loaded BPF LSM programs providing
> > > security_inode_init_security() callbacks will be a problem.
> >
> > I don't think there is such a check. Also, a single BPF LSM function
> > may call the kfunc multiple times, which is also problematic.
> >
> > I think we will need to make the default bigger, and also introduce
> > some realloc mechanism for the worst case scenario. This should
> > work, but the code might be a bit messy.
>
> Thanks for the clarification, that is what I was afraid of when
> looking at the code, but I was hoping I was just missing it.
>
> Increasing the default is an option, but I don't think we want to
> support a dynamic reallocation scheme for the xattr slots, that will
> likely get extremely messy with synchronization between the LSM
> framework and BPF LSM hook registrations as well as special code to
> handle inodes with lifetimes that are disjoint from the BPF LSM
> programs ... I suppose there may be a way to do it, but it will surely
> be ugly and come at a cost.
BPF trampoline already handles all the synchronizations, such as
add hook, remove hook, etc. properly. So this is not that hard.
All we really need is to allocate a new array, copy pointers, and free
the old array. And we only really need this in the worst case
scenarios.
Thanks,
Song
^ permalink raw reply
* Re: [PATCH v2 1/2] bpf: add bpf_init_inode_xattr kfunc for atomic inode labeling
From: David Windsor @ 2026-05-05 1:07 UTC (permalink / raw)
To: Song Liu
Cc: Paul Moore, Alexander Viro, Christian Brauner, Alexei Starovoitov,
Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman,
Kumar Kartikeya Dwivedi, KP Singh, Matt Bobrowski, James Morris,
Serge E. Hallyn, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Stephen Smalley, Casey Schaufler, Jan Kara, John Fastabend,
Martin KaFai Lau, Yonghong Song, Jiri Olsa, Eric Snowberg,
Ondrej Mosnacek, linux-fsdevel, linux-kernel, bpf,
linux-security-module, linux-integrity, selinux
In-Reply-To: <CAPhsuW5nDaLAV5UfAHeX6QPeF6bs-WDkFYOzYO7Q9_O6v=jEHA@mail.gmail.com>
On Mon, May 4, 2026 at 7:09 PM Song Liu <song@kernel.org> wrote:
>
> On Tue, May 5, 2026 at 12:42 AM Paul Moore <paul@paul-moore.com> wrote:
> [...]
> > > > Perhaps I'm simply not seeing it, but is there a check to ensure that
> > > > there is only one BPF LSM calling into security_inode_init_security()
> > > > at any given time? With the BPF LSM only reserving a single xattr
> > > > slot, multiple loaded BPF LSM programs providing
> > > > security_inode_init_security() callbacks will be a problem.
> > >
> > > I don't think there is such a check. Also, a single BPF LSM function
> > > may call the kfunc multiple times, which is also problematic.
> > >
bpf_xattrs_used() guards against this. The lsm_xattr_ctx is shared
between all callers, so xattr additions by another LSM (or by calling
it multiple times in the same function) will be tracked by this.
> > > I think we will need to make the default bigger, and also introduce
> > > some realloc mechanism for the worst case scenario. This should
> > > work, but the code might be a bit messy.
> >
> > Thanks for the clarification, that is what I was afraid of when
> > looking at the code, but I was hoping I was just missing it.
> >
> > Increasing the default is an option, but I don't think we want to
> > support a dynamic reallocation scheme for the xattr slots, that will
> > likely get extremely messy with synchronization between the LSM
> > framework and BPF LSM hook registrations as well as special code to
> > handle inodes with lifetimes that are disjoint from the BPF LSM
> > programs ... I suppose there may be a way to do it, but it will surely
> > be ugly and come at a cost.
>
> BPF trampoline already handles all the synchronizations, such as
> add hook, remove hook, etc. properly. So this is not that hard.
> All we really need is to allocate a new array, copy pointers, and free
> the old array. And we only really need this in the worst case
> scenarios.
>
How many bpf-lsm programs do we envision being attached at once? I'd
think that stacking of bpf-lsms would be difficult to reason about
(moreso than static LSMs) and won't work that well in practice, but
may be wrong. Most LSMs use 1 xattr, Smack is the only one who uses 2
IIRC.
> Thanks,
> Song
^ permalink raw reply
* Re: [PATCH v2 1/2] bpf: add bpf_init_inode_xattr kfunc for atomic inode labeling
From: Paul Moore @ 2026-05-05 2:02 UTC (permalink / raw)
To: Song Liu
Cc: David Windsor, Alexander Viro, Christian Brauner,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, KP Singh,
Matt Bobrowski, James Morris, Serge E. Hallyn, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Stephen Smalley, Casey Schaufler,
Jan Kara, John Fastabend, Martin KaFai Lau, Yonghong Song,
Jiri Olsa, Eric Snowberg, Ondrej Mosnacek, linux-fsdevel,
linux-kernel, bpf, linux-security-module, linux-integrity,
selinux
In-Reply-To: <CAPhsuW5nDaLAV5UfAHeX6QPeF6bs-WDkFYOzYO7Q9_O6v=jEHA@mail.gmail.com>
On Mon, May 4, 2026 at 7:09 PM Song Liu <song@kernel.org> wrote:
> On Tue, May 5, 2026 at 12:42 AM Paul Moore <paul@paul-moore.com> wrote:
> [...]
> > > > Perhaps I'm simply not seeing it, but is there a check to ensure that
> > > > there is only one BPF LSM calling into security_inode_init_security()
> > > > at any given time? With the BPF LSM only reserving a single xattr
> > > > slot, multiple loaded BPF LSM programs providing
> > > > security_inode_init_security() callbacks will be a problem.
> > >
> > > I don't think there is such a check. Also, a single BPF LSM function
> > > may call the kfunc multiple times, which is also problematic.
> > >
> > > I think we will need to make the default bigger, and also introduce
> > > some realloc mechanism for the worst case scenario. This should
> > > work, but the code might be a bit messy.
> >
> > Thanks for the clarification, that is what I was afraid of when
> > looking at the code, but I was hoping I was just missing it.
> >
> > Increasing the default is an option, but I don't think we want to
> > support a dynamic reallocation scheme for the xattr slots, that will
> > likely get extremely messy with synchronization between the LSM
> > framework and BPF LSM hook registrations as well as special code to
> > handle inodes with lifetimes that are disjoint from the BPF LSM
> > programs ... I suppose there may be a way to do it, but it will surely
> > be ugly and come at a cost.
>
> BPF trampoline already handles all the synchronizations, such as
> add hook, remove hook, etc. properly. So this is not that hard.
How do you plan to handle the issue of disjoint lifetimes?
> All we really need is to allocate a new array, copy pointers, and free
> the old array. And we only really need this in the worst case
> scenarios.
Oh, is that all? :D
Keep in mind that the code must also handle arbitrary ordering of
LSMs; in other words, you must handle a BPF LSM that isn't at the end
of the LSM order. While a BPF LSM at the end of the LSM list is the
most common, and recommended ordering for the vast majority of users,
we've been working to make the ordering as generalized as possible.
--
paul-moore.com
^ permalink raw reply
* Re: [PATCH v2 1/2] bpf: add bpf_init_inode_xattr kfunc for atomic inode labeling
From: Paul Moore @ 2026-05-05 2:05 UTC (permalink / raw)
To: Song Liu
Cc: David Windsor, Alexander Viro, Christian Brauner,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, KP Singh,
Matt Bobrowski, James Morris, Serge E. Hallyn, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Stephen Smalley, Casey Schaufler,
Jan Kara, John Fastabend, Martin KaFai Lau, Yonghong Song,
Jiri Olsa, Eric Snowberg, Ondrej Mosnacek, linux-fsdevel,
linux-kernel, bpf, linux-security-module, linux-integrity,
selinux
In-Reply-To: <CAHC9VhRx7L1WXYgQvWmGN0a7ssSaDKx4JPhup2E3W161sdp74A@mail.gmail.com>
On Mon, May 4, 2026 at 10:02 PM Paul Moore <paul@paul-moore.com> wrote:
> On Mon, May 4, 2026 at 7:09 PM Song Liu <song@kernel.org> wrote:
> > On Tue, May 5, 2026 at 12:42 AM Paul Moore <paul@paul-moore.com> wrote:
> > [...]
> > > > > Perhaps I'm simply not seeing it, but is there a check to ensure that
> > > > > there is only one BPF LSM calling into security_inode_init_security()
> > > > > at any given time? With the BPF LSM only reserving a single xattr
> > > > > slot, multiple loaded BPF LSM programs providing
> > > > > security_inode_init_security() callbacks will be a problem.
> > > >
> > > > I don't think there is such a check. Also, a single BPF LSM function
> > > > may call the kfunc multiple times, which is also problematic.
> > > >
> > > > I think we will need to make the default bigger, and also introduce
> > > > some realloc mechanism for the worst case scenario. This should
> > > > work, but the code might be a bit messy.
> > >
> > > Thanks for the clarification, that is what I was afraid of when
> > > looking at the code, but I was hoping I was just missing it.
> > >
> > > Increasing the default is an option, but I don't think we want to
> > > support a dynamic reallocation scheme for the xattr slots, that will
> > > likely get extremely messy with synchronization between the LSM
> > > framework and BPF LSM hook registrations as well as special code to
> > > handle inodes with lifetimes that are disjoint from the BPF LSM
> > > programs ... I suppose there may be a way to do it, but it will surely
> > > be ugly and come at a cost.
> >
> > BPF trampoline already handles all the synchronizations, such as
> > add hook, remove hook, etc. properly. So this is not that hard.
>
> How do you plan to handle the issue of disjoint lifetimes?
>
> > All we really need is to allocate a new array, copy pointers, and free
> > the old array. And we only really need this in the worst case
> > scenarios.
>
> Oh, is that all? :D
>
> Keep in mind that the code must also handle arbitrary ordering of
> LSMs; in other words, you must handle a BPF LSM that isn't at the end
> of the LSM order. While a BPF LSM at the end of the LSM list is the
> most common, and recommended ordering for the vast majority of users,
> we've been working to make the ordering as generalized as possible.
I just realized I probably wasn't as clear as I should have been ... I
really don't like telling people not to go experiment with things and
play with the code as that feels wrong for many reasons, but I do want
to warn you that if the code to handle this ends up looking like I
think it will, I'm not going to want to support it in the LSM
framework.
--
paul-moore.com
^ permalink raw reply
* Re: [PATCH v2 1/2] bpf: add bpf_init_inode_xattr kfunc for atomic inode labeling
From: Song Liu @ 2026-05-05 9:00 UTC (permalink / raw)
To: Paul Moore
Cc: David Windsor, Alexander Viro, Christian Brauner,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, KP Singh,
Matt Bobrowski, James Morris, Serge E. Hallyn, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Stephen Smalley, Casey Schaufler,
Jan Kara, John Fastabend, Martin KaFai Lau, Yonghong Song,
Jiri Olsa, Eric Snowberg, Ondrej Mosnacek, linux-fsdevel,
linux-kernel, bpf, linux-security-module, linux-integrity,
selinux
In-Reply-To: <CAHC9VhRx7L1WXYgQvWmGN0a7ssSaDKx4JPhup2E3W161sdp74A@mail.gmail.com>
On Tue, May 5, 2026 at 4:02 AM Paul Moore <paul@paul-moore.com> wrote:
>
> On Mon, May 4, 2026 at 7:09 PM Song Liu <song@kernel.org> wrote:
> > On Tue, May 5, 2026 at 12:42 AM Paul Moore <paul@paul-moore.com> wrote:
> > [...]
> > > > > Perhaps I'm simply not seeing it, but is there a check to ensure that
> > > > > there is only one BPF LSM calling into security_inode_init_security()
> > > > > at any given time? With the BPF LSM only reserving a single xattr
> > > > > slot, multiple loaded BPF LSM programs providing
> > > > > security_inode_init_security() callbacks will be a problem.
> > > >
> > > > I don't think there is such a check. Also, a single BPF LSM function
> > > > may call the kfunc multiple times, which is also problematic.
> > > >
> > > > I think we will need to make the default bigger, and also introduce
> > > > some realloc mechanism for the worst case scenario. This should
> > > > work, but the code might be a bit messy.
> > >
> > > Thanks for the clarification, that is what I was afraid of when
> > > looking at the code, but I was hoping I was just missing it.
> > >
> > > Increasing the default is an option, but I don't think we want to
> > > support a dynamic reallocation scheme for the xattr slots, that will
> > > likely get extremely messy with synchronization between the LSM
> > > framework and BPF LSM hook registrations as well as special code to
> > > handle inodes with lifetimes that are disjoint from the BPF LSM
> > > programs ... I suppose there may be a way to do it, but it will surely
> > > be ugly and come at a cost.
> >
> > BPF trampoline already handles all the synchronizations, such as
> > add hook, remove hook, etc. properly. So this is not that hard.
>
> How do you plan to handle the issue of disjoint lifetimes?
>
> > All we really need is to allocate a new array, copy pointers, and free
> > the old array. And we only really need this in the worst case
> > scenarios.
>
> Oh, is that all? :D
>
> Keep in mind that the code must also handle arbitrary ordering of
> LSMs; in other words, you must handle a BPF LSM that isn't at the end
> of the LSM order. While a BPF LSM at the end of the LSM list is the
> most common, and recommended ordering for the vast majority of users,
> we've been working to make the ordering as generalized as possible.
All the BPF LSM hooks are called together, so it should be fine.
Maybe I missed some corner cases.
Either way, I agree with David that we don't need too many xattrs.
Since BPF LSM is reserved to the privileged users only, it is safe
to put a reasonable limit, say 4 or 8, and do not handle the realloc.
If the admin would like to brick a system with BPF LSM, there are
many other ways to do it.
Thanks,
Song
^ permalink raw reply
* [PATCH v5 00/14] module: Introduce hash-based integrity checking
From: Thomas Weißschuh @ 2026-05-05 9:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Bouchinet, Xiu Jianfeng, Christophe Leroy
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi, Eric Biggers,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity, debian-kernel, Thomas Weißschuh
The current signature-based module integrity checking has some drawbacks
in combination with reproducible builds. Either the module signing key
is generated at build time, which makes the build unreproducible, or a
static signing key is used, which precludes rebuilds by third parties
and makes the whole build and packaging process much more complicated.
The goal is to reach bit-for-bit reproducibility. Excluding certain
parts of the build output from the reproducibility analysis would be
error-prone and force each downstream consumer to introduce new tooling.
Introduce a new mechanism to ensure only well-known modules are loaded
by embedding a merkle tree root of all modules built as part of the full
kernel build into vmlinux.
Interest has been proclaimed by Arch Linux, Debian, Proxmox, SUSE, NixOS
and the general reproducible builds community.
Compatibility with IMA modsig is not provided yet. It is still unclear
to me if it should be hooked up transparently without any changes to the
policy or it should require new policy options.
BPF/BTF folks, please take a look at patch 1.
Further improvements:
* Use MODULE_SIG_HASH for configuration
* UAPI for discovery?
To: Nathan Chancellor <nathan@kernel.org>
To: Nicolas Schier <nsc@kernel.org>
To: Arnd Bergmann <arnd@arndb.de>
To: Luis Chamberlain <mcgrof@kernel.org>
To: Petr Pavlu <petr.pavlu@suse.com>
To: Sami Tolvanen <samitolvanen@google.com>
To: Daniel Gomez <da.gomez@samsung.com>
To: Paul Moore <paul@paul-moore.com>
To: James Morris <jmorris@namei.org>
To: Serge E. Hallyn <serge@hallyn.com>
To: Jonathan Corbet <corbet@lwn.net>
To: Madhavan Srinivasan <maddy@linux.ibm.com>
To: Michael Ellerman <mpe@ellerman.id.au>
To: Nicholas Piggin <npiggin@gmail.com>
To: Christophe Leroy <christophe.leroy@csgroup.eu>
To: Naveen N Rao <naveen@kernel.org>
To: Mimi Zohar <zohar@linux.ibm.com>
To: Roberto Sassu <roberto.sassu@huawei.com>
To: Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
To: Eric Snowberg <eric.snowberg@oracle.com>
To: Nicolas Schier <nicolas.schier@linux.dev>
To: Daniel Gomez <da.gomez@kernel.org>
To: Aaron Tomlin <atomlin@atomlin.com>
To: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
To: Nicolas Schier <nsc@kernel.org>
To: Nicolas Bouchinet <nicolas.bouchinet@oss.cyber.gouv.fr>
To: Xiu Jianfeng <xiujianfeng@huawei.com>
Cc: Fabian Grünbichler <f.gruenbichler@proxmox.com>
Cc: Arnout Engelen <arnout@bzzt.net>
Cc: Mattia Rizzolo <mattia@mapreri.org>
Cc: kpcyrd <kpcyrd@archlinux.org>
Cc: Christian Heusel <christian@heusel.eu>
Cc: Câju Mihai-Drosi <mcaju95@gmail.com>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: linux-kbuild@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-arch@vger.kernel.org
Cc: linux-modules@vger.kernel.org
Cc: linux-security-module@vger.kernel.org
Cc: linux-doc@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-integrity@vger.kernel.org
Cc: debian-kernel@lists.debian.org
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
Changes in v5:
- Document tree layout.
- Make scripts/module-merkle-tree more robust.
- Remove all changes to link-vmlinux.sh, use vmlinux.unstripped instead.
- Clean up types and logic in modules-merkle-tree.c.
- Use "auth" over "integrity" naming scheme.
- Reduce the changes to the existing authentication flow.
- Explicitly send the series to BTF folks for review of BTF changes.
- Link to v4: https://patch.msgid.link/20260113-module-hashes-v4-0-0b932db9b56b@weissschuh.net
Changes in v4:
- Use as Merkle tree over a linera list of hashes.
- Provide compatibilith with INSTALL_MOD_STRIP
- Rework commit messages.
- Use vmlinux.unstripped over plain "vmlinux".
- Link to v3: https://lore.kernel.org/r/20250429-module-hashes-v3-0-00e9258def9e@weissschuh.net
Changes in v3:
- Rebase on v6.15-rc1
- Use openssl to calculate hash
- Avoid warning if no modules are built
- Simplify module_integrity_check() a bit
- Make incompatibility with INSTALL_MOD_STRIP explicit
- Update docs
- Add IMA cleanups
- Link to v2: https://lore.kernel.org/r/20250120-module-hashes-v2-0-ba1184e27b7f@weissschuh.net
Changes in v2:
- Drop RFC state
- Mention interested parties in cover letter
- Expand Kconfig description
- Add compatibility with CONFIG_MODULE_SIG
- Parallelize module-hashes.sh
- Update Documentation/kbuild/reproducible-builds.rst
- Link to v1: https://lore.kernel.org/r/20241225-module-hashes-v1-0-d710ce7a3fd1@weissschuh.net
---
Thomas Weißschuh (14):
kbuild: generate module BTF based on vmlinux.unstripped
lockdown: Make the relationship to MODULE_SIG a dependency
kbuild: rename the strip_relocs command
module: Drop pointless debugging message
module: Make mod_verify_sig() static
module: Switch load_info::len to size_t
module: Make module authentication usable without MODULE_SIG
module: Move authentication logic into dedicated new file
module: Move signature type check out of mod_check_sig()
module: Prepare for additional module authentication mechanisms
module: update timestamp of modules.order after modules are built
module: Introduce hash-based integrity checking
kbuild: move handling of module stripping to Makefile.lib
kbuild: make CONFIG_MODULE_HASHES compatible with module stripping
.gitignore | 2 +
Documentation/kbuild/reproducible-builds.rst | 5 +-
Makefile | 7 +-
crypto/algapi.c | 4 +-
include/asm-generic/vmlinux.lds.h | 11 +
include/linux/module.h | 18 +-
include/linux/module_hashes.h | 29 ++
include/uapi/linux/module_signature.h | 1 +
kernel/module/Kconfig | 29 +-
kernel/module/Makefile | 2 +
kernel/module/auth.c | 139 +++++++++
kernel/module/hashes.c | 95 ++++++
kernel/module/hashes_root.c | 6 +
kernel/module/internal.h | 18 +-
kernel/module/main.c | 16 +-
kernel/module/signing.c | 113 +-------
kernel/module_signature.c | 8 +-
scripts/.gitignore | 1 +
scripts/Makefile | 4 +
scripts/Makefile.lib | 32 +++
scripts/Makefile.modfinal | 28 +-
scripts/Makefile.modinst | 44 +--
scripts/Makefile.vmlinux | 40 ++-
scripts/include/xalloc.h | 29 ++
scripts/link-vmlinux.sh | 3 +-
scripts/modules-merkle-tree.c | 416 +++++++++++++++++++++++++++
security/integrity/ima/ima_modsig.c | 5 +
security/lockdown/Kconfig | 2 +-
tools/include/uapi/linux/module_signature.h | 1 +
29 files changed, 919 insertions(+), 189 deletions(-)
---
base-commit: 585c2e775b12ef45bdf9cef5f679dcb1220e0d65
change-id: 20241225-module-hashes-7a50a7cc2a30
Best regards,
--
Thomas Weißschuh <linux@weissschuh.net>
^ permalink raw reply
* [PATCH v5 01/14] kbuild: generate module BTF based on vmlinux.unstripped
From: Thomas Weißschuh @ 2026-05-05 9:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Bouchinet, Xiu Jianfeng, Christophe Leroy
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi, Eric Biggers,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity, debian-kernel, Thomas Weißschuh
In-Reply-To: <20260505-module-hashes-v5-0-e174a5a49fce@weissschuh.net>
The upcoming module hashes functionality will build the modules in
between the generation of the BTF data and the final link of vmlinux.
At this point vmlinux is not yet built and therefore can't be used for
module BTF generation. vmlinux.unstripped however is usable and
sufficient for BTF generation.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Reviewed-by: Nicolas Schier <nsc@kernel.org>
---
scripts/Makefile.modfinal | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index adcbcde16a07..b09040ccddd2 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -38,12 +38,14 @@ quiet_cmd_ld_ko_o = LD [M] $@
$(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
-T $(objtree)/scripts/module.lds -o $@ $(filter %.o, $^)
+btf-vmlinux := $(if $(KBUILD_EXTMOD),vmlinux,vmlinux.unstripped)
+
quiet_cmd_btf_ko = BTF [M] $@
cmd_btf_ko = \
- if [ ! -f $(objtree)/vmlinux ]; then \
- printf "Skipping BTF generation for %s due to unavailability of vmlinux\n" $@ 1>&2; \
+ if [ ! -f $(objtree)/$(btf-vmlinux) ]; then \
+ printf "Skipping BTF generation for %s due to unavailability of $(btf-vmlinux)\n" $@ 1>&2; \
else \
- $(CONFIG_SHELL) $(srctree)/scripts/gen-btf.sh --btf_base $(objtree)/vmlinux $@; \
+ $(CONFIG_SHELL) $(srctree)/scripts/gen-btf.sh --btf_base $(objtree)/$(btf-vmlinux) $@; \
fi;
# Same as newer-prereqs, but allows to exclude specified extra dependencies
@@ -55,8 +57,8 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
printf '%s\n' 'savedcmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
# Re-generate module BTFs if either module's .ko or vmlinux changed
-%.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),$(objtree)/vmlinux) FORCE
- +$(call if_changed_except,ld_ko_o,$(objtree)/vmlinux)
+%.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),$(objtree)/$(btf-vmlinux)) FORCE
+ +$(call if_changed_except,ld_ko_o,$(objtree)/$(btf-vmlinux))
ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+$(if $(newer-prereqs),$(call cmd,btf_ko))
endif
--
2.54.0
^ permalink raw reply related
* [PATCH v5 03/14] kbuild: rename the strip_relocs command
From: Thomas Weißschuh @ 2026-05-05 9:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Bouchinet, Xiu Jianfeng, Christophe Leroy
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi, Eric Biggers,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity, debian-kernel, Thomas Weißschuh
In-Reply-To: <20260505-module-hashes-v5-0-e174a5a49fce@weissschuh.net>
This command is doing more than just stripping relocations.
With the introduction of CONFIG_MODULE_HASHES it will do even more.
Use a more generic name for the variable.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
scripts/Makefile.vmlinux | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux
index fcae1e432d9a..6cc661e5292b 100644
--- a/scripts/Makefile.vmlinux
+++ b/scripts/Makefile.vmlinux
@@ -91,13 +91,13 @@ remove-symbols := -w --strip-unneeded-symbol='__mod_device_table__*'
# To avoid warnings: "empty loadable segment detected at ..." from GNU objcopy,
# it is necessary to remove the PT_LOAD flag from the segment.
-quiet_cmd_strip_relocs = OBJCOPY $@
- cmd_strip_relocs = $(OBJCOPY) $(patsubst %,--set-section-flags %=noload,$(remove-section-y)) $< $@; \
- $(OBJCOPY) $(addprefix --remove-section=,$(remove-section-y)) $(remove-symbols) $@
+quiet_cmd_objcopy_vmlinux = OBJCOPY $@
+ cmd_objcopy_vmlinux = $(OBJCOPY) $(patsubst %,--set-section-flags %=noload,$(remove-section-y)) $< $@; \
+ $(OBJCOPY) $(addprefix --remove-section=,$(remove-section-y)) $(remove-symbols) $@
targets += vmlinux
vmlinux: vmlinux.unstripped FORCE
- $(call if_changed,strip_relocs)
+ $(call if_changed,objcopy_vmlinux)
# modules.builtin.modinfo
# ---------------------------------------------------------------------------
--
2.54.0
^ permalink raw reply related
* [PATCH v5 04/14] module: Drop pointless debugging message
From: Thomas Weißschuh @ 2026-05-05 9:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Bouchinet, Xiu Jianfeng, Christophe Leroy
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi, Eric Biggers,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity, debian-kernel, Thomas Weißschuh
In-Reply-To: <20260505-module-hashes-v5-0-e174a5a49fce@weissschuh.net>
This is the only instance of pr_devel() in the whole module subsystem
and essentially useless.
Drop it.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
kernel/module/signing.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/kernel/module/signing.c b/kernel/module/signing.c
index 590ba29c85ab..4a5e4eef250d 100644
--- a/kernel/module/signing.c
+++ b/kernel/module/signing.c
@@ -46,8 +46,6 @@ int mod_verify_sig(const void *mod, struct load_info *info)
size_t sig_len, modlen = info->len;
int ret;
- pr_devel("==>%s(,%zu)\n", __func__, modlen);
-
if (modlen <= sizeof(ms))
return -EBADMSG;
--
2.54.0
^ permalink raw reply related
* [PATCH v5 05/14] module: Make mod_verify_sig() static
From: Thomas Weißschuh @ 2026-05-05 9:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Bouchinet, Xiu Jianfeng, Christophe Leroy
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi, Eric Biggers,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity, debian-kernel, Thomas Weißschuh
In-Reply-To: <20260505-module-hashes-v5-0-e174a5a49fce@weissschuh.net>
It is not used outside of signing.c.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Reviewed-by: Aaron Tomlin <atomlin@atomlin.com>
Reviewed-by: Nicolas Schier <nsc@kernel.org>
Reviewed-by: Eric Biggers <ebiggers@kernel.org>
---
kernel/module/internal.h | 1 -
kernel/module/signing.c | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index 061161cc79d9..071999743341 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -117,7 +117,6 @@ struct module_use {
struct module *source, *target;
};
-int mod_verify_sig(const void *mod, struct load_info *info);
int try_to_force_load(struct module *mod, const char *reason);
bool find_symbol(struct find_symbol_arg *fsa);
struct module *find_module_all(const char *name, size_t len, bool even_unformed);
diff --git a/kernel/module/signing.c b/kernel/module/signing.c
index 4a5e4eef250d..69d4b1758540 100644
--- a/kernel/module/signing.c
+++ b/kernel/module/signing.c
@@ -40,7 +40,7 @@ void set_module_sig_enforced(void)
/*
* Verify the signature on a module.
*/
-int mod_verify_sig(const void *mod, struct load_info *info)
+static int mod_verify_sig(const void *mod, struct load_info *info)
{
struct module_signature ms;
size_t sig_len, modlen = info->len;
--
2.54.0
^ permalink raw reply related
* [PATCH v5 02/14] lockdown: Make the relationship to MODULE_SIG a dependency
From: Thomas Weißschuh @ 2026-05-05 9:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Bouchinet, Xiu Jianfeng, Christophe Leroy
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi, Eric Biggers,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity, debian-kernel, Thomas Weißschuh
In-Reply-To: <20260505-module-hashes-v5-0-e174a5a49fce@weissschuh.net>
The new hash-based module integrity checking will also be able to
satisfy the requirements of lockdown.
Such an alternative is not representable with "select", so use
"depends on" instead.
Acked-by: Paul Moore <paul@paul-moore.com>
Reviewed-by: Nicolas Schier <nsc@kernel.org>
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
security/lockdown/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/lockdown/Kconfig b/security/lockdown/Kconfig
index e84ddf484010..155959205b8e 100644
--- a/security/lockdown/Kconfig
+++ b/security/lockdown/Kconfig
@@ -1,7 +1,7 @@
config SECURITY_LOCKDOWN_LSM
bool "Basic module for enforcing kernel lockdown"
depends on SECURITY
- select MODULE_SIG if MODULES
+ depends on !MODULES || MODULE_SIG
help
Build support for an LSM that enforces a coarse kernel lockdown
behaviour.
--
2.54.0
^ permalink raw reply related
* [PATCH v5 09/14] module: Move signature type check out of mod_check_sig()
From: Thomas Weißschuh @ 2026-05-05 9:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Bouchinet, Xiu Jianfeng, Christophe Leroy
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi, Eric Biggers,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity, debian-kernel, Thomas Weißschuh
In-Reply-To: <20260505-module-hashes-v5-0-e174a5a49fce@weissschuh.net>
Additional signature types are about to be added.
As each caller of mod_check_sig() can have different support for these,
move the type validation into the callers.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
kernel/module/auth.c | 5 +++++
kernel/module_signature.c | 8 +-------
security/integrity/ima/ima_modsig.c | 5 +++++
3 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/kernel/module/auth.c b/kernel/module/auth.c
index 831a13eb0c9b..21e49eb4967c 100644
--- a/kernel/module/auth.c
+++ b/kernel/module/auth.c
@@ -48,6 +48,11 @@ static int mod_verify_sig(const void *mod, struct load_info *info)
memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
+ if (ms.id_type != MODULE_SIGNATURE_TYPE_PKCS7) {
+ pr_err("module: not signed with expected PKCS#7 message\n");
+ return -ENOPKG;
+ }
+
ret = mod_check_sig(&ms, modlen, "module");
if (ret)
return ret;
diff --git a/kernel/module_signature.c b/kernel/module_signature.c
index a0eee2fe4368..4d0476bcdb72 100644
--- a/kernel/module_signature.c
+++ b/kernel/module_signature.c
@@ -24,12 +24,6 @@ int mod_check_sig(const struct module_signature *ms, size_t file_len,
if (be32_to_cpu(ms->sig_len) >= file_len - sizeof(*ms))
return -EBADMSG;
- if (ms->id_type != MODULE_SIGNATURE_TYPE_PKCS7) {
- pr_err("%s: not signed with expected PKCS#7 message\n",
- name);
- return -ENOPKG;
- }
-
if (ms->algo != 0 ||
ms->hash != 0 ||
ms->signer_len != 0 ||
@@ -37,7 +31,7 @@ int mod_check_sig(const struct module_signature *ms, size_t file_len,
ms->__pad[0] != 0 ||
ms->__pad[1] != 0 ||
ms->__pad[2] != 0) {
- pr_err("%s: PKCS#7 signature info has unexpected non-zero params\n",
+ pr_err("%s: signature info has unexpected non-zero params\n",
name);
return -EBADMSG;
}
diff --git a/security/integrity/ima/ima_modsig.c b/security/integrity/ima/ima_modsig.c
index 632c746fd81e..ebfcdd368a2a 100644
--- a/security/integrity/ima/ima_modsig.c
+++ b/security/integrity/ima/ima_modsig.c
@@ -57,6 +57,11 @@ int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
buf_len -= marker_len;
sig = (const struct module_signature *)(p - sizeof(*sig));
+ if (sig->id_type != MODULE_SIGNATURE_TYPE_PKCS7) {
+ pr_err("%s: not signed with expected PKCS#7 message\n", func_tokens[func]);
+ return -ENOPKG;
+ }
+
rc = mod_check_sig(sig, buf_len, func_tokens[func]);
if (rc)
return rc;
--
2.54.0
^ permalink raw reply related
* [PATCH v5 07/14] module: Make module authentication usable without MODULE_SIG
From: Thomas Weißschuh @ 2026-05-05 9:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Bouchinet, Xiu Jianfeng, Christophe Leroy
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi, Eric Biggers,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity, debian-kernel, Thomas Weißschuh
In-Reply-To: <20260505-module-hashes-v5-0-e174a5a49fce@weissschuh.net>
The module authentication functionality will also be used by the
hash-based module authentication. Split it out from CONFIG_MODULE_SIG
so it is usable by both.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
crypto/algapi.c | 4 ++--
include/linux/module.h | 18 +++++++++---------
kernel/module/Kconfig | 5 ++++-
kernel/module/Makefile | 1 +
kernel/module/auth.c | 32 ++++++++++++++++++++++++++++++++
kernel/module/internal.h | 2 +-
kernel/module/main.c | 8 ++++----
kernel/module/signing.c | 23 +----------------------
8 files changed, 54 insertions(+), 39 deletions(-)
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 37de377719ae..14252b780266 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -24,8 +24,8 @@ static LIST_HEAD(crypto_template_list);
static inline void crypto_check_module_sig(struct module *mod)
{
- if (fips_enabled && mod && !module_sig_ok(mod))
- panic("Module %s signature verification failed in FIPS mode\n",
+ if (fips_enabled && mod && !module_auth_ok(mod))
+ panic("Module %s authentication failed in FIPS mode\n",
module_name(mod));
}
diff --git a/include/linux/module.h b/include/linux/module.h
index 7566815fabbe..b4760777daad 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -437,9 +437,9 @@ struct module {
/* GPL-only exported symbols. */
bool using_gplonly_symbols;
-#ifdef CONFIG_MODULE_SIG
- /* Signature was verified. */
- bool sig_ok;
+#ifdef CONFIG_MODULE_AUTH
+ /* Module was authenticated. */
+ bool auth_ok;
#endif
bool async_probe_requested;
@@ -918,16 +918,16 @@ static inline bool retpoline_module_ok(bool has_retpoline)
}
#endif
-#ifdef CONFIG_MODULE_SIG
+#ifdef CONFIG_MODULE_AUTH
bool is_module_sig_enforced(void);
void set_module_sig_enforced(void);
-static inline bool module_sig_ok(struct module *module)
+static inline bool module_auth_ok(struct module *module)
{
- return module->sig_ok;
+ return module->auth_ok;
}
-#else /* !CONFIG_MODULE_SIG */
+#else /* !CONFIG_MODULE_AUTH */
static inline bool is_module_sig_enforced(void)
{
return false;
@@ -937,11 +937,11 @@ static inline void set_module_sig_enforced(void)
{
}
-static inline bool module_sig_ok(struct module *module)
+static inline bool module_auth_ok(struct module *module)
{
return true;
}
-#endif /* CONFIG_MODULE_SIG */
+#endif /* CONFIG_MODULE_AUTH */
#if defined(CONFIG_MODULES) && defined(CONFIG_KALLSYMS)
int module_kallsyms_on_each_symbol(const char *modname,
diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig
index f535181e0d98..84297da666ff 100644
--- a/kernel/module/Kconfig
+++ b/kernel/module/Kconfig
@@ -271,9 +271,12 @@ config MODULE_SIG
debuginfo strip done by some packagers (such as rpmbuild) and
inclusion into an initramfs that wants the module size reduced.
+config MODULE_AUTH
+ def_bool MODULE_SIG
+
config MODULE_SIG_FORCE
bool "Require modules to be validly signed"
- depends on MODULE_SIG
+ depends on MODULE_AUTH
help
Reject unsigned modules or signed modules for which we don't have a
key. Without this, such modules will simply taint the kernel.
diff --git a/kernel/module/Makefile b/kernel/module/Makefile
index d9e8759a7b05..c7200e293d04 100644
--- a/kernel/module/Makefile
+++ b/kernel/module/Makefile
@@ -14,6 +14,7 @@ obj-y += strict_rwx.o
obj-y += kmod.o
obj-$(CONFIG_MODULE_DEBUG_AUTOLOAD_DUPS) += dups.o
obj-$(CONFIG_MODULE_DECOMPRESS) += decompress.o
+obj-$(CONFIG_MODULE_AUTH) += auth.o
obj-$(CONFIG_MODULE_SIG) += signing.o
obj-$(CONFIG_LIVEPATCH) += livepatch.o
obj-$(CONFIG_MODULES_TREE_LOOKUP) += tree_lookup.o
diff --git a/kernel/module/auth.c b/kernel/module/auth.c
new file mode 100644
index 000000000000..956ac63d9d33
--- /dev/null
+++ b/kernel/module/auth.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Module authentication checker
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+
+#undef MODULE_PARAM_PREFIX
+#define MODULE_PARAM_PREFIX "module."
+
+static bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE);
+module_param(sig_enforce, bool_enable_only, 0644);
+
+/*
+ * Export sig_enforce kernel cmdline parameter to allow other subsystems rely
+ * on that instead of directly to CONFIG_MODULE_SIG_FORCE config.
+ */
+bool is_module_sig_enforced(void)
+{
+ return sig_enforce;
+}
+EXPORT_SYMBOL(is_module_sig_enforced);
+
+void set_module_sig_enforced(void)
+{
+ sig_enforce = true;
+}
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index 006ada7d4e6e..f8f425b167f1 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -68,7 +68,7 @@ struct load_info {
Elf_Shdr *sechdrs;
char *secstrings, *strtab;
unsigned long symoffs, stroffs, init_typeoffs, core_typeoffs;
- bool sig_ok;
+ bool auth_ok;
#ifdef CONFIG_KALLSYMS
unsigned long mod_kallsyms_init_off;
#endif
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 17a352198016..cd8a74df117e 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2601,10 +2601,10 @@ static void module_augment_kernel_taints(struct module *mod, struct load_info *i
mod->name);
add_taint_module(mod, TAINT_TEST, LOCKDEP_STILL_OK);
}
-#ifdef CONFIG_MODULE_SIG
- mod->sig_ok = info->sig_ok;
- if (!mod->sig_ok) {
- pr_notice_once("%s: module verification failed: signature "
+#ifdef CONFIG_MODULE_AUTH
+ mod->auth_ok = info->auth_ok;
+ if (!mod->auth_ok) {
+ pr_notice_once("%s: module authentication failed: signature "
"and/or required key missing - tainting "
"kernel\n", mod->name);
add_taint_module(mod, TAINT_UNSIGNED_MODULE, LOCKDEP_STILL_OK);
diff --git a/kernel/module/signing.c b/kernel/module/signing.c
index 69d4b1758540..07a786723221 100644
--- a/kernel/module/signing.c
+++ b/kernel/module/signing.c
@@ -16,27 +16,6 @@
#include <uapi/linux/module.h>
#include "internal.h"
-#undef MODULE_PARAM_PREFIX
-#define MODULE_PARAM_PREFIX "module."
-
-static bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE);
-module_param(sig_enforce, bool_enable_only, 0644);
-
-/*
- * Export sig_enforce kernel cmdline parameter to allow other subsystems rely
- * on that instead of directly to CONFIG_MODULE_SIG_FORCE config.
- */
-bool is_module_sig_enforced(void)
-{
- return sig_enforce;
-}
-EXPORT_SYMBOL(is_module_sig_enforced);
-
-void set_module_sig_enforced(void)
-{
- sig_enforce = true;
-}
-
/*
* Verify the signature on a module.
*/
@@ -84,7 +63,7 @@ int module_sig_check(struct load_info *info, int flags)
info->len -= markerlen;
err = mod_verify_sig(mod, info);
if (!err) {
- info->sig_ok = true;
+ info->auth_ok = true;
return 0;
}
}
--
2.54.0
^ permalink raw reply related
* [PATCH v5 08/14] module: Move authentication logic into dedicated new file
From: Thomas Weißschuh @ 2026-05-05 9:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Bouchinet, Xiu Jianfeng, Christophe Leroy
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi, Eric Biggers,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity, debian-kernel, Thomas Weißschuh
In-Reply-To: <20260505-module-hashes-v5-0-e174a5a49fce@weissschuh.net>
The module authentication functionality will also be used by the
hash-based module authentication. To make it usable even if
CONFIG_MODULE_SIG is disabled, move it to a new file.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
kernel/module/auth.c | 85 +++++++++++++++++++++++++++++++++++++++++++++
kernel/module/internal.h | 14 ++++++--
kernel/module/main.c | 6 ++--
kernel/module/signing.c | 90 ++----------------------------------------------
4 files changed, 103 insertions(+), 92 deletions(-)
diff --git a/kernel/module/auth.c b/kernel/module/auth.c
index 956ac63d9d33..831a13eb0c9b 100644
--- a/kernel/module/auth.c
+++ b/kernel/module/auth.c
@@ -5,10 +5,16 @@
* Written by David Howells (dhowells@redhat.com)
*/
+#include <linux/errno.h>
#include <linux/export.h>
#include <linux/module.h>
+#include <linux/module_signature.h>
#include <linux/moduleparam.h>
+#include <linux/security.h>
+#include <linux/string.h>
#include <linux/types.h>
+#include <uapi/linux/module.h>
+#include "internal.h"
#undef MODULE_PARAM_PREFIX
#define MODULE_PARAM_PREFIX "module."
@@ -30,3 +36,82 @@ void set_module_sig_enforced(void)
{
sig_enforce = true;
}
+
+static int mod_verify_sig(const void *mod, struct load_info *info)
+{
+ struct module_signature ms;
+ size_t sig_len, modlen = info->len;
+ int ret;
+
+ if (modlen <= sizeof(ms))
+ return -EBADMSG;
+
+ memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
+
+ ret = mod_check_sig(&ms, modlen, "module");
+ if (ret)
+ return ret;
+
+ sig_len = be32_to_cpu(ms.sig_len);
+ modlen -= sig_len + sizeof(ms);
+ info->len = modlen;
+
+ return module_sig_check(mod, modlen, mod + modlen, sig_len);
+}
+
+int module_auth_check(struct load_info *info, int flags)
+{
+ int err = -ENODATA;
+ const unsigned long markerlen = sizeof(MODULE_SIGNATURE_MARKER) - 1;
+ const char *reason;
+ const void *mod = info->hdr;
+ bool mangled_module = flags & (MODULE_INIT_IGNORE_MODVERSIONS |
+ MODULE_INIT_IGNORE_VERMAGIC);
+ /*
+ * Do not allow mangled modules as a module with version information
+ * removed is no longer the module that was signed.
+ */
+ if (!mangled_module &&
+ info->len > markerlen &&
+ memcmp(mod + info->len - markerlen, MODULE_SIGNATURE_MARKER, markerlen) == 0) {
+ /* We truncate the module to discard the signature */
+ info->len -= markerlen;
+ err = mod_verify_sig(mod, info);
+ if (!err) {
+ info->auth_ok = true;
+ return 0;
+ }
+ }
+
+ /*
+ * We don't permit modules to be loaded into the trusted kernels
+ * without a valid signature on them, but if we're not enforcing,
+ * certain errors are non-fatal.
+ */
+ switch (err) {
+ case -ENODATA:
+ reason = "unsigned module";
+ break;
+ case -ENOPKG:
+ reason = "module with unsupported crypto";
+ break;
+ case -ENOKEY:
+ reason = "module with unavailable key";
+ break;
+
+ default:
+ /*
+ * All other errors are fatal, including lack of memory,
+ * unparseable signatures, and signature check failures --
+ * even if signatures aren't required.
+ */
+ return err;
+ }
+
+ if (is_module_sig_enforced()) {
+ pr_notice("Loading of %s is rejected\n", reason);
+ return -EKEYREJECTED;
+ }
+
+ return security_locked_down(LOCKDOWN_MODULE_SIGNATURE);
+}
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index f8f425b167f1..d923e31a5d8e 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -336,14 +336,24 @@ void module_mark_ro_after_init(const Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
const char *secstrings);
#ifdef CONFIG_MODULE_SIG
-int module_sig_check(struct load_info *info, int flags);
+int module_sig_check(const void *mod, size_t mod_len, const void *sig, size_t sig_len);
#else /* !CONFIG_MODULE_SIG */
-static inline int module_sig_check(struct load_info *info, int flags)
+static inline int module_sig_check(const void *mod, size_t mod_len,
+ const void *sig, size_t sig_len)
{
return 0;
}
#endif /* !CONFIG_MODULE_SIG */
+#ifdef CONFIG_MODULE_AUTH
+int module_auth_check(struct load_info *info, int flags);
+#else /* !CONFIG_MODULE_AUTH */
+static inline int module_auth_check(struct load_info *info, int flags)
+{
+ return 0;
+}
+#endif /* !CONFIG_MODULE_AUTH */
+
#ifdef CONFIG_DEBUG_KMEMLEAK
void kmemleak_load_module(const struct module *mod, const struct load_info *info);
#else /* !CONFIG_DEBUG_KMEMLEAK */
diff --git a/kernel/module/main.c b/kernel/module/main.c
index cd8a74df117e..55a010383a8d 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -3428,8 +3428,8 @@ static int load_module(struct load_info *info, const char __user *uargs,
char *after_dashes;
/*
- * Do the signature check (if any) first. All that
- * the signature check needs is info->len, it does
+ * Do the authentication checks (if any) first. All that
+ * the authentication checks need is info->len, it does
* not need any of the section info. That can be
* set up later. This will minimize the chances
* of a corrupt module causing problems before
@@ -3439,7 +3439,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
* off the sig length at the end of the module, making
* checks against info->len more correct.
*/
- err = module_sig_check(info, flags);
+ err = module_auth_check(info, flags);
if (err)
goto free_copy;
diff --git a/kernel/module/signing.c b/kernel/module/signing.c
index 07a786723221..a49317e3c66f 100644
--- a/kernel/module/signing.c
+++ b/kernel/module/signing.c
@@ -5,98 +5,14 @@
* Written by David Howells (dhowells@redhat.com)
*/
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/module_signature.h>
-#include <linux/string.h>
+#include <linux/types.h>
#include <linux/verification.h>
-#include <linux/security.h>
-#include <crypto/public_key.h>
-#include <uapi/linux/module.h>
#include "internal.h"
-/*
- * Verify the signature on a module.
- */
-static int mod_verify_sig(const void *mod, struct load_info *info)
+int module_sig_check(const void *mod, size_t mod_len, const void *sig, size_t sig_len)
{
- struct module_signature ms;
- size_t sig_len, modlen = info->len;
- int ret;
-
- if (modlen <= sizeof(ms))
- return -EBADMSG;
-
- memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
-
- ret = mod_check_sig(&ms, modlen, "module");
- if (ret)
- return ret;
-
- sig_len = be32_to_cpu(ms.sig_len);
- modlen -= sig_len + sizeof(ms);
- info->len = modlen;
-
- return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
+ return verify_pkcs7_signature(mod, mod_len, sig, sig_len,
VERIFY_USE_SECONDARY_KEYRING,
VERIFYING_MODULE_SIGNATURE,
NULL, NULL);
}
-
-int module_sig_check(struct load_info *info, int flags)
-{
- int err = -ENODATA;
- const unsigned long markerlen = sizeof(MODULE_SIGNATURE_MARKER) - 1;
- const char *reason;
- const void *mod = info->hdr;
- bool mangled_module = flags & (MODULE_INIT_IGNORE_MODVERSIONS |
- MODULE_INIT_IGNORE_VERMAGIC);
- /*
- * Do not allow mangled modules as a module with version information
- * removed is no longer the module that was signed.
- */
- if (!mangled_module &&
- info->len > markerlen &&
- memcmp(mod + info->len - markerlen, MODULE_SIGNATURE_MARKER, markerlen) == 0) {
- /* We truncate the module to discard the signature */
- info->len -= markerlen;
- err = mod_verify_sig(mod, info);
- if (!err) {
- info->auth_ok = true;
- return 0;
- }
- }
-
- /*
- * We don't permit modules to be loaded into the trusted kernels
- * without a valid signature on them, but if we're not enforcing,
- * certain errors are non-fatal.
- */
- switch (err) {
- case -ENODATA:
- reason = "unsigned module";
- break;
- case -ENOPKG:
- reason = "module with unsupported crypto";
- break;
- case -ENOKEY:
- reason = "module with unavailable key";
- break;
-
- default:
- /*
- * All other errors are fatal, including lack of memory,
- * unparseable signatures, and signature check failures --
- * even if signatures aren't required.
- */
- return err;
- }
-
- if (is_module_sig_enforced()) {
- pr_notice("Loading of %s is rejected\n", reason);
- return -EKEYREJECTED;
- }
-
- return security_locked_down(LOCKDOWN_MODULE_SIGNATURE);
-}
--
2.54.0
^ permalink raw reply related
* [PATCH v5 06/14] module: Switch load_info::len to size_t
From: Thomas Weißschuh @ 2026-05-05 9:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Bouchinet, Xiu Jianfeng, Christophe Leroy
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi, Eric Biggers,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity, debian-kernel, Thomas Weißschuh
In-Reply-To: <20260505-module-hashes-v5-0-e174a5a49fce@weissschuh.net>
Switching the types will make some later changes cleaner.
size_t is also the semantically correct type for this field.
As both 'size_t' and 'unsigned long' are always the same size, this
should be risk-free.
Reviewed-by: Nicolas Schier <nsc@kernel.org>
Acked-by: Nicolas Schier <nsc@kernel.org>
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
kernel/module/internal.h | 2 +-
kernel/module/main.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index 071999743341..006ada7d4e6e 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -64,7 +64,7 @@ struct load_info {
/* pointer to module in temporary copy, freed at end of load_module() */
struct module *mod;
Elf_Ehdr *hdr;
- unsigned long len;
+ size_t len;
Elf_Shdr *sechdrs;
char *secstrings, *strtab;
unsigned long symoffs, stroffs, init_typeoffs, core_typeoffs;
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 46dd8d25a605..17a352198016 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -1898,7 +1898,7 @@ static int validate_section_offset(const struct load_info *info, Elf_Shdr *shdr)
static int elf_validity_ehdr(const struct load_info *info)
{
if (info->len < sizeof(*(info->hdr))) {
- pr_err("Invalid ELF header len %lu\n", info->len);
+ pr_err("Invalid ELF header len %zu\n", info->len);
return -ENOEXEC;
}
if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0) {
--
2.54.0
^ permalink raw reply related
* [PATCH v5 10/14] module: Prepare for additional module authentication mechanisms
From: Thomas Weißschuh @ 2026-05-05 9:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Bouchinet, Xiu Jianfeng, Christophe Leroy
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi, Eric Biggers,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity, debian-kernel, Thomas Weißschuh
In-Reply-To: <20260505-module-hashes-v5-0-e174a5a49fce@weissschuh.net>
Reorganize the code to make it easier to add the new hash-based module
authentication.
Also drop the now unnecessary stub for module_sig_check().
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
kernel/module/auth.c | 17 ++++++++++++++---
kernel/module/internal.h | 8 --------
2 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/kernel/module/auth.c b/kernel/module/auth.c
index 21e49eb4967c..2ee512d26790 100644
--- a/kernel/module/auth.c
+++ b/kernel/module/auth.c
@@ -37,6 +37,14 @@ void set_module_sig_enforced(void)
sig_enforce = true;
}
+static __always_inline bool mod_sig_type_valid(enum module_signature_type id_type)
+{
+ if (id_type == MODULE_SIGNATURE_TYPE_PKCS7 && IS_ENABLED(CONFIG_MODULE_SIG))
+ return true;
+
+ return false;
+}
+
static int mod_verify_sig(const void *mod, struct load_info *info)
{
struct module_signature ms;
@@ -48,8 +56,8 @@ static int mod_verify_sig(const void *mod, struct load_info *info)
memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
- if (ms.id_type != MODULE_SIGNATURE_TYPE_PKCS7) {
- pr_err("module: not signed with expected PKCS#7 message\n");
+ if (!mod_sig_type_valid(ms.id_type)) {
+ pr_err("module: not signed with expected signature\n");
return -ENOPKG;
}
@@ -61,7 +69,10 @@ static int mod_verify_sig(const void *mod, struct load_info *info)
modlen -= sig_len + sizeof(ms);
info->len = modlen;
- return module_sig_check(mod, modlen, mod + modlen, sig_len);
+ if (ms.id_type == MODULE_SIGNATURE_TYPE_PKCS7 && IS_ENABLED(CONFIG_MODULE_SIG))
+ return module_sig_check(mod, modlen, mod + modlen, sig_len);
+
+ return 0;
}
int module_auth_check(struct load_info *info, int flags)
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index d923e31a5d8e..aabe7f8e1af4 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -335,15 +335,7 @@ int module_enforce_rwx_sections(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
void module_mark_ro_after_init(const Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
const char *secstrings);
-#ifdef CONFIG_MODULE_SIG
int module_sig_check(const void *mod, size_t mod_len, const void *sig, size_t sig_len);
-#else /* !CONFIG_MODULE_SIG */
-static inline int module_sig_check(const void *mod, size_t mod_len,
- const void *sig, size_t sig_len)
-{
- return 0;
-}
-#endif /* !CONFIG_MODULE_SIG */
#ifdef CONFIG_MODULE_AUTH
int module_auth_check(struct load_info *info, int flags);
--
2.54.0
^ permalink raw reply related
* [PATCH v5 14/14] kbuild: make CONFIG_MODULE_HASHES compatible with module stripping
From: Thomas Weißschuh @ 2026-05-05 9:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Bouchinet, Xiu Jianfeng, Christophe Leroy
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi, Eric Biggers,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity, debian-kernel, Thomas Weißschuh
In-Reply-To: <20260505-module-hashes-v5-0-e174a5a49fce@weissschuh.net>
CONFIG_MODULE_HASHES needs to process the modules at build time in the
exact form they will be loaded at runtime. If the modules are stripped
afterwards they will not be loadable anymore.
Also evaluate INSTALL_MOD_STRIP at build time and build the hashes based
on modules stripped this way.
If users specify inconsistent values of INSTALL_MOD_STRIP between build
and installation time, an error is reported.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
.gitignore | 1 +
kernel/module/Kconfig | 5 +++++
scripts/Makefile.modfinal | 9 +++++++++
scripts/Makefile.modinst | 4 ++--
scripts/Makefile.vmlinux | 2 +-
5 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/.gitignore b/.gitignore
index 78cf799401e6..6ce10623c5a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,7 @@
*.gz
*.i
*.ko
+*.ko.stripped
*.lex.c
*.ll
*.lst
diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig
index acbbda58e7c8..48be498a4452 100644
--- a/kernel/module/Kconfig
+++ b/kernel/module/Kconfig
@@ -423,6 +423,11 @@ config MODULE_HASHES
Also see the warning in MODULE_SIG about stripping modules.
+# To validate the consistency of INSTALL_MOD_STRIP for MODULE_HASHES
+config MODULE_INSTALL_STRIP
+ string
+ default "$(INSTALL_MOD_STRIP)"
+
config MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
bool "Allow loading of modules with missing namespace imports"
help
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index 44a382689a5a..9924a7bb73c5 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -64,7 +64,16 @@ ifdef CONFIG_DEBUG_INFO_BTF_MODULES
endif
+$(call cmd,check_tracepoint)
+%.ko.stripped: %.ko $(wildcard include/config/MODULE_INSTALL_STRIP)
+ $(call cmd,install_mod)
+ $(call cmd,strip_mod)
+
+ifneq ($(CONFIG_MODULE_INSTALL_STRIP),)
+modules.order: $(modules:%.o=%.ko.stripped)
+endif
+
targets += $(modules:%.o=%.ko) $(modules:%.o=%.mod.o) .module-common.o
+targets += $(modules:%.o=%.ko.stripped)
# Update modules.order when a module is (re-)built.
# Allow using it as target dependency.
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index b95f613e23c8..fd1fb89bb0bd 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -68,8 +68,8 @@ __modinst: $(install-y)
ifdef CONFIG_MODULE_HASHES
ifeq ($(KBUILD_EXTMOD),)
-ifdef INSTALL_MOD_STRIP
-$(error CONFIG_MODULE_HASHES and INSTALL_MOD_STRIP are mutually exclusive)
+ifneq ($(INSTALL_MOD_STRIP),$(CONFIG_MODULE_INSTALL_STRIP))
+$(error Inconsistent values for INSTALL_MOD_STRIP between build and installation)
endif
endif
endif
diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux
index a0332c06bde1..a2d170241a2f 100644
--- a/scripts/Makefile.vmlinux
+++ b/scripts/Makefile.vmlinux
@@ -86,7 +86,7 @@ modules.order: vmlinux.unstripped FORCE
$(Q)$(MAKE) -f $(srctree)/Makefile modules
quiet_cmd_modules_merkle_tree = MERKLE $@
- cmd_modules_merkle_tree = $< $@ .ko
+ cmd_modules_merkle_tree = $< $@ $(if $(CONFIG_MODULE_INSTALL_STRIP),.ko.stripped,.ko)
targets += .tmp_module_hashes.c
.tmp_module_hashes.c: $(objtree)/scripts/modules-merkle-tree modules.order FORCE
--
2.54.0
^ permalink raw reply related
* [PATCH v5 11/14] module: update timestamp of modules.order after modules are built
From: Thomas Weißschuh @ 2026-05-05 9:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Bouchinet, Xiu Jianfeng, Christophe Leroy
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi, Eric Biggers,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity, debian-kernel, Thomas Weißschuh
In-Reply-To: <20260505-module-hashes-v5-0-e174a5a49fce@weissschuh.net>
Make sure that modules.order is always newer than the module .ko files.
Other rules can then use modules.order as a prerequisite and rerun if
any module is (re-)built.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
scripts/Makefile.modfinal | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index b09040ccddd2..44a382689a5a 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -66,6 +66,13 @@ endif
targets += $(modules:%.o=%.ko) $(modules:%.o=%.mod.o) .module-common.o
+# Update modules.order when a module is (re-)built.
+# Allow using it as target dependency.
+targets += modules.order
+__modfinal: modules.order
+modules.order: $(modules:%.o=%.ko)
+ @touch $@
+
# Add FORCE to the prerequisites of a target to force it to be always rebuilt.
# ---------------------------------------------------------------------------
--
2.54.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox