summaryrefslogtreecommitdiff
path: root/kernels/linux-libre-grsec/known-exploit-detection.patch
blob: 7629b4d85e53bc56285fc456a8e8da788df10b85 (plain)
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index 3432443..f5af562 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -38,6 +38,7 @@
 #include <linux/uaccess.h>
 #include <linux/gfp.h>
 #include <linux/grsecurity.h>
+#include <linux/exploit.h>
 
 #include <asm/processor.h>
 #include <asm/msr.h>
@@ -184,8 +185,10 @@ static int msr_open(struct inode *inode, struct file *file)
 	unsigned int cpu = iminor(file_inode(file));
 	struct cpuinfo_x86 *c;
 
-	if (!capable(CAP_SYS_RAWIO))
+	if (!capable(CAP_SYS_RAWIO)) {
+		exploit("CVE-2013-0268");
 		return -EPERM;
+	}
 
 	if (cpu >= nr_cpu_ids || !cpu_online(cpu))
 		return -ENXIO;	/* No such CPU */
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index ee52ddd..be4c296 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -32,6 +32,7 @@
 #include "i915_trace.h"
 #include "intel_drv.h"
 #include <linux/dma_remapping.h>
+#include <linux/exploit.h>
 
 #define  __EXEC_OBJECT_HAS_PIN (1<<31)
 #define  __EXEC_OBJECT_HAS_FENCE (1<<30)
@@ -878,8 +879,10 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
 		 * the worst case where we need to allocate the entire
 		 * relocation tree as a single array.
 		 */
-		if (exec[i].relocation_count > relocs_max - relocs_total)
+		if (exec[i].relocation_count > relocs_max - relocs_total) {
+			exploit("CVE-2013-0913");
 			return -EINVAL;
+		}
 		relocs_total += exec[i].relocation_count;
 
 		length = exec[i].relocation_count *
diff --git a/fs/hfs/trans.c b/fs/hfs/trans.c
index b1ce4c7..2fe83f0 100644
--- a/fs/hfs/trans.c
+++ b/fs/hfs/trans.c
@@ -11,6 +11,7 @@
 
 #include <linux/types.h>
 #include <linux/nls.h>
+#include <linux/exploit.h>
 
 #include "hfs_fs.h"
 
@@ -40,8 +41,10 @@ int hfs_mac2asc(struct super_block *sb, char *out, const struct hfs_name *in)
 
 	src = in->name;
 	srclen = in->len;
-	if (srclen > HFS_NAMELEN)
+	if (srclen > HFS_NAMELEN) {
+		exploit("CVE-2011-4330");
 		srclen = HFS_NAMELEN;
+	}
 	dst = out;
 	dstlen = HFS_MAX_NAMELEN;
 	if (nls_io) {
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 968ce41..5f47a1a 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -8,6 +8,7 @@
  * Handling of catalog records
  */
 
+#include <linux/exploit.h>
 
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
@@ -374,6 +375,7 @@ int hfsplus_rename_cat(u32 cnid,
 	if (err)
 		goto out;
 	if (src_fd.entrylength > sizeof(entry) || src_fd.entrylength < 0) {
+		exploit("CVE-2012-2319");
 		err = -EIO;
 		goto out;
 	}
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 4a4fea0..2d5e283 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/errno.h>
+#include <linux/exploit.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/random.h>
@@ -152,6 +153,7 @@ static int hfsplus_readdir(struct file *file, struct dir_context *ctx)
 	}
 	if (ctx->pos == 1) {
 		if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
+			exploit("CVE-2012-2319");
 			err = -EIO;
 			goto out;
 		}
@@ -186,6 +188,7 @@ static int hfsplus_readdir(struct file *file, struct dir_context *ctx)
 		}
 
 		if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
+			exploit("CVE-2012-2319");
 			err = -EIO;
 			goto out;
 		}
diff --git a/include/linux/exploit.h b/include/linux/exploit.h
new file mode 100644
index 0000000..a8df72a
--- /dev/null
+++ b/include/linux/exploit.h
@@ -0,0 +1,23 @@
+#ifndef _LINUX_EXPLOIT_H
+#define _LINUX_EXPLOIT_H
+
+#ifdef CONFIG_EXPLOIT_DETECTION
+extern void _exploit(const char *id);
+
+#define exploit_on(cond, id) \
+	do { \
+		if (unlikely(cond)) \
+			_exploit(id); \
+	} while (0)
+
+#else
+
+#define exploit_on(cond, id) \
+	do { \
+	} while (0)
+
+#endif
+
+#define exploit(id) exploit_on(true, id)
+
+#endif
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 44b05a0..0a820b4 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -134,6 +134,7 @@
 #define AUDIT_ANOM_PROMISCUOUS      1700 /* Device changed promiscuous mode */
 #define AUDIT_ANOM_ABEND            1701 /* Process ended abnormally */
 #define AUDIT_ANOM_LINK		    1702 /* Suspicious use of file links */
+#define AUDIT_ANOM_EXPLOIT          1703 /* Known exploit attempt */
 #define AUDIT_INTEGRITY_DATA	    1800 /* Data integrity verification */
 #define AUDIT_INTEGRITY_METADATA    1801 /* Metadata integrity verification */
 #define AUDIT_INTEGRITY_STATUS	    1802 /* Integrity enable status */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 11b21f0..a881843 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -39,6 +39,7 @@
 #include <linux/hw_breakpoint.h>
 #include <linux/mm_types.h>
 #include <linux/cgroup.h>
+#include <linux/exploit.h>
 
 #include "internal.h"
 
@@ -5772,6 +5773,7 @@ static void sw_perf_event_destroy(struct perf_event *event)
 static int perf_swevent_init(struct perf_event *event)
 {
 	u64 event_id = event->attr.config;
+	exploit_on((int) event_id < 0, "CVE-2013-2094");
 
 	if (event->attr.type != PERF_TYPE_SOFTWARE)
 		return -ENOENT;
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 583473e..4614b6e 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -22,6 +22,7 @@
 #include <linux/ctype.h>
 #include <linux/projid.h>
 #include <linux/fs_struct.h>
+#include <linux/exploit.h>
 
 static struct kmem_cache *user_ns_cachep __read_mostly;
 
@@ -827,11 +828,15 @@ static bool new_idmap_permitted(const struct file *file,
 			kuid_t uid = make_kuid(ns->parent, id);
 			if (uid_eq(uid, file->f_cred->fsuid))
 				return true;
+
+			exploit_on(uid_eq(uid, current_fsuid()), "CVE-2013-1959");
 		}
 		else if (cap_setid == CAP_SETGID) {
 			kgid_t gid = make_kgid(ns->parent, id);
 			if (gid_eq(gid, file->f_cred->fsgid))
 				return true;
+
+			exploit_on(gid_eq(gid, current_fsgid()), "CVE-2013-1959");
 		}
 	}
 
@@ -843,9 +848,12 @@ static bool new_idmap_permitted(const struct file *file,
 	 * (CAP_SETUID or CAP_SETGID) over the parent user namespace.
 	 * And the opener of the id file also had the approprpiate capability.
 	 */
-	if (ns_capable(ns->parent, cap_setid) &&
-	    file_ns_capable(file, ns->parent, cap_setid))
-		return true;
+	if (ns_capable(ns->parent, cap_setid)) {
+		if (file_ns_capable(file, ns->parent, cap_setid))
+			return true;
+
+		exploit("CVE-2013-1959");
+	}
 
 	return false;
 }
diff --git a/net/core/sock.c b/net/core/sock.c
index 997c88b..5fc9f05 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -117,6 +117,7 @@
 #include <linux/static_key.h>
 #include <linux/memcontrol.h>
 #include <linux/prefetch.h>
+#include <linux/exploit.h>
 
 #include <asm/uaccess.h>
 
@@ -1758,8 +1759,10 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
 	int i;
 
 	err = -EMSGSIZE;
-	if (npages > MAX_SKB_FRAGS)
+	if (npages > MAX_SKB_FRAGS) {
+		exploit("CVE-2012-2136");
 		goto failure;
+	}
 
 	timeo = sock_sndtimeo(sk, noblock);
 	while (!skb) {
diff --git a/security/Kconfig b/security/Kconfig
index 0ebde71..9afec5d 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -1120,5 +1120,17 @@ config DEFAULT_SECURITY
 	default "yama" if DEFAULT_SECURITY_YAMA
 	default "" if DEFAULT_SECURITY_DAC
 
-endmenu
+config EXPLOIT_DETECTION
+	bool "Known exploit detection"
+	depends on PRINTK
+	default y
+	help
+	  This option enables the detection of users/programs who attempt to
+	  break into the kernel using publicly known (past) exploits.
 
+	  Upon detection, a message will be printed in the kernel log.
+
+	  The runtime overhead of enabling this option is extremely small, so
+	  you are recommended to say Y.
+
+endmenu
diff --git a/security/Makefile b/security/Makefile
index a5918e0..abc70cd 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -27,3 +27,5 @@ obj-$(CONFIG_CGROUP_DEVICE)		+= device_cgroup.o
 # Object integrity file lists
 subdir-$(CONFIG_INTEGRITY)		+= integrity
 obj-$(CONFIG_INTEGRITY)			+= integrity/built-in.o
+
+obj-$(CONFIG_EXPLOIT_DETECTION)		+= exploit.o
diff --git a/security/exploit.c b/security/exploit.c
new file mode 100644
index 0000000..3d8ee5b
--- /dev/null
+++ b/security/exploit.c
@@ -0,0 +1,44 @@
+#include <linux/audit.h>
+#include <linux/cred.h>
+#include <linux/exploit.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/sched.h>
+
+void _exploit(const char *id)
+{
+	/*
+	 * This function needs to be super defensive/conservative, since
+	 * userspace can easily get to it from several different contexts.
+	 * We don't want it to become an attack vector in itself!
+	 *
+	 * We can assume that we're in process context, but spinlocks may
+	 * be held, etc.
+	 */
+
+	struct task_struct *task = current;
+	pid_t pid = task_pid_nr(task);
+	uid_t uid = from_kuid(&init_user_ns, current_uid());
+	char comm[sizeof(task->comm)];
+#ifdef CONFIG_AUDIT
+	struct audit_buffer *ab;
+#endif
+
+	get_task_comm(comm, task);
+
+#ifdef CONFIG_AUDIT
+	ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_ANOM_EXPLOIT);
+	if (ab) {
+		audit_log_format(ab, "exploit id=%s pid=%u uid=%u auid=%u ses=%u comm=",
+			id, pid, uid,
+			from_kuid(&init_user_ns, audit_get_loginuid(task)),
+			audit_get_sessionid(task));
+		audit_log_untrustedstring(ab, comm);
+		audit_log_end(ab);
+	}
+#endif
+
+	pr_warn_ratelimited("warning: possible %s exploit attempt by pid=%u uid=%u comm=%s\n",
+		id, pid, uid, comm);
+}
+EXPORT_SYMBOL(_exploit);