-
Notifications
You must be signed in to change notification settings - Fork 0
/
0006-tty_make_TIOCSTI_ioctl_require_CAP_SYS_ADMIN.patch
193 lines (168 loc) · 6.65 KB
/
0006-tty_make_TIOCSTI_ioctl_require_CAP_SYS_ADMIN.patch
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
From 7c3df637556c8f326241458b1d6758506b1ca96a Mon Sep 17 00:00:00 2001
From: Matt Brown <[email protected]>
Date: Mon, 29 May 2017 17:38:00 -0400
Subject: [PATCH] security: tty: make TIOCSTI ioctl require CAP_SYS_ADMIN
This introduces the tiocsti_restrict sysctl, whose default is controlled
via CONFIG_SECURITY_TIOCSTI_RESTRICT. When activated, this control
restricts all TIOCSTI ioctl calls from non CAP_SYS_ADMIN users.
This patch depends on patch 1/2
This patch was inspired from GRKERNSEC_HARDEN_TTY.
This patch would have prevented
https://bugzilla.redhat.com/show_bug.cgi?id=1411256 under the following
conditions:
* non-privileged container
* container run inside new user namespace
Possible effects on userland:
There could be a few user programs that would be effected by this
change.
See: <https://codesearch.debian.net/search?q=ioctl%5C%28.*TIOCSTI>
notable programs are: agetty, csh, xemacs and tcsh
However, I still believe that this change is worth it given that the
Kconfig defaults to n. This will be a feature that is turned on for the
same reason that people activate it when using grsecurity. Users of this
opt-in feature will realize that they are choosing security over some OS
features like unprivileged TIOCSTI ioctls, as should be clear in the
Kconfig help message.
Threat Model/Patch Rational:
>From grsecurity's config for GRKERNSEC_HARDEN_TTY.
| There are very few legitimate uses for this functionality and it
| has made vulnerabilities in several 'su'-like programs possible in
| the past. Even without these vulnerabilities, it provides an
| attacker with an easy mechanism to move laterally among other
| processes within the same user's compromised session.
So if one process within a tty session becomes compromised it can follow
that additional processes, that are thought to be in different security
boundaries, can be compromised as a result. When using a program like su
or sudo, these additional processes could be in a tty session where TTY
file descriptors are indeed shared over privilege boundaries.
This is also an excellent writeup about the issue:
<http://www.halfdog.net/Security/2012/TtyPushbackPrivilegeEscalation/>
When user namespaces are in use, the check for the capability
CAP_SYS_ADMIN is done against the user namespace that originally opened
the tty.
Acked-by: Serge Hallyn <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
Signed-off-by: Matt Brown <[email protected]>
Signed-off-by: Thibaut Sautereau <[email protected]>
Signed-off-by: Levente Polyak <[email protected]>
---
Documentation/admin-guide/sysctl/kernel.rst | 20 ++++++++++++++++++++
drivers/tty/tty_io.c | 8 ++++++++
include/linux/tty.h | 2 ++
kernel/sysctl.c | 14 ++++++++++++++
security/Kconfig | 13 +++++++++++++
5 files changed, 57 insertions(+)
diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
index d92e933127ff6..59b1ee24aed4c 100644
--- a/Documentation/admin-guide/sysctl/kernel.rst
+++ b/Documentation/admin-guide/sysctl/kernel.rst
@@ -1385,6 +1385,26 @@ If a value outside of this range is written to ``threads-max`` an
``EINVAL`` error occurs.
+tiocsti_restrict
+================
+
+This toggle indicates whether unprivileged users are prevented from using the
+``TIOCSTI`` ioctl to inject commands into other processes which share a tty
+session.
+
+= ============================================================================
+0 No restriction, except the default one of only being able to inject commands
+ into one's own tty.
+1 Users must have ``CAP_SYS_ADMIN`` to use the ``TIOCSTI`` ioctl.
+= ============================================================================
+
+When user namespaces are in use, the check for ``CAP_SYS_ADMIN`` is done
+against the user namespace that originally opened the tty.
+
+The kernel config option ``CONFIG_SECURITY_TIOCSTI_RESTRICT`` sets the default
+value of ``tiocsti_restrict``.
+
+
traceoff_on_warning
===================
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 00e8a4bb74c16..573713186b0e8 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -2300,11 +2300,19 @@ static int tty_fasync(int fd, struct file *filp, int on)
* FIXME: may race normal receive processing
*/
+int tiocsti_restrict = IS_ENABLED(CONFIG_SECURITY_TIOCSTI_RESTRICT);
+
static int tiocsti(struct tty_struct *tty, char __user *p)
{
char ch, mbz = 0;
struct tty_ldisc *ld;
+ if (tiocsti_restrict &&
+ !ns_capable(tty->owner_user_ns, CAP_SYS_ADMIN)) {
+ dev_warn_ratelimited(tty->dev,
+ "Denied TIOCSTI ioctl for non-privileged process\n");
+ return -EPERM;
+ }
if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
return -EPERM;
if (get_user(ch, p))
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 85f6c554a6185..b5f4d9cd20a0b 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -351,6 +351,8 @@ struct tty_file_private {
struct list_head list;
};
+extern int tiocsti_restrict;
+
/* tty magic number */
#define TTY_MAGIC 0x5401
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 5c4bd8a2dd701..36470990b2e6e 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -106,6 +106,9 @@
#ifdef CONFIG_USER_NS
#include <linux/user_namespace.h>
#endif
+#if defined CONFIG_TTY
+#include <linux/tty.h>
+#endif
#if defined(CONFIG_SYSCTL)
@@ -2295,6 +2298,17 @@ static struct ctl_table kern_table[] = {
.extra1 = SYSCTL_ZERO,
.extra2 = &two,
},
+#endif
+#if defined CONFIG_TTY
+ {
+ .procname = "tiocsti_restrict",
+ .data = &tiocsti_restrict,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax_sysadmin,
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = SYSCTL_ONE,
+ },
#endif
{
.procname = "device_sidechannel_restrict",
diff --git a/security/Kconfig b/security/Kconfig
index 2348ff7d4e1d6..bbbe7760e5cde 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -29,6 +29,19 @@ config SECURITY_PERF_EVENTS_RESTRICT
perf_event_open syscall will be permitted unless it is
changed.
+config SECURITY_TIOCSTI_RESTRICT
+ bool "Restrict unprivileged use of tiocsti command injection"
+ default n
+ help
+ This enforces restrictions on unprivileged users injecting commands
+ into other processes which share a tty session using the TIOCSTI
+ ioctl. This option makes TIOCSTI use require CAP_SYS_ADMIN.
+
+ If this option is not selected, no restrictions will be enforced
+ unless the tiocsti_restrict sysctl is explicitly set to (1).
+
+ If you are unsure how to answer this question, answer N.
+
config SECURITY
bool "Enable different security models"
depends on SYSFS