[RFC PATCH] loadpin: allow untoggleable enforcement on filesystems which don't appear to be read-only
Randy Dunlap
rdunlap at infradead.org
Sat Oct 24 01:38:15 UTC 2026
Hi,
On 10/23/26 10:15 AM, Amelia Crate wrote:
> Some filesystems, such as composefs created from layers which are entirely
> read-only, can't be easily detected as a read-only file system. In addition to
> filesystems which are read-only without having a backing read-only block device
> I believe this is also useful for cases where immutability of the filesystem is
> enforced by the hypervisor or the host, such as 9p shares or virtiofs.
>
> It is still desirable to enforce LoadPin and disallow toggling enforcement in these cases.
> This patch gives system administrators a way to disallow toggling LoadPin enforcement even
> when the immutability of a filesystem is unclear.
>
> Signed-off-by: Amelia Crate <acrate at waldn.net>
> Assisted-by: Codex:gpt-6
> ---
> Documentation/admin-guide/LSM/LoadPin.rst | 8 +++++++-
> .../admin-guide/kernel-parameters.txt | 7 +++++++
> security/loadpin/loadpin.c | 20 ++++++++++++++++++-
> 3 files changed, 33 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/admin-guide/LSM/LoadPin.rst b/Documentation/admin-guide/LSM/LoadPin.rst
> index a90fd9dac960..f1e8825d0fe8 100644
> --- a/Documentation/admin-guide/LSM/LoadPin.rst
> +++ b/Documentation/admin-guide/LSM/LoadPin.rst
> @@ -16,10 +16,16 @@ boot ("``loadpin.enforce=0``").
>
> LoadPin starts pinning when it sees the first file loaded. If the
> block device backing the filesystem is not read-only, a sysctl is
> -created to toggle pinning: ``/proc/sys/kernel/loadpin/enabled``. (Having
> +created to toggle pinning: ``/proc/sys/kernel/loadpin/enforce``. (Having
Ah. The sysctl documentation had the incorrect name there.
Would it be possible to put all of these command line parameters / sysctls
in the same place instead of having one of them in LoadPin.rst and
another one in kernel-parameters.txt ?
Thanks.
> a mutable filesystem means pinning is mutable too, but having the
> sysctl allows for easy testing on systems with a mutable filesystem.)
>
> +Some filesystems may appear to be mutable, but are in fact read-only.
> +In this case, ``loadpin.force_enforce=1`` can be set to require enforcement
> +of LoadPin on all filesystems. When LoadPin is enabled,
> +``/proc/sys/kernel/loadpin/force_enforce`` reports the state of this option.
> +This option is independent of whether LoadPin is enabled.
> +
> It's also possible to exclude specific file types from LoadPin using kernel
> command line option "``loadpin.exclude``". By default, all files are
> included, but they can be excluded using kernel command line option such
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 1b2ae71def21..df8c145cc63d 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -3540,6 +3540,13 @@ Kernel parameters
> Enable Live Update Orchestrator (LUO).
> Default: off.
>
> + loadpin.force_enforce= [SECURITY]
> + Format: <bool>
> + Force LoadPin enforcement until reboot, even when the
> + pinned filesystem is not backed by a read-only block
> + device. Requires LoadPin to be enabled in the active LSM list.
> + Default: off.
> +
> lockd.nlm_grace_period=P [NFS] Assign grace period.
> Format: <integer>
>
> diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
> index f71861f98e1a..b260ad299a2c 100644
> --- a/security/loadpin/loadpin.c
> +++ b/security/loadpin/loadpin.c
> @@ -45,6 +45,7 @@ static void report_load(const char *origin, struct file *file, char *operation)
> }
>
> static int enforce = IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE);
> +static bool force_enforce __ro_after_init;
> static char *exclude_read_files[READING_MAX_ID];
> static int ignore_read_file_id[READING_MAX_ID] __ro_after_init;
> static struct super_block *pinned_root;
> @@ -60,11 +61,19 @@ static bool loadpin_root_writable;
> static int proc_handler_loadpin(const struct ctl_table *table, int dir,
> void *buffer, size_t *lenp, loff_t *ppos)
> {
> - if (!loadpin_root_writable && SYSCTL_USER_TO_KERN(dir))
> + if ((force_enforce || !loadpin_root_writable) && SYSCTL_USER_TO_KERN(dir))
> return -EINVAL;
> return proc_dointvec_minmax(table, dir, buffer, lenp, ppos);
> }
>
> +static int proc_handler_force_enforce(const struct ctl_table *table, int dir,
> + void *buffer, size_t *lenp, loff_t *ppos)
> +{
> + if (SYSCTL_USER_TO_KERN(dir))
> + return -EPERM;
> + return proc_dobool(table, dir, buffer, lenp, ppos);
> +}
> +
> static const struct ctl_table loadpin_sysctl_table[] = {
> {
> .procname = "enforce",
> @@ -75,6 +84,13 @@ static const struct ctl_table loadpin_sysctl_table[] = {
> .extra1 = SYSCTL_ZERO,
> .extra2 = SYSCTL_ONE,
> },
> + {
> + .procname = "force_enforce",
> + .data = &force_enforce,
> + .maxlen = sizeof(force_enforce),
> + .mode = 0444,
> + .proc_handler = proc_handler_force_enforce,
> + },
> };
> #endif
>
> @@ -436,6 +452,8 @@ DEFINE_LSM(loadpin) = {
> };
>
> /* Should not be mutable after boot, so not listed in sysfs (perm == 0). */
> +module_param(force_enforce, bool, 0);
> +MODULE_PARM_DESC(force_enforce, "Always enforce module/firmware pinning");
> module_param(enforce, int, 0);
> MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning");
> module_param_array_named(exclude, exclude_read_files, charp, NULL, 0);
--
~Randy
More information about the Linux-security-module-archive
mailing list