1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2019 SUSE LLC
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci * Author:	Christian Amann <camann@suse.com>
6f08c3bdfSopenharmony_ci */
7f08c3bdfSopenharmony_ci/*
8f08c3bdfSopenharmony_ci * Regression test for CVE-2017-18344:
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci * In kernels prior to 4.14.8 sigevent.sigev_notify is not
11f08c3bdfSopenharmony_ci * properly verified when calling timer_create(2) with the
12f08c3bdfSopenharmony_ci * field being set to (SIGEV_SIGNAL | SIGEV_THREAD_ID).
13f08c3bdfSopenharmony_ci * This can be used to read arbitrary kernel memory.
14f08c3bdfSopenharmony_ci *
15f08c3bdfSopenharmony_ci * For more info see: https://nvd.nist.gov/vuln/detail/CVE-2017-18344
16f08c3bdfSopenharmony_ci * or commit: cef31d9af908
17f08c3bdfSopenharmony_ci *
18f08c3bdfSopenharmony_ci * This test uses an unused number instead of SIGEV_THREAD_ID to check
19f08c3bdfSopenharmony_ci * if this field gets verified correctly.
20f08c3bdfSopenharmony_ci */
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_ci#include <errno.h>
23f08c3bdfSopenharmony_ci#include <signal.h>
24f08c3bdfSopenharmony_ci#include <time.h>
25f08c3bdfSopenharmony_ci#include "tst_test.h"
26f08c3bdfSopenharmony_ci#include "lapi/common_timers.h"
27f08c3bdfSopenharmony_ci
28f08c3bdfSopenharmony_ci#define RANDOM_UNUSED_NUMBER (54321)
29f08c3bdfSopenharmony_ci
30f08c3bdfSopenharmony_cistatic void run(void)
31f08c3bdfSopenharmony_ci{
32f08c3bdfSopenharmony_ci	struct sigevent evp;
33f08c3bdfSopenharmony_ci	clock_t clock = CLOCK_MONOTONIC;
34f08c3bdfSopenharmony_ci	kernel_timer_t created_timer_id;
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci	memset(&evp, 0, sizeof(evp));
37f08c3bdfSopenharmony_ci
38f08c3bdfSopenharmony_ci	evp.sigev_signo  = SIGALRM;
39f08c3bdfSopenharmony_ci	evp.sigev_notify = SIGEV_SIGNAL | RANDOM_UNUSED_NUMBER;
40f08c3bdfSopenharmony_ci	evp._sigev_un._tid = getpid();
41f08c3bdfSopenharmony_ci
42f08c3bdfSopenharmony_ci	TEST(tst_syscall(__NR_timer_create, clock, &evp, &created_timer_id));
43f08c3bdfSopenharmony_ci
44f08c3bdfSopenharmony_ci	if (TST_RET != 0) {
45f08c3bdfSopenharmony_ci		if (TST_ERR == EINVAL) {
46f08c3bdfSopenharmony_ci			tst_res(TPASS | TTERRNO,
47f08c3bdfSopenharmony_ci					"timer_create() failed as expected");
48f08c3bdfSopenharmony_ci		} else {
49f08c3bdfSopenharmony_ci			tst_res(TFAIL | TTERRNO,
50f08c3bdfSopenharmony_ci					"timer_create() unexpectedly failed");
51f08c3bdfSopenharmony_ci		}
52f08c3bdfSopenharmony_ci		return;
53f08c3bdfSopenharmony_ci	}
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_ci	tst_res(TFAIL,
56f08c3bdfSopenharmony_ci		"timer_create() succeeded for invalid notification type");
57f08c3bdfSopenharmony_ci
58f08c3bdfSopenharmony_ci	TEST(tst_syscall(__NR_timer_delete, created_timer_id));
59f08c3bdfSopenharmony_ci	if (TST_RET != 0) {
60f08c3bdfSopenharmony_ci		tst_res(TFAIL | TTERRNO, "Failed to delete timer %s",
61f08c3bdfSopenharmony_ci			get_clock_str(clock));
62f08c3bdfSopenharmony_ci	}
63f08c3bdfSopenharmony_ci}
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_cistatic struct tst_test test = {
66f08c3bdfSopenharmony_ci	.test_all = run,
67f08c3bdfSopenharmony_ci	.tags = (const struct tst_tag[]) {
68f08c3bdfSopenharmony_ci		{"CVE", "2017-18344"},
69f08c3bdfSopenharmony_ci		{"linux-git", "cef31d9af908"},
70f08c3bdfSopenharmony_ci		{}
71f08c3bdfSopenharmony_ci	}
72f08c3bdfSopenharmony_ci};
73