* [PATCH] killswitch: add per-function short-circuit mitigation primitive
@ 2026-05-07 7:05 Sasha Levin
2026-05-07 10:47 ` Greg KH
` (4 more replies)
0 siblings, 5 replies; 48+ messages in thread
From: Sasha Levin @ 2026-05-07 7:05 UTC (permalink / raw)
To: corbet, akpm
Cc: skhan, linux-doc, linux-kernel, linux-kselftest, gregkh,
Sasha Levin
When a (security) issue goes public, fleets stay exposed until a patched kernel
is built, distributed, and rebooted into.
For many such issues the simplest mitigation is to stop calling the buggy
function. Killswitch provides that. An admin writes:
echo "engage af_alg_sendmsg -1" \
> /sys/kernel/security/killswitch/control
After this, af_alg_sendmsg() returns -EPERM on every call without
running its body. The mitigation takes effect immediately, and is dropped on
the next reboot.
A lot of recent kernel issues sit in code paths most installs only have enabled
to support a relative minority of users: AF_ALG, ksmbd, nf_tables, vsock, ax25,
and friends.
For most users, the cost of "this socket family stops working for the day" is
much smaller than the cost of running a known vulnerable kernel until the fix
land.
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
Documentation/admin-guide/index.rst | 1 +
Documentation/admin-guide/killswitch.rst | 159 ++++
Documentation/admin-guide/tainted-kernels.rst | 8 +
MAINTAINERS | 11 +
include/linux/killswitch.h | 19 +
include/linux/panic.h | 3 +-
init/Kconfig | 2 +
kernel/Kconfig.killswitch | 31 +
kernel/Makefile | 1 +
kernel/killswitch.c | 798 ++++++++++++++++++
kernel/panic.c | 1 +
lib/Kconfig.debug | 13 +
lib/Makefile | 1 +
lib/test_killswitch.c | 85 ++
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/killswitch/.gitignore | 1 +
tools/testing/selftests/killswitch/Makefile | 8 +
.../selftests/killswitch/cve_31431_test.c | 162 ++++
.../selftests/killswitch/killswitch_test.sh | 147 ++++
19 files changed, 1451 insertions(+), 1 deletion(-)
create mode 100644 Documentation/admin-guide/killswitch.rst
create mode 100644 include/linux/killswitch.h
create mode 100644 kernel/Kconfig.killswitch
create mode 100644 kernel/killswitch.c
create mode 100644 lib/test_killswitch.c
create mode 100644 tools/testing/selftests/killswitch/.gitignore
create mode 100644 tools/testing/selftests/killswitch/Makefile
create mode 100644 tools/testing/selftests/killswitch/cve_31431_test.c
create mode 100755 tools/testing/selftests/killswitch/killswitch_test.sh
diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst
index cd28dfe91b060..ca37dd70f108d 100644
--- a/Documentation/admin-guide/index.rst
+++ b/Documentation/admin-guide/index.rst
@@ -70,6 +70,7 @@ problems and bugs in particular.
bug-hunting
bug-bisect
tainted-kernels
+ killswitch
ramoops
dynamic-debug-howto
init
diff --git a/Documentation/admin-guide/killswitch.rst b/Documentation/admin-guide/killswitch.rst
new file mode 100644
index 0000000000000..cb967ec348fdc
--- /dev/null
+++ b/Documentation/admin-guide/killswitch.rst
@@ -0,0 +1,159 @@
+.. SPDX-License-Identifier: GPL-2.0
+..
+.. Copyright (C) 2026 Sasha Levin <sashal@kernel.org>
+
+============
+Killswitch
+============
+
+Killswitch lets a privileged operator make a chosen kernel function
+return a fixed value without executing its body, as a temporary
+mitigation for a security bug while a real fix is being prepared.
+
+The function returns the operator-supplied value and nothing else
+runs in its place. There is no allowlist, no return-type check; if
+the kprobe layer accepts the symbol, killswitch engages it. Once
+engaged, the change is in effect on every CPU until ``disengage`` is
+written or the system reboots.
+
+Configuration
+=============
+
+``CONFIG_KILLSWITCH``
+ Enables the feature. Depends on ``SECURITYFS``, ``KPROBES`` (with
+ ftrace support), and ``FUNCTION_ERROR_INJECTION``.
+
+The interface
+=============
+
+::
+
+ /sys/kernel/security/killswitch/
+ engaged RO currently-engaged functions
+ control WO command sink
+ taint RO 0 or 1
+ fn/<name>/ per-function directory, created on engage
+ retval RW return value
+ hits RO per-cpu summed call count
+
+Three commands are accepted by ``control``::
+
+ engage <symbol> <retval>
+ disengage <symbol>
+ disengage_all
+
+Each engage and disengage emits a single ``KERN_WARNING`` line to
+dmesg with the symbol, retval, hit count (on disengage), and the
+operator's identity (uid/auid/sessionid/comm, or ``source=cmdline``).
+
+Engagement is rejected when:
+
+* the symbol is unknown, in a non-traceable section, on the kprobe
+ blacklist, or otherwise refused by ``register_kprobe`` (the error
+ from the kprobe layer is logged and returned to userspace);
+* the symbol is already engaged (``-EBUSY``);
+* the operator does not hold ``CAP_SYS_ADMIN``.
+
+Whatever value the operator writes is what the function returns.
+Writing the wrong type or wrong value lands in the caller as-is.
+
+Boot parameter
+==============
+
+``killswitch=fn1=<val>,fn2=<val>,...``
+
+Parsed early; engagements are applied at the end of kernel init
+once the kprobe subsystem is up. Parse failures emit a warning and
+skip the offending entry; they never panic.
+
+Useful for fleet rollout: when an issue drops, ship the mitigation
+in the bootloader / PXE config and roll the fleet through reboots
+while the real fix is being prepared.
+
+Tainting
+========
+
+The first successful engagement (runtime or boot-time) sets
+``TAINT_KILLSWITCH`` (bit 20, char ``H``). The taint persists across
+``disengage`` until reboot, so an oops on a killswitch-modified
+kernel is identifiable from the banner: ``Tainted: ... H`` tells a
+maintainer to consult ``engaged`` before further triage.
+
+Module unload
+=============
+
+If a module containing an engaged target is unloaded, killswitch
+auto-disengages the entry and emits a ``KERN_WARNING`` so the loss
+of mitigation is visible. Reloading the module does not silently
+re-arm the killswitch; the operator re-engages explicitly.
+
+Choosing the right target
+=========================
+
+A function that *looks* skippable may be relied on by callers for a
+side effect (a lock the caller releases, a refcount the caller
+drops, a scatterlist the caller consumes). The rule of thumb:
+
+ Pick the **highest-level** entry point that contains the bug.
+
+That gives callers no chance to dereference half-initialised state
+from a function whose body was skipped. Two illustrative examples
+from ``crypto/af_alg.c``:
+
+Anti-pattern: ``af_alg_count_tsgl``
+-----------------------------------
+
+``af_alg_count_tsgl()`` returns ``unsigned int`` (the number of TX
+SG entries). Engaging it with retval ``0`` causes the caller in
+``algif_aead.c`` to allocate a 1-entry scatterlist (its
+``if (!entries) entries = 1`` guard) and then walk the *real* TX
+SGL into that undersized destination via ``af_alg_pull_tsgl``,
+producing out-of-bounds writes. **Killswitching here introduces a
+worse bug than the one being mitigated.**
+
+Anti-pattern: ``af_alg_pull_tsgl``
+----------------------------------
+
+``af_alg_pull_tsgl()`` returns ``void``, so any retval is accepted.
+But its caller depends on the per-request SGL being filled in.
+Skipping the body leaves the per-request SGL with NULL pages; the
+next-stage ``memcpy_sglist`` dereferences them and the kernel
+oopses.
+
+Correct pattern: ``af_alg_sendmsg``
+-----------------------------------
+
+``af_alg_sendmsg()`` is the highest-level entry into the AF_ALG
+send path. Engaging it with retval ``-EPERM`` causes every send
+attempt to return -EPERM to userspace; no caller ever sees
+half-initialised state, and any AF_ALG-reachable bug downstream of
+``sendmsg`` is unreachable until the killswitch is disengaged.
+
+The canonical pattern: pick a syscall-handler-shaped function whose
+return value already encodes "this operation didn't happen", and
+let userspace handle the error as it would any other failed
+syscall.
+
+Safety notes
+============
+
+* In-flight calls during ``write()`` to ``control`` may run either
+ the original body or the override. The override is ``return X``,
+ which has no preconditions to violate.
+* SMP visibility comes from ``text_poke_bp()``. ``write()`` to
+ ``control`` returns only after every CPU sees the new path.
+* The ftrace ops unregister waits for in-flight pre-handlers, so
+ freeing the engagement attribute on disengage is safe.
+* Inline functions, freed ``__init`` symbols, and anything compiled
+ away cannot be killswitched. ``register_kprobe`` rejects them
+ with whatever error the kprobe layer chooses.
+
+Diagnostics
+===========
+
+Per-call hits are aggregated in a per-cpu counter readable at
+``/sys/kernel/security/killswitch/fn/<name>/hits``. Per-hit logging
+is not provided to avoid log storms on hot paths.
+
+A ``KILLSWITCH`` entry appears in the kernel taint vector once any
+engagement succeeds (also visible as ``H`` in the oops banner).
diff --git a/Documentation/admin-guide/tainted-kernels.rst b/Documentation/admin-guide/tainted-kernels.rst
index 9ead927a37c0f..71a6e3364eddc 100644
--- a/Documentation/admin-guide/tainted-kernels.rst
+++ b/Documentation/admin-guide/tainted-kernels.rst
@@ -102,6 +102,7 @@ Bit Log Number Reason that got the kernel tainted
17 _/T 131072 kernel was built with the struct randomization plugin
18 _/N 262144 an in-kernel test has been run
19 _/J 524288 userspace used a mutating debug operation in fwctl
+ 20 _/H 1048576 killswitch override engaged (function short-circuited)
=== === ====== ========================================================
Note: The character ``_`` is representing a blank in this table to make reading
@@ -189,3 +190,10 @@ More detailed explanation for tainting
19) ``J`` if userspace opened /dev/fwctl/* and performed a FWTCL_RPC_DEBUG_WRITE
to use the devices debugging features. Device debugging features could
cause the device to malfunction in undefined ways.
+
+ 20) ``H`` if the killswitch primitive (see
+ Documentation/admin-guide/killswitch.rst) has been engaged on at least
+ one function. The kernel is no longer running its source: at least one
+ function has been short-circuited to return a fixed value. The taint
+ persists across ``disengage`` until the next reboot — once the running
+ image has been modified, oops triage must reflect that.
diff --git a/MAINTAINERS b/MAINTAINERS
index 882214b0e7db5..61851ef1d9b1c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14347,6 +14347,17 @@ F: lib/Kconfig.kmsan
F: mm/kmsan/
F: scripts/Makefile.kmsan
+KILLSWITCH (function short-circuit mitigation)
+M: Sasha Levin <sashal@kernel.org>
+L: linux-kernel@vger.kernel.org
+S: Maintained
+F: Documentation/admin-guide/killswitch.rst
+F: include/linux/killswitch.h
+F: kernel/Kconfig.killswitch
+F: kernel/killswitch.c
+F: lib/test_killswitch.c
+F: tools/testing/selftests/killswitch/
+
KPROBES
M: Naveen N Rao <naveen@kernel.org>
M: "David S. Miller" <davem@davemloft.net>
diff --git a/include/linux/killswitch.h b/include/linux/killswitch.h
new file mode 100644
index 0000000000000..c18515bec09f1
--- /dev/null
+++ b/include/linux/killswitch.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2026 Sasha Levin <sashal@kernel.org>
+ */
+#ifndef _LINUX_KILLSWITCH_H
+#define _LINUX_KILLSWITCH_H
+
+#ifdef CONFIG_KILLSWITCH
+int killswitch_engage(const char *symbol, long retval);
+int killswitch_disengage(const char *symbol);
+bool killswitch_is_engaged(const char *symbol);
+#else
+static inline int killswitch_engage(const char *symbol, long retval)
+{ return -ENOSYS; }
+static inline int killswitch_disengage(const char *symbol) { return -ENOSYS; }
+static inline bool killswitch_is_engaged(const char *symbol) { return false; }
+#endif
+
+#endif /* _LINUX_KILLSWITCH_H */
diff --git a/include/linux/panic.h b/include/linux/panic.h
index f1dd417e54b29..6699261a61f13 100644
--- a/include/linux/panic.h
+++ b/include/linux/panic.h
@@ -88,7 +88,8 @@ static inline void set_arch_panic_timeout(int timeout, int arch_default_timeout)
#define TAINT_RANDSTRUCT 17
#define TAINT_TEST 18
#define TAINT_FWCTL 19
-#define TAINT_FLAGS_COUNT 20
+#define TAINT_KILLSWITCH 20
+#define TAINT_FLAGS_COUNT 21
#define TAINT_FLAGS_MAX ((1UL << TAINT_FLAGS_COUNT) - 1)
struct taint_flag {
diff --git a/init/Kconfig b/init/Kconfig
index 2937c4d308aec..5368dd4b5c65b 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2278,6 +2278,8 @@ config ASN1
source "kernel/Kconfig.locks"
+source "kernel/Kconfig.killswitch"
+
config ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
bool
diff --git a/kernel/Kconfig.killswitch b/kernel/Kconfig.killswitch
new file mode 100644
index 0000000000000..067d41087e8da
--- /dev/null
+++ b/kernel/Kconfig.killswitch
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Killswitch: per-function short-circuit mitigation primitive.
+#
+# Copyright (C) 2026 Sasha Levin <sashal@kernel.org>
+#
+
+config KILLSWITCH
+ bool "Killswitch: short-circuit a kernel function as a CVE mitigation"
+ depends on SECURITYFS
+ depends on KPROBES && HAVE_KPROBES_ON_FTRACE
+ depends on HAVE_FUNCTION_ERROR_INJECTION
+ select FUNCTION_ERROR_INJECTION
+ help
+ Provide an admin-facing mechanism to make a chosen kernel function
+ return a fixed value without executing its body, as a temporary
+ mitigation for a security bug before a real fix is available.
+
+ Operators write "engage <symbol> <retval> [reason]" to
+ /sys/kernel/security/killswitch/control. The function entry is
+ redirected via a kprobe whose pre-handler sets the chosen return
+ value and short-circuits the call. There is no allowlist,
+ denylist, or return-type validation: if the kprobe layer accepts
+ the symbol the engagement proceeds, otherwise its error is
+ returned to userspace.
+
+ This is *not* livepatch: there is no replacement implementation,
+ the function simply returns the chosen value. Engaging a killswitch
+ taints the kernel (TAINT_KILLSWITCH, 'H'). Requires CAP_SYS_ADMIN.
+
+ If unsure, say N.
diff --git a/kernel/Makefile b/kernel/Makefile
index 6785982013dce..b3e408d9f275e 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -100,6 +100,7 @@ obj-$(CONFIG_GCOV_KERNEL) += gcov/
obj-$(CONFIG_KCOV) += kcov.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_FAIL_FUNCTION) += fail_function.o
+obj-$(CONFIG_KILLSWITCH) += killswitch.o
obj-$(CONFIG_KGDB) += debug/
obj-$(CONFIG_DETECT_HUNG_TASK) += hung_task.o
obj-$(CONFIG_LOCKUP_DETECTOR) += watchdog.o
diff --git a/kernel/killswitch.c b/kernel/killswitch.c
new file mode 100644
index 0000000000000..6b3e2982e1c5c
--- /dev/null
+++ b/kernel/killswitch.c
@@ -0,0 +1,798 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Per-function short-circuit mitigation.
+ *
+ * Copyright (C) 2026 Sasha Levin <sashal@kernel.org>
+ *
+ * Engaging a killswitch installs a kprobe at the function's entry
+ * whose pre-handler sets the return register and skips the body via
+ * override_function_with_return(). Operator interface lives at
+ * /sys/kernel/security/killswitch/.
+ */
+
+#include <linux/audit.h>
+#include <linux/capability.h>
+#include <linux/cred.h>
+#include <linux/ctype.h>
+#include <linux/error-injection.h>
+#include <linux/init.h>
+#include <linux/killswitch.h>
+#include <linux/kprobes.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/notifier.h>
+#include <linux/panic.h>
+#include <linux/percpu.h>
+#include <linux/printk.h>
+#include <linux/refcount.h>
+#include <linux/sched.h>
+#include <linux/security.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+#include <linux/uidgid.h>
+
+struct ks_attr {
+ struct list_head list;
+ struct kprobe kp;
+ atomic_long_t retval;
+ /* false once disengaged; per-fn file ops then return -EIDRM. */
+ bool engaged;
+ unsigned long __percpu *hits;
+ struct dentry *dir;
+ /* engaged_list holds one ref; each open per-fn fd holds one. */
+ refcount_t refcnt;
+};
+
+static DEFINE_MUTEX(ks_lock);
+static LIST_HEAD(ks_engaged_list);
+static struct dentry *ks_root_dir;
+static struct dentry *ks_fn_dir; /* parent for per-fn directories */
+
+/* ------------------------------------------------------------------ *
+ * Pre-handler: the actual override *
+ * ------------------------------------------------------------------ */
+
+static int ks_kprobe_pre_handler(struct kprobe *kp, struct pt_regs *regs)
+{
+ struct ks_attr *attr = container_of(kp, struct ks_attr, kp);
+
+ this_cpu_inc(*attr->hits);
+ regs_set_return_value(regs, (unsigned long)atomic_long_read(&attr->retval));
+ override_function_with_return(regs);
+ return 1;
+}
+NOKPROBE_SYMBOL(ks_kprobe_pre_handler);
+
+/* Defined non-NULL so the kprobe layer keeps the IPMODIFY ops. */
+static void ks_kprobe_post_handler(struct kprobe *kp, struct pt_regs *regs,
+ unsigned long flags)
+{
+}
+
+/* ------------------------------------------------------------------ *
+ * Attribute lifecycle *
+ * ------------------------------------------------------------------ */
+
+static struct ks_attr *ks_attr_lookup(const char *symbol)
+{
+ struct ks_attr *attr;
+
+ list_for_each_entry(attr, &ks_engaged_list, list)
+ if (!strcmp(attr->kp.symbol_name, symbol))
+ return attr;
+ return NULL;
+}
+
+static unsigned long ks_attr_hits(const struct ks_attr *attr)
+{
+ unsigned long total = 0;
+ int cpu;
+
+ for_each_possible_cpu(cpu)
+ total += *per_cpu_ptr(attr->hits, cpu);
+ return total;
+}
+
+static void ks_attr_destroy(struct ks_attr *attr)
+{
+ if (!attr)
+ return;
+ free_percpu(attr->hits);
+ kfree(attr->kp.symbol_name);
+ kfree(attr);
+}
+
+static void ks_attr_get(struct ks_attr *attr)
+{
+ refcount_inc(&attr->refcnt);
+}
+
+static void ks_attr_put(struct ks_attr *attr)
+{
+ if (attr && refcount_dec_and_test(&attr->refcnt))
+ ks_attr_destroy(attr);
+}
+
+static struct ks_attr *ks_attr_alloc(const char *symbol)
+{
+ struct ks_attr *attr;
+
+ attr = kzalloc(sizeof(*attr), GFP_KERNEL);
+ if (!attr)
+ return NULL;
+
+ attr->kp.symbol_name = kstrdup(symbol, GFP_KERNEL);
+ if (!attr->kp.symbol_name)
+ goto err;
+
+ attr->hits = alloc_percpu(unsigned long);
+ if (!attr->hits)
+ goto err;
+
+ attr->kp.pre_handler = ks_kprobe_pre_handler;
+ attr->kp.post_handler = ks_kprobe_post_handler;
+ INIT_LIST_HEAD(&attr->list);
+ refcount_set(&attr->refcnt, 1);
+ return attr;
+
+err:
+ ks_attr_destroy(attr);
+ return NULL;
+}
+
+/* ------------------------------------------------------------------ *
+ * Securityfs: per-fn attribute files *
+ * ------------------------------------------------------------------ */
+
+/*
+ * Look up by symbol name (the parent dentry's basename) under
+ * ks_lock and confirm attr->dir is the file's parent dentry. This
+ * binds the fd to the engagement it was opened against and avoids
+ * dereferencing inode->i_private, which a racing disengage may have
+ * freed. d_parent is stable for the open's lifetime via the file's
+ * dentry reference.
+ */
+static int ks_attr_open(struct inode *inode, struct file *file)
+{
+ struct dentry *parent = file->f_path.dentry->d_parent;
+ const char *name = parent->d_name.name;
+ struct ks_attr *attr;
+
+ mutex_lock(&ks_lock);
+ attr = ks_attr_lookup(name);
+ if (attr && attr->dir == parent)
+ ks_attr_get(attr);
+ else
+ attr = NULL;
+ mutex_unlock(&ks_lock);
+ if (!attr)
+ return -ENOENT;
+ file->private_data = attr;
+ return 0;
+}
+
+static int ks_attr_release(struct inode *inode, struct file *file)
+{
+ ks_attr_put(file->private_data);
+ file->private_data = NULL;
+ return 0;
+}
+
+/* Caller must hold ks_lock. */
+static int ks_attr_check_live(const struct ks_attr *attr)
+{
+ return attr->engaged ? 0 : -EIDRM;
+}
+
+static ssize_t ks_retval_read(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct ks_attr *attr = file->private_data;
+ char buf[32];
+ long val;
+ int ret, len;
+
+ mutex_lock(&ks_lock);
+ ret = ks_attr_check_live(attr);
+ val = atomic_long_read(&attr->retval);
+ mutex_unlock(&ks_lock);
+ if (ret)
+ return ret;
+ len = scnprintf(buf, sizeof(buf), "%ld\n", val);
+ return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static ssize_t ks_retval_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct ks_attr *attr = file->private_data;
+ char buf[32];
+ long val;
+ int ret;
+
+ if (count >= sizeof(buf))
+ return -EINVAL;
+ if (copy_from_user(buf, ubuf, count))
+ return -EFAULT;
+ buf[count] = '\0';
+ strim(buf);
+
+ ret = kstrtol(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ mutex_lock(&ks_lock);
+ ret = ks_attr_check_live(attr);
+ if (!ret)
+ atomic_long_set(&attr->retval, val);
+ mutex_unlock(&ks_lock);
+
+ return ret ? ret : count;
+}
+
+static const struct file_operations ks_retval_fops = {
+ .open = ks_attr_open,
+ .release = ks_attr_release,
+ .read = ks_retval_read,
+ .write = ks_retval_write,
+ .llseek = default_llseek,
+};
+
+static ssize_t ks_hits_read(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct ks_attr *attr = file->private_data;
+ char buf[32];
+ unsigned long hits;
+ int ret, len;
+
+ mutex_lock(&ks_lock);
+ ret = ks_attr_check_live(attr);
+ hits = ks_attr_hits(attr);
+ mutex_unlock(&ks_lock);
+ if (ret)
+ return ret;
+ len = scnprintf(buf, sizeof(buf), "%lu\n", hits);
+ return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static const struct file_operations ks_hits_fops = {
+ .open = ks_attr_open,
+ .release = ks_attr_release,
+ .read = ks_hits_read,
+ .llseek = default_llseek,
+};
+
+static int ks_create_attr_dir(struct ks_attr *attr)
+{
+ struct dentry *d;
+
+ attr->dir = securityfs_create_dir(attr->kp.symbol_name, ks_fn_dir);
+ if (IS_ERR(attr->dir))
+ return PTR_ERR(attr->dir);
+
+ /* ks_attr_open looks the attr up by name; i_private is unused. */
+ d = securityfs_create_file("retval", 0600, attr->dir,
+ NULL, &ks_retval_fops);
+ if (IS_ERR(d))
+ goto err;
+ d = securityfs_create_file("hits", 0400, attr->dir,
+ NULL, &ks_hits_fops);
+ if (IS_ERR(d))
+ goto err;
+ return 0;
+err:
+ securityfs_remove(attr->dir);
+ attr->dir = NULL;
+ return PTR_ERR(d);
+}
+
+/* ------------------------------------------------------------------ *
+ * Engage / disengage *
+ * ------------------------------------------------------------------ */
+
+static int __ks_engage(const char *symbol, long retval, bool from_cmdline)
+{
+ struct ks_attr *attr;
+ int ret;
+
+ if (!symbol || !*symbol)
+ return -EINVAL;
+
+ mutex_lock(&ks_lock);
+
+ if (ks_attr_lookup(symbol)) {
+ ret = -EBUSY;
+ goto out_unlock;
+ }
+
+ attr = ks_attr_alloc(symbol);
+ if (!attr) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
+
+ atomic_long_set(&attr->retval, retval);
+
+ ret = register_kprobe(&attr->kp);
+ if (ret) {
+ pr_warn("killswitch: register_kprobe(%s) failed: %d\n",
+ symbol, ret);
+ ks_attr_put(attr);
+ goto out_unlock;
+ }
+
+ ret = ks_create_attr_dir(attr);
+ if (ret) {
+ unregister_kprobe(&attr->kp);
+ ks_attr_put(attr);
+ goto out_unlock;
+ }
+
+ list_add_tail(&attr->list, &ks_engaged_list);
+ attr->engaged = true;
+ add_taint(TAINT_KILLSWITCH, LOCKDEP_STILL_OK);
+
+ if (from_cmdline) {
+ pr_warn("killswitch: engage %s=%ld source=cmdline\n",
+ symbol, retval);
+ } else {
+ pr_warn("killswitch: engage %s=%ld uid=%u auid=%u ses=%u comm=%s\n",
+ symbol, retval,
+ from_kuid(&init_user_ns, current_uid()),
+ from_kuid(&init_user_ns, audit_get_loginuid(current)),
+ audit_get_sessionid(current),
+ current->comm);
+ }
+ ret = 0;
+
+out_unlock:
+ mutex_unlock(&ks_lock);
+ return ret;
+}
+
+int killswitch_engage(const char *symbol, long retval)
+{
+ return __ks_engage(symbol, retval, false);
+}
+
+static int __ks_disengage(const char *symbol)
+{
+ struct ks_attr *attr;
+ unsigned long hits;
+ int ret = 0;
+
+ mutex_lock(&ks_lock);
+ attr = ks_attr_lookup(symbol);
+ if (!attr) {
+ ret = -ENOENT;
+ goto out_unlock;
+ }
+
+ unregister_kprobe(&attr->kp);
+ attr->engaged = false;
+ list_del(&attr->list);
+ hits = ks_attr_hits(attr);
+ securityfs_remove(attr->dir);
+
+ pr_warn("killswitch: disengage %s hits=%lu uid=%u auid=%u ses=%u comm=%s\n",
+ symbol, hits,
+ from_kuid(&init_user_ns, current_uid()),
+ from_kuid(&init_user_ns, audit_get_loginuid(current)),
+ audit_get_sessionid(current),
+ current->comm);
+
+ /* unregister_kprobe() already waited out in-flight pre-handlers. */
+ ks_attr_put(attr);
+
+out_unlock:
+ mutex_unlock(&ks_lock);
+ return ret;
+}
+
+int killswitch_disengage(const char *symbol)
+{
+ return __ks_disengage(symbol);
+}
+
+bool killswitch_is_engaged(const char *symbol)
+{
+ bool engaged;
+
+ mutex_lock(&ks_lock);
+ engaged = ks_attr_lookup(symbol) != NULL;
+ mutex_unlock(&ks_lock);
+ return engaged;
+}
+
+static void ks_disengage_all_locked(void)
+{
+ struct ks_attr *attr, *n;
+
+ list_for_each_entry_safe(attr, n, &ks_engaged_list, list) {
+ unregister_kprobe(&attr->kp);
+ attr->engaged = false;
+ list_del(&attr->list);
+ securityfs_remove(attr->dir);
+ pr_warn("killswitch: disengage %s hits=%lu (disengage_all)\n",
+ attr->kp.symbol_name, ks_attr_hits(attr));
+ ks_attr_put(attr);
+ }
+}
+
+/* ------------------------------------------------------------------ *
+ * Module unload: drop engagements on functions in the going module *
+ * ------------------------------------------------------------------ */
+
+static int ks_module_notify(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct module *mod = data;
+ struct ks_attr *attr, *n;
+
+ if (action != MODULE_STATE_GOING)
+ return NOTIFY_DONE;
+
+ mutex_lock(&ks_lock);
+ list_for_each_entry_safe(attr, n, &ks_engaged_list, list) {
+ if (!attr->kp.addr ||
+ __module_address((unsigned long)attr->kp.addr) != mod)
+ continue;
+
+ pr_warn("killswitch: %s mitigation lost: module %s unloading; re-engage after reload if still needed\n",
+ attr->kp.symbol_name, mod->name);
+ unregister_kprobe(&attr->kp);
+ attr->engaged = false;
+ list_del(&attr->list);
+ securityfs_remove(attr->dir);
+ ks_attr_put(attr);
+ }
+ mutex_unlock(&ks_lock);
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ks_module_nb = {
+ .notifier_call = ks_module_notify,
+};
+
+/* ------------------------------------------------------------------ *
+ * Top-level securityfs files: control / engaged / taint *
+ * ------------------------------------------------------------------ */
+
+static int ks_engaged_show(struct seq_file *m, void *v)
+{
+ struct ks_attr *attr;
+
+ mutex_lock(&ks_lock);
+ list_for_each_entry(attr, &ks_engaged_list, list) {
+ seq_printf(m, "%s retval=%ld hits=%lu\n",
+ attr->kp.symbol_name,
+ atomic_long_read(&attr->retval),
+ ks_attr_hits(attr));
+ }
+ mutex_unlock(&ks_lock);
+ return 0;
+}
+
+static int ks_engaged_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ks_engaged_show, NULL);
+}
+
+static const struct file_operations ks_engaged_fops = {
+ .open = ks_engaged_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static ssize_t ks_taint_read(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[4];
+ int len;
+
+ len = scnprintf(buf, sizeof(buf), "%d\n",
+ test_taint(TAINT_KILLSWITCH) ? 1 : 0);
+ return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static const struct file_operations ks_taint_fops = {
+ .open = simple_open,
+ .read = ks_taint_read,
+ .llseek = default_llseek,
+};
+
+/*
+ * control: parse one of:
+ * engage <symbol> <retval>
+ * disengage <symbol>
+ * disengage_all
+ */
+static ssize_t ks_control_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char *buf, *cur, *verb, *sym, *retstr;
+ long retval = 0;
+ int ret;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (count == 0 || count > 4096)
+ return -EINVAL;
+
+ buf = memdup_user_nul(ubuf, count);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
+ cur = strim(buf);
+ verb = strsep(&cur, " \t\n");
+ if (!verb || !*verb) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!strcmp(verb, "disengage_all")) {
+ mutex_lock(&ks_lock);
+ ks_disengage_all_locked();
+ mutex_unlock(&ks_lock);
+ ret = count;
+ goto out;
+ }
+
+ sym = strsep(&cur, " \t\n");
+ if (!sym || !*sym) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!strcmp(verb, "disengage")) {
+ ret = __ks_disengage(sym);
+ ret = ret ? ret : count;
+ goto out;
+ }
+
+ if (strcmp(verb, "engage")) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ retstr = strsep(&cur, " \t\n");
+ if (!retstr || !*retstr) {
+ ret = -EINVAL;
+ goto out;
+ }
+ if (kstrtol(retstr, 0, &retval)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = killswitch_engage(sym, retval);
+ if (!ret)
+ ret = count;
+
+out:
+ kfree(buf);
+ return ret;
+}
+
+static const struct file_operations ks_control_fops = {
+ .open = simple_open,
+ .write = ks_control_write,
+ .llseek = noop_llseek,
+};
+
+/* ------------------------------------------------------------------ *
+ * Boot parameter: *
+ * killswitch=fn1=-1:reason,fn2=0,fn3=void *
+ * ------------------------------------------------------------------ */
+
+#define KS_BOOT_BUF 1024
+static char ks_boot_buf[KS_BOOT_BUF] __initdata;
+static bool ks_boot_present __initdata;
+
+static int __init ks_boot_setup(char *str)
+{
+ if (!str)
+ return 0;
+ strscpy(ks_boot_buf, str, sizeof(ks_boot_buf));
+ ks_boot_present = true;
+ return 1;
+}
+__setup("killswitch=", ks_boot_setup);
+
+static void __init ks_apply_boot_params(void)
+{
+ char *cur, *tok;
+ long retval;
+
+ if (!ks_boot_present)
+ return;
+
+ cur = ks_boot_buf;
+ while ((tok = strsep(&cur, ",")) != NULL) {
+ char *eq, *sym, *retstr;
+
+ if (!*tok)
+ continue;
+ eq = strchr(tok, '=');
+ if (!eq) {
+ pr_warn("killswitch: cmdline missing '=': %s\n", tok);
+ continue;
+ }
+ *eq++ = '\0';
+ sym = tok;
+ retstr = eq;
+
+ if (kstrtol(retstr, 0, &retval)) {
+ pr_warn("killswitch: cmdline bad retval %s=%s\n",
+ sym, retstr);
+ continue;
+ }
+
+ if (__ks_engage(sym, retval, true))
+ pr_warn("killswitch: cmdline engage %s failed\n", sym);
+ }
+}
+
+/* ------------------------------------------------------------------ *
+ * Init *
+ * ------------------------------------------------------------------ */
+
+static int __init killswitch_init(void)
+{
+ struct dentry *d;
+
+ ks_root_dir = securityfs_create_dir("killswitch", NULL);
+ if (IS_ERR(ks_root_dir))
+ return PTR_ERR(ks_root_dir);
+
+ d = securityfs_create_file("control", 0200, ks_root_dir,
+ NULL, &ks_control_fops);
+ if (IS_ERR(d))
+ goto err;
+ d = securityfs_create_file("engaged", 0444, ks_root_dir,
+ NULL, &ks_engaged_fops);
+ if (IS_ERR(d))
+ goto err;
+ d = securityfs_create_file("taint", 0444, ks_root_dir,
+ NULL, &ks_taint_fops);
+ if (IS_ERR(d))
+ goto err;
+
+ ks_fn_dir = securityfs_create_dir("fn", ks_root_dir);
+ if (IS_ERR(ks_fn_dir)) {
+ d = ks_fn_dir;
+ goto err;
+ }
+
+ register_module_notifier(&ks_module_nb);
+ ks_apply_boot_params();
+
+ pr_info("killswitch: ready (sysfs at /sys/kernel/security/killswitch/)\n");
+ return 0;
+
+err:
+ securityfs_remove(ks_root_dir);
+ return PTR_ERR(d);
+}
+late_initcall(killswitch_init);
+
+/* ------------------------------------------------------------------ *
+ * KUnit tests *
+ * ------------------------------------------------------------------ */
+
+#if IS_ENABLED(CONFIG_KUNIT)
+#include <kunit/test.h>
+
+/* Non-static so kallsyms resolves them without CONFIG_KALLSYMS_ALL. */
+int ks_kunit_target_int(int x);
+void *ks_kunit_target_ptr(int x);
+
+/* noipa keeps the call out-of-line and uneliminated. */
+__attribute__((__noipa__)) int ks_kunit_target_int(int x)
+{
+ return x + 1;
+}
+
+__attribute__((__noipa__)) void *ks_kunit_target_ptr(int x)
+{
+ return ERR_PTR(-EIO);
+}
+
+static void ks_disengage_quiet(const char *sym)
+{
+ if (killswitch_is_engaged(sym))
+ killswitch_disengage(sym);
+}
+
+static void ks_test_engage_int(struct kunit *test)
+{
+ int ret;
+
+ ret = killswitch_engage("ks_kunit_target_int", -EPERM);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ KUNIT_EXPECT_EQ(test, ks_kunit_target_int(7), -EPERM);
+ KUNIT_EXPECT_EQ(test, killswitch_disengage("ks_kunit_target_int"), 0);
+ KUNIT_EXPECT_EQ(test, ks_kunit_target_int(7), 8);
+}
+
+static void ks_test_double_engage(struct kunit *test)
+{
+ KUNIT_ASSERT_EQ(test,
+ killswitch_engage("ks_kunit_target_int", 0), 0);
+ KUNIT_EXPECT_EQ(test,
+ killswitch_engage("ks_kunit_target_int", 0), -EBUSY);
+ ks_disengage_quiet("ks_kunit_target_int");
+}
+
+static void ks_test_disengage_unknown(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test,
+ killswitch_disengage("ks_kunit_target_int"), -ENOENT);
+}
+
+static void ks_test_pointer_target(struct kunit *test)
+{
+ long retval = (long)(unsigned long)ERR_PTR(-EACCES);
+
+ KUNIT_ASSERT_EQ(test,
+ killswitch_engage("ks_kunit_target_ptr", retval), 0);
+ KUNIT_EXPECT_TRUE(test, IS_ERR(ks_kunit_target_ptr(0)));
+ KUNIT_EXPECT_EQ(test, PTR_ERR(ks_kunit_target_ptr(0)), -EACCES);
+ ks_disengage_quiet("ks_kunit_target_ptr");
+}
+
+static void ks_test_taint_set(struct kunit *test)
+{
+ KUNIT_ASSERT_EQ(test,
+ killswitch_engage("ks_kunit_target_int", 0), 0);
+ KUNIT_EXPECT_TRUE(test, test_taint(TAINT_KILLSWITCH));
+ ks_disengage_quiet("ks_kunit_target_int");
+ /* taint must persist even after disengage */
+ KUNIT_EXPECT_TRUE(test, test_taint(TAINT_KILLSWITCH));
+}
+
+static void ks_test_hits_counter(struct kunit *test)
+{
+ struct ks_attr *attr;
+ int i;
+
+ KUNIT_ASSERT_EQ(test,
+ killswitch_engage("ks_kunit_target_int", 0), 0);
+
+ for (i = 0; i < 17; i++)
+ (void)ks_kunit_target_int(i);
+
+ mutex_lock(&ks_lock);
+ attr = ks_attr_lookup("ks_kunit_target_int");
+ KUNIT_EXPECT_NOT_NULL(test, attr);
+ if (attr)
+ KUNIT_EXPECT_EQ(test, ks_attr_hits(attr), 17UL);
+ mutex_unlock(&ks_lock);
+
+ ks_disengage_quiet("ks_kunit_target_int");
+}
+
+static struct kunit_case ks_kunit_cases[] = {
+ KUNIT_CASE(ks_test_engage_int),
+ KUNIT_CASE(ks_test_double_engage),
+ KUNIT_CASE(ks_test_disengage_unknown),
+ KUNIT_CASE(ks_test_pointer_target),
+ KUNIT_CASE(ks_test_taint_set),
+ KUNIT_CASE(ks_test_hits_counter),
+ {}
+};
+
+static struct kunit_suite ks_kunit_suite = {
+ .name = "killswitch",
+ .test_cases = ks_kunit_cases,
+};
+kunit_test_suite(ks_kunit_suite);
+
+#endif /* CONFIG_KUNIT */
+
diff --git a/kernel/panic.c b/kernel/panic.c
index 20feada5319d4..8ee174c7b7dd0 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -825,6 +825,7 @@ const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = {
TAINT_FLAG(RANDSTRUCT, 'T', ' '),
TAINT_FLAG(TEST, 'N', ' '),
TAINT_FLAG(FWCTL, 'J', ' '),
+ TAINT_FLAG(KILLSWITCH, 'H', ' '),
};
#undef TAINT_FLAG
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 8ff5adcfe1e0a..5770639c7b0ea 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -3349,6 +3349,19 @@ config TEST_HMM
If unsure, say N.
+config TEST_KILLSWITCH
+ tristate "Test module for the killswitch mitigation primitive"
+ depends on KILLSWITCH && DEBUG_FS
+ depends on m
+ help
+ Build a module that exposes a deliberately-vulnerable function
+ ks_test_vuln() and a debugfs trigger /sys/kernel/debug/test_killswitch/fire.
+ The killswitch selftest in tools/testing/selftests/killswitch/
+ uses this to confirm engaging a killswitch suppresses the BUG()
+ the function would otherwise hit.
+
+ If unsure, say N.
+
config TEST_FREE_PAGES
tristate "Test freeing pages"
help
diff --git a/lib/Makefile b/lib/Makefile
index f33a24bf1c19a..d763225340674 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -100,6 +100,7 @@ obj-$(CONFIG_TEST_MEMCAT_P) += test_memcat_p.o
obj-$(CONFIG_TEST_OBJAGG) += test_objagg.o
obj-$(CONFIG_TEST_MEMINIT) += test_meminit.o
obj-$(CONFIG_TEST_LOCKUP) += test_lockup.o
+obj-$(CONFIG_TEST_KILLSWITCH) += test_killswitch.o
obj-$(CONFIG_TEST_HMM) += test_hmm.o
obj-$(CONFIG_TEST_FREE_PAGES) += test_free_pages.o
obj-$(CONFIG_TEST_REF_TRACKER) += test_ref_tracker.o
diff --git a/lib/test_killswitch.c b/lib/test_killswitch.c
new file mode 100644
index 0000000000000..cc2584ad652ff
--- /dev/null
+++ b/lib/test_killswitch.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test target for the killswitch selftest. ks_test_vuln() returns
+ * -EBADMSG on a magic input, standing in for "the buggy path runs
+ * and produces a bad outcome". Engaging killswitch on this function
+ * with retval 0 is the mitigation.
+ *
+ * Copyright (C) 2026 Sasha Levin <sashal@kernel.org>
+ */
+
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+#define KS_TEST_MAGIC 0xC0FFEEL
+
+int ks_test_vuln(long magic);
+
+/*
+ * Returns -EBADMSG on the magic input -- stands in for "the buggy
+ * path runs and produces a bad outcome". Engaging a killswitch on
+ * this function with retval 0 represents the mitigation: even on
+ * the magic input, callers see success because the body never runs.
+ *
+ * noipa prevents inlining/IPA so the call actually reaches the
+ * kprobe-instrumented entry point.
+ */
+noinline int ks_test_vuln(long magic)
+{
+ if (magic == KS_TEST_MAGIC)
+ return -EBADMSG;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ks_test_vuln);
+
+static struct dentry *ks_test_dir;
+
+static ssize_t ks_test_fire_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[32];
+ long magic;
+ int ret;
+
+ if (count == 0 || count >= sizeof(buf))
+ return -EINVAL;
+ if (copy_from_user(buf, ubuf, count))
+ return -EFAULT;
+ buf[count] = '\0';
+
+ ret = kstrtol(strim(buf), 0, &magic);
+ if (ret)
+ return ret;
+
+ ret = ks_test_vuln(magic);
+ return ret ? ret : count;
+}
+
+static const struct file_operations ks_test_fire_fops = {
+ .write = ks_test_fire_write,
+ .open = simple_open,
+ .llseek = noop_llseek,
+};
+
+static int __init test_killswitch_init(void)
+{
+ ks_test_dir = debugfs_create_dir("test_killswitch", NULL);
+ debugfs_create_file("fire", 0200, ks_test_dir, NULL,
+ &ks_test_fire_fops);
+ pr_info("test_killswitch: loaded (magic=0x%lx)\n", KS_TEST_MAGIC);
+ return 0;
+}
+module_init(test_killswitch_init);
+
+static void __exit test_killswitch_exit(void)
+{
+ debugfs_remove_recursive(ks_test_dir);
+}
+module_exit(test_killswitch_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Deliberately-vulnerable target for killswitch selftest");
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 6e59b8f63e416..04c3f8c5ff229 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -53,6 +53,7 @@ TARGETS += ipc
TARGETS += ir
TARGETS += kcmp
TARGETS += kexec
+TARGETS += killswitch
TARGETS += kselftest_harness
TARGETS += kvm
TARGETS += landlock
diff --git a/tools/testing/selftests/killswitch/.gitignore b/tools/testing/selftests/killswitch/.gitignore
new file mode 100644
index 0000000000000..cbf204ce18615
--- /dev/null
+++ b/tools/testing/selftests/killswitch/.gitignore
@@ -0,0 +1 @@
+cve_31431_test
diff --git a/tools/testing/selftests/killswitch/Makefile b/tools/testing/selftests/killswitch/Makefile
new file mode 100644
index 0000000000000..daf5d001e66c8
--- /dev/null
+++ b/tools/testing/selftests/killswitch/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2026 Sasha Levin <sashal@kernel.org>
+TEST_GEN_PROGS := cve_31431_test
+TEST_PROGS := killswitch_test.sh
+
+CFLAGS += -O2 -g -std=gnu99 -Wall $(KHDR_INCLUDES)
+
+include ../lib.mk
diff --git a/tools/testing/selftests/killswitch/cve_31431_test.c b/tools/testing/selftests/killswitch/cve_31431_test.c
new file mode 100644
index 0000000000000..1ff817c51d881
--- /dev/null
+++ b/tools/testing/selftests/killswitch/cve_31431_test.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AF_ALG AEAD round-trip prober. The killswitch selftest uses this
+ * to demonstrate that engaging a killswitch on af_alg_sendmsg
+ * neuters AF_ALG operations (sendmsg returns -EPERM), mitigating
+ * any AF_ALG-reachable bug whose exploit primitive runs from the
+ * send path.
+ *
+ * Exit codes:
+ * 0 AEAD round-trip succeeded (function intact)
+ * 1 AEAD round-trip refused (mitigation engaged)
+ * 2 setup error (no AF_ALG, missing aead/gcm(aes), etc.) -> SKIP
+ *
+ * Copyright (C) 2026 Sasha Levin <sashal@kernel.org>
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <linux/if_alg.h>
+
+#define KEY_LEN 16
+#define IV_LEN 12
+#define AAD_LEN 16
+#define PT_LEN 64
+#define TAG_LEN 16
+#define EXPECTED_LEN (AAD_LEN + PT_LEN + TAG_LEN)
+
+#ifndef AF_ALG
+#define AF_ALG 38
+#endif
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
+int main(void)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "aead",
+ .salg_name = "gcm(aes)",
+ };
+ unsigned char key[KEY_LEN] = { 0 };
+ unsigned char iv[IV_LEN] = { 0 };
+ unsigned char buf[1024] = { 0 };
+ struct msghdr msg = { 0 };
+ struct iovec iov;
+ struct cmsghdr *cmsg;
+ struct af_alg_iv *aiv;
+ char cbuf[256] = { 0 };
+ int *p_op, *p_assoclen;
+ int sk, opfd;
+ ssize_t n;
+
+ sk = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ if (sk < 0) {
+ fprintf(stderr, "AF_ALG socket: %s -- skip\n", strerror(errno));
+ return 2;
+ }
+ if (bind(sk, (struct sockaddr *)&sa, sizeof(sa))) {
+ fprintf(stderr, "bind aead/gcm(aes): %s -- skip\n",
+ strerror(errno));
+ close(sk);
+ return 2;
+ }
+ if (setsockopt(sk, SOL_ALG, ALG_SET_KEY, key, KEY_LEN)) {
+ fprintf(stderr, "ALG_SET_KEY: %s -- skip\n", strerror(errno));
+ close(sk);
+ return 2;
+ }
+ if (setsockopt(sk, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, TAG_LEN)) {
+ fprintf(stderr, "ALG_SET_AEAD_AUTHSIZE: %s -- skip\n",
+ strerror(errno));
+ close(sk);
+ return 2;
+ }
+
+ opfd = accept(sk, NULL, 0);
+ if (opfd < 0) {
+ fprintf(stderr, "accept: %s -- skip\n", strerror(errno));
+ close(sk);
+ return 2;
+ }
+
+ /* control message: ENCRYPT op + IV + assoclen */
+ msg.msg_control = cbuf;
+ msg.msg_controllen = CMSG_SPACE(sizeof(int))
+ + CMSG_SPACE(sizeof(*aiv) + IV_LEN)
+ + CMSG_SPACE(sizeof(int));
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ p_op = (int *)CMSG_DATA(cmsg);
+ *p_op = ALG_OP_ENCRYPT;
+
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_IV;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(*aiv) + IV_LEN);
+ aiv = (struct af_alg_iv *)CMSG_DATA(cmsg);
+ aiv->ivlen = IV_LEN;
+ memcpy(aiv->iv, iv, IV_LEN);
+
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_AEAD_ASSOCLEN;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ p_assoclen = (int *)CMSG_DATA(cmsg);
+ *p_assoclen = AAD_LEN;
+
+ /* AAD || plaintext */
+ memset(buf, 0xaa, AAD_LEN);
+ memset(buf + AAD_LEN, 0x55, PT_LEN);
+ iov.iov_base = buf;
+ iov.iov_len = AAD_LEN + PT_LEN;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ n = sendmsg(opfd, &msg, 0);
+ if (n < 0) {
+ /*
+ * sendmsg refused: this is exactly the killswitch
+ * af_alg_sendmsg=-EPERM mitigation outcome. Distinct
+ * exit code from setup failure so the test script can
+ * tell them apart.
+ */
+ fprintf(stderr, "sendmsg: %s -- mitigation engaged?\n",
+ strerror(errno));
+ close(opfd); close(sk);
+ return 1;
+ }
+
+ /* recv: AAD echoed, plus ciphertext + tag */
+ memset(buf, 0, sizeof(buf));
+ n = read(opfd, buf, EXPECTED_LEN);
+ close(opfd); close(sk);
+
+ if (n == 0) {
+ printf("AEAD returned 0 bytes -- killswitch mitigation engaged\n");
+ return 1;
+ }
+ if (n != EXPECTED_LEN) {
+ fprintf(stderr,
+ "AEAD short read: got %zd, expected %d -- mitigated?\n",
+ n, EXPECTED_LEN);
+ return 1;
+ }
+
+ /* sanity: ciphertext (after AAD) shouldn't equal the plaintext bytes */
+ if (memcmp(buf + AAD_LEN, buf + AAD_LEN + 1, PT_LEN - 1) == 0) {
+ fprintf(stderr, "AEAD output looks unencrypted\n");
+ return 2;
+ }
+
+ printf("AEAD round-trip OK (%zd bytes)\n", n);
+ return 0;
+}
diff --git a/tools/testing/selftests/killswitch/killswitch_test.sh b/tools/testing/selftests/killswitch/killswitch_test.sh
new file mode 100755
index 0000000000000..7bfb821ce437f
--- /dev/null
+++ b/tools/testing/selftests/killswitch/killswitch_test.sh
@@ -0,0 +1,147 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# End-to-end killswitch selftest. Drives the test_killswitch module
+# through an engage/disengage cycle and confirms each transition
+# behaves as expected. Also runs the AF_ALG mitigation proof.
+#
+# Requirements (see Documentation/admin-guide/killswitch.rst):
+# - CONFIG_KILLSWITCH=y
+# - CONFIG_TEST_KILLSWITCH=m
+# - run as root (CAP_SYS_ADMIN)
+#
+# Copyright (C) 2026 Sasha Levin <sashal@kernel.org>
+#
+
+set -u
+
+KS=/sys/kernel/security/killswitch
+TRIG=/sys/kernel/debug/test_killswitch/fire
+
+NOMOD=0
+SKIP_RC=4
+N=0
+FAIL=0
+
+ksft_pass() { N=$((N+1)); echo "ok $N - $*"; }
+ksft_fail() { N=$((N+1)); FAIL=$((FAIL+1)); echo "not ok $N - $*"; }
+ksft_skip() { echo "ok 1 - SKIP $*"; echo "1..1"; exit $SKIP_RC; }
+
+[[ $EUID -eq 0 ]] || ksft_skip "must be root"
+[[ -d $KS ]] || ksft_skip "$KS not present (CONFIG_KILLSWITCH disabled?)"
+
+if ! modprobe test_killswitch 2>/dev/null; then
+ NOMOD=1
+fi
+[[ -e $TRIG ]] || ksft_skip "$TRIG missing (test_killswitch.ko not installed?)"
+
+cleanup() {
+ echo "disengage_all" > $KS/control 2>/dev/null || true
+ [[ $NOMOD -eq 0 ]] && rmmod test_killswitch 2>/dev/null || true
+}
+trap cleanup EXIT
+
+# --- pre-engage: bad path runs, write fails with EBADMSG ---
+if echo 0xC0FFEE > $TRIG 2>/dev/null; then
+ ksft_fail "pre-engage: write should have failed (-EBADMSG)"
+else
+ [[ $? -ne 0 ]] && ksft_pass "pre-engage: bad path returns error" \
+ || ksft_fail "pre-engage: unexpected outcome"
+fi
+
+# --- engage ---
+echo "engage ks_test_vuln 0 ksft" > $KS/control
+grep -q "^ks_test_vuln" $KS/engaged \
+ && ksft_pass "engage: ks_test_vuln in engaged list" \
+ || ksft_fail "engage: missing from engaged list"
+
+[[ $(cat $KS/taint) == 1 ]] \
+ && ksft_pass "engage: taint set" \
+ || ksft_fail "engage: taint not set"
+
+[[ -d $KS/fn/ks_test_vuln ]] \
+ && ksft_pass "engage: per-fn dir created" \
+ || ksft_fail "engage: per-fn dir missing"
+
+# --- post-engage: BUG suppressed; write returns successfully ---
+if echo 0xC0FFEE > $TRIG 2>/dev/null; then
+ ksft_pass "post-engage: BUG suppressed, write succeeded"
+else
+ ksft_fail "post-engage: write should succeed"
+fi
+
+[[ $(cat $KS/fn/ks_test_vuln/hits) -ge 1 ]] \
+ && ksft_pass "post-engage: hits counter incremented" \
+ || ksft_fail "post-engage: hits counter did not move"
+
+# --- retval rewrite is a plain write (no validation) ---
+echo 7 > $KS/fn/ks_test_vuln/retval
+[[ $(cat $KS/fn/ks_test_vuln/retval) == 7 ]] \
+ && ksft_pass "retval rewrite round-trips" \
+ || ksft_fail "retval rewrite failed"
+
+# --- engage on a kprobe-rejected function fails ---
+# warn_thunk_thunk is in /sys/kernel/debug/kprobes/blacklist;
+# register_kprobe() refuses it.
+KP_REJECT=warn_thunk_thunk
+if echo "engage $KP_REJECT 0 ksft" > $KS/control 2>/dev/null; then
+ ksft_fail "register_kprobe should have rejected $KP_REJECT"
+ echo "disengage $KP_REJECT" > $KS/control
+else
+ ksft_pass "register_kprobe refuses blacklisted target"
+fi
+
+# --- disengage ---
+echo "disengage ks_test_vuln" > $KS/control
+[[ -z "$(cat $KS/engaged)" ]] \
+ && ksft_pass "disengage: engaged list empty" \
+ || ksft_fail "disengage: engaged list not empty"
+
+[[ ! -d $KS/fn/ks_test_vuln ]] \
+ && ksft_pass "disengage: per-fn dir removed" \
+ || ksft_fail "disengage: per-fn dir still present"
+
+[[ $(cat $KS/taint) == 1 ]] \
+ && ksft_pass "disengage: taint persists" \
+ || ksft_fail "disengage: taint should persist"
+
+# --- post-disengage: bad path active again ---
+if echo 0xC0FFEE > $TRIG 2>/dev/null; then
+ ksft_fail "post-disengage: write should fail again"
+else
+ ksft_pass "post-disengage: bad path active again"
+fi
+
+# ---- CVE-2026-31431 mitigation proof (AF_ALG aead via af_alg_sendmsg) ----
+# Skip the whole block if AF_ALG / AEAD machinery isn't compiled in.
+if [[ -x $(dirname "$0")/cve_31431_test ]]; then
+ CVE=$(dirname "$0")/cve_31431_test
+ $CVE >/dev/null 2>&1 && PRE=$? || PRE=$?
+ if [[ $PRE -eq 0 ]]; then
+ ksft_pass "cve-31431: pre-engage AEAD round-trip OK"
+
+ echo "engage af_alg_sendmsg -1 CVE-2026-31431" > $KS/control
+ $CVE >/dev/null 2>&1 && POST=$? || POST=$?
+ if [[ $POST -eq 1 ]]; then
+ ksft_pass "cve-31431: post-engage AEAD refused (mitigated)"
+ else
+ ksft_fail "cve-31431: post-engage exit=$POST (expected 1)"
+ fi
+
+ HITS=$(cat $KS/fn/af_alg_sendmsg/hits 2>/dev/null || echo 0)
+ [[ $HITS -ge 1 ]] && ksft_pass "cve-31431: hits=$HITS recorded" \
+ || ksft_fail "cve-31431: hits not recorded"
+
+ echo "disengage af_alg_sendmsg" > $KS/control
+ $CVE >/dev/null 2>&1 && POST2=$? || POST2=$?
+ [[ $POST2 -eq 0 ]] && ksft_pass "cve-31431: post-disengage restored" \
+ || ksft_fail "cve-31431: post-disengage exit=$POST2"
+ elif [[ $PRE -eq 2 ]]; then
+ echo "# SKIP cve-31431 (AF_ALG/AEAD not available)"
+ else
+ ksft_fail "cve-31431: pre-engage exit=$PRE"
+ fi
+fi
+
+echo "1..$N"
+exit $((FAIL > 0))
--
2.53.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-07 7:05 [PATCH] killswitch: add per-function short-circuit mitigation primitive Sasha Levin
@ 2026-05-07 10:47 ` Greg KH
2026-05-07 13:40 ` Sasha Levin
2026-05-07 15:21 ` Jonathan Corbet
` (3 subsequent siblings)
4 siblings, 1 reply; 48+ messages in thread
From: Greg KH @ 2026-05-07 10:47 UTC (permalink / raw)
To: Sasha Levin; +Cc: corbet, akpm, skhan, linux-doc, linux-kernel, linux-kselftest
On Thu, May 07, 2026 at 03:05:45AM -0400, Sasha Levin wrote:
> When a (security) issue goes public, fleets stay exposed until a patched kernel
> is built, distributed, and rebooted into.
>
> For many such issues the simplest mitigation is to stop calling the buggy
> function. Killswitch provides that. An admin writes:
>
> echo "engage af_alg_sendmsg -1" \
> > /sys/kernel/security/killswitch/control
>
> After this, af_alg_sendmsg() returns -EPERM on every call without
> running its body. The mitigation takes effect immediately, and is dropped on
> the next reboot.
>
> A lot of recent kernel issues sit in code paths most installs only have enabled
> to support a relative minority of users: AF_ALG, ksmbd, nf_tables, vsock, ax25,
> and friends.
>
> For most users, the cost of "this socket family stops working for the day" is
> much smaller than the cost of running a known vulnerable kernel until the fix
> land.
>
> Assisted-by: Claude:claude-opus-4-7
> Signed-off-by: Sasha Levin <sashal@kernel.org>
This is kind of funny, but understandable. Odds are a distro would want
to pick this up so that they can enable this for when their kernel
updates do not get out to users quick enough.
One question:
> +struct ks_attr {
> + struct list_head list;
> + struct kprobe kp;
> + atomic_long_t retval;
Why is this an atomic value? Shouldn't it be whatever the userspace
return type is?
> + /* false once disengaged; per-fn file ops then return -EIDRM. */
> + bool engaged;
> + unsigned long __percpu *hits;
> + struct dentry *dir;
> + /* engaged_list holds one ref; each open per-fn fd holds one. */
> + refcount_t refcnt;
Why is a refcnt needed? Why not use a kref instead?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 48+ messages in thread* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-07 10:47 ` Greg KH
@ 2026-05-07 13:40 ` Sasha Levin
2026-05-07 16:23 ` Greg KH
0 siblings, 1 reply; 48+ messages in thread
From: Sasha Levin @ 2026-05-07 13:40 UTC (permalink / raw)
To: Greg KH; +Cc: corbet, akpm, skhan, linux-doc, linux-kernel, linux-kselftest
On Thu, May 07, 2026 at 12:47:43PM +0200, Greg KH wrote:
>On Thu, May 07, 2026 at 03:05:45AM -0400, Sasha Levin wrote:
>> When a (security) issue goes public, fleets stay exposed until a patched kernel
>> is built, distributed, and rebooted into.
>>
>> For many such issues the simplest mitigation is to stop calling the buggy
>> function. Killswitch provides that. An admin writes:
>>
>> echo "engage af_alg_sendmsg -1" \
>> > /sys/kernel/security/killswitch/control
>>
>> After this, af_alg_sendmsg() returns -EPERM on every call without
>> running its body. The mitigation takes effect immediately, and is dropped on
>> the next reboot.
>>
>> A lot of recent kernel issues sit in code paths most installs only have enabled
>> to support a relative minority of users: AF_ALG, ksmbd, nf_tables, vsock, ax25,
>> and friends.
>>
>> For most users, the cost of "this socket family stops working for the day" is
>> much smaller than the cost of running a known vulnerable kernel until the fix
>> land.
>>
>> Assisted-by: Claude:claude-opus-4-7
>> Signed-off-by: Sasha Levin <sashal@kernel.org>
>
>This is kind of funny, but understandable. Odds are a distro would want
>to pick this up so that they can enable this for when their kernel
>updates do not get out to users quick enough.
I figure that even if the new kernel does go out in a timely manner, there are
still days (weeks? months?) between when a new kernel is available and when the
user reboots.
Might as well try and improve their chances of survival during that period :)
>One question:
>
>> +struct ks_attr {
>> + struct list_head list;
>> + struct kprobe kp;
>> + atomic_long_t retval;
>
>Why is this an atomic value? Shouldn't it be whatever the userspace
>return type is?
The return register is `long` on every arch.
While testing this, I added the ability to modify the return value after we
create a killswitch, and figured that it could be a useful thing to keep in the
code.
But then I got worried about a race between a user changing the return value of
the killswitch and some program trying to execute the code, and getting some
combination of the old and the new return value.
Is that a real concern? I'm not sure - but making this atomic was cheap enough.
>> + /* false once disengaged; per-fn file ops then return -EIDRM. */
>> + bool engaged;
>> + unsigned long __percpu *hits;
>> + struct dentry *dir;
>> + /* engaged_list holds one ref; each open per-fn fd holds one. */
>> + refcount_t refcnt;
>
>Why is a refcnt needed? Why not use a kref instead?
Ugh... no good reason, I can switch to a kref.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-07 13:40 ` Sasha Levin
@ 2026-05-07 16:23 ` Greg KH
0 siblings, 0 replies; 48+ messages in thread
From: Greg KH @ 2026-05-07 16:23 UTC (permalink / raw)
To: Sasha Levin; +Cc: corbet, akpm, skhan, linux-doc, linux-kernel, linux-kselftest
On Thu, May 07, 2026 at 09:40:44AM -0400, Sasha Levin wrote:
> On Thu, May 07, 2026 at 12:47:43PM +0200, Greg KH wrote:
> > > + atomic_long_t retval;
> >
> > Why is this an atomic value? Shouldn't it be whatever the userspace
> > return type is?
>
> The return register is `long` on every arch.
>
> While testing this, I added the ability to modify the return value after we
> create a killswitch, and figured that it could be a useful thing to keep in the
> code.
>
> But then I got worried about a race between a user changing the return value of
> the killswitch and some program trying to execute the code, and getting some
> combination of the old and the new return value.
>
> Is that a real concern? I'm not sure - but making this atomic was cheap enough.
I don't think that a combination should matter all that much here, but
at least it makes sense now. You might want to document that somewhere
here.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-07 7:05 [PATCH] killswitch: add per-function short-circuit mitigation primitive Sasha Levin
2026-05-07 10:47 ` Greg KH
@ 2026-05-07 15:21 ` Jonathan Corbet
2026-05-08 13:44 ` Sasha Levin
2026-05-08 15:40 ` Joshua Peisach
` (2 subsequent siblings)
4 siblings, 1 reply; 48+ messages in thread
From: Jonathan Corbet @ 2026-05-07 15:21 UTC (permalink / raw)
To: Sasha Levin, akpm
Cc: skhan, linux-doc, linux-kernel, linux-kselftest, gregkh,
Sasha Levin
Sasha Levin <sashal@kernel.org> writes:
> When a (security) issue goes public, fleets stay exposed until a patched kernel
> is built, distributed, and rebooted into.
>
> For many such issues the simplest mitigation is to stop calling the buggy
> function. Killswitch provides that. An admin writes:
>
> echo "engage af_alg_sendmsg -1" \
> > /sys/kernel/security/killswitch/control
>
> After this, af_alg_sendmsg() returns -EPERM on every call without
> running its body. The mitigation takes effect immediately, and is dropped on
> the next reboot.
A quick look suggests that you're not checking lockdown status. I don't
doubt for a second that this thing could be used to bypass lockdown - by
shorting out security_locked_down() if nothing else. I'm guessing that
might not prove entirely popular.
jon
^ permalink raw reply [flat|nested] 48+ messages in thread* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-07 15:21 ` Jonathan Corbet
@ 2026-05-08 13:44 ` Sasha Levin
0 siblings, 0 replies; 48+ messages in thread
From: Sasha Levin @ 2026-05-08 13:44 UTC (permalink / raw)
To: Jonathan Corbet
Cc: akpm, skhan, linux-doc, linux-kernel, linux-kselftest, gregkh
On Thu, May 07, 2026 at 09:21:15AM -0600, Jonathan Corbet wrote:
>Sasha Levin <sashal@kernel.org> writes:
>
>> When a (security) issue goes public, fleets stay exposed until a patched kernel
>> is built, distributed, and rebooted into.
>>
>> For many such issues the simplest mitigation is to stop calling the buggy
>> function. Killswitch provides that. An admin writes:
>>
>> echo "engage af_alg_sendmsg -1" \
>> > /sys/kernel/security/killswitch/control
>>
>> After this, af_alg_sendmsg() returns -EPERM on every call without
>> running its body. The mitigation takes effect immediately, and is dropped on
>> the next reboot.
>
>A quick look suggests that you're not checking lockdown status. I don't
>doubt for a second that this thing could be used to bypass lockdown - by
>shorting out security_locked_down() if nothing else. I'm guessing that
>might not prove entirely popular.
Hmm... Good point. I'll respin a v2 adressing this and Greg's comments.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-07 7:05 [PATCH] killswitch: add per-function short-circuit mitigation primitive Sasha Levin
2026-05-07 10:47 ` Greg KH
2026-05-07 15:21 ` Jonathan Corbet
@ 2026-05-08 15:40 ` Joshua Peisach
2026-05-08 15:48 ` Mathieu Desnoyers
2026-05-08 20:56 ` Andrew Morton
2026-05-15 3:48 ` Paul Moore
4 siblings, 1 reply; 48+ messages in thread
From: Joshua Peisach @ 2026-05-08 15:40 UTC (permalink / raw)
To: Sasha Levin, corbet, akpm
Cc: skhan, linux-doc, linux-kernel, linux-kselftest, gregkh
On Thu May 7, 2026 at 3:05 AM EDT, Sasha Levin wrote:
>
> For many such issues the simplest mitigation is to stop calling the buggy
> function. Killswitch provides that. An admin writes:
>
> echo "engage af_alg_sendmsg -1" \
> > /sys/kernel/security/killswitch/control
>
> After this, af_alg_sendmsg() returns -EPERM on every call without
> running its body. The mitigation takes effect immediately, and is dropped on
> the next reboot.
>
> A lot of recent kernel issues sit in code paths most installs only have enabled
> to support a relative minority of users: AF_ALG, ksmbd, nf_tables, vsock, ax25,
> and friends.
>
> For most users, the cost of "this socket family stops working for the day" is
> much smaller than the cost of running a known vulnerable kernel until the fix
> land.
I like the concept - but is there any way to ensure that important functions
like malloc aren't being patched? Or some way to make sure that what is being
patched will not kill the entire kernel?
I know this probably boils down to "operator has to use it correctly", but just
wondering if this was considered.
-Josh
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-08 15:40 ` Joshua Peisach
@ 2026-05-08 15:48 ` Mathieu Desnoyers
2026-05-08 16:13 ` Sasha Levin
0 siblings, 1 reply; 48+ messages in thread
From: Mathieu Desnoyers @ 2026-05-08 15:48 UTC (permalink / raw)
To: Joshua Peisach
Cc: Sasha Levin, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh
On 08-May-2026 11:40:54 AM, Joshua Peisach wrote:
> On Thu May 7, 2026 at 3:05 AM EDT, Sasha Levin wrote:
> >
> > For many such issues the simplest mitigation is to stop calling the buggy
> > function. Killswitch provides that. An admin writes:
> >
> > echo "engage af_alg_sendmsg -1" \
> > > /sys/kernel/security/killswitch/control
> >
> > After this, af_alg_sendmsg() returns -EPERM on every call without
> > running its body. The mitigation takes effect immediately, and is dropped on
> > the next reboot.
> >
> > A lot of recent kernel issues sit in code paths most installs only have enabled
> > to support a relative minority of users: AF_ALG, ksmbd, nf_tables, vsock, ax25,
> > and friends.
> >
> > For most users, the cost of "this socket family stops working for the day" is
> > much smaller than the cost of running a known vulnerable kernel until the fix
> > land.
>
> I like the concept - but is there any way to ensure that important functions
> like malloc aren't being patched? Or some way to make sure that what is being
> patched will not kill the entire kernel?
>
> I know this probably boils down to "operator has to use it correctly", but just
> wondering if this was considered.
I like the idea too, it should help prevent a few devops burnouts in the
coming weeks.
One possible approach to prevent "footgun" type of killswitch use would
be to first apply a statistics collection killswitch handler that does
not change the behavior: it checks whether the target function is
invoked at all on the system for a given period of time. Then it applies
the killswitch if it was not invoked during that period. Overall
sequence:
- pre-soak killswitch for e.g. 30s, checking whether the function is
invoked at all. (period would be user-configurable)
- if no calls were detected, engage killswitch, else report failure to
the user.
This should prevent footguns such as trying to killswitch fork, malloc
or other core functions which are inherently required.
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-08 15:48 ` Mathieu Desnoyers
@ 2026-05-08 16:13 ` Sasha Levin
2026-05-08 16:18 ` Mathieu Desnoyers
0 siblings, 1 reply; 48+ messages in thread
From: Sasha Levin @ 2026-05-08 16:13 UTC (permalink / raw)
To: Mathieu Desnoyers
Cc: Joshua Peisach, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh
On Fri, May 08, 2026 at 11:48:19AM -0400, Mathieu Desnoyers wrote:
>On 08-May-2026 11:40:54 AM, Joshua Peisach wrote:
>> On Thu May 7, 2026 at 3:05 AM EDT, Sasha Levin wrote:
>> >
>> > For many such issues the simplest mitigation is to stop calling the buggy
>> > function. Killswitch provides that. An admin writes:
>> >
>> > echo "engage af_alg_sendmsg -1" \
>> > > /sys/kernel/security/killswitch/control
>> >
>> > After this, af_alg_sendmsg() returns -EPERM on every call without
>> > running its body. The mitigation takes effect immediately, and is dropped on
>> > the next reboot.
>> >
>> > A lot of recent kernel issues sit in code paths most installs only have enabled
>> > to support a relative minority of users: AF_ALG, ksmbd, nf_tables, vsock, ax25,
>> > and friends.
>> >
>> > For most users, the cost of "this socket family stops working for the day" is
>> > much smaller than the cost of running a known vulnerable kernel until the fix
>> > land.
>>
>> I like the concept - but is there any way to ensure that important functions
>> like malloc aren't being patched? Or some way to make sure that what is being
>> patched will not kill the entire kernel?
>>
>> I know this probably boils down to "operator has to use it correctly", but just
>> wondering if this was considered.
So I thought about it, and realized it would be very difficult to decide on
this list of functions, and even more difficult to keep it maintained over time
(functions get added, removed, refactored, ...).
>I like the idea too, it should help prevent a few devops burnouts in the
>coming weeks.
>
>One possible approach to prevent "footgun" type of killswitch use would
>be to first apply a statistics collection killswitch handler that does
>not change the behavior: it checks whether the target function is
>invoked at all on the system for a given period of time. Then it applies
>the killswitch if it was not invoked during that period. Overall
>sequence:
>
>- pre-soak killswitch for e.g. 30s, checking whether the function is
> invoked at all. (period would be user-configurable)
>- if no calls were detected, engage killswitch, else report failure to
> the user.
>
>This should prevent footguns such as trying to killswitch fork, malloc
>or other core functions which are inherently required.
Why not just use our good old tracing infra? Set tracepoints where ever you
want, collect any data you might need, and engage the killswitch when you're
happy with the data you have?
It feels a bit weird adding something like this into killswitch.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-08 16:13 ` Sasha Levin
@ 2026-05-08 16:18 ` Mathieu Desnoyers
2026-05-08 16:23 ` Sasha Levin
0 siblings, 1 reply; 48+ messages in thread
From: Mathieu Desnoyers @ 2026-05-08 16:18 UTC (permalink / raw)
To: Sasha Levin
Cc: Joshua Peisach, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh
On 2026-05-08 12:13, Sasha Levin wrote:
[...]
>> One possible approach to prevent "footgun" type of killswitch use would
>> be to first apply a statistics collection killswitch handler that does
>> not change the behavior: it checks whether the target function is
>> invoked at all on the system for a given period of time. Then it applies
>> the killswitch if it was not invoked during that period. Overall
>> sequence:
>>
>> - pre-soak killswitch for e.g. 30s, checking whether the function is
>> invoked at all. (period would be user-configurable)
>> - if no calls were detected, engage killswitch, else report failure to
>> the user.
>>
>> This should prevent footguns such as trying to killswitch fork, malloc
>> or other core functions which are inherently required.
>
> Why not just use our good old tracing infra? Set tracepoints where ever you
> want, collect any data you might need, and engage the killswitch when
> you're
> happy with the data you have?
>
> It feels a bit weird adding something like this into killswitch.
It really depends on whether you want to include some basic safety nets
directly within killswitch, or leave that entirely to the end user.
I don't have a strong opinion either way. I was just pointing out the
feasibility of a pre-soak sanity check before applying the killswitch.
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-08 16:18 ` Mathieu Desnoyers
@ 2026-05-08 16:23 ` Sasha Levin
2026-05-08 16:26 ` Mathieu Desnoyers
0 siblings, 1 reply; 48+ messages in thread
From: Sasha Levin @ 2026-05-08 16:23 UTC (permalink / raw)
To: Mathieu Desnoyers
Cc: Joshua Peisach, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh
On Fri, May 08, 2026 at 12:18:28PM -0400, Mathieu Desnoyers wrote:
>On 2026-05-08 12:13, Sasha Levin wrote:
>[...]
>>>One possible approach to prevent "footgun" type of killswitch use would
>>>be to first apply a statistics collection killswitch handler that does
>>>not change the behavior: it checks whether the target function is
>>>invoked at all on the system for a given period of time. Then it applies
>>>the killswitch if it was not invoked during that period. Overall
>>>sequence:
>>>
>>>- pre-soak killswitch for e.g. 30s, checking whether the function is
>>> invoked at all. (period would be user-configurable)
>>>- if no calls were detected, engage killswitch, else report failure to
>>> the user.
>>>
>>>This should prevent footguns such as trying to killswitch fork, malloc
>>>or other core functions which are inherently required.
>>
>>Why not just use our good old tracing infra? Set tracepoints where ever you
>>want, collect any data you might need, and engage the killswitch
>>when you're
>>happy with the data you have?
>>
>>It feels a bit weird adding something like this into killswitch.
>
>It really depends on whether you want to include some basic safety nets
>directly within killswitch, or leave that entirely to the end user.
>
>I don't have a strong opinion either way. I was just pointing out the
>feasibility of a pre-soak sanity check before applying the killswitch.
What about doing this with some userspace tooling (maybe under scripts/) to
facilitate this?
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-08 16:23 ` Sasha Levin
@ 2026-05-08 16:26 ` Mathieu Desnoyers
2026-05-08 16:54 ` Sasha Levin
0 siblings, 1 reply; 48+ messages in thread
From: Mathieu Desnoyers @ 2026-05-08 16:26 UTC (permalink / raw)
To: Sasha Levin
Cc: Joshua Peisach, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh
On 2026-05-08 12:23, Sasha Levin wrote:
> On Fri, May 08, 2026 at 12:18:28PM -0400, Mathieu Desnoyers wrote:
>> On 2026-05-08 12:13, Sasha Levin wrote:
>> [...]
>>>> One possible approach to prevent "footgun" type of killswitch use would
>>>> be to first apply a statistics collection killswitch handler that does
>>>> not change the behavior: it checks whether the target function is
>>>> invoked at all on the system for a given period of time. Then it
>>>> applies
>>>> the killswitch if it was not invoked during that period. Overall
>>>> sequence:
>>>>
>>>> - pre-soak killswitch for e.g. 30s, checking whether the function is
>>>> invoked at all. (period would be user-configurable)
>>>> - if no calls were detected, engage killswitch, else report failure to
>>>> the user.
>>>>
>>>> This should prevent footguns such as trying to killswitch fork, malloc
>>>> or other core functions which are inherently required.
>>>
>>> Why not just use our good old tracing infra? Set tracepoints where
>>> ever you
>>> want, collect any data you might need, and engage the killswitch when
>>> you're
>>> happy with the data you have?
>>>
>>> It feels a bit weird adding something like this into killswitch.
>>
>> It really depends on whether you want to include some basic safety nets
>> directly within killswitch, or leave that entirely to the end user.
>>
>> I don't have a strong opinion either way. I was just pointing out the
>> feasibility of a pre-soak sanity check before applying the killswitch.
>
> What about doing this with some userspace tooling (maybe under scripts/) to
> facilitate this?
>
That could work, although it requires additional infrastructure to be in
place (tracing) on production environments, which may not be the case
everywhere. In comparison, if the sanity check is done within
killswitch, you only need killswitch and kprobe to be compiled into
the production system, which is more lightweight.
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-08 16:26 ` Mathieu Desnoyers
@ 2026-05-08 16:54 ` Sasha Levin
0 siblings, 0 replies; 48+ messages in thread
From: Sasha Levin @ 2026-05-08 16:54 UTC (permalink / raw)
To: Mathieu Desnoyers
Cc: Joshua Peisach, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh
On Fri, May 08, 2026 at 12:26:45PM -0400, Mathieu Desnoyers wrote:
>On 2026-05-08 12:23, Sasha Levin wrote:
>>On Fri, May 08, 2026 at 12:18:28PM -0400, Mathieu Desnoyers wrote:
>>>On 2026-05-08 12:13, Sasha Levin wrote:
>>>[...]
>>>>>One possible approach to prevent "footgun" type of killswitch use would
>>>>>be to first apply a statistics collection killswitch handler that does
>>>>>not change the behavior: it checks whether the target function is
>>>>>invoked at all on the system for a given period of time. Then
>>>>>it applies
>>>>>the killswitch if it was not invoked during that period. Overall
>>>>>sequence:
>>>>>
>>>>>- pre-soak killswitch for e.g. 30s, checking whether the function is
>>>>> invoked at all. (period would be user-configurable)
>>>>>- if no calls were detected, engage killswitch, else report failure to
>>>>> the user.
>>>>>
>>>>>This should prevent footguns such as trying to killswitch fork, malloc
>>>>>or other core functions which are inherently required.
>>>>
>>>>Why not just use our good old tracing infra? Set tracepoints
>>>>where ever you
>>>>want, collect any data you might need, and engage the killswitch
>>>>when you're
>>>>happy with the data you have?
>>>>
>>>>It feels a bit weird adding something like this into killswitch.
>>>
>>>It really depends on whether you want to include some basic safety nets
>>>directly within killswitch, or leave that entirely to the end user.
>>>
>>>I don't have a strong opinion either way. I was just pointing out the
>>>feasibility of a pre-soak sanity check before applying the killswitch.
>>
>>What about doing this with some userspace tooling (maybe under scripts/) to
>>facilitate this?
>>
>
>That could work, although it requires additional infrastructure to be in
>place (tracing) on production environments, which may not be the case
>everywhere. In comparison, if the sanity check is done within
>killswitch, you only need killswitch and kprobe to be compiled into
>the production system, which is more lightweight.
So CONFIG_KPROBES but no CONFIG_KPROBES_EVENTS or BPF?
This sounds like a pretty small crowd :)
I think it makes sense to document/script a workflow around tracing or
bpftrace, but I don't think it's worth adding all that logic in the kernel.
I'd also note that you can always reverse the killswitch if you observe issues.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-07 7:05 [PATCH] killswitch: add per-function short-circuit mitigation primitive Sasha Levin
` (2 preceding siblings ...)
2026-05-08 15:40 ` Joshua Peisach
@ 2026-05-08 20:56 ` Andrew Morton
2026-05-08 21:47 ` Sasha Levin
2026-05-15 3:48 ` Paul Moore
4 siblings, 1 reply; 48+ messages in thread
From: Andrew Morton @ 2026-05-08 20:56 UTC (permalink / raw)
To: Sasha Levin
Cc: corbet, skhan, linux-doc, linux-kernel, linux-kselftest, gregkh
On Thu, 7 May 2026 03:05:45 -0400 Sasha Levin <sashal@kernel.org> wrote:
> When a (security) issue goes public, fleets stay exposed until a patched kernel
> is built, distributed, and rebooted into.
>
> For many such issues the simplest mitigation is to stop calling the buggy
> function. Killswitch provides that. An admin writes:
>
> echo "engage af_alg_sendmsg -1" \
> > /sys/kernel/security/killswitch/control
It certainly sounds useful, but what would I know. How do we hunt down
suitable operations people (aka "target audience") to find out how
useful this is to them?
Also,
> 19 files changed, 1451 insertions(+), 1 deletion(-)
wowzers. I'm looking at samples/livepatch/livepatch-sample.c wondering
"why"?
^ permalink raw reply [flat|nested] 48+ messages in thread* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-08 20:56 ` Andrew Morton
@ 2026-05-08 21:47 ` Sasha Levin
2026-05-08 23:49 ` Andrew Morton
2026-05-11 11:41 ` Breno Leitao
0 siblings, 2 replies; 48+ messages in thread
From: Sasha Levin @ 2026-05-08 21:47 UTC (permalink / raw)
To: Andrew Morton
Cc: corbet, skhan, linux-doc, linux-kernel, linux-kselftest, gregkh
On Fri, May 08, 2026 at 01:56:30PM -0700, Andrew Morton wrote:
>On Thu, 7 May 2026 03:05:45 -0400 Sasha Levin <sashal@kernel.org> wrote:
>
>> When a (security) issue goes public, fleets stay exposed until a patched kernel
>> is built, distributed, and rebooted into.
>>
>> For many such issues the simplest mitigation is to stop calling the buggy
>> function. Killswitch provides that. An admin writes:
>>
>> echo "engage af_alg_sendmsg -1" \
>> > /sys/kernel/security/killswitch/control
>
>It certainly sounds useful, but what would I know. How do we hunt down
>suitable operations people (aka "target audience") to find out how
>useful this is to them?
I'm not entierly sure here... If folks have suggestions on folks to loop in,
that'll be great!
>> 19 files changed, 1451 insertions(+), 1 deletion(-)
>
>wowzers. I'm looking at samples/livepatch/livepatch-sample.c wondering
>"why"?
Yup, a bit chunky, but over half of it is documentation and testing, and the
actual functional code is largely the securityfs interface.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-08 21:47 ` Sasha Levin
@ 2026-05-08 23:49 ` Andrew Morton
2026-05-09 0:15 ` Sasha Levin
2026-05-11 11:41 ` Breno Leitao
1 sibling, 1 reply; 48+ messages in thread
From: Andrew Morton @ 2026-05-08 23:49 UTC (permalink / raw)
To: Sasha Levin
Cc: corbet, skhan, linux-doc, linux-kernel, linux-kselftest, gregkh
On Fri, 8 May 2026 17:47:04 -0400 Sasha Levin <sashal@kernel.org> wrote:
> >> 19 files changed, 1451 insertions(+), 1 deletion(-)
> >
> >wowzers. I'm looking at samples/livepatch/livepatch-sample.c wondering
> >"why"?
>
> Yup, a bit chunky, but over half of it is documentation and testing, and the
> actual functional code is largely the securityfs interface.
So we can't use livepatch here?
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-08 23:49 ` Andrew Morton
@ 2026-05-09 0:15 ` Sasha Levin
2026-05-09 0:36 ` Andrew Morton
0 siblings, 1 reply; 48+ messages in thread
From: Sasha Levin @ 2026-05-09 0:15 UTC (permalink / raw)
To: Andrew Morton
Cc: corbet, skhan, linux-doc, linux-kernel, linux-kselftest, gregkh
On Fri, May 08, 2026 at 04:49:25PM -0700, Andrew Morton wrote:
>On Fri, 8 May 2026 17:47:04 -0400 Sasha Levin <sashal@kernel.org> wrote:
>
>> >> 19 files changed, 1451 insertions(+), 1 deletion(-)
>> >
>> >wowzers. I'm looking at samples/livepatch/livepatch-sample.c wondering
>> >"why"?
>>
>> Yup, a bit chunky, but over half of it is documentation and testing, and the
>> actual functional code is largely the securityfs interface.
>
>So we can't use livepatch here?
I might have misunderstood your original question.
Livepatch is great when you have one. The problem is getting one...
To get a livepatch, somebody has to write the fix, build it against the exact
kernel you're running (for distros, thats hundreds of different
kernel/arch/flavor combinations), sign it, and get it onto every machine.
Most regular users won't be able to do it on their own because of secure boot
limitations, so they depend on their vendor to provide them with one.
Yes, you could write a livepatch that just stubs the function out, same end
state as killswitch, but you still have to build, sign, and ship a module per
kernel to do it
Killswitch would be just a single write to /sys which an ordinary user can do
to mitigate a critical issue immediately.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-09 0:15 ` Sasha Levin
@ 2026-05-09 0:36 ` Andrew Morton
0 siblings, 0 replies; 48+ messages in thread
From: Andrew Morton @ 2026-05-09 0:36 UTC (permalink / raw)
To: Sasha Levin
Cc: corbet, skhan, linux-doc, linux-kernel, linux-kselftest, gregkh
On Fri, 8 May 2026 20:15:00 -0400 Sasha Levin <sashal@kernel.org> wrote:
> Livepatch is great when you have one. The problem is getting one...
>
> To get a livepatch, somebody has to write the fix, build it against the exact
> kernel you're running (for distros, thats hundreds of different
> kernel/arch/flavor combinations), sign it, and get it onto every machine.
>
> Most regular users won't be able to do it on their own because of secure boot
> limitations, so they depend on their vendor to provide them with one.
>
> Yes, you could write a livepatch that just stubs the function out, same end
> state as killswitch, but you still have to build, sign, and ship a module per
> kernel to do it
>
> Killswitch would be just a single write to /sys which an ordinary user can do
> to mitigate a critical issue immediately.
OK, thanks. Worth adding the changelog in case someone else was
wondering?
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-08 21:47 ` Sasha Levin
2026-05-08 23:49 ` Andrew Morton
@ 2026-05-11 11:41 ` Breno Leitao
2026-05-11 13:07 ` Michal Hocko
1 sibling, 1 reply; 48+ messages in thread
From: Breno Leitao @ 2026-05-11 11:41 UTC (permalink / raw)
To: Sasha Levin
Cc: Andrew Morton, corbet, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh
On Fri, May 08, 2026 at 05:47:04PM -0400, Sasha Levin wrote:
> On Fri, May 08, 2026 at 01:56:30PM -0700, Andrew Morton wrote:
> > On Thu, 7 May 2026 03:05:45 -0400 Sasha Levin <sashal@kernel.org> wrote:
> >
> > > When a (security) issue goes public, fleets stay exposed until a patched kernel
> > > is built, distributed, and rebooted into.
> > >
> > > For many such issues the simplest mitigation is to stop calling the buggy
> > > function. Killswitch provides that. An admin writes:
> > >
> > > echo "engage af_alg_sendmsg -1" \
> > > > /sys/kernel/security/killswitch/control
> >
> > It certainly sounds useful, but what would I know. How do we hunt down
> > suitable operations people (aka "target audience") to find out how
> > useful this is to them?
>
> I'm not entierly sure here... If folks have suggestions on folks to loop in,
> that'll be great!
I work with these issues at Meta, and this approach would address a real
need we have.
While livepatch could theoretically solve this problem, it's less suited
for rapid mitigation for a couple of reasons:
1) Livepatch rollout is inherently slower due to the blast radius if a
bug exists in the livepatch mechanism itself.
2) It's common to run hundreds of different kernel versions across a
fleet. Since livepatch is kernel-specific, a single CVE suddenly
requires building and deploying hundreds of individual livepatches—
far less practical than a simple sysfs write.
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 11:41 ` Breno Leitao
@ 2026-05-11 13:07 ` Michal Hocko
2026-05-11 13:39 ` Sasha Levin
` (2 more replies)
0 siblings, 3 replies; 48+ messages in thread
From: Michal Hocko @ 2026-05-11 13:07 UTC (permalink / raw)
To: Breno Leitao
Cc: Sasha Levin, Andrew Morton, corbet, skhan, linux-doc,
linux-kernel, linux-kselftest, gregkh
On Mon 11-05-26 04:41:38, Breno Leitao wrote:
> On Fri, May 08, 2026 at 05:47:04PM -0400, Sasha Levin wrote:
> > On Fri, May 08, 2026 at 01:56:30PM -0700, Andrew Morton wrote:
> > > On Thu, 7 May 2026 03:05:45 -0400 Sasha Levin <sashal@kernel.org> wrote:
> > >
> > > > When a (security) issue goes public, fleets stay exposed until a patched kernel
> > > > is built, distributed, and rebooted into.
> > > >
> > > > For many such issues the simplest mitigation is to stop calling the buggy
> > > > function. Killswitch provides that. An admin writes:
> > > >
> > > > echo "engage af_alg_sendmsg -1" \
> > > > > /sys/kernel/security/killswitch/control
> > >
> > > It certainly sounds useful, but what would I know. How do we hunt down
> > > suitable operations people (aka "target audience") to find out how
> > > useful this is to them?
> >
> > I'm not entierly sure here... If folks have suggestions on folks to loop in,
> > that'll be great!
>
> I work with these issues at Meta, and this approach would address a real
> need we have.
>
> While livepatch could theoretically solve this problem, it's less suited
> for rapid mitigation for a couple of reasons:
>
> 1) Livepatch rollout is inherently slower due to the blast radius if a
> bug exists in the livepatch mechanism itself.
>
> 2) It's common to run hundreds of different kernel versions across a
> fleet. Since livepatch is kernel-specific, a single CVE suddenly
> requires building and deploying hundreds of individual livepatches—
> far less practical than a simple sysfs write.
LP is certainly a more laborous solution. I guess this is quite clear.
It is also much safer option as it deals with all implementation details
like consistency. All that is not done for fun. I am really wondering
how admins are expected to a) know which kernel functions are ok/safe to
disable and b) when it is safe to do so without introducing unsafe
kernel state or introduce an outright bug that way.
Thiking about this I can see how waiting for an official LP can be time
consuming and sometimes creating those is far from trivial. But would it
make sense to have automated LP creation tooling available that would
allow to return early from a function and relly on the existing
infrastructure to do the right thing?
--
Michal Hocko
SUSE Labs
^ permalink raw reply [flat|nested] 48+ messages in thread* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 13:07 ` Michal Hocko
@ 2026-05-11 13:39 ` Sasha Levin
2026-05-11 13:49 ` Michal Hocko
2026-05-11 13:40 ` Breno Leitao
2026-05-11 22:31 ` Andrew Morton
2 siblings, 1 reply; 48+ messages in thread
From: Sasha Levin @ 2026-05-11 13:39 UTC (permalink / raw)
To: Michal Hocko
Cc: Breno Leitao, Andrew Morton, corbet, skhan, linux-doc,
linux-kernel, linux-kselftest, gregkh
On Mon, May 11, 2026 at 03:07:51PM +0200, Michal Hocko wrote:
>On Mon 11-05-26 04:41:38, Breno Leitao wrote:
>> On Fri, May 08, 2026 at 05:47:04PM -0400, Sasha Levin wrote:
>> > On Fri, May 08, 2026 at 01:56:30PM -0700, Andrew Morton wrote:
>> > > On Thu, 7 May 2026 03:05:45 -0400 Sasha Levin <sashal@kernel.org> wrote:
>> > >
>> > > > When a (security) issue goes public, fleets stay exposed until a patched kernel
>> > > > is built, distributed, and rebooted into.
>> > > >
>> > > > For many such issues the simplest mitigation is to stop calling the buggy
>> > > > function. Killswitch provides that. An admin writes:
>> > > >
>> > > > echo "engage af_alg_sendmsg -1" \
>> > > > > /sys/kernel/security/killswitch/control
>> > >
>> > > It certainly sounds useful, but what would I know. How do we hunt down
>> > > suitable operations people (aka "target audience") to find out how
>> > > useful this is to them?
>> >
>> > I'm not entierly sure here... If folks have suggestions on folks to loop in,
>> > that'll be great!
>>
>> I work with these issues at Meta, and this approach would address a real
>> need we have.
Thanks for the feedback!
>> While livepatch could theoretically solve this problem, it's less suited
>> for rapid mitigation for a couple of reasons:
>>
>> 1) Livepatch rollout is inherently slower due to the blast radius if a
>> bug exists in the livepatch mechanism itself.
>>
>> 2) It's common to run hundreds of different kernel versions across a
>> fleet. Since livepatch is kernel-specific, a single CVE suddenly
>> requires building and deploying hundreds of individual livepatches—
>> far less practical than a simple sysfs write.
>
>LP is certainly a more laborous solution. I guess this is quite clear.
>It is also much safer option as it deals with all implementation details
>like consistency. All that is not done for fun. I am really wondering
>how admins are expected to a) know which kernel functions are ok/safe to
>disable and b) when it is safe to do so without introducing unsafe
>kernel state or introduce an outright bug that way.
In a similar way to how they would know if a given livepatch is safe to apply -
ideally it would be communicated by the vendor/distro/kernel team.
"On Debian XX.YY, use the following command to mitigate CVE-AAAA-BBBB:
echo "engage woops -1" > /sys/kernel/security/killswitch/control"
>Thiking about this I can see how waiting for an official LP can be time
>consuming and sometimes creating those is far from trivial. But would it
>make sense to have automated LP creation tooling available that would
>allow to return early from a function and relly on the existing
>infrastructure to do the right thing?
This would definitely help (and in light of how the last couple of weeks played
out, the case for livepatches definitely increased), but not all
vendors/distros provide livepatches.
My personal usecase is simple: I use debian, with their kernel. I'm not going
to get livepatches from debian, and it would take a few days/weeks for a kernel
update to land. I want a simple solution that'll let me disable functionality I
don't care about.
So I can't use livepatching/fault injection/etc easily.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 13:39 ` Sasha Levin
@ 2026-05-11 13:49 ` Michal Hocko
2026-05-11 13:56 ` Sasha Levin
0 siblings, 1 reply; 48+ messages in thread
From: Michal Hocko @ 2026-05-11 13:49 UTC (permalink / raw)
To: Sasha Levin
Cc: Breno Leitao, Andrew Morton, corbet, skhan, linux-doc,
linux-kernel, linux-kselftest, gregkh
On Mon 11-05-26 09:39:32, Sasha Levin wrote:
> On Mon, May 11, 2026 at 03:07:51PM +0200, Michal Hocko wrote:
> > On Mon 11-05-26 04:41:38, Breno Leitao wrote:
> > > On Fri, May 08, 2026 at 05:47:04PM -0400, Sasha Levin wrote:
> > > > On Fri, May 08, 2026 at 01:56:30PM -0700, Andrew Morton wrote:
> > > > > On Thu, 7 May 2026 03:05:45 -0400 Sasha Levin <sashal@kernel.org> wrote:
> > > > >
> > > > > > When a (security) issue goes public, fleets stay exposed until a patched kernel
> > > > > > is built, distributed, and rebooted into.
> > > > > >
> > > > > > For many such issues the simplest mitigation is to stop calling the buggy
> > > > > > function. Killswitch provides that. An admin writes:
> > > > > >
> > > > > > echo "engage af_alg_sendmsg -1" \
> > > > > > > /sys/kernel/security/killswitch/control
> > > > >
> > > > > It certainly sounds useful, but what would I know. How do we hunt down
> > > > > suitable operations people (aka "target audience") to find out how
> > > > > useful this is to them?
> > > >
> > > > I'm not entierly sure here... If folks have suggestions on folks to loop in,
> > > > that'll be great!
> > >
> > > I work with these issues at Meta, and this approach would address a real
> > > need we have.
>
> Thanks for the feedback!
>
> > > While livepatch could theoretically solve this problem, it's less suited
> > > for rapid mitigation for a couple of reasons:
> > >
> > > 1) Livepatch rollout is inherently slower due to the blast radius if a
> > > bug exists in the livepatch mechanism itself.
> > >
> > > 2) It's common to run hundreds of different kernel versions across a
> > > fleet. Since livepatch is kernel-specific, a single CVE suddenly
> > > requires building and deploying hundreds of individual livepatches—
> > > far less practical than a simple sysfs write.
> >
> > LP is certainly a more laborous solution. I guess this is quite clear.
> > It is also much safer option as it deals with all implementation details
> > like consistency. All that is not done for fun. I am really wondering
> > how admins are expected to a) know which kernel functions are ok/safe to
> > disable and b) when it is safe to do so without introducing unsafe
> > kernel state or introduce an outright bug that way.
>
> In a similar way to how they would know if a given livepatch is safe to apply -
> ideally it would be communicated by the vendor/distro/kernel team.
You have missed my point. KLP takes an extra steps to make sure patching
a particular function is safe to modify or to put the change into the
effect.
> "On Debian XX.YY, use the following command to mitigate CVE-AAAA-BBBB:
>
> echo "engage woops -1" > /sys/kernel/security/killswitch/control"
>
> > Thiking about this I can see how waiting for an official LP can be time
> > consuming and sometimes creating those is far from trivial. But would it
> > make sense to have automated LP creation tooling available that would
> > allow to return early from a function and relly on the existing
> > infrastructure to do the right thing?
>
> This would definitely help (and in light of how the last couple of weeks played
> out, the case for livepatches definitely increased), but not all
> vendors/distros provide livepatches.
The point I've tried to make is that you (as an admin) shouldn't depend
on your vendor to provide you with an official LP just to disable a
certain function(ality). That is/should be a trivial case where the LP
should be ideally generated automagically if you have a tooling
available. I might be wrong and overlook some complexity here.
--
Michal Hocko
SUSE Labs
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 13:49 ` Michal Hocko
@ 2026-05-11 13:56 ` Sasha Levin
2026-05-11 14:25 ` Michal Hocko
0 siblings, 1 reply; 48+ messages in thread
From: Sasha Levin @ 2026-05-11 13:56 UTC (permalink / raw)
To: Michal Hocko
Cc: Breno Leitao, Andrew Morton, corbet, skhan, linux-doc,
linux-kernel, linux-kselftest, gregkh
On Mon, May 11, 2026 at 03:49:24PM +0200, Michal Hocko wrote:
>On Mon 11-05-26 09:39:32, Sasha Levin wrote:
>> On Mon, May 11, 2026 at 03:07:51PM +0200, Michal Hocko wrote:
>> > On Mon 11-05-26 04:41:38, Breno Leitao wrote:
>> > > On Fri, May 08, 2026 at 05:47:04PM -0400, Sasha Levin wrote:
>> > > > On Fri, May 08, 2026 at 01:56:30PM -0700, Andrew Morton wrote:
>> > > > > On Thu, 7 May 2026 03:05:45 -0400 Sasha Levin <sashal@kernel.org> wrote:
>> > > > >
>> > > > > > When a (security) issue goes public, fleets stay exposed until a patched kernel
>> > > > > > is built, distributed, and rebooted into.
>> > > > > >
>> > > > > > For many such issues the simplest mitigation is to stop calling the buggy
>> > > > > > function. Killswitch provides that. An admin writes:
>> > > > > >
>> > > > > > echo "engage af_alg_sendmsg -1" \
>> > > > > > > /sys/kernel/security/killswitch/control
>> > > > >
>> > > > > It certainly sounds useful, but what would I know. How do we hunt down
>> > > > > suitable operations people (aka "target audience") to find out how
>> > > > > useful this is to them?
>> > > >
>> > > > I'm not entierly sure here... If folks have suggestions on folks to loop in,
>> > > > that'll be great!
>> > >
>> > > I work with these issues at Meta, and this approach would address a real
>> > > need we have.
>>
>> Thanks for the feedback!
>>
>> > > While livepatch could theoretically solve this problem, it's less suited
>> > > for rapid mitigation for a couple of reasons:
>> > >
>> > > 1) Livepatch rollout is inherently slower due to the blast radius if a
>> > > bug exists in the livepatch mechanism itself.
>> > >
>> > > 2) It's common to run hundreds of different kernel versions across a
>> > > fleet. Since livepatch is kernel-specific, a single CVE suddenly
>> > > requires building and deploying hundreds of individual livepatches—
>> > > far less practical than a simple sysfs write.
>> >
>> > LP is certainly a more laborous solution. I guess this is quite clear.
>> > It is also much safer option as it deals with all implementation details
>> > like consistency. All that is not done for fun. I am really wondering
>> > how admins are expected to a) know which kernel functions are ok/safe to
>> > disable and b) when it is safe to do so without introducing unsafe
>> > kernel state or introduce an outright bug that way.
>>
>> In a similar way to how they would know if a given livepatch is safe to apply -
>> ideally it would be communicated by the vendor/distro/kernel team.
>
>You have missed my point. KLP takes an extra steps to make sure patching
>a particular function is safe to modify or to put the change into the
>effect.
Safety checks like making sure the patched function is on the stack, or did you
mean something else?
>> "On Debian XX.YY, use the following command to mitigate CVE-AAAA-BBBB:
>>
>> echo "engage woops -1" > /sys/kernel/security/killswitch/control"
>>
>> > Thiking about this I can see how waiting for an official LP can be time
>> > consuming and sometimes creating those is far from trivial. But would it
>> > make sense to have automated LP creation tooling available that would
>> > allow to return early from a function and relly on the existing
>> > infrastructure to do the right thing?
>>
>> This would definitely help (and in light of how the last couple of weeks played
>> out, the case for livepatches definitely increased), but not all
>> vendors/distros provide livepatches.
>
>The point I've tried to make is that you (as an admin) shouldn't depend
>on your vendor to provide you with an official LP just to disable a
>certain function(ality). That is/should be a trivial case where the LP
>should be ideally generated automagically if you have a tooling
>available. I might be wrong and overlook some complexity here.
Module signing is what stops that approach for me.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 13:56 ` Sasha Levin
@ 2026-05-11 14:25 ` Michal Hocko
2026-05-11 15:55 ` Sasha Levin
0 siblings, 1 reply; 48+ messages in thread
From: Michal Hocko @ 2026-05-11 14:25 UTC (permalink / raw)
To: Sasha Levin
Cc: Breno Leitao, Andrew Morton, corbet, skhan, linux-doc,
linux-kernel, linux-kselftest, gregkh
On Mon 11-05-26 09:56:30, Sasha Levin wrote:
> On Mon, May 11, 2026 at 03:49:24PM +0200, Michal Hocko wrote:
> > On Mon 11-05-26 09:39:32, Sasha Levin wrote:
> > > On Mon, May 11, 2026 at 03:07:51PM +0200, Michal Hocko wrote:
> > > > On Mon 11-05-26 04:41:38, Breno Leitao wrote:
> > > > > On Fri, May 08, 2026 at 05:47:04PM -0400, Sasha Levin wrote:
> > > > > > On Fri, May 08, 2026 at 01:56:30PM -0700, Andrew Morton wrote:
> > > > > > > On Thu, 7 May 2026 03:05:45 -0400 Sasha Levin <sashal@kernel.org> wrote:
> > > > > > >
> > > > > > > > When a (security) issue goes public, fleets stay exposed until a patched kernel
> > > > > > > > is built, distributed, and rebooted into.
> > > > > > > >
> > > > > > > > For many such issues the simplest mitigation is to stop calling the buggy
> > > > > > > > function. Killswitch provides that. An admin writes:
> > > > > > > >
> > > > > > > > echo "engage af_alg_sendmsg -1" \
> > > > > > > > > /sys/kernel/security/killswitch/control
> > > > > > >
> > > > > > > It certainly sounds useful, but what would I know. How do we hunt down
> > > > > > > suitable operations people (aka "target audience") to find out how
> > > > > > > useful this is to them?
> > > > > >
> > > > > > I'm not entierly sure here... If folks have suggestions on folks to loop in,
> > > > > > that'll be great!
> > > > >
> > > > > I work with these issues at Meta, and this approach would address a real
> > > > > need we have.
> > >
> > > Thanks for the feedback!
> > >
> > > > > While livepatch could theoretically solve this problem, it's less suited
> > > > > for rapid mitigation for a couple of reasons:
> > > > >
> > > > > 1) Livepatch rollout is inherently slower due to the blast radius if a
> > > > > bug exists in the livepatch mechanism itself.
> > > > >
> > > > > 2) It's common to run hundreds of different kernel versions across a
> > > > > fleet. Since livepatch is kernel-specific, a single CVE suddenly
> > > > > requires building and deploying hundreds of individual livepatches—
> > > > > far less practical than a simple sysfs write.
> > > >
> > > > LP is certainly a more laborous solution. I guess this is quite clear.
> > > > It is also much safer option as it deals with all implementation details
> > > > like consistency. All that is not done for fun. I am really wondering
> > > > how admins are expected to a) know which kernel functions are ok/safe to
> > > > disable and b) when it is safe to do so without introducing unsafe
> > > > kernel state or introduce an outright bug that way.
> > >
> > > In a similar way to how they would know if a given livepatch is safe to apply -
> > > ideally it would be communicated by the vendor/distro/kernel team.
> >
> > You have missed my point. KLP takes an extra steps to make sure patching
> > a particular function is safe to modify or to put the change into the
> > effect.
>
> Safety checks like making sure the patched function is on the stack, or did you
> mean something else?
Yes, exactly what LP infrastructure already provides.
> > > "On Debian XX.YY, use the following command to mitigate CVE-AAAA-BBBB:
> > >
> > > echo "engage woops -1" > /sys/kernel/security/killswitch/control"
> > >
> > > > Thiking about this I can see how waiting for an official LP can be time
> > > > consuming and sometimes creating those is far from trivial. But would it
> > > > make sense to have automated LP creation tooling available that would
> > > > allow to return early from a function and relly on the existing
> > > > infrastructure to do the right thing?
> > >
> > > This would definitely help (and in light of how the last couple of weeks played
> > > out, the case for livepatches definitely increased), but not all
> > > vendors/distros provide livepatches.
> >
> > The point I've tried to make is that you (as an admin) shouldn't depend
> > on your vendor to provide you with an official LP just to disable a
> > certain function(ality). That is/should be a trivial case where the LP
> > should be ideally generated automagically if you have a tooling
> > available. I might be wrong and overlook some complexity here.
>
> Module signing is what stops that approach for me.
OK, so the actual constrain here is that you cannot load your own
modules. That was not really clear from your description. I assume you
cannot enroll your own key and sign?
--
Michal Hocko
SUSE Labs
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 14:25 ` Michal Hocko
@ 2026-05-11 15:55 ` Sasha Levin
2026-05-11 16:10 ` Michal Hocko
0 siblings, 1 reply; 48+ messages in thread
From: Sasha Levin @ 2026-05-11 15:55 UTC (permalink / raw)
To: Michal Hocko
Cc: Breno Leitao, Andrew Morton, corbet, skhan, linux-doc,
linux-kernel, linux-kselftest, gregkh
On Mon, May 11, 2026 at 04:25:57PM +0200, Michal Hocko wrote:
>On Mon 11-05-26 09:56:30, Sasha Levin wrote:
>> On Mon, May 11, 2026 at 03:49:24PM +0200, Michal Hocko wrote:
>> > On Mon 11-05-26 09:39:32, Sasha Levin wrote:
>> > > On Mon, May 11, 2026 at 03:07:51PM +0200, Michal Hocko wrote:
>> > > > On Mon 11-05-26 04:41:38, Breno Leitao wrote:
>> > > > > On Fri, May 08, 2026 at 05:47:04PM -0400, Sasha Levin wrote:
>> > > > > > On Fri, May 08, 2026 at 01:56:30PM -0700, Andrew Morton wrote:
>> > > > > > > On Thu, 7 May 2026 03:05:45 -0400 Sasha Levin <sashal@kernel.org> wrote:
>> > > > > > >
>> > > > > > > > When a (security) issue goes public, fleets stay exposed until a patched kernel
>> > > > > > > > is built, distributed, and rebooted into.
>> > > > > > > >
>> > > > > > > > For many such issues the simplest mitigation is to stop calling the buggy
>> > > > > > > > function. Killswitch provides that. An admin writes:
>> > > > > > > >
>> > > > > > > > echo "engage af_alg_sendmsg -1" \
>> > > > > > > > > /sys/kernel/security/killswitch/control
>> > > > > > >
>> > > > > > > It certainly sounds useful, but what would I know. How do we hunt down
>> > > > > > > suitable operations people (aka "target audience") to find out how
>> > > > > > > useful this is to them?
>> > > > > >
>> > > > > > I'm not entierly sure here... If folks have suggestions on folks to loop in,
>> > > > > > that'll be great!
>> > > > >
>> > > > > I work with these issues at Meta, and this approach would address a real
>> > > > > need we have.
>> > >
>> > > Thanks for the feedback!
>> > >
>> > > > > While livepatch could theoretically solve this problem, it's less suited
>> > > > > for rapid mitigation for a couple of reasons:
>> > > > >
>> > > > > 1) Livepatch rollout is inherently slower due to the blast radius if a
>> > > > > bug exists in the livepatch mechanism itself.
>> > > > >
>> > > > > 2) It's common to run hundreds of different kernel versions across a
>> > > > > fleet. Since livepatch is kernel-specific, a single CVE suddenly
>> > > > > requires building and deploying hundreds of individual livepatches—
>> > > > > far less practical than a simple sysfs write.
>> > > >
>> > > > LP is certainly a more laborous solution. I guess this is quite clear.
>> > > > It is also much safer option as it deals with all implementation details
>> > > > like consistency. All that is not done for fun. I am really wondering
>> > > > how admins are expected to a) know which kernel functions are ok/safe to
>> > > > disable and b) when it is safe to do so without introducing unsafe
>> > > > kernel state or introduce an outright bug that way.
>> > >
>> > > In a similar way to how they would know if a given livepatch is safe to apply -
>> > > ideally it would be communicated by the vendor/distro/kernel team.
>> >
>> > You have missed my point. KLP takes an extra steps to make sure patching
>> > a particular function is safe to modify or to put the change into the
>> > effect.
>>
>> Safety checks like making sure the patched function is on the stack, or did you
>> mean something else?
>
>Yes, exactly what LP infrastructure already provides.
But do we actually need it here?
For threads already inside the body when killswitch is engaged: they just keep
executing the body to completion.
For threads at entry after the kprobe arms: pre-handler fires, they exit with
the override retval, never enter the body.
For threads arriving while the kprobe is being armed: kprobes-on-ftrace uses
ftrace's text_poke for atomic arm, so there's no "half-armed" window.
>> > > "On Debian XX.YY, use the following command to mitigate CVE-AAAA-BBBB:
>> > >
>> > > echo "engage woops -1" > /sys/kernel/security/killswitch/control"
>> > >
>> > > > Thiking about this I can see how waiting for an official LP can be time
>> > > > consuming and sometimes creating those is far from trivial. But would it
>> > > > make sense to have automated LP creation tooling available that would
>> > > > allow to return early from a function and relly on the existing
>> > > > infrastructure to do the right thing?
>> > >
>> > > This would definitely help (and in light of how the last couple of weeks played
>> > > out, the case for livepatches definitely increased), but not all
>> > > vendors/distros provide livepatches.
>> >
>> > The point I've tried to make is that you (as an admin) shouldn't depend
>> > on your vendor to provide you with an official LP just to disable a
>> > certain function(ality). That is/should be a trivial case where the LP
>> > should be ideally generated automagically if you have a tooling
>> > available. I might be wrong and overlook some complexity here.
>>
>> Module signing is what stops that approach for me.
>
>OK, so the actual constrain here is that you cannot load your own
>modules. That was not really clear from your description. I assume you
>cannot enroll your own key and sign?
It's one of them, yes. I don't want to build my own kernel (and assume that
most distro users don't build their own kernel), so I can't enroll my own keys.
Outside of that, you would still need to have a patch-per-version (or at least,
per group of versions where the patch applies without conflicts).
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 15:55 ` Sasha Levin
@ 2026-05-11 16:10 ` Michal Hocko
2026-05-11 16:45 ` Sasha Levin
0 siblings, 1 reply; 48+ messages in thread
From: Michal Hocko @ 2026-05-11 16:10 UTC (permalink / raw)
To: Sasha Levin
Cc: Breno Leitao, Andrew Morton, corbet, skhan, linux-doc,
linux-kernel, linux-kselftest, gregkh
On Mon 11-05-26 11:55:41, Sasha Levin wrote:
> On Mon, May 11, 2026 at 04:25:57PM +0200, Michal Hocko wrote:
> > On Mon 11-05-26 09:56:30, Sasha Levin wrote:
> > > On Mon, May 11, 2026 at 03:49:24PM +0200, Michal Hocko wrote:
> > > > On Mon 11-05-26 09:39:32, Sasha Levin wrote:
> > > > > On Mon, May 11, 2026 at 03:07:51PM +0200, Michal Hocko wrote:
> > > > > In a similar way to how they would know if a given livepatch is safe to apply -
> > > > > ideally it would be communicated by the vendor/distro/kernel team.
> > > >
> > > > You have missed my point. KLP takes an extra steps to make sure patching
> > > > a particular function is safe to modify or to put the change into the
> > > > effect.
> > >
> > > Safety checks like making sure the patched function is on the stack, or did you
> > > mean something else?
> >
> > Yes, exactly what LP infrastructure already provides.
>
> But do we actually need it here?
If not then you can simply systemtap or use BPF to inject the code. In
other words we have several ways how to runtime modify the kernel so
before yet another interface is provided (with a non-trivial amount of
code and very limited functionality) you should really start by
describing why none of the existing one is fitting well.
I do understand your argument that solutions based on loading a module
might have an additional step to deal with (AFAIK you do not need to
build your own kernel to deploy your key) is that a brohibitive
roadblock? We also do have fault injection which is much less convenient
because of all the existing constraines but can those be elevated?
So nothing really against playing with ideas nad LLMs to generated a
quick PoC. That is all good but for this to be considered more seriously
I think we really need to think deeper whether the existing
infrastructure is really not fitting and if not whether it could be
changed to cover more usecase like the one you have mentioned here and I
believe it is something worth thinking about.
--
Michal Hocko
SUSE Labs
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 16:10 ` Michal Hocko
@ 2026-05-11 16:45 ` Sasha Levin
2026-05-11 17:10 ` Michal Hocko
0 siblings, 1 reply; 48+ messages in thread
From: Sasha Levin @ 2026-05-11 16:45 UTC (permalink / raw)
To: Michal Hocko
Cc: Breno Leitao, Andrew Morton, corbet, skhan, linux-doc,
linux-kernel, linux-kselftest, gregkh
On Mon, May 11, 2026 at 06:10:20PM +0200, Michal Hocko wrote:
>On Mon 11-05-26 11:55:41, Sasha Levin wrote:
>> On Mon, May 11, 2026 at 04:25:57PM +0200, Michal Hocko wrote:
>> > On Mon 11-05-26 09:56:30, Sasha Levin wrote:
>> > > On Mon, May 11, 2026 at 03:49:24PM +0200, Michal Hocko wrote:
>> > > > On Mon 11-05-26 09:39:32, Sasha Levin wrote:
>> > > > > On Mon, May 11, 2026 at 03:07:51PM +0200, Michal Hocko wrote:
>> > > > > In a similar way to how they would know if a given livepatch is safe to apply -
>> > > > > ideally it would be communicated by the vendor/distro/kernel team.
>> > > >
>> > > > You have missed my point. KLP takes an extra steps to make sure patching
>> > > > a particular function is safe to modify or to put the change into the
>> > > > effect.
>> > >
>> > > Safety checks like making sure the patched function is on the stack, or did you
>> > > mean something else?
>> >
>> > Yes, exactly what LP infrastructure already provides.
>>
>> But do we actually need it here?
>
>If not then you can simply systemtap or use BPF to inject the code. In
>other words we have several ways how to runtime modify the kernel so
>before yet another interface is provided (with a non-trivial amount of
>code and very limited functionality) you should really start by
>describing why none of the existing one is fitting well.
>
>I do understand your argument that solutions based on loading a module
>might have an additional step to deal with (AFAIK you do not need to
>build your own kernel to deploy your key) is that a brohibitive
>roadblock? We also do have fault injection which is much less convenient
>because of all the existing constraines but can those be elevated?
>
>So nothing really against playing with ideas nad LLMs to generated a
>quick PoC. That is all good but for this to be considered more seriously
>I think we really need to think deeper whether the existing
>infrastructure is really not fitting and if not whether it could be
>changed to cover more usecase like the one you have mentioned here and I
>believe it is something worth thinking about.
Could you describe an existing infrastructure I can use here? Let's look at
this recent "Copy Fail" thing as an example.
I can obviously build my own kernel and enroll my own key, but 99.9% of our
users won't be doing that.
Livepatching, or manually building a module that just injects a kprobe is out
of the question as we previously agreed.
systemtap falls into the same bucket as building my own module.
BPF doesn't help because bpf_override_return() requires the target to be on the
same within_error_injection_list() whitelist as fault injection, and the CVE
targets never are. Some of our fleet doesn't even have BPF enabled either, but
that's the smaller objection.
I can't use fault injection because:
a. It's almost never built in production/distro kernels, and I suspect this
won't change.
b. The functions I need are not whitelisted.
c. Even if (a) and (b) were addressed, fault injection would still need a
securityfs front-end, a cmdline parser, a module-unload notifier, a taint flag,
and audit on engage and disengage. By the time those land in fail_function and
tie into/refactor the fault injection code, the net diff is bigger than this
proposal.
In my case I can remove the module, but not if I run a distro that shipped with
CONFIG_CRYPTO_USER_API_AEAD=y (like RHEL/SUSE).
I can use "initcall_blacklist=" hack and reboot, but as things stand today,
I'll need to be rebooting few times a day.
Even if I'm okay with rebooting that often (and I really really would prefer
not to), this doesn't solve the issues of a larger fleet of servers that can't
just reboot that often.
What am I missing?
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 16:45 ` Sasha Levin
@ 2026-05-11 17:10 ` Michal Hocko
2026-05-11 18:09 ` Sasha Levin
0 siblings, 1 reply; 48+ messages in thread
From: Michal Hocko @ 2026-05-11 17:10 UTC (permalink / raw)
To: Sasha Levin
Cc: Breno Leitao, Andrew Morton, corbet, skhan, linux-doc,
linux-kernel, linux-kselftest, gregkh
On Mon 11-05-26 12:45:36, Sasha Levin wrote:
> Could you describe an existing infrastructure I can use here?
I think it would help to CC maintainers of subsystems that provide
kernel modification functionality. They will surely have a better
insight than me.
> Let's look at
> this recent "Copy Fail" thing as an example.
>
> I can obviously build my own kernel and enroll my own key, but 99.9% of our
> users won't be doing that.
> Livepatching, or manually building a module that just injects a kprobe is out
> of the question as we previously agreed.
Onless I am mistaken you can enroll your own key through MOK. But you
are right that this is an additional step. But the real question is
whether this is a major road block for users of this specific feature.
> systemtap falls into the same bucket as building my own module.
>
> BPF doesn't help because bpf_override_return() requires the target to be on the
> same within_error_injection_list() whitelist as fault injection, and the CVE
> targets never are. Some of our fleet doesn't even have BPF enabled either, but
> that's the smaller objection.
>
> I can't use fault injection because:
>
> a. It's almost never built in production/distro kernels, and I suspect this
> won't change.
> b. The functions I need are not whitelisted.
> c. Even if (a) and (b) were addressed, fault injection would still need a
> securityfs front-end, a cmdline parser, a module-unload notifier, a taint flag,
> and audit on engage and disengage. By the time those land in fail_function and
> tie into/refactor the fault injection code, the net diff is bigger than this
> proposal.
I cannot comment on fault injection imeplementation details of course
but I have to say that the whitelist nature is something that makes its
use very limited. Maybe this is a good opportunity to change the
approach.
>
> In my case I can remove the module, but not if I run a distro that shipped with
> CONFIG_CRYPTO_USER_API_AEAD=y (like RHEL/SUSE).
If you look at copy fail[2], IIRC algif_aead, esp[46] and rxrcp are all
modules that could be blacklisted.
> I can use "initcall_blacklist=" hack and reboot, but as things stand today,
> I'll need to be rebooting few times a day.
with your just disable some functions in the kernel you might need to
reboot even more. But more seriously...
> Even if I'm okay with rebooting that often (and I really really would prefer
> not to), this doesn't solve the issues of a larger fleet of servers that can't
> just reboot that often.
>
> What am I missing?
For one, you are missing more maintainers of code modification infrastructures.
--
Michal Hocko
SUSE Labs
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 17:10 ` Michal Hocko
@ 2026-05-11 18:09 ` Sasha Levin
2026-05-14 14:35 ` Jiri Olsa
0 siblings, 1 reply; 48+ messages in thread
From: Sasha Levin @ 2026-05-11 18:09 UTC (permalink / raw)
To: Michal Hocko
Cc: Breno Leitao, Andrew Morton, corbet, skhan, linux-doc,
linux-kernel, linux-kselftest, gregkh, akinobu.mita,
live-patching
On Mon, May 11, 2026 at 07:10:46PM +0200, Michal Hocko wrote:
>On Mon 11-05-26 12:45:36, Sasha Levin wrote:
>> Could you describe an existing infrastructure I can use here?
>
>I think it would help to CC maintainers of subsystems that provide
>kernel modification functionality. They will surely have a better
>insight than me.
>
>> Let's look at
>> this recent "Copy Fail" thing as an example.
>>
>> I can obviously build my own kernel and enroll my own key, but 99.9% of our
>> users won't be doing that.
>> Livepatching, or manually building a module that just injects a kprobe is out
>> of the question as we previously agreed.
>
>Onless I am mistaken you can enroll your own key through MOK. But you
>are right that this is an additional step. But the real question is
>whether this is a major road block for users of this specific feature.
The roadblock here is that then I need to start owning the kernel package: I
need to pull updates, rebuild, reinstall, etc. I lose the support I might be
getting from the distro vendor.
I see "users of this particular feature" as the other 99.9% of folks who don't
build their own kernel, who follow security updates from their distro vendor
and could apply the simple workaround that those vendors could now provide.
>> systemtap falls into the same bucket as building my own module.
>>
>> BPF doesn't help because bpf_override_return() requires the target to be on the
>> same within_error_injection_list() whitelist as fault injection, and the CVE
>> targets never are. Some of our fleet doesn't even have BPF enabled either, but
>> that's the smaller objection.
>>
>> I can't use fault injection because:
>>
>> a. It's almost never built in production/distro kernels, and I suspect this
>> won't change.
>> b. The functions I need are not whitelisted.
>> c. Even if (a) and (b) were addressed, fault injection would still need a
>> securityfs front-end, a cmdline parser, a module-unload notifier, a taint flag,
>> and audit on engage and disengage. By the time those land in fail_function and
>> tie into/refactor the fault injection code, the net diff is bigger than this
>> proposal.
>
>I cannot comment on fault injection imeplementation details of course
>but I have to say that the whitelist nature is something that makes its
>use very limited. Maybe this is a good opportunity to change the
>approach.
Possibly, but IMO the bigger hurdle is the refactoring we'll need to do so
seperate fail_function out of the fault injection umbrella.
One approach would be to abstract the kprobe logic out of fail_function into a
common lib that killswitch could also use, but from a brief look the benefit
will be minimal.
>> In my case I can remove the module, but not if I run a distro that shipped with
>> CONFIG_CRYPTO_USER_API_AEAD=y (like RHEL/SUSE).
>
>If you look at copy fail[2], IIRC algif_aead, esp[46] and rxrcp are all
>modules that could be blacklisted.
On some distros sure, on some others, not:
https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/raw/main/redhat/configs/common/generic/CONFIG_CRYPTO_USER_API_AEAD
Even if it is a module, what if I can't just unload it because I have something
that actually uses it?
Look at the ESP issue for example. I can mitigate it by simply doing:
echo "engage xfrm4_udp_encap_rcv 0" > /sys/kernel/security/killswitch/control
echo "engage xfrm6_udp_encap_rcv 0" > /sys/kernel/security/killswitch/control
which only kills ESP encapsulated in UDP. The remaining functionality will keep
working just fine.
>> I can use "initcall_blacklist=" hack and reboot, but as things stand today,
>> I'll need to be rebooting few times a day.
>
>with your just disable some functions in the kernel you might need to
>reboot even more. But more seriously...
>
>> Even if I'm okay with rebooting that often (and I really really would prefer
>> not to), this doesn't solve the issues of a larger fleet of servers that can't
>> just reboot that often.
>>
>> What am I missing?
>
>For one, you are missing more maintainers of code modification infrastructures.
Happy to add more, but I don't want to be too spammy. I'll add in the
livepatching ML and the fault injection maintainer (I couldn't find a list).
Please add any other folks/lists who you think might want to contribute to this
discussion.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 18:09 ` Sasha Levin
@ 2026-05-14 14:35 ` Jiri Olsa
0 siblings, 0 replies; 48+ messages in thread
From: Jiri Olsa @ 2026-05-14 14:35 UTC (permalink / raw)
To: Sasha Levin
Cc: Michal Hocko, Breno Leitao, Andrew Morton, corbet, skhan,
linux-doc, linux-kernel, linux-kselftest, gregkh, akinobu.mita,
live-patching
On Mon, May 11, 2026 at 02:09:45PM -0400, Sasha Levin wrote:
SNIP
> > > Even if I'm okay with rebooting that often (and I really really would prefer
> > > not to), this doesn't solve the issues of a larger fleet of servers that can't
> > > just reboot that often.
> > >
> > > What am I missing?
> >
> > For one, you are missing more maintainers of code modification infrastructures.
>
> Happy to add more, but I don't want to be too spammy. I'll add in the
> livepatching ML and the fault injection maintainer (I couldn't find a list).
> Please add any other folks/lists who you think might want to contribute to this
> discussion.
hi,
could you please add bpf (bpf@vger.kernel.org) to the loop?
thanks,
jirka
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 13:07 ` Michal Hocko
2026-05-11 13:39 ` Sasha Levin
@ 2026-05-11 13:40 ` Breno Leitao
2026-05-11 22:31 ` Andrew Morton
2 siblings, 0 replies; 48+ messages in thread
From: Breno Leitao @ 2026-05-11 13:40 UTC (permalink / raw)
To: Michal Hocko
Cc: Sasha Levin, Andrew Morton, corbet, skhan, linux-doc,
linux-kernel, linux-kselftest, gregkh, ivaz
Hello Michal,
On Mon, May 11, 2026 at 03:07:51PM +0200, Michal Hocko wrote:
> > I work with these issues at Meta, and this approach would address a real
> > need we have.
> >
> > While livepatch could theoretically solve this problem, it's less suited
> > for rapid mitigation for a couple of reasons:
> >
> > 1) Livepatch rollout is inherently slower due to the blast radius if a
> > bug exists in the livepatch mechanism itself.
> >
> > 2) It's common to run hundreds of different kernel versions across a
> > fleet. Since livepatch is kernel-specific, a single CVE suddenly
> > requires building and deploying hundreds of individual livepatches—
> > far less practical than a simple sysfs write.
>
> LP is certainly a more laborous solution. I guess this is quite clear.
>
> It is also much safer option as it deals with all implementation details
> like consistency. All that is not done for fun. I am really wondering
> how admins are expected to a) know which kernel functions are ok/safe to
> disable and b) when it is safe to do so without introducing unsafe
> kernel state or introduce an outright bug that way.
You raise a valid concern. There's no simple answer. Making these decisions
requires deep understanding of both the code and the potential consequences.
The value proposition here (IMO) is the ability to completely disable a
code path by returning an error code (such as -EINVAL or -EBUSY) at key
entry points, rather than attempting surgical modifications.
While this approach is far from perfect, it can serve as an effective
stopgap measure until a proper fix is deployed or a livepatch becomes
available.
> Thiking about this I can see how waiting for an official LP can be time
> consuming and sometimes creating those is far from trivial. But would it
> make sense to have automated LP creation tooling available that would
> allow to return early from a function and relly on the existing
> infrastructure to do the right thing?
Absolutely. I view this as a progression of mitigation strategies, where
the ultimate goal is deploying a properly fixed kernel, but reaching that
endpoint may require intermediate steps.
1) Fix and deploy a new kernel:
* Pros: Lowest risk, permanent solution
* Cons:
- Requires reboot and extended downtime
2) Livepatch:
* Pros: Complete mitigation, clean approach, zero downtime
* Cons:
- Time-intensive rollout (requires bake time and health checks)
- Demands manual patch creation and review for each kernel version
(i.e., kernel developer involvement is essential)
3) This approach (killswitch):
* Pros: Immediate deployment capability
- Security engineers familiar with kernel code can act independently
* Cons:
- Risk of instability if the operator misjudges the impact
In short, I see killswitch as a complementary tool in the security
toolbox, not a universal solution.
--breno
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 13:07 ` Michal Hocko
2026-05-11 13:39 ` Sasha Levin
2026-05-11 13:40 ` Breno Leitao
@ 2026-05-11 22:31 ` Andrew Morton
2026-05-11 23:01 ` Song Liu
2026-05-11 23:05 ` Sasha Levin
2 siblings, 2 replies; 48+ messages in thread
From: Andrew Morton @ 2026-05-11 22:31 UTC (permalink / raw)
To: Michal Hocko
Cc: Breno Leitao, Sasha Levin, corbet, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh
On Mon, 11 May 2026 15:07:51 +0200 Michal Hocko <mhocko@suse.com> wrote:
> > 2) It's common to run hundreds of different kernel versions across a
> > fleet. Since livepatch is kernel-specific, a single CVE suddenly
> > requires building and deploying hundreds of individual livepatches—
> > far less practical than a simple sysfs write.
>
> LP is certainly a more laborous solution.
<another please-educate-akpm email>
Does a livepatch *have* to be distributed as a ready-to-load kernel
module?
Is it not possible to distribute a "livepatch" to the fleet as a single
string? Send out "make function some_bad_function() return -EINVAL"
and let scripting on each machine figure out how to locally write,
build, sign and install such a livepatch?
That would require that each machine locally contains enough data for
it to be able to build a kernel for the currently-running kernel, and
that each machine contains a build environment.
I *think* this is feasible on distro-based machines? But perhaps not
on stripped-down hyperscalar boxen?
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 22:31 ` Andrew Morton
@ 2026-05-11 23:01 ` Song Liu
2026-05-11 23:05 ` Sasha Levin
1 sibling, 0 replies; 48+ messages in thread
From: Song Liu @ 2026-05-11 23:01 UTC (permalink / raw)
To: Andrew Morton
Cc: Michal Hocko, Breno Leitao, Sasha Levin, corbet, skhan, linux-doc,
linux-kernel, linux-kselftest, gregkh
On Mon, May 11, 2026 at 3:32 PM Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Mon, 11 May 2026 15:07:51 +0200 Michal Hocko <mhocko@suse.com> wrote:
>
> > > 2) It's common to run hundreds of different kernel versions across a
> > > fleet. Since livepatch is kernel-specific, a single CVE suddenly
> > > requires building and deploying hundreds of individual livepatches—
> > > far less practical than a simple sysfs write.
> >
> > LP is certainly a more laborous solution.
>
> <another please-educate-akpm email>
>
> Does a livepatch *have* to be distributed as a ready-to-load kernel
> module?
As of today, livepatch is loaded to the kernel as a module. It requires
kernel config CONFIG_LIVEPATCH. If CONFIG_LIVEPATCH is not
set in the running kernel, livepatch module won't work.
> Is it not possible to distribute a "livepatch" to the fleet as a single
> string? Send out "make function some_bad_function() return -EINVAL"
> and let scripting on each machine figure out how to locally write,
> build, sign and install such a livepatch?
With CONFIG_LIVEPATCH, and with proper toolchain and keys,
this is surely possible. But I guess this comes with some security
concerns (sharing the keys, etc.).
> That would require that each machine locally contains enough data for
> it to be able to build a kernel for the currently-running kernel, and
> that each machine contains a build environment.
>
> I *think* this is feasible on distro-based machines? But perhaps not
> on stripped-down hyperscalar boxen?
Do most distro machines have CONFIG_LIVEPATCH enabled?
AFAICT, Ubuntu 26.04 does have it enabled.
Thanks,
Song
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-11 22:31 ` Andrew Morton
2026-05-11 23:01 ` Song Liu
@ 2026-05-11 23:05 ` Sasha Levin
1 sibling, 0 replies; 48+ messages in thread
From: Sasha Levin @ 2026-05-11 23:05 UTC (permalink / raw)
To: Andrew Morton
Cc: Michal Hocko, Breno Leitao, corbet, skhan, linux-doc,
linux-kernel, linux-kselftest, gregkh
On Mon, May 11, 2026 at 03:31:58PM -0700, Andrew Morton wrote:
>On Mon, 11 May 2026 15:07:51 +0200 Michal Hocko <mhocko@suse.com> wrote:
>
>> > 2) It's common to run hundreds of different kernel versions across a
>> > fleet. Since livepatch is kernel-specific, a single CVE suddenly
>> > requires building and deploying hundreds of individual livepatches—
>> > far less practical than a simple sysfs write.
>>
>> LP is certainly a more laborous solution.
>
><another please-educate-akpm email>
>
>Does a livepatch *have* to be distributed as a ready-to-load kernel
>module?
>
>Is it not possible to distribute a "livepatch" to the fleet as a single
>string? Send out "make function some_bad_function() return -EINVAL"
>and let scripting on each machine figure out how to locally write,
>build, sign and install such a livepatch?
>
>That would require that each machine locally contains enough data for
>it to be able to build a kernel for the currently-running kernel, and
>that each machine contains a build environment.
So we'll need to have a kernel build env, the sources for the current kernel,
debug info, and some sort of a semantic patch (.cocci?) to make the
transformation. I think we could even script all of that per-distro, yes.
>I *think* this is feasible on distro-based machines? But perhaps not
>on stripped-down hyperscalar boxen?
Few concerns:
1. Tiny/embedded machines that will have a really hard time building a kernel
either because of storage, CPU power, etc... Consider something like your home
router running OpenWRT.
Actually, this is a good example for a killswitch too I think. I went digging
for issues that would affect OpenWRT routers, and
https://www.cve.org/CVERecord?id=CVE-2024-1086 is a good example: OpenWRT
supports user namespaces to allow containers to run on the router, so any
container could then compromise the router.
There's no way to build kernel modules on the router - no toolchain nor storage.
With killswitch, you could simply do something like:
echo "engage nft_verdict_init -1" > /sys/kernel/security/killswitch/control
Which, if I understand the code correctly, would disable us from adding any new
netfilter rules, but existing rules would keep working (and on most routers the
rules are fairly static).
2. Having to install a build env is not only wasteful but also not secure. For
example, a certain hyperscaler we both know does not allow compilers on
production machines. It's probably a good practice for regular distro based
machines too.
3. With secure boot a user can't load their own unsigned modules, so the user
will need to spin their own kernel and enroll their keys. Having to turn off
secure boot is a really bad solution too.
4. Nightmare as far as reproducibility goes: think of all the odd
compiler/toolchain/etc combos you'll encounter. No way to track what went
wrong, where, and how.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-07 7:05 [PATCH] killswitch: add per-function short-circuit mitigation primitive Sasha Levin
` (3 preceding siblings ...)
2026-05-08 20:56 ` Andrew Morton
@ 2026-05-15 3:48 ` Paul Moore
2026-05-18 6:31 ` Song Liu
4 siblings, 1 reply; 48+ messages in thread
From: Paul Moore @ 2026-05-15 3:48 UTC (permalink / raw)
To: Sasha Levin
Cc: corbet, akpm, skhan, linux-doc, linux-kernel, linux-kselftest,
gregkh, linux-security-module
On Thu, May 7, 2026 at 3:05 AM Sasha Levin <sashal@kernel.org> wrote:
>
> When a (security) issue goes public, fleets stay exposed until a patched kernel
> is built, distributed, and rebooted into.
>
> For many such issues the simplest mitigation is to stop calling the buggy
> function. Killswitch provides that. An admin writes:
>
> echo "engage af_alg_sendmsg -1" \
> > /sys/kernel/security/killswitch/control
>
> After this, af_alg_sendmsg() returns -EPERM on every call without
> running its body. The mitigation takes effect immediately, and is dropped on
> the next reboot.
>
> A lot of recent kernel issues sit in code paths most installs only have enabled
> to support a relative minority of users: AF_ALG, ksmbd, nf_tables, vsock, ax25,
> and friends.
>
> For most users, the cost of "this socket family stops working for the day" is
> much smaller than the cost of running a known vulnerable kernel until the fix
> land.
>
> Assisted-by: Claude:claude-opus-4-7
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> ---
> Documentation/admin-guide/index.rst | 1 +
> Documentation/admin-guide/killswitch.rst | 159 ++++
> Documentation/admin-guide/tainted-kernels.rst | 8 +
> MAINTAINERS | 11 +
> include/linux/killswitch.h | 19 +
> include/linux/panic.h | 3 +-
> init/Kconfig | 2 +
> kernel/Kconfig.killswitch | 31 +
> kernel/Makefile | 1 +
> kernel/killswitch.c | 798 ++++++++++++++++++
> kernel/panic.c | 1 +
> lib/Kconfig.debug | 13 +
> lib/Makefile | 1 +
> lib/test_killswitch.c | 85 ++
> tools/testing/selftests/Makefile | 1 +
> tools/testing/selftests/killswitch/.gitignore | 1 +
> tools/testing/selftests/killswitch/Makefile | 8 +
> .../selftests/killswitch/cve_31431_test.c | 162 ++++
> .../selftests/killswitch/killswitch_test.sh | 147 ++++
> 19 files changed, 1451 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/admin-guide/killswitch.rst
> create mode 100644 include/linux/killswitch.h
> create mode 100644 kernel/Kconfig.killswitch
> create mode 100644 kernel/killswitch.c
> create mode 100644 lib/test_killswitch.c
> create mode 100644 tools/testing/selftests/killswitch/.gitignore
> create mode 100644 tools/testing/selftests/killswitch/Makefile
> create mode 100644 tools/testing/selftests/killswitch/cve_31431_test.c
> create mode 100755 tools/testing/selftests/killswitch/killswitch_test.sh
If we made Lockdown an LSM, we should probably also make killswitch an LSM.
For the LSM crowd who might be seeing this for the first time, the
original thread can be found on lore via the link below:
https://lore.kernel.org/all/20260507070547.2268452-1-sashal@kernel.org
--
paul-moore.com
^ permalink raw reply [flat|nested] 48+ messages in thread* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-15 3:48 ` Paul Moore
@ 2026-05-18 6:31 ` Song Liu
2026-05-18 21:29 ` Paul Moore
0 siblings, 1 reply; 48+ messages in thread
From: Song Liu @ 2026-05-18 6:31 UTC (permalink / raw)
To: Paul Moore
Cc: Sasha Levin, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh, linux-security-module
On Thu, May 14, 2026 at 8:48 PM Paul Moore <paul@paul-moore.com> wrote:
>
> On Thu, May 7, 2026 at 3:05 AM Sasha Levin <sashal@kernel.org> wrote:
> >
> > When a (security) issue goes public, fleets stay exposed until a patched kernel
> > is built, distributed, and rebooted into.
> >
> > For many such issues the simplest mitigation is to stop calling the buggy
> > function. Killswitch provides that. An admin writes:
> >
> > echo "engage af_alg_sendmsg -1" \
> > > /sys/kernel/security/killswitch/control
> >
> > After this, af_alg_sendmsg() returns -EPERM on every call without
> > running its body. The mitigation takes effect immediately, and is dropped on
> > the next reboot.
> >
> > A lot of recent kernel issues sit in code paths most installs only have enabled
> > to support a relative minority of users: AF_ALG, ksmbd, nf_tables, vsock, ax25,
> > and friends.
> >
> > For most users, the cost of "this socket family stops working for the day" is
> > much smaller than the cost of running a known vulnerable kernel until the fix
> > land.
> >
> > Assisted-by: Claude:claude-opus-4-7
> > Signed-off-by: Sasha Levin <sashal@kernel.org>
> > ---
> > Documentation/admin-guide/index.rst | 1 +
> > Documentation/admin-guide/killswitch.rst | 159 ++++
> > Documentation/admin-guide/tainted-kernels.rst | 8 +
> > MAINTAINERS | 11 +
> > include/linux/killswitch.h | 19 +
> > include/linux/panic.h | 3 +-
> > init/Kconfig | 2 +
> > kernel/Kconfig.killswitch | 31 +
> > kernel/Makefile | 1 +
> > kernel/killswitch.c | 798 ++++++++++++++++++
> > kernel/panic.c | 1 +
> > lib/Kconfig.debug | 13 +
> > lib/Makefile | 1 +
> > lib/test_killswitch.c | 85 ++
> > tools/testing/selftests/Makefile | 1 +
> > tools/testing/selftests/killswitch/.gitignore | 1 +
> > tools/testing/selftests/killswitch/Makefile | 8 +
> > .../selftests/killswitch/cve_31431_test.c | 162 ++++
> > .../selftests/killswitch/killswitch_test.sh | 147 ++++
> > 19 files changed, 1451 insertions(+), 1 deletion(-)
> > create mode 100644 Documentation/admin-guide/killswitch.rst
> > create mode 100644 include/linux/killswitch.h
> > create mode 100644 kernel/Kconfig.killswitch
> > create mode 100644 kernel/killswitch.c
> > create mode 100644 lib/test_killswitch.c
> > create mode 100644 tools/testing/selftests/killswitch/.gitignore
> > create mode 100644 tools/testing/selftests/killswitch/Makefile
> > create mode 100644 tools/testing/selftests/killswitch/cve_31431_test.c
> > create mode 100755 tools/testing/selftests/killswitch/killswitch_test.sh
>
> If we made Lockdown an LSM, we should probably also make killswitch an LSM.
I don't think killswitch can stack with other LSMs. In fact, killswitch
can be used to bypass other LSMs, for example:
echo engage security_file_open 0 > /sys/kernel/security/killswitch/control
will bypass all hooks on security_file_open.
Thanks,
Song
> For the LSM crowd who might be seeing this for the first time, the
> original thread can be found on lore via the link below:
> https://lore.kernel.org/all/20260507070547.2268452-1-sashal@kernel.org
>
> --
> paul-moore.com
>
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-18 6:31 ` Song Liu
@ 2026-05-18 21:29 ` Paul Moore
2026-05-18 23:22 ` Song Liu
2026-05-19 0:31 ` Sasha Levin
0 siblings, 2 replies; 48+ messages in thread
From: Paul Moore @ 2026-05-18 21:29 UTC (permalink / raw)
To: Song Liu
Cc: Sasha Levin, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh, linux-security-module
On Mon, May 18, 2026 at 2:31 AM Song Liu <song@kernel.org> wrote:
> On Thu, May 14, 2026 at 8:48 PM Paul Moore <paul@paul-moore.com> wrote:
> > On Thu, May 7, 2026 at 3:05 AM Sasha Levin <sashal@kernel.org> wrote:
> > >
> > > When a (security) issue goes public, fleets stay exposed until a patched kernel
> > > is built, distributed, and rebooted into.
> > >
> > > For many such issues the simplest mitigation is to stop calling the buggy
> > > function. Killswitch provides that. An admin writes:
> > >
> > > echo "engage af_alg_sendmsg -1" \
> > > > /sys/kernel/security/killswitch/control
> > >
> > > After this, af_alg_sendmsg() returns -EPERM on every call without
> > > running its body. The mitigation takes effect immediately, and is dropped on
> > > the next reboot.
> > >
> > > A lot of recent kernel issues sit in code paths most installs only have enabled
> > > to support a relative minority of users: AF_ALG, ksmbd, nf_tables, vsock, ax25,
> > > and friends.
> > >
> > > For most users, the cost of "this socket family stops working for the day" is
> > > much smaller than the cost of running a known vulnerable kernel until the fix
> > > land.
> > >
> > > Assisted-by: Claude:claude-opus-4-7
> > > Signed-off-by: Sasha Levin <sashal@kernel.org>
> > > ---
> > > Documentation/admin-guide/index.rst | 1 +
> > > Documentation/admin-guide/killswitch.rst | 159 ++++
> > > Documentation/admin-guide/tainted-kernels.rst | 8 +
> > > MAINTAINERS | 11 +
> > > include/linux/killswitch.h | 19 +
> > > include/linux/panic.h | 3 +-
> > > init/Kconfig | 2 +
> > > kernel/Kconfig.killswitch | 31 +
> > > kernel/Makefile | 1 +
> > > kernel/killswitch.c | 798 ++++++++++++++++++
> > > kernel/panic.c | 1 +
> > > lib/Kconfig.debug | 13 +
> > > lib/Makefile | 1 +
> > > lib/test_killswitch.c | 85 ++
> > > tools/testing/selftests/Makefile | 1 +
> > > tools/testing/selftests/killswitch/.gitignore | 1 +
> > > tools/testing/selftests/killswitch/Makefile | 8 +
> > > .../selftests/killswitch/cve_31431_test.c | 162 ++++
> > > .../selftests/killswitch/killswitch_test.sh | 147 ++++
> > > 19 files changed, 1451 insertions(+), 1 deletion(-)
> > > create mode 100644 Documentation/admin-guide/killswitch.rst
> > > create mode 100644 include/linux/killswitch.h
> > > create mode 100644 kernel/Kconfig.killswitch
> > > create mode 100644 kernel/killswitch.c
> > > create mode 100644 lib/test_killswitch.c
> > > create mode 100644 tools/testing/selftests/killswitch/.gitignore
> > > create mode 100644 tools/testing/selftests/killswitch/Makefile
> > > create mode 100644 tools/testing/selftests/killswitch/cve_31431_test.c
> > > create mode 100755 tools/testing/selftests/killswitch/killswitch_test.sh
> >
> > If we made Lockdown an LSM, we should probably also make killswitch an LSM.
>
> I don't think killswitch can stack with other LSMs. In fact, killswitch
> can be used to bypass other LSMs, for example:
>
> echo engage security_file_open 0 > /sys/kernel/security/killswitch/control
>
> will bypass all hooks on security_file_open.
From my perspective there are two different issues here: should
killswitch be a LSM, and should killswitch leverage kprobes to be able
to "kill" security related symbols. After all, are we okay with
killswitch killing capable() and friends?
In my opinion, making killswitch an LSM is more of a procedural item
that deals with how we view a capability like killswitch. I
personally view killswitch as somewhat similar to Lockdown, which is
why I made the suggestion.
The use of kprobes, while an interesting idea, presents problems as
allowing any kernel symbol to be killed introduces the potential for
security regressions. As a reminder, some LSMs, as well as other
kernel subsystems, have mechanisms in place to restrict root and/or
enforce one-way configuration locks; while many people equate "root"
with full control, in many cases today that is not strictly correct.
Yes, kprobes have been around for some time, this is not a new
problem, but killswitch makes it far more convenient and accessible to
do dangerous things with kprobes. If killswitch makes it past the RFC
stage without any significant changes to its kill mechanism, we may
need to start considering more liberal usage of NOKPROBE_SYMBOL()
which I think would be an unfortunate casualty.
--
paul-moore.com
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-18 21:29 ` Paul Moore
@ 2026-05-18 23:22 ` Song Liu
2026-05-18 23:57 ` Paul Moore
2026-05-19 0:31 ` Sasha Levin
1 sibling, 1 reply; 48+ messages in thread
From: Song Liu @ 2026-05-18 23:22 UTC (permalink / raw)
To: Paul Moore
Cc: Sasha Levin, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh, linux-security-module
On Mon, May 18, 2026 at 2:29 PM Paul Moore <paul@paul-moore.com> wrote:
[...]
> In my opinion, making killswitch an LSM is more of a procedural item
> that deals with how we view a capability like killswitch. I
> personally view killswitch as somewhat similar to Lockdown, which is
> why I made the suggestion.
>
> The use of kprobes, while an interesting idea, presents problems as
> allowing any kernel symbol to be killed introduces the potential for
> security regressions. As a reminder, some LSMs, as well as other
> kernel subsystems, have mechanisms in place to restrict root and/or
> enforce one-way configuration locks; while many people equate "root"
> with full control, in many cases today that is not strictly correct.
>
> Yes, kprobes have been around for some time, this is not a new
> problem, but killswitch makes it far more convenient and accessible to
> do dangerous things with kprobes. If killswitch makes it past the RFC
> stage without any significant changes to its kill mechanism, we may
> need to start considering more liberal usage of NOKPROBE_SYMBOL()
> which I think would be an unfortunate casualty.
I don't think we can use NOKPROBE_SYMBOL(). There are functions
that we don't want to killswitch, but still want to trace.
Thanks,
Song
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-18 23:22 ` Song Liu
@ 2026-05-18 23:57 ` Paul Moore
2026-05-19 0:01 ` Song Liu
2026-05-19 0:21 ` Sasha Levin
0 siblings, 2 replies; 48+ messages in thread
From: Paul Moore @ 2026-05-18 23:57 UTC (permalink / raw)
To: Song Liu
Cc: Sasha Levin, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh, linux-security-module
On Mon, May 18, 2026 at 7:23 PM Song Liu <song@kernel.org> wrote:
> On Mon, May 18, 2026 at 2:29 PM Paul Moore <paul@paul-moore.com> wrote:
> [...]
> > In my opinion, making killswitch an LSM is more of a procedural item
> > that deals with how we view a capability like killswitch. I
> > personally view killswitch as somewhat similar to Lockdown, which is
> > why I made the suggestion.
> >
> > The use of kprobes, while an interesting idea, presents problems as
> > allowing any kernel symbol to be killed introduces the potential for
> > security regressions. As a reminder, some LSMs, as well as other
> > kernel subsystems, have mechanisms in place to restrict root and/or
> > enforce one-way configuration locks; while many people equate "root"
> > with full control, in many cases today that is not strictly correct.
> >
> > Yes, kprobes have been around for some time, this is not a new
> > problem, but killswitch makes it far more convenient and accessible to
> > do dangerous things with kprobes. If killswitch makes it past the RFC
> > stage without any significant changes to its kill mechanism, we may
> > need to start considering more liberal usage of NOKPROBE_SYMBOL()
> > which I think would be an unfortunate casualty.
>
> I don't think we can use NOKPROBE_SYMBOL(). There are functions
> that we don't want to killswitch, but still want to trace.
That was exactly my point, but we need to figure something out so
killswitch doesn't make it easier to cause a regression.
--
paul-moore.com
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-18 23:57 ` Paul Moore
@ 2026-05-19 0:01 ` Song Liu
2026-05-19 2:55 ` Paul Moore
2026-05-19 0:21 ` Sasha Levin
1 sibling, 1 reply; 48+ messages in thread
From: Song Liu @ 2026-05-19 0:01 UTC (permalink / raw)
To: Paul Moore
Cc: Sasha Levin, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh, linux-security-module
On Mon, May 18, 2026 at 4:57 PM Paul Moore <paul@paul-moore.com> wrote:
>
> On Mon, May 18, 2026 at 7:23 PM Song Liu <song@kernel.org> wrote:
> > On Mon, May 18, 2026 at 2:29 PM Paul Moore <paul@paul-moore.com> wrote:
> > [...]
> > > In my opinion, making killswitch an LSM is more of a procedural item
> > > that deals with how we view a capability like killswitch. I
> > > personally view killswitch as somewhat similar to Lockdown, which is
> > > why I made the suggestion.
> > >
> > > The use of kprobes, while an interesting idea, presents problems as
> > > allowing any kernel symbol to be killed introduces the potential for
> > > security regressions. As a reminder, some LSMs, as well as other
> > > kernel subsystems, have mechanisms in place to restrict root and/or
> > > enforce one-way configuration locks; while many people equate "root"
> > > with full control, in many cases today that is not strictly correct.
> > >
> > > Yes, kprobes have been around for some time, this is not a new
> > > problem, but killswitch makes it far more convenient and accessible to
> > > do dangerous things with kprobes. If killswitch makes it past the RFC
> > > stage without any significant changes to its kill mechanism, we may
> > > need to start considering more liberal usage of NOKPROBE_SYMBOL()
> > > which I think would be an unfortunate casualty.
> >
> > I don't think we can use NOKPROBE_SYMBOL(). There are functions
> > that we don't want to killswitch, but still want to trace.
>
> That was exactly my point, but we need to figure something out so
> killswitch doesn't make it easier to cause a regression.
killswitch is making it easier to fix a CVE. It can surely make it easier
to cause a regression. AFAICT, the only protection here is "it is only
for root".
Thanks,
Song
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-19 0:01 ` Song Liu
@ 2026-05-19 2:55 ` Paul Moore
0 siblings, 0 replies; 48+ messages in thread
From: Paul Moore @ 2026-05-19 2:55 UTC (permalink / raw)
To: Song Liu
Cc: Sasha Levin, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh, linux-security-module
On Mon, May 18, 2026 at 8:01 PM Song Liu <song@kernel.org> wrote:
> On Mon, May 18, 2026 at 4:57 PM Paul Moore <paul@paul-moore.com> wrote:
> > On Mon, May 18, 2026 at 7:23 PM Song Liu <song@kernel.org> wrote:
> > > On Mon, May 18, 2026 at 2:29 PM Paul Moore <paul@paul-moore.com> wrote:
> > > [...]
> > > > In my opinion, making killswitch an LSM is more of a procedural item
> > > > that deals with how we view a capability like killswitch. I
> > > > personally view killswitch as somewhat similar to Lockdown, which is
> > > > why I made the suggestion.
> > > >
> > > > The use of kprobes, while an interesting idea, presents problems as
> > > > allowing any kernel symbol to be killed introduces the potential for
> > > > security regressions. As a reminder, some LSMs, as well as other
> > > > kernel subsystems, have mechanisms in place to restrict root and/or
> > > > enforce one-way configuration locks; while many people equate "root"
> > > > with full control, in many cases today that is not strictly correct.
> > > >
> > > > Yes, kprobes have been around for some time, this is not a new
> > > > problem, but killswitch makes it far more convenient and accessible to
> > > > do dangerous things with kprobes. If killswitch makes it past the RFC
> > > > stage without any significant changes to its kill mechanism, we may
> > > > need to start considering more liberal usage of NOKPROBE_SYMBOL()
> > > > which I think would be an unfortunate casualty.
> > >
> > > I don't think we can use NOKPROBE_SYMBOL(). There are functions
> > > that we don't want to killswitch, but still want to trace.
> >
> > That was exactly my point, but we need to figure something out so
> > killswitch doesn't make it easier to cause a regression.
>
> killswitch is making it easier to fix a CVE. It can surely make it easier
> to cause a regression. AFAICT, the only protection here is "it is only
> for root".
As I mentioned earlier, several LSMs have the ability to restrict root
beyond what is possible with traditional Linux accesscontrols. For
example, with SELinux one could deny root a specific privilege while
also blocking changes to the SELinux policy; the root user would not
be able to restore that privilege without rebooting the system.
On a killswitch enabled system the ability to restrict root is lost as
root would be able to kill the enforcement of those access controls.
Presumably one could have the LSM block access to killswitch in this
particular case, but that defeats the purpose doesn't it?
The audit subsystem also has a somewhat similar one-way configuration
lock, which when set does not allow even root to unlock it, a reboot
is required. By a bit of luck with regards to how the code is
written*, it may not be vulnerable to a killswitch regression but I do
wonder if there are other similar things in the kernel which would
have the same type of problem.
* This is probably the first time I think I've ever considered myself
lucky with respect to the audit code implementation.
--
paul-moore.com
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-18 23:57 ` Paul Moore
2026-05-19 0:01 ` Song Liu
@ 2026-05-19 0:21 ` Sasha Levin
1 sibling, 0 replies; 48+ messages in thread
From: Sasha Levin @ 2026-05-19 0:21 UTC (permalink / raw)
To: Paul Moore
Cc: Song Liu, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh, linux-security-module
On Mon, May 18, 2026 at 07:57:37PM -0400, Paul Moore wrote:
>On Mon, May 18, 2026 at 7:23 PM Song Liu <song@kernel.org> wrote:
>> On Mon, May 18, 2026 at 2:29 PM Paul Moore <paul@paul-moore.com> wrote:
>> [...]
>> > In my opinion, making killswitch an LSM is more of a procedural item
>> > that deals with how we view a capability like killswitch. I
>> > personally view killswitch as somewhat similar to Lockdown, which is
>> > why I made the suggestion.
>> >
>> > The use of kprobes, while an interesting idea, presents problems as
>> > allowing any kernel symbol to be killed introduces the potential for
>> > security regressions. As a reminder, some LSMs, as well as other
>> > kernel subsystems, have mechanisms in place to restrict root and/or
>> > enforce one-way configuration locks; while many people equate "root"
>> > with full control, in many cases today that is not strictly correct.
>> >
>> > Yes, kprobes have been around for some time, this is not a new
>> > problem, but killswitch makes it far more convenient and accessible to
>> > do dangerous things with kprobes. If killswitch makes it past the RFC
>> > stage without any significant changes to its kill mechanism, we may
>> > need to start considering more liberal usage of NOKPROBE_SYMBOL()
>> > which I think would be an unfortunate casualty.
>>
>> I don't think we can use NOKPROBE_SYMBOL(). There are functions
>> that we don't want to killswitch, but still want to trace.
>
>That was exactly my point, but we need to figure something out so
>killswitch doesn't make it easier to cause a regression.
At this point it sounds like you're trying to stop root from shooting itself in
the foot, which we always avoided doing.
killswitch doesn't add any new functionality in that regard: rood can always
load a module, write to /dev/mem, etc which would allow it to do the same
thing. It's just a more convenient way to do it.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-18 21:29 ` Paul Moore
2026-05-18 23:22 ` Song Liu
@ 2026-05-19 0:31 ` Sasha Levin
2026-05-19 3:08 ` Paul Moore
2026-05-19 5:29 ` Song Liu
1 sibling, 2 replies; 48+ messages in thread
From: Sasha Levin @ 2026-05-19 0:31 UTC (permalink / raw)
To: Paul Moore
Cc: Song Liu, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh, linux-security-module
On Mon, May 18, 2026 at 05:29:32PM -0400, Paul Moore wrote:
>From my perspective there are two different issues here: should
>killswitch be a LSM, and should killswitch leverage kprobes to be able
>to "kill" security related symbols. After all, are we okay with
>killswitch killing capable() and friends?
killswitch doesn't do it on it's own. It may be instructed by root to do that,
at which point that is root's problem.
>In my opinion, making killswitch an LSM is more of a procedural item
>that deals with how we view a capability like killswitch. I
>personally view killswitch as somewhat similar to Lockdown, which is
>why I made the suggestion.
Maybe I'm not all that familiar with LSMs, but we would need to be able to stop
"random" code paths from executing, and I don't think we can create LSM hooks
at that granularity, no?
>The use of kprobes, while an interesting idea, presents problems as
>allowing any kernel symbol to be killed introduces the potential for
>security regressions. As a reminder, some LSMs, as well as other
>kernel subsystems, have mechanisms in place to restrict root and/or
>enforce one-way configuration locks; while many people equate "root"
>with full control, in many cases today that is not strictly correct.
killswitch "complies" with lockdown. Is there a different scenario which we
should be blocking?
>Yes, kprobes have been around for some time, this is not a new
>problem, but killswitch makes it far more convenient and accessible to
>do dangerous things with kprobes. If killswitch makes it past the RFC
>stage without any significant changes to its kill mechanism, we may
>need to start considering more liberal usage of NOKPROBE_SYMBOL()
>which I think would be an unfortunate casualty.
Why? If I don't really mind the security impact, I want to be able to have a
killswitch-like interface on my systems. If an attacker is in my systems,
killswitch is the least of my concerns I think.
If you are security concious, just don't enable CONFIG_KILLSWITCH?
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-19 0:31 ` Sasha Levin
@ 2026-05-19 3:08 ` Paul Moore
2026-05-19 20:00 ` Sasha Levin
2026-05-19 5:29 ` Song Liu
1 sibling, 1 reply; 48+ messages in thread
From: Paul Moore @ 2026-05-19 3:08 UTC (permalink / raw)
To: Sasha Levin
Cc: Song Liu, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh, linux-security-module
On Mon, May 18, 2026 at 8:31 PM Sasha Levin <sashal@kernel.org> wrote:
> On Mon, May 18, 2026 at 05:29:32PM -0400, Paul Moore wrote:
> >From my perspective there are two different issues here: should
> >killswitch be a LSM, and should killswitch leverage kprobes to be able
> >to "kill" security related symbols. After all, are we okay with
> >killswitch killing capable() and friends?
>
> killswitch doesn't do it on it's own. It may be instructed by root to do that,
> at which point that is root's problem.
As I mentioned previously, there are cases where we can restrict
root's privileges today, but a functional killswitch would allow that
restriction to be bypassed. My last email to Song has an example with
SELinux.
> >In my opinion, making killswitch an LSM is more of a procedural item
> >that deals with how we view a capability like killswitch. I
> >personally view killswitch as somewhat similar to Lockdown, which is
> >why I made the suggestion.
>
> Maybe I'm not all that familiar with LSMs, but we would need to be able to stop
> "random" code paths from executing, and I don't think we can create LSM hooks
> at that granularity, no?
I don't see any LSM hooks in this revision of killswitch, and as long
as it is based on a kprobes I can't imagine it would ever use any. As
I mentioned above, my killswitch-as-a-LSM comment is primarily about
killswitch filling a role very similar to Lockdown.
> >The use of kprobes, while an interesting idea, presents problems as
> >allowing any kernel symbol to be killed introduces the potential for
> >security regressions. As a reminder, some LSMs, as well as other
> >kernel subsystems, have mechanisms in place to restrict root and/or
> >enforce one-way configuration locks; while many people equate "root"
> >with full control, in many cases today that is not strictly correct.
>
> killswitch "complies" with lockdown. Is there a different scenario which we
> should be blocking?
See the SELinux example I mentioned in my email to Song.
> >Yes, kprobes have been around for some time, this is not a new
> >problem, but killswitch makes it far more convenient and accessible to
> >do dangerous things with kprobes. If killswitch makes it past the RFC
> >stage without any significant changes to its kill mechanism, we may
> >need to start considering more liberal usage of NOKPROBE_SYMBOL()
> >which I think would be an unfortunate casualty.
>
> Why? If I don't really mind the security impact, I want to be able to have a
> killswitch-like interface on my systems. If an attacker is in my systems,
> killswitch is the least of my concerns I think.
>
> If you are security concious, just don't enable CONFIG_KILLSWITCH?
Isn't the whole point of killswitch to have it enabled everywhere
because you never know when you might want/need it?
--
paul-moore.com
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-19 3:08 ` Paul Moore
@ 2026-05-19 20:00 ` Sasha Levin
2026-05-19 20:50 ` Paul Moore
0 siblings, 1 reply; 48+ messages in thread
From: Sasha Levin @ 2026-05-19 20:00 UTC (permalink / raw)
To: Paul Moore
Cc: Song Liu, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh, linux-security-module
On Mon, May 18, 2026 at 11:08:38PM -0400, Paul Moore wrote:
>On Mon, May 18, 2026 at 8:31 PM Sasha Levin <sashal@kernel.org> wrote:
>> On Mon, May 18, 2026 at 05:29:32PM -0400, Paul Moore wrote:
>> >From my perspective there are two different issues here: should
>> >killswitch be a LSM, and should killswitch leverage kprobes to be able
>> >to "kill" security related symbols. After all, are we okay with
>> >killswitch killing capable() and friends?
>>
>> killswitch doesn't do it on it's own. It may be instructed by root to do that,
>> at which point that is root's problem.
>
>As I mentioned previously, there are cases where we can restrict
>root's privileges today, but a functional killswitch would allow that
>restriction to be bypassed. My last email to Song has an example with
>SELinux.
This would be handled by just disabling killswitch in those scenarios like how
we do with lockdown, no?
>> >In my opinion, making killswitch an LSM is more of a procedural item
>> >that deals with how we view a capability like killswitch. I
>> >personally view killswitch as somewhat similar to Lockdown, which is
>> >why I made the suggestion.
>>
>> Maybe I'm not all that familiar with LSMs, but we would need to be able to stop
>> "random" code paths from executing, and I don't think we can create LSM hooks
>> at that granularity, no?
>
>I don't see any LSM hooks in this revision of killswitch, and as long
>as it is based on a kprobes I can't imagine it would ever use any. As
>I mentioned above, my killswitch-as-a-LSM comment is primarily about
>killswitch filling a role very similar to Lockdown.
My question was more about how to structure killswitch as an LSM. I want to be
able to poke at pretty much any function in the kernel, rather than restrict
access to a known list of functions.
>> >The use of kprobes, while an interesting idea, presents problems as
>> >allowing any kernel symbol to be killed introduces the potential for
>> >security regressions. As a reminder, some LSMs, as well as other
>> >kernel subsystems, have mechanisms in place to restrict root and/or
>> >enforce one-way configuration locks; while many people equate "root"
>> >with full control, in many cases today that is not strictly correct.
>>
>> killswitch "complies" with lockdown. Is there a different scenario which we
>> should be blocking?
>
>See the SELinux example I mentioned in my email to Song.
>
>> >Yes, kprobes have been around for some time, this is not a new
>> >problem, but killswitch makes it far more convenient and accessible to
>> >do dangerous things with kprobes. If killswitch makes it past the RFC
>> >stage without any significant changes to its kill mechanism, we may
>> >need to start considering more liberal usage of NOKPROBE_SYMBOL()
>> >which I think would be an unfortunate casualty.
>>
>> Why? If I don't really mind the security impact, I want to be able to have a
>> killswitch-like interface on my systems. If an attacker is in my systems,
>> killswitch is the least of my concerns I think.
>>
>> If you are security concious, just don't enable CONFIG_KILLSWITCH?
>
>Isn't the whole point of killswitch to have it enabled everywhere
>because you never know when you might want/need it?
Right. We have different usecases. If you want selinux/lockdown/etc and a
really crippled root, that should be an option. If you choose to allow
something like killswitch, it should be an option too.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-19 20:00 ` Sasha Levin
@ 2026-05-19 20:50 ` Paul Moore
0 siblings, 0 replies; 48+ messages in thread
From: Paul Moore @ 2026-05-19 20:50 UTC (permalink / raw)
To: Sasha Levin
Cc: Song Liu, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh, linux-security-module
On Tue, May 19, 2026 at 4:00 PM Sasha Levin <sashal@kernel.org> wrote:
> On Mon, May 18, 2026 at 11:08:38PM -0400, Paul Moore wrote:
> >On Mon, May 18, 2026 at 8:31 PM Sasha Levin <sashal@kernel.org> wrote:
> >> On Mon, May 18, 2026 at 05:29:32PM -0400, Paul Moore wrote:
> >> >From my perspective there are two different issues here: should
> >> >killswitch be a LSM, and should killswitch leverage kprobes to be able
> >> >to "kill" security related symbols. After all, are we okay with
> >> >killswitch killing capable() and friends?
> >>
> >> killswitch doesn't do it on it's own. It may be instructed by root to do that,
> >> at which point that is root's problem.
> >
> >As I mentioned previously, there are cases where we can restrict
> >root's privileges today, but a functional killswitch would allow that
> >restriction to be bypassed. My last email to Song has an example with
> >SELinux.
>
> This would be handled by just disabling killswitch in those scenarios like how
> we do with lockdown, no?
One could presumably deny access to killswitch, but that pushes the
burden of choice onto the users/admins. Yes, that is the easy way to
solve thorny use case conflicts like this, but it would be nice if we
could do better for those who have to deal with this in the wild.
> >> >In my opinion, making killswitch an LSM is more of a procedural item
> >> >that deals with how we view a capability like killswitch. I
> >> >personally view killswitch as somewhat similar to Lockdown, which is
> >> >why I made the suggestion.
> >>
> >> Maybe I'm not all that familiar with LSMs, but we would need to be able to stop
> >> "random" code paths from executing, and I don't think we can create LSM hooks
> >> at that granularity, no?
> >
> >I don't see any LSM hooks in this revision of killswitch, and as long
> >as it is based on a kprobes I can't imagine it would ever use any. As
> >I mentioned above, my killswitch-as-a-LSM comment is primarily about
> >killswitch filling a role very similar to Lockdown.
>
> My question was more about how to structure killswitch as an LSM. I want to be
> able to poke at pretty much any function in the kernel, rather than restrict
> access to a known list of functions.
Well, like I said in my last reply to you, I can't imagine a kprobes
based killswitch would need to worry about the LSM hooks. Structuring
killswitch as an LSM would be mostly a few lines of code to register
it as an LSM and that's about it. Benefits would be minor, and likely
a matter of opinion, it's mostly about how we view something like
killswitch in the kernel. If we view it as a security mechanism
similar to lockdown, then it makes sense as a LSM, if we view this as
a completely different thing then it can be whatever it wants to be.
--
paul-moore.com
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-19 0:31 ` Sasha Levin
2026-05-19 3:08 ` Paul Moore
@ 2026-05-19 5:29 ` Song Liu
2026-05-19 20:33 ` Paul Moore
1 sibling, 1 reply; 48+ messages in thread
From: Song Liu @ 2026-05-19 5:29 UTC (permalink / raw)
To: Sasha Levin
Cc: Paul Moore, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh, linux-security-module
On Mon, May 18, 2026 at 5:31 PM Sasha Levin <sashal@kernel.org> wrote:
>
> On Mon, May 18, 2026 at 05:29:32PM -0400, Paul Moore wrote:
> >From my perspective there are two different issues here: should
> >killswitch be a LSM, and should killswitch leverage kprobes to be able
> >to "kill" security related symbols. After all, are we okay with
> >killswitch killing capable() and friends?
>
> killswitch doesn't do it on it's own. It may be instructed by root to do that,
> at which point that is root's problem.
>
> >In my opinion, making killswitch an LSM is more of a procedural item
> >that deals with how we view a capability like killswitch. I
> >personally view killswitch as somewhat similar to Lockdown, which is
> >why I made the suggestion.
>
> Maybe I'm not all that familiar with LSMs, but we would need to be able to stop
> "random" code paths from executing, and I don't think we can create LSM hooks
> at that granularity, no?
There are much fewer LSM hooks than ftrace-able (killswitch-able)
functions. In this sense, killswitch is more granular. However, LSM
hooks allow LSM policies to make different decisions for different
arguments. In this sense, LSM hooks are more granular than
killswitch, as killswitch can only set a fixed return value for each
engaged function.
With current LSM solutions, we can mitigate issues like Copy Fail
without breaking other features of the system. In [1], Cloudflare
shared how they mitigate Copy Fail with BPF LSM.
Thanks,
Song
[1] https://blog.cloudflare.com/copy-fail-linux-vulnerability-mitigation/
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH] killswitch: add per-function short-circuit mitigation primitive
2026-05-19 5:29 ` Song Liu
@ 2026-05-19 20:33 ` Paul Moore
0 siblings, 0 replies; 48+ messages in thread
From: Paul Moore @ 2026-05-19 20:33 UTC (permalink / raw)
To: Song Liu
Cc: Sasha Levin, corbet, akpm, skhan, linux-doc, linux-kernel,
linux-kselftest, gregkh, linux-security-module
On Tue, May 19, 2026 at 1:29 AM Song Liu <song@kernel.org> wrote:
> On Mon, May 18, 2026 at 5:31 PM Sasha Levin <sashal@kernel.org> wrote:
> >
> > On Mon, May 18, 2026 at 05:29:32PM -0400, Paul Moore wrote:
> > >From my perspective there are two different issues here: should
> > >killswitch be a LSM, and should killswitch leverage kprobes to be able
> > >to "kill" security related symbols. After all, are we okay with
> > >killswitch killing capable() and friends?
> >
> > killswitch doesn't do it on it's own. It may be instructed by root to do that,
> > at which point that is root's problem.
> >
> > >In my opinion, making killswitch an LSM is more of a procedural item
> > >that deals with how we view a capability like killswitch. I
> > >personally view killswitch as somewhat similar to Lockdown, which is
> > >why I made the suggestion.
> >
> > Maybe I'm not all that familiar with LSMs, but we would need to be able to stop
> > "random" code paths from executing, and I don't think we can create LSM hooks
> > at that granularity, no?
>
> There are much fewer LSM hooks than ftrace-able (killswitch-able)
> functions. In this sense, killswitch is more granular.
I don't know if I would say it is necessarily more granular as its
ability to filter access is limited to a breakpoint set on a symbol,
but killswitch definitely has a larger quantity of control points.
> However, LSM
> hooks allow LSM policies to make different decisions for different
> arguments. In this sense, LSM hooks are more granular than
> killswitch, as killswitch can only set a fixed return value for each
> engaged function.
Yes, I think we agree here.
> With current LSM solutions, we can mitigate issues like Copy Fail
> without breaking other features of the system. In [1], Cloudflare
> shared how they mitigate Copy Fail with BPF LSM.
... and Android has been shown to not be vulnerable in the first place
due to their use of SELinux and a well crafted SELinux policy.
--
paul-moore.com
^ permalink raw reply [flat|nested] 48+ messages in thread
end of thread, other threads:[~2026-05-19 20:50 UTC | newest]
Thread overview: 48+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-07 7:05 [PATCH] killswitch: add per-function short-circuit mitigation primitive Sasha Levin
2026-05-07 10:47 ` Greg KH
2026-05-07 13:40 ` Sasha Levin
2026-05-07 16:23 ` Greg KH
2026-05-07 15:21 ` Jonathan Corbet
2026-05-08 13:44 ` Sasha Levin
2026-05-08 15:40 ` Joshua Peisach
2026-05-08 15:48 ` Mathieu Desnoyers
2026-05-08 16:13 ` Sasha Levin
2026-05-08 16:18 ` Mathieu Desnoyers
2026-05-08 16:23 ` Sasha Levin
2026-05-08 16:26 ` Mathieu Desnoyers
2026-05-08 16:54 ` Sasha Levin
2026-05-08 20:56 ` Andrew Morton
2026-05-08 21:47 ` Sasha Levin
2026-05-08 23:49 ` Andrew Morton
2026-05-09 0:15 ` Sasha Levin
2026-05-09 0:36 ` Andrew Morton
2026-05-11 11:41 ` Breno Leitao
2026-05-11 13:07 ` Michal Hocko
2026-05-11 13:39 ` Sasha Levin
2026-05-11 13:49 ` Michal Hocko
2026-05-11 13:56 ` Sasha Levin
2026-05-11 14:25 ` Michal Hocko
2026-05-11 15:55 ` Sasha Levin
2026-05-11 16:10 ` Michal Hocko
2026-05-11 16:45 ` Sasha Levin
2026-05-11 17:10 ` Michal Hocko
2026-05-11 18:09 ` Sasha Levin
2026-05-14 14:35 ` Jiri Olsa
2026-05-11 13:40 ` Breno Leitao
2026-05-11 22:31 ` Andrew Morton
2026-05-11 23:01 ` Song Liu
2026-05-11 23:05 ` Sasha Levin
2026-05-15 3:48 ` Paul Moore
2026-05-18 6:31 ` Song Liu
2026-05-18 21:29 ` Paul Moore
2026-05-18 23:22 ` Song Liu
2026-05-18 23:57 ` Paul Moore
2026-05-19 0:01 ` Song Liu
2026-05-19 2:55 ` Paul Moore
2026-05-19 0:21 ` Sasha Levin
2026-05-19 0:31 ` Sasha Levin
2026-05-19 3:08 ` Paul Moore
2026-05-19 20:00 ` Sasha Levin
2026-05-19 20:50 ` Paul Moore
2026-05-19 5:29 ` Song Liu
2026-05-19 20:33 ` Paul Moore
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox