1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
From 6bd227c9e1cf1401db656f1644498f573a6ad058 Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge.hallyn@canonical.com>
Date: Fri, 31 May 2013 19:12:12 +0100
Subject: [PATCH] add sysctl to allow disabling unprivileged CLONE_NEWUSER
This is a short-term patch. Unprivileged use of CLONE_NEWUSER
is certainly an intended feature of user namespaces. However
for at least saucy we want to make sure that, if any security
issues are found, we have a fail-safe.
[bwh: Remove unneeded binary sysctl bits]
[bwh: Keep this sysctl, but change the default to enabled]
[heftig: correct commit subject to reduce confusion]
[heftig: for 6.17, move all code into kernel/fork.c]
---
kernel/fork.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/kernel/fork.c b/kernel/fork.c
index 3da0f08615a95e..07349223afff68 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -123,6 +123,12 @@
#include <kunit/visibility.h>
+#ifdef CONFIG_USER_NS
+static int unprivileged_userns_clone = 1;
+#else
+#define unprivileged_userns_clone 1
+#endif
+
/*
* Minimum number of threads to boot the kernel
*/
@@ -1990,6 +1996,11 @@ __latent_entropy struct task_struct *copy_process(
return ERR_PTR(-EINVAL);
}
+ if ((clone_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) {
+ if (!capable(CAP_SYS_ADMIN))
+ return ERR_PTR(-EPERM);
+ }
+
/*
* Force any signals received before this point to be delivered
* before the fork happens. Collect up signals sent to multiple
@@ -3025,6 +3036,10 @@ static int check_unshare_flags(unsigned long unshare_flags)
if (!current_is_single_threaded())
return -EINVAL;
}
+ if ((unshare_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) {
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ }
return 0;
}
@@ -3255,6 +3270,15 @@ static const struct ctl_table fork_sysctl_table[] = {
.mode = 0644,
.proc_handler = sysctl_max_threads,
},
+#ifdef CONFIG_USER_NS
+ {
+ .procname = "unprivileged_userns_clone",
+ .data = &unprivileged_userns_clone,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+#endif
};
static int __init init_fork_sysctl(void)
|