• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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