1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <BufferAllocator/BufferAllocator.h>
18 #include <TrustyIpc.h>
19 #include <iostream>
20 #include <stdlib.h>
21 #include <sys/mman.h>
22 #include <time.h>
23 #include <trusty/coverage/coverage.h>
24 #include <trusty/fuzz/counters.h>
25 #include <trusty/fuzz/utils.h>
26 #include <trusty/tipc.h>
27 #include <unistd.h>
28
29 using android::trusty::coverage::CoverageRecord;
30 using android::trusty::fuzz::ExtraCounters;
31 using android::trusty::fuzz::TrustyApp;
32
33 #define countof(arr) (sizeof(arr) / sizeof(arr[0]))
34
35 #define TIPC_DEV "/dev/trusty-ipc-dev0"
36 #define CONFIRMATIONUI_PORT "com.android.trusty.confirmationui"
37 #define CONFIRMATIONUI_MODULE_NAME "confirmationui.syms.elf"
38
39 /* A request to render to screen may take a while. */
40 const size_t kTimeoutSeconds = 30;
41
42 /* ConfirmationUI TA's UUID is 7dee2364-c036-425b-b086-df0f6c233c1b */
43 static struct uuid confirmationui_uuid = {
44 0x7dee2364,
45 0xc036,
46 0x425b,
47 {0xb0, 0x86, 0xdf, 0x0f, 0x6c, 0x23, 0x3c, 0x1b},
48 };
49
50 static CoverageRecord record(TIPC_DEV, &confirmationui_uuid, CONFIRMATIONUI_MODULE_NAME);
51
52 static android::base::unique_fd dma_buf;
53 static void* shm_base;
54
LLVMFuzzerInitialize(int *,char ***)55 extern "C" int LLVMFuzzerInitialize(int* /* argc */, char*** /* argv */) {
56 auto ret = record.Open();
57 if (!ret.ok()) {
58 std::cerr << ret.error() << std::endl;
59 exit(-1);
60 }
61
62 BufferAllocator allocator;
63 dma_buf.reset(allocator.Alloc(kDmabufSystemHeapName, CONFIRMATIONUI_MAX_MSG_SIZE));
64 if (dma_buf < 0) {
65 std::cerr << "Failed to allocate dma_buf" << std::endl;
66 exit(-1);
67 }
68
69 shm_base = mmap(0, CONFIRMATIONUI_MAX_MSG_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf, 0);
70 if (shm_base == MAP_FAILED) {
71 std::cerr << "Failed to mmap() dma_buf" << std::endl;
72 exit(-1);
73 }
74
75 return 0;
76 }
77
Init(int chan,int dma_buf)78 static bool Init(int chan, int dma_buf) {
79 confirmationui_hdr hdr = {
80 .cmd = CONFIRMATIONUI_CMD_INIT,
81 };
82 confirmationui_init_req args = {
83 .shm_len = CONFIRMATIONUI_MAX_MSG_SIZE,
84 };
85 iovec iov[] = {
86 {
87 .iov_base = &hdr,
88 .iov_len = sizeof(hdr),
89 },
90 {
91 .iov_base = &args,
92 .iov_len = sizeof(args),
93 },
94 };
95 trusty_shm shm = {
96 .fd = dma_buf,
97 .transfer = TRUSTY_SHARE,
98 };
99
100 int rc = tipc_send(chan, iov, countof(iov), &shm, 1);
101 if (rc != static_cast<int>(sizeof(hdr) + sizeof(args))) {
102 return false;
103 }
104
105 rc = read(chan, &hdr, sizeof(hdr));
106 if (rc != static_cast<int>(sizeof(hdr))) {
107 return false;
108 }
109
110 return true;
111 }
112
Msg(int chan,const uint8_t * data,size_t size)113 static bool Msg(int chan, const uint8_t* data, size_t size) {
114 confirmationui_hdr hdr = {
115 .cmd = CONFIRMATIONUI_CMD_MSG,
116 };
117 confirmationui_msg_args args = {
118 .msg_len = static_cast<uint32_t>(size),
119 };
120 iovec iov[] = {
121 {
122 .iov_base = &hdr,
123 .iov_len = sizeof(hdr),
124 },
125 {
126 .iov_base = &args,
127 .iov_len = sizeof(args),
128 },
129 };
130
131 memset(shm_base, 0, CONFIRMATIONUI_MAX_MSG_SIZE);
132 memcpy(shm_base, data, size);
133
134 int rc = tipc_send(chan, iov, countof(iov), NULL, 0);
135 if (rc != static_cast<int>(sizeof(hdr) + sizeof(args))) {
136 return false;
137 }
138
139 rc = readv(chan, iov, countof(iov));
140 if (rc != static_cast<int>(sizeof(hdr) + sizeof(args))) {
141 return false;
142 }
143
144 return true;
145 }
146
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)147 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
148 ExtraCounters counters(&record);
149 counters.Reset();
150
151 TrustyApp ta(TIPC_DEV, CONFIRMATIONUI_PORT);
152 auto ret = ta.Connect();
153 if (!ret.ok()) {
154 android::trusty::fuzz::Abort();
155 }
156 int chan = *ta.GetRawFd();
157
158 alarm(kTimeoutSeconds);
159 bool success = Init(chan, dma_buf);
160 alarm(0);
161 if (!success) {
162 android::trusty::fuzz::Abort();
163 }
164
165 alarm(kTimeoutSeconds);
166 success = Msg(chan, data, size);
167 alarm(0);
168 if (!success) {
169 android::trusty::fuzz::Abort();
170 }
171
172 return 0;
173 }
174