1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) Zilogic Systems Pvt. Ltd <code@zilogic.com>, 2020
4f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2021-2023
5f08c3bdfSopenharmony_ci *
6f08c3bdfSopenharmony_ci * Based on testcases/kernel/syscalls/adjtimex/adjtimex01.c
7f08c3bdfSopenharmony_ci * Copyright (c) Wipro Technologies Ltd, 2002.
8f08c3bdfSopenharmony_ci */
9f08c3bdfSopenharmony_ci
10f08c3bdfSopenharmony_ci/*\
11f08c3bdfSopenharmony_ci * [Description]
12f08c3bdfSopenharmony_ci *
13f08c3bdfSopenharmony_ci * CVE-2018-11508: Test 4-byte kernel data leak via adjtimex.
14f08c3bdfSopenharmony_ci *
15f08c3bdfSopenharmony_ci * On calling the adjtimex() function call with invalid mode (let's say
16f08c3bdfSopenharmony_ci * 0x8000), ideally all the parameters should return with null data. But,
17f08c3bdfSopenharmony_ci * when we read the last parameter we will receive 4 bytes of kernel data.
18f08c3bdfSopenharmony_ci * This proves that there are 4 bytes of info leaked. The bug was fixed in
19f08c3bdfSopenharmony_ci * Kernel Version 4.16.9. Therefore, the below test case will only be
20f08c3bdfSopenharmony_ci * applicable for the kernel version 4.16.9 and above.
21f08c3bdfSopenharmony_ci *
22f08c3bdfSopenharmony_ci * So basically, this test shall check whether there is any data leak.
23f08c3bdfSopenharmony_ci * To test that, Pass struct timex buffer filled with zero with
24f08c3bdfSopenharmony_ci * some INVALID mode to the system call adjtimex. Passing an invalid
25f08c3bdfSopenharmony_ci * parameters will not call do_adjtimex() and before that, it shall throw
26f08c3bdfSopenharmony_ci * an error(On error test shall not break). Therefore, none of the parameters
27f08c3bdfSopenharmony_ci * will get initialized.
28f08c3bdfSopenharmony_ci *
29f08c3bdfSopenharmony_ci * On reading the last attribute tai of the struct, if the attribute is non-
30f08c3bdfSopenharmony_ci * zero the test is considered to have failed, else the test is considered
31f08c3bdfSopenharmony_ci * to have passed.
32f08c3bdfSopenharmony_ci */
33f08c3bdfSopenharmony_ci
34f08c3bdfSopenharmony_ci#include <errno.h>
35f08c3bdfSopenharmony_ci#include <sys/timex.h>
36f08c3bdfSopenharmony_ci#include "tst_test.h"
37f08c3bdfSopenharmony_ci
38f08c3bdfSopenharmony_ci#define ADJ_ADJTIME 0x8000
39f08c3bdfSopenharmony_ci#define LOOPS 10
40f08c3bdfSopenharmony_ci
41f08c3bdfSopenharmony_cistatic struct timex *buf;
42f08c3bdfSopenharmony_ci
43f08c3bdfSopenharmony_civoid verify_adjtimex(void)
44f08c3bdfSopenharmony_ci{
45f08c3bdfSopenharmony_ci	int i;
46f08c3bdfSopenharmony_ci	int data_leak = 0;
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_ci	for (i = 0; i < LOOPS; i++) {
49f08c3bdfSopenharmony_ci		memset(buf, 0, sizeof(struct timex));
50f08c3bdfSopenharmony_ci		buf->modes = ADJ_ADJTIME; /* Invalid mode */
51f08c3bdfSopenharmony_ci		TEST(adjtimex(buf));
52f08c3bdfSopenharmony_ci		if ((TST_RET == -1) && (TST_ERR == EINVAL)) {
53f08c3bdfSopenharmony_ci			tst_res(TINFO,
54f08c3bdfSopenharmony_ci				"expecting adjtimex() to fail with EINVAL with mode 0x%x",
55f08c3bdfSopenharmony_ci				ADJ_ADJTIME);
56f08c3bdfSopenharmony_ci		} else {
57f08c3bdfSopenharmony_ci			tst_brk(TBROK | TERRNO,
58f08c3bdfSopenharmony_ci				"adjtimex(): Unexpeceted error, expecting EINVAL with mode 0x%x",
59f08c3bdfSopenharmony_ci				ADJ_ADJTIME);
60f08c3bdfSopenharmony_ci		}
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ci		tst_res(TINFO, "tai : 0x%08x", buf->tai);
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_ci		if (buf->tai != 0) {
65f08c3bdfSopenharmony_ci			data_leak = 1;
66f08c3bdfSopenharmony_ci			break;
67f08c3bdfSopenharmony_ci		}
68f08c3bdfSopenharmony_ci	}
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_ci	if (data_leak != 0)
71f08c3bdfSopenharmony_ci		tst_res(TFAIL, "Data leak observed");
72f08c3bdfSopenharmony_ci	else
73f08c3bdfSopenharmony_ci		tst_res(TPASS, "Data leak not observed");
74f08c3bdfSopenharmony_ci}
75f08c3bdfSopenharmony_ci
76f08c3bdfSopenharmony_cistatic struct tst_test test = {
77f08c3bdfSopenharmony_ci	.test_all = verify_adjtimex,
78f08c3bdfSopenharmony_ci	.bufs = (struct tst_buffers []) {
79f08c3bdfSopenharmony_ci		{&buf, .size = sizeof(*buf)},
80f08c3bdfSopenharmony_ci		{},
81f08c3bdfSopenharmony_ci	},
82f08c3bdfSopenharmony_ci	.tags = (const struct tst_tag[]) {
83f08c3bdfSopenharmony_ci		{"CVE", "2018-11508"},
84f08c3bdfSopenharmony_ci		{"linux-git", "0a0b98734479"},
85f08c3bdfSopenharmony_ci		{},
86f08c3bdfSopenharmony_ci	}
87f08c3bdfSopenharmony_ci};
88