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 <stdlib.h>
19 #include <sys/mman.h>
20 #include <trusty/coverage/coverage.h>
21 #include <trusty/fuzz/counters.h>
22 #include <trusty/fuzz/utils.h>
23 #include <trusty/tipc.h>
24 #include <unistd.h>
25 #include <iostream>
26
27 using android::trusty::coverage::CoverageRecord;
28 using android::trusty::fuzz::ExtraCounters;
29 using android::trusty::fuzz::TrustyApp;
30
31 #define countof(arr) (sizeof(arr) / sizeof(arr[0]))
32
33 #define TIPC_DEV "/dev/trusty-ipc-dev0"
34 #define WIDEVINE_PORT "com.android.trusty.widevine"
35 #define WIDEVINE_MODULE_NAME "widevine.syms.elf"
36
37 #define WV_IPC_BUFFER_SIZE (32)
38 #define WV_MESSAGE_BUFFER_SIZE (32 * 1024)
39 #define WV_SHARED_BUFFER_SIZE (16 * 1024 * 1024)
40
41 struct wv_ipc_header {
42 uint16_t tag;
43 };
44
45 enum wv_tag : uint16_t {
46 WV_TAG_ACK = 0u,
47 WV_TAG_BIND = 1u,
48 WV_TAG_WIDEVINE = 2u,
49 };
50
51 struct bind_message {
52 uint32_t protocol_version;
53 uint32_t message_buffer_size;
54 uint32_t shared_buffer_size;
55 };
56
57 struct widevine_message {
58 uint32_t message_size;
59 };
60
61 /* Widevine TA's UUID is 08d3ed40-bde2-448c-a91d-75f1989c57ef */
62 static struct uuid widevine_uuid = {
63 0x08d3ed40,
64 0xbde2,
65 0x448c,
66 {0xa9, 0x1d, 0x75, 0xf1, 0x98, 0x9c, 0x57, 0xef},
67 };
68
69 static android::base::unique_fd wv_msg_buf_fd;
70 static void* wv_msg_buf_base;
71
72 static android::base::unique_fd wv_shared_buf_fd;
73 static void* wv_shared_buf_base;
74
75 static TrustyApp trusty_app(TIPC_DEV, WIDEVINE_PORT);
76 static CoverageRecord record(TIPC_DEV, &widevine_uuid, WIDEVINE_MODULE_NAME);
77
LLVMFuzzerInitialize(int *,char ***)78 extern "C" int LLVMFuzzerInitialize(int* /* argc */, char*** /* argv */) {
79 auto ret = trusty_app.Connect();
80 if (!ret.ok()) {
81 std::cerr << ret.error() << std::endl;
82 exit(-1);
83 }
84
85 ret = record.Open();
86 if (!ret.ok()) {
87 std::cerr << ret.error() << std::endl;
88 exit(-1);
89 }
90
91 BufferAllocator allocator;
92
93 wv_msg_buf_fd.reset(allocator.Alloc(kDmabufSystemHeapName, WV_MESSAGE_BUFFER_SIZE));
94 if (wv_msg_buf_fd < 0) {
95 std::cerr << "Failed to allocate message buffer." << std::endl;
96 exit(-1);
97 }
98
99 wv_msg_buf_base = mmap(0, WV_MESSAGE_BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
100 wv_msg_buf_fd, 0);
101 if (wv_msg_buf_base == MAP_FAILED) {
102 std::cerr << "Failed to mmap() message buffer." << std::endl;
103 exit(-1);
104 }
105
106 wv_shared_buf_fd.reset(allocator.Alloc(kDmabufSystemHeapName, WV_SHARED_BUFFER_SIZE));
107 if (wv_shared_buf_fd < 0) {
108 std::cerr << "Failed to allocate shared buffer." << std::endl;
109 exit(-1);
110 }
111
112 wv_shared_buf_base = mmap(0, WV_SHARED_BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
113 wv_shared_buf_fd, 0);
114 if (wv_shared_buf_base == MAP_FAILED) {
115 std::cerr << "Failed to mmap() shared buffer." << std::endl;
116 exit(-1);
117 }
118
119 return 0;
120 }
121
Bind()122 static bool Bind() {
123 wv_ipc_header hdr = {
124 .tag = WV_TAG_BIND,
125 };
126 bind_message args = {
127 .protocol_version = 0,
128 .message_buffer_size = WV_MESSAGE_BUFFER_SIZE,
129 .shared_buffer_size = WV_SHARED_BUFFER_SIZE,
130 };
131 iovec iov[] = {
132 {
133 .iov_base = &hdr,
134 .iov_len = sizeof(hdr),
135 },
136 {
137 .iov_base = &args,
138 .iov_len = sizeof(args),
139 },
140 };
141 trusty_shm handles[] = {
142 {
143 .fd = wv_msg_buf_fd,
144 .transfer = TRUSTY_SHARE,
145 },
146 {
147 .fd = wv_shared_buf_fd,
148 .transfer = TRUSTY_SHARE,
149 },
150 };
151 int chan = *trusty_app.GetRawFd();
152
153 int rc = tipc_send(chan, iov, countof(iov), handles, countof(handles));
154 if (rc != static_cast<int>(sizeof(hdr) + sizeof(args))) {
155 return false;
156 }
157
158 rc = read(chan, &hdr, sizeof(hdr));
159 if (rc != static_cast<int>(sizeof(hdr))) {
160 return false;
161 }
162
163 return true;
164 }
165
Msg(const uint8_t * data,size_t size)166 static bool Msg(const uint8_t* data, size_t size) {
167 size = std::min((size_t)WV_MESSAGE_BUFFER_SIZE, size);
168 wv_ipc_header hdr = {
169 .tag = WV_TAG_WIDEVINE,
170 };
171 widevine_message args = {
172 .message_size = static_cast<uint32_t>(size),
173 };
174 iovec iov[] = {
175 {
176 .iov_base = &hdr,
177 .iov_len = sizeof(hdr),
178 },
179 {
180 .iov_base = &args,
181 .iov_len = sizeof(args),
182 },
183 };
184 int chan = *trusty_app.GetRawFd();
185
186 memset(wv_msg_buf_base, 0, WV_MESSAGE_BUFFER_SIZE);
187 memcpy(wv_msg_buf_base, data, size);
188
189 int rc = tipc_send(chan, iov, countof(iov), NULL, 0);
190 if (rc != static_cast<int>(sizeof(hdr) + sizeof(args))) {
191 return false;
192 }
193
194 rc = readv(chan, iov, countof(iov));
195 if (rc != static_cast<int>(sizeof(hdr) + sizeof(args))) {
196 return false;
197 }
198
199 return true;
200 }
201
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)202 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
203 ExtraCounters counters(&record);
204 counters.Reset();
205
206 bool success = Bind();
207 if (!success) {
208 android::trusty::fuzz::Abort();
209 }
210
211 success = Msg(data, size);
212 if (!success) {
213 android::trusty::fuzz::Abort();
214 }
215
216 // Reconnect to ensure that the service is still up.
217 trusty_app.Disconnect();
218 auto ret = trusty_app.Connect();
219 if (!ret.ok()) {
220 std::cerr << ret.error() << std::endl;
221 android::trusty::fuzz::Abort();
222 }
223
224 return 0;
225 }
226