public inbox for ltp@lists.linux.it
 help / color / mirror / Atom feed
* [LTP] [PATCH 1/2] Add SAFE_TIMER_*() functions to tst_safe_clocks.h
@ 2020-08-17 16:05 Martin Doucha
  2020-08-17 16:05 ` [LTP] [PATCH 2/2] Add test for CVE 2018-12896 Martin Doucha
  2020-08-24 17:30 ` [LTP] [PATCH 1/2] Add SAFE_TIMER_*() functions to tst_safe_clocks.h Petr Vorel
  0 siblings, 2 replies; 4+ messages in thread
From: Martin Doucha @ 2020-08-17 16:05 UTC (permalink / raw)
  To: ltp

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
 include/tst_safe_clocks.h | 90 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/include/tst_safe_clocks.h b/include/tst_safe_clocks.h
index 4cb5f41ed..5909f4083 100644
--- a/include/tst_safe_clocks.h
+++ b/include/tst_safe_clocks.h
@@ -55,6 +55,83 @@ static inline void safe_clock_settime(const char *file, const int lineno,
 	}
 }
 
+static inline int safe_timer_create(const char *file, const int lineno,
+	clockid_t clockid, struct sigevent *sevp, timer_t *timerid)
+{
+	int ret;
+
+	errno = 0;
+	ret = timer_create(clockid, sevp, timerid);
+
+	if (ret == -1) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"timer_create(%s) failed", tst_clock_name(clockid));
+	} else if (ret) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"Invalid timer_create(%s) return value %d",
+			tst_clock_name(clockid), ret);
+	}
+
+	return ret;
+}
+
+static inline int safe_timer_settime(const char *file, const int lineno,
+	timer_t timerid, int flags, const struct itimerspec *new_value,
+	struct itimerspec *old_value)
+{
+	int ret;
+
+	errno = 0;
+	ret = timer_settime(timerid, flags, new_value, old_value);
+
+	if (ret == -1) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"timer_settime() failed");
+	} else if (ret) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"Invalid timer_settime() return value %d", ret);
+	}
+
+	return ret;
+}
+
+static inline int safe_timer_gettime(const char *file, const int lineno,
+	timer_t timerid, struct itimerspec *curr_value)
+{
+	int ret;
+
+	errno = 0;
+	ret = timer_gettime(timerid, curr_value);
+
+	if (ret == -1) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"timer_gettime() failed");
+	} else if (ret) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"Invalid timer_gettime() return value %d", ret);
+	}
+
+	return ret;
+}
+
+static inline int safe_timer_delete(const char *file, const int lineno,
+	timer_t timerid)
+{
+	int ret;
+
+	errno = 0;
+	ret = timer_delete(timerid);
+
+	if (ret == -1) {
+		tst_brk_(file, lineno, TBROK | TERRNO, "timer_delete() failed");
+	} else if (ret) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"Invalid timer_delete() return value %d", ret);
+	}
+
+	return ret;
+}
+
 #define SAFE_CLOCK_GETRES(clk_id, res)\
 	safe_clock_getres(__FILE__, __LINE__, (clk_id), (res))
 
@@ -64,4 +141,17 @@ static inline void safe_clock_settime(const char *file, const int lineno,
 #define SAFE_CLOCK_SETTIME(clk_id, tp)\
 	safe_clock_settime(__FILE__, __LINE__, (clk_id), (tp))
 
+#define SAFE_TIMER_CREATE(clockid, sevp, timerid)\
+	safe_timer_create(__FILE__, __LINE__, (clockid), (sevp), (timerid))
+
+#define SAFE_TIMER_SETTIME(timerid, flags, new_value, old_value)\
+	safe_timer_settime(__FILE__, __LINE__, (timerid), (flags),\
+		(new_value), (old_value))
+
+#define SAFE_TIMER_GETTIME(timerid, curr_value)\
+	safe_timer_gettime(__FILE__, __LINE__, (timerid), (curr_value))
+
+#define SAFE_TIMER_DELETE(timerid)\
+	safe_timer_delete(__FILE__, __LINE__, timerid)
+
 #endif /* SAFE_CLOCKS_H__ */
-- 
2.27.0


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

* [LTP] [PATCH 2/2] Add test for CVE 2018-12896
  2020-08-17 16:05 [LTP] [PATCH 1/2] Add SAFE_TIMER_*() functions to tst_safe_clocks.h Martin Doucha
@ 2020-08-17 16:05 ` Martin Doucha
  2020-08-24 17:37   ` Petr Vorel
  2020-08-24 17:30 ` [LTP] [PATCH 1/2] Add SAFE_TIMER_*() functions to tst_safe_clocks.h Petr Vorel
  1 sibling, 1 reply; 4+ messages in thread
From: Martin Doucha @ 2020-08-17 16:05 UTC (permalink / raw)
  To: ltp

Fixes #353

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
 runtest/cve                                   |   1 +
 runtest/syscalls                              |   1 +
 .../kernel/syscalls/timer_settime/.gitignore  |   1 +
 .../syscalls/timer_settime/timer_settime03.c  | 120 ++++++++++++++++++
 4 files changed, 123 insertions(+)
 create mode 100644 testcases/kernel/syscalls/timer_settime/timer_settime03.c

diff --git a/runtest/cve b/runtest/cve
index a2ca8d27c..07c69e8ff 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -52,6 +52,7 @@ cve-2018-9568 connect02
 cve-2018-1000001 realpath01
 cve-2018-1000199 ptrace08
 cve-2018-1000204 ioctl_sg01
+cve-2018-12896 timer_settime03
 cve-2018-18445 bpf_prog04
 cve-2018-18559 bind06
 cve-2018-19854 crypto_user01
diff --git a/runtest/syscalls b/runtest/syscalls
index 860c5c36d..a589a84dd 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1545,6 +1545,7 @@ timer_gettime01 timer_gettime01
 
 timer_settime01 timer_settime01
 timer_settime02 timer_settime02
+timer_settime03 timer_settime03
 
 tkill01 tkill01
 tkill02 tkill02
diff --git a/testcases/kernel/syscalls/timer_settime/.gitignore b/testcases/kernel/syscalls/timer_settime/.gitignore
index e1ed3ef17..2541a5b57 100644
--- a/testcases/kernel/syscalls/timer_settime/.gitignore
+++ b/testcases/kernel/syscalls/timer_settime/.gitignore
@@ -1,2 +1,3 @@
 /timer_settime01
 /timer_settime02
+/timer_settime03
diff --git a/testcases/kernel/syscalls/timer_settime/timer_settime03.c b/testcases/kernel/syscalls/timer_settime/timer_settime03.c
new file mode 100644
index 000000000..68eff853b
--- /dev/null
+++ b/testcases/kernel/syscalls/timer_settime/timer_settime03.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 SUSE LLC <mdoucha@suse.cz>
+ */
+
+/*
+ * CVE 2018-12896
+ *
+ * Check for possible overflow of posix timer overrun counter. Create
+ * a CLOCK_REALTIME timer, set extremely low timer interval and expiration
+ * value just right to cause overrun overflow into negative values, start
+ * the timer with TIMER_ABSTIME flag to cause overruns immediately. Then just
+ * check the overrun counter in the timer signal handler. On a patched system,
+ * the value returned by timer_getoverrun() should be capped at INT_MAX and
+ * not allowed to overflow into negative range. Bug fixed in:
+ *
+ *  commit 78c9c4dfbf8c04883941445a195276bb4bb92c76
+ *  Author: Thomas Gleixner <tglx@linutronix.de>
+ *  Date:   Tue Jun 26 15:21:32 2018 +0200
+ *
+ *  posix-timers: Sanitize overrun handling
+ */
+
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <limits.h>
+
+#include "tst_test.h"
+#include "tst_safe_clocks.h"
+
+static timer_t timer;
+static volatile int handler_called;
+
+static void sighandler(int sig)
+{
+	struct itimerspec spec;
+
+	/*
+	 * Signal handler will be called twice in total because kernel will
+	 * schedule another pending signal before the timer gets disabled.
+	 */
+	if (handler_called)
+		return;
+
+	TEST(timer_getoverrun(timer));
+
+	memset(&spec, 0, sizeof(struct itimerspec));
+	SAFE_TIMER_SETTIME(timer, 0, &spec, NULL);
+	handler_called = 1;
+
+	if (TST_RET == -1)
+		tst_brk(TBROK | TTERRNO, "Error reading timer overrun count");
+
+	if (TST_RET == INT_MAX) {
+		tst_res(TPASS, "Timer overrun count is capped");
+		return;
+	}
+
+	if (TST_RET < 0) {
+		tst_res(TFAIL, "Timer overrun counter overflow");
+		return;
+	}
+
+	tst_res(TFAIL, "Timer overrun counter is wrong: %ld; expected %d or "
+		"negative number", TST_RET, INT_MAX);
+}
+
+static void setup(void)
+{
+	struct sigevent sev;
+
+	memset(&sev, 0, sizeof(struct sigevent));
+	sev.sigev_notify = SIGEV_SIGNAL;
+	sev.sigev_signo = SIGUSR1;
+
+	SAFE_SIGNAL(SIGUSR1, sighandler);
+	SAFE_TIMER_CREATE(CLOCK_REALTIME, &sev, &timer);
+}
+
+static void run(void)
+{
+	int handler_delay = INT_MAX / 7;
+	long nsec;
+	struct itimerspec spec;
+
+	memset(&spec, 0, sizeof(struct itimerspec));
+	SAFE_CLOCK_GETTIME(CLOCK_REALTIME, &spec.it_value);
+	nsec = (handler_delay % 100000000) * 10L;
+
+	if (nsec > spec.it_value.tv_nsec) {
+		spec.it_value.tv_sec -= 1;
+		spec.it_value.tv_nsec += 1000000000;
+	}
+
+	/* spec.it_value = now - 1.4 * max overrun value */
+	/* IOW, overflow will land right in the middle of negative range */
+	spec.it_value.tv_sec -= handler_delay / 100000000;
+	spec.it_value.tv_nsec -= nsec;
+	spec.it_interval.tv_nsec = 1;
+
+	SAFE_TIMER_SETTIME(timer, TIMER_ABSTIME, &spec, NULL);
+	while (!handler_called);
+}
+
+static void cleanup(void)
+{
+	SAFE_TIMER_DELETE(timer);
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "78c9c4dfbf8c"},
+		{"CVE", "2018-12896"},
+		{}
+	}
+};
-- 
2.27.0


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

* [LTP] [PATCH 1/2] Add SAFE_TIMER_*() functions to tst_safe_clocks.h
  2020-08-17 16:05 [LTP] [PATCH 1/2] Add SAFE_TIMER_*() functions to tst_safe_clocks.h Martin Doucha
  2020-08-17 16:05 ` [LTP] [PATCH 2/2] Add test for CVE 2018-12896 Martin Doucha
@ 2020-08-24 17:30 ` Petr Vorel
  1 sibling, 0 replies; 4+ messages in thread
From: Petr Vorel @ 2020-08-24 17:30 UTC (permalink / raw)
  To: ltp

Hi Martin,

Reviewed-by: Petr Vorel <pvorel@suse.cz>

Kind regards,
Petr

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

* [LTP] [PATCH 2/2] Add test for CVE 2018-12896
  2020-08-17 16:05 ` [LTP] [PATCH 2/2] Add test for CVE 2018-12896 Martin Doucha
@ 2020-08-24 17:37   ` Petr Vorel
  0 siblings, 0 replies; 4+ messages in thread
From: Petr Vorel @ 2020-08-24 17:37 UTC (permalink / raw)
  To: ltp

Hi Martin,

...
> +++ b/testcases/kernel/syscalls/timer_settime/timer_settime03.c
...
> +static volatile int handler_called;
> +
> +static void sighandler(int sig)
static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)

> +{
> +	struct itimerspec spec;
> +
> +	/*
> +	 * Signal handler will be called twice in total because kernel will
> +	 * schedule another pending signal before the timer gets disabled.
> +	 */
> +	if (handler_called)
> +		return;
> +
> +	TEST(timer_getoverrun(timer));
> +
> +	memset(&spec, 0, sizeof(struct itimerspec));
> +	SAFE_TIMER_SETTIME(timer, 0, &spec, NULL);
> +	handler_called = 1;
Test cannot run with -i > 1.

> +	if (TST_RET == -1)
> +		tst_brk(TBROK | TTERRNO, "Error reading timer overrun count");
> +
> +	if (TST_RET == INT_MAX) {
> +		tst_res(TPASS, "Timer overrun count is capped");
> +		return;
> +	}
> +
> +	if (TST_RET < 0) {
> +		tst_res(TFAIL, "Timer overrun counter overflow");
> +		return;
> +	}
> +
> +	tst_res(TFAIL, "Timer overrun counter is wrong: %ld; expected %d or "
> +		"negative number", TST_RET, INT_MAX);

According to Cyril [1] tst_res() is not signal-async-safe (uses printf()).

[1] https://patchwork.ozlabs.org/project/ltp/patch/47e40724c2a7a9612aca0265e493e62c69d65996.1594204153.git.viresh.kumar@linaro.org/#2483231
> +}
...

Kind regards,
Petr

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

end of thread, other threads:[~2020-08-24 17:37 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-08-17 16:05 [LTP] [PATCH 1/2] Add SAFE_TIMER_*() functions to tst_safe_clocks.h Martin Doucha
2020-08-17 16:05 ` [LTP] [PATCH 2/2] Add test for CVE 2018-12896 Martin Doucha
2020-08-24 17:37   ` Petr Vorel
2020-08-24 17:30 ` [LTP] [PATCH 1/2] Add SAFE_TIMER_*() functions to tst_safe_clocks.h Petr Vorel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox