mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Amelia Crate <acrate@waldn.net>
To: Kees Cook <kees@kernel.org>, linux-security-module@vger.kernel.org
Cc: Paul Moore <paul@paul-moore.com>,
	James Morris <jmorris@namei.org>,
	"Serge E . Hallyn" <serge@hallyn.com>,
	Jonathan Corbet <corbet@lwn.net>,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Amelia Crate <acrate@waldn.net>
Subject: [RFC PATCH v2] loadpin: allow untoggleable enforcement on filesystems which don't appear to be read-only
Date: Thu, 29 Oct 2026 10:13:45 -0500	[thread overview]
Message-ID: <20261029151432.27642-1-acrate@waldn.net> (raw)
In-Reply-To: <20261023171508.3460300-1-acrate@waldn.net>

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@waldn.net>
Assisted-by: Codex:gpt-6
---
Changes in v2:
- Move new kernel parameters to LoadPin.rst
  This is where the existing kernel parameters already were, if its preferred to move everything
  to kernel-parameters.txt I can do that instead.
- Make loadpin.force_enforce select loadpin.enforce
  These are the semantics suggested by Sashiko, I considered this originally but wasn't sure which design
  would be preferred.

v1: https://lore.kernel.org/linux-security-module/20261023171508.3460300-1-acrate@waldn.net/

 Documentation/admin-guide/LSM/LoadPin.rst |  8 +++++++-
 security/loadpin/loadpin.c                | 22 +++++++++++++++++++++-
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/Documentation/admin-guide/LSM/LoadPin.rst b/Documentation/admin-guide/LSM/LoadPin.rst
index a90fd9dac960..3f6968063559 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
 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. This is disabled by default. When LoadPin is enabled,
+``/proc/sys/kernel/loadpin/force_enforce`` reports the state of this option.
+This option selects ``loadpin.enforce=1``.
+
 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/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
index f71861f98e1a..0014f78799b2 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
 
@@ -253,6 +269,8 @@ static void __init parse_exclude(void)
 
 static int __init loadpin_init(void)
 {
+	if (force_enforce)
+		enforce = 1;
 	pr_info("ready to pin (currently %senforcing)\n",
 		enforce ? "" : "not ");
 	parse_exclude();
@@ -436,6 +454,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);
-- 
2.54.0


      parent reply	other threads:[~2026-10-29 15:14 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-23 17:15 [RFC PATCH] " Amelia Crate
2026-10-24  1:38 ` Randy Dunlap
2026-10-29 15:13 ` Amelia Crate [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261029151432.27642-1-acrate@waldn.net \
    --to=acrate@waldn.net \
    --cc=corbet@lwn.net \
    --cc=jmorris@namei.org \
    --cc=kees@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=paul@paul-moore.com \
    --cc=serge@hallyn.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®