1 /*
2 * Copyright (C) 2020 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 #define TLOG_TAG "crasher"
18
19 #include <assert.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <trusty_log.h>
23 #include <uapi/err.h>
24
25 #include <lib/tipc/tipc.h>
26 #include <lib/tipc/tipc_srv.h>
27
28 #include <crasher.h>
29 #include <crasher_consts.h>
30 #include <crasher_funcs.h>
31
32 static struct tipc_port_acl crasher_port_acl = {
33 .flags = IPC_PORT_ALLOW_TA_CONNECT,
34 .uuid_num = 0,
35 .uuids = NULL,
36 .extra_data = NULL,
37 };
38
39 static struct tipc_port crasher_port = {
40 .name = CRASHER_PORT,
41 .msg_max_size = sizeof(struct crasher_msg),
42 .msg_queue_len = 1,
43 .acl = &crasher_port_acl,
44 .priv = NULL,
45 };
46
47 static int __attribute__((no_sanitize("undefined")))
crasher_on_message(const struct tipc_port * port,handle_t chan,void * ctx)48 crasher_on_message(const struct tipc_port* port, handle_t chan, void* ctx) {
49 assert(port == &crasher_port);
50 assert(ctx == NULL);
51 struct crasher_msg msg;
52
53 int ret = tipc_recv1(chan, sizeof(msg), &msg, sizeof(msg));
54 if (ret < 0 || ret != sizeof(msg)) {
55 TLOGE("Failed to receive message (%d)\n", ret);
56 return ret;
57 }
58
59 TLOGD("cmd %d\n", msg.cmd);
60
61 switch (msg.cmd) {
62 case CRASHER_NOP:
63 TLOGI("nop\n");
64 break;
65 case CRASHER_EXIT_SUCCESS:
66 TLOGI("exit success\n");
67 exit(EXIT_SUCCESS);
68 break;
69 case CRASHER_EXIT_FAILURE:
70 TLOGI("exit failure\n");
71 exit(EXIT_FAILURE);
72 break;
73 case CRASHER_READ_NULL_PTR:
74 TLOGI("read null\n");
75 READ_ONCE(*(uint8_t*)NULL);
76 break;
77 case CRASHER_READ_BAD_PTR:
78 TLOGI("read bad ptr\n");
79 READ_ONCE(*(uint8_t*)1);
80 break;
81 case CRASHER_WRITE_BAD_PTR:
82 TLOGI("write bad ptr\n");
83 WRITE_ONCE(*(uint8_t*)1, 0);
84 break;
85 case CRASHER_WRITE_RO_PTR:
86 TLOGI("write ro ptr\n");
87 WRITE_ONCE(*(uint8_t*)crasher_rodata_func, 0);
88 break;
89 case CRASHER_EXEC_RODATA:
90 TLOGI("call crasher_rodata_func\n");
91 crasher_rodata_func();
92 break;
93 case CRASHER_EXEC_DATA:
94 TLOGI("call crasher_data_func\n");
95 crasher_data_func();
96 break;
97 #ifdef __aarch64__
98 case CRASHER_BRK:
99 TLOGI("BRK instruction\n");
100 __asm__("brk #42");
101 break;
102 #endif
103 default:
104 TLOGE("Bad command: %d\n", msg.cmd);
105 return -1;
106 }
107
108 ret = tipc_send1(chan, &msg, sizeof(msg));
109 if (ret < 0 || ret != sizeof(msg)) {
110 TLOGE("Failed to send message (%d)\n", ret);
111 return ret < 0 ? ret : ERR_IO;
112 }
113 TLOGD("cmd %d done\n", msg.cmd);
114
115 return 0;
116 }
117
118 static struct tipc_srv_ops crasher_ops = {
119 .on_message = crasher_on_message,
120 };
121
main(void)122 int main(void) {
123 struct tipc_hset* hset = tipc_hset_create();
124 if (!hset) {
125 return -1;
126 }
127
128 int rc = tipc_add_service(hset, &crasher_port, 1, 1, &crasher_ops);
129 if (rc < 0) {
130 return rc;
131 }
132
133 rc = tipc_run_event_loop(hset);
134 TLOGE("crasher going down: (%d)\n", rc);
135 return rc;
136 }
137