[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