1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2019 Xiao Yang <ice_yangxiao@163.com> 4 * 5 * Description: 6 * Check various errnos for futex(FUTEX_CMP_REQUEUE). 7 * 1) futex(FUTEX_CMP_REQUEUE) with invalid val returns EINVAL. 8 * 2) futex(FUTEX_CMP_REQUEUE) with invalid val2 returns EINVAL. 9 * 3) futex(FUTEX_CMP_REQUEUE) with mismatched val3 returns EAGAIN. 10 * 11 * It's also a regression test for CVE-2018-6927: 12 * fbe0e839d1e2 ("futex: Prevent overflow by strengthen input validation") 13 */ 14 15#include <errno.h> 16#include <sys/time.h> 17 18#include "tst_test.h" 19#include "futextest.h" 20#include "lapi/futex.h" 21 22static futex_t *futexes; 23 24static struct tcase { 25 int set_wakes; 26 int set_requeues; 27 int exp_val; 28 int exp_errno; 29} tcases[] = { 30 {1, -1, FUTEX_INITIALIZER, EINVAL}, 31 {-1, 1, FUTEX_INITIALIZER, EINVAL}, 32 {1, 1, FUTEX_INITIALIZER + 1, EAGAIN}, 33}; 34 35static struct futex_test_variants variants[] = { 36#if (__NR_futex != __LTP__NR_INVALID_SYSCALL) 37 { .fntype = FUTEX_FN_FUTEX, .desc = "syscall with old kernel spec"}, 38#endif 39 40#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL) 41 { .fntype = FUTEX_FN_FUTEX64, .desc = "syscall time64 with kernel spec"}, 42#endif 43}; 44 45static void verify_futex_cmp_requeue(unsigned int n) 46{ 47 struct futex_test_variants *tv = &variants[tst_variant]; 48 struct tcase *tc = &tcases[n]; 49 50 TEST(futex_cmp_requeue(tv->fntype, &futexes[0], tc->exp_val, 51 &futexes[1], tc->set_wakes, tc->set_requeues, 0)); 52 if (TST_RET != -1) { 53 tst_res(TFAIL, "futex_cmp_requeue() succeeded unexpectedly"); 54 return; 55 } 56 57 if (TST_ERR != tc->exp_errno) { 58 tst_res(TFAIL | TTERRNO, 59 "futex_cmp_requeue() failed unexpectedly, expected %s", 60 tst_strerrno(tc->exp_errno)); 61 return; 62 } 63 64 tst_res(TPASS | TTERRNO, "futex_cmp_requeue() failed as expected"); 65} 66 67static void setup(void) 68{ 69 struct futex_test_variants *tv = &variants[tst_variant]; 70 71 tst_res(TINFO, "Testing variant: %s", tv->desc); 72 futex_supported_by_kernel(tv->fntype); 73 74 futexes = SAFE_MMAP(NULL, sizeof(futex_t) * 2, PROT_READ | PROT_WRITE, 75 MAP_ANONYMOUS | MAP_SHARED, -1, 0); 76 77 futexes[0] = FUTEX_INITIALIZER; 78 futexes[1] = FUTEX_INITIALIZER + 1; 79} 80 81static void cleanup(void) 82{ 83 if (futexes) 84 SAFE_MUNMAP((void *)futexes, sizeof(futex_t) * 2); 85} 86 87static struct tst_test test = { 88 .setup = setup, 89 .cleanup = cleanup, 90 .test = verify_futex_cmp_requeue, 91 .tcnt = ARRAY_SIZE(tcases), 92 .test_variants = ARRAY_SIZE(variants), 93 .tags = (const struct tst_tag[]) { 94 {"CVE", "2018-6927"}, 95 {"linux-git", "fbe0e839d1e2"}, 96 {} 97 } 98}; 99