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 { |
44 | 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 | |
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. |
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(req: desc_value, desc: &desc); |
82 | EXPECT_TRUE(res); |
83 | EXPECT_EQ(ioctl_desc::WRITE, desc.type); |
84 | EXPECT_EQ(4U, desc.size); |
85 | } |
86 | |
87 | TEST(SanitizerIoctl, KVM_GET_LAPIC) { |
88 | ioctl_desc desc; |
89 | unsigned int desc_value = SANITIZER_MIPS ? 0x4400ae8eU : 0x8400ae8eU; |
90 | bool res = ioctl_decode(req: desc_value, desc: &desc); |
91 | EXPECT_TRUE(res); |
92 | EXPECT_EQ(ioctl_desc::WRITE, desc.type); |
93 | EXPECT_EQ(1024U, desc.size); |
94 | } |
95 | |
96 | TEST(SanitizerIoctl, KVM_GET_MSR_INDEX_LIST) { |
97 | ioctl_desc desc; |
98 | bool res = ioctl_decode(req: 0xc004ae02U, desc: &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 | |