1 //===-- sanitizer_ioctl_test.cpp ------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Tests for ioctl interceptor implementation in sanitizer_common.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "sanitizer_common/sanitizer_platform.h"
14 #if SANITIZER_LINUX
15 
16 #include <linux/input.h>
17 #include <vector>
18 
19 #include "interception/interception.h"
20 #include "sanitizer_test_utils.h"
21 #include "sanitizer_common/sanitizer_platform_limits_posix.h"
22 #include "sanitizer_common/sanitizer_common.h"
23 #include "gtest/gtest.h"
24 
25 
26 using namespace __sanitizer;
27 
28 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, sz) \
29   do {                                              \
30     (void) ctx;                                     \
31     (void) ptr;                                     \
32     (void) sz;                                      \
33   } while (0)
34 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sz) \
35   do {                                               \
36     (void) ctx;                                      \
37     (void) ptr;                                      \
38     (void) sz;                                       \
39   } while (0)
40 
41 #include "sanitizer_common/sanitizer_common_interceptors_ioctl.inc"
42 
43 static struct IoctlInit {
IoctlInitIoctlInit44   IoctlInit() {
45     ioctl_init();
46     // Avoid unused function warnings.
47     (void)&ioctl_common_pre;
48     (void)&ioctl_common_post;
49     (void)&ioctl_decode;
50   }
51 } ioctl_static_initializer;
52 
TEST(SanitizerIoctl,Fixup)53 TEST(SanitizerIoctl, Fixup) {
54   EXPECT_EQ((unsigned)FIONBIO, ioctl_request_fixup(FIONBIO));
55 
56   EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(0, 16)));
57   EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(1, 16)));
58   EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(1, 17)));
59   EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(31, 16)));
60   EXPECT_NE(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(32, 16)));
61 
62   EXPECT_EQ(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(0)));
63   EXPECT_EQ(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(5)));
64   EXPECT_EQ(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(63)));
65   EXPECT_NE(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(64)));
66 
67   EXPECT_EQ(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(0)));
68   EXPECT_EQ(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(5)));
69   EXPECT_EQ(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(63)));
70   EXPECT_NE(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(64)));
71 
72   const ioctl_desc *desc = ioctl_lookup(EVIOCGKEY(16));
73   EXPECT_NE((void *)0, desc);
74   EXPECT_EQ(EVIOCGKEY(0), desc->req);
75 }
76 
77 // Test decoding KVM ioctl numbers.
TEST(SanitizerIoctl,KVM_GET_MP_STATE)78 TEST(SanitizerIoctl, KVM_GET_MP_STATE) {
79   ioctl_desc desc;
80   unsigned int desc_value = SANITIZER_MIPS ? 0x4004ae98U : 0x8004ae98U;
81   bool res = ioctl_decode(desc_value, &desc);
82   EXPECT_TRUE(res);
83   EXPECT_EQ(ioctl_desc::WRITE, desc.type);
84   EXPECT_EQ(4U, desc.size);
85 }
86 
TEST(SanitizerIoctl,KVM_GET_LAPIC)87 TEST(SanitizerIoctl, KVM_GET_LAPIC) {
88   ioctl_desc desc;
89   unsigned int desc_value = SANITIZER_MIPS ? 0x4400ae8eU : 0x8400ae8eU;
90   bool res = ioctl_decode(desc_value, &desc);
91   EXPECT_TRUE(res);
92   EXPECT_EQ(ioctl_desc::WRITE, desc.type);
93   EXPECT_EQ(1024U, desc.size);
94 }
95 
TEST(SanitizerIoctl,KVM_GET_MSR_INDEX_LIST)96 TEST(SanitizerIoctl, KVM_GET_MSR_INDEX_LIST) {
97   ioctl_desc desc;
98   bool res = ioctl_decode(0xc004ae02U, &desc);
99   EXPECT_TRUE(res);
100   EXPECT_EQ(ioctl_desc::READWRITE, desc.type);
101   EXPECT_EQ(4U, desc.size);
102 }
103 
104 #endif // SANITIZER_LINUX
105