[PATCH RFC v3 71/90] umh: run no program for a task of a cell
From: Josef Bacik
Date: Thu Nov 05 2026 - 10:28:11 EST
Some things that a task does make the kernel run a program:
- socket() for a protocol family that is not loaded runs modprobe, and so
do several other lookups by name.
- request_key() for a key that does not exist runs /sbin/request-key.
- A crash runs the program that core_pattern pipes core dumps to.
The program runs as root in the initial namespaces, and the task has
influence over its arguments or its input. None of this requires a
capability. For containers it has long been a way to attack the host: any
module on disk can be loaded into the kernel, with whatever bugs it has,
and the helper programs have had bugs of their own.
A cell only has what it is given, and here the host acts on its behalf.
All of these cases end up in call_usermodehelper_exec(), in the context of
the task that caused them. Refuse there, so that cases which are added
later are covered too.
The original request then fails. socket() returns EAFNOSUPPORT, as for any
protocol that is not available, and request_key() returns EPERM. A module
that a cell is supposed to use has to be loaded beforehand.
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
---
kernel/umh.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/kernel/umh.c b/kernel/umh.c
index 512dc018a50b..e812a0008cfc 100644
--- a/kernel/umh.c
+++ b/kernel/umh.c
@@ -6,6 +6,7 @@
#include <linux/sched.h>
#include <linux/sched/task.h>
#include <linux/binfmts.h>
+#include <linux/cell_ids.h>
#include <linux/syscalls.h>
#include <linux/unistd.h>
#include <linux/umh.h>
@@ -406,6 +407,14 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
call_usermodehelper_freeinfo(sub_info);
return -EINVAL;
}
+ /*
+ * The helper runs as root, on the host, in no namespace but the first. That
+ * is not for a task of a cell to bring about, whatever it is it asked for.
+ */
+ if (userns_is_cell(current_user_ns())) {
+ call_usermodehelper_freeinfo(sub_info);
+ return -EPERM;
+ }
helper_lock();
if (usermodehelper_disabled) {
retval = -EBUSY;
--
2.55.0