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