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