blob: 51c679f5d07797d3464d6fee854c4126a8594457 [file] [log] [blame]
Connor O'Briena963ae82016-09-12 15:52:04 -07001/*
2 * Copyright (C) 2016 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#include <sys/mman.h>
18#include <cutils/ashmem.h>
19#include <gtest/gtest.h>
20#include <android-base/unique_fd.h>
21
22using android::base::unique_fd;
23
24void TestCreateRegion(size_t size, unique_fd &fd, int prot) {
25 fd = unique_fd(ashmem_create_region(nullptr, size));
26 ASSERT_TRUE(fd >= 0);
27 ASSERT_TRUE(ashmem_valid(fd));
28 ASSERT_EQ(size, static_cast<size_t>(ashmem_get_size_region(fd)));
29 ASSERT_EQ(0, ashmem_set_prot_region(fd, prot));
30}
31
32void TestMmap(const unique_fd &fd, size_t size, int prot, void **region) {
33 *region = mmap(nullptr, size, prot, MAP_SHARED, fd, 0);
34 ASSERT_NE(MAP_FAILED, *region);
35}
36
37void TestProtDenied(const unique_fd &fd, size_t size, int prot) {
38 EXPECT_EQ(MAP_FAILED, mmap(nullptr, size, prot, MAP_SHARED, fd, 0));
39}
40
41void FillData(uint8_t* data, size_t dataLen) {
42 for (size_t i = 0; i < dataLen; i++) {
43 data[i] = i & 0xFF;
44 }
45}
46
47TEST(AshmemTest, BasicTest) {
48 constexpr size_t size = PAGE_SIZE;
49 uint8_t data[size];
50 FillData(data, size);
51
52 unique_fd fd;
53 ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
54
55 void *region1;
56 ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, &region1));
57
58 memcpy(region1, &data, size);
59 ASSERT_EQ(0, memcmp(region1, &data, size));
60
61 EXPECT_EQ(0, munmap(region1, size));
62
63 void *region2;
64 ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ, &region2));
65 ASSERT_EQ(0, memcmp(region2, &data, size));
66 EXPECT_EQ(0, munmap(region2, size));
67}
68
69TEST(AshmemTest, ForkTest) {
70 constexpr size_t size = PAGE_SIZE;
71 uint8_t data[size];
72 FillData(data, size);
73
74 unique_fd fd;
75 ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
76
77 void *region1;
78 ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, &region1));
79
80 memcpy(region1, &data, size);
81 ASSERT_EQ(0, memcmp(region1, &data, size));
82 EXPECT_EQ(0, munmap(region1, size));
83
84 ASSERT_EXIT({
85 void *region2 = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
86 if (region2 == MAP_FAILED) {
87 _exit(1);
88 }
89 if (memcmp(region2, &data, size) != 0) {
90 _exit(2);
91 }
92 memset(region2, 0, size);
93 munmap(region2, size);
94 _exit(0);
95 }, ::testing::ExitedWithCode(0),"");
96
97 memset(&data, 0, size);
98 void *region2;
99 ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, &region2));
100 ASSERT_EQ(0, memcmp(region2, &data, size));
101 EXPECT_EQ(0, munmap(region2, size));
102}
103
104TEST(AshmemTest, ProtTest) {
105 unique_fd fd;
106 constexpr size_t size = PAGE_SIZE;
107 void *region;
108
109 ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ));
110 TestProtDenied(fd, size, PROT_WRITE);
111 ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ, &region));
112 EXPECT_EQ(0, munmap(region, size));
113
114 ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_WRITE));
115 TestProtDenied(fd, size, PROT_READ);
116 ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_WRITE, &region));
117 EXPECT_EQ(0, munmap(region, size));
118}
119
120TEST(AshmemTest, ForkProtTest) {
121 unique_fd fd;
122 constexpr size_t size = PAGE_SIZE;
123
124 int protFlags[] = { PROT_READ, PROT_WRITE };
125 for (int i = 0; i < 2; i++) {
126 ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
127 ASSERT_EXIT({
128 if (ashmem_set_prot_region(fd, protFlags[i]) >= 0) {
129 _exit(0);
130 } else {
131 _exit(1);
132 }
133 }, ::testing::ExitedWithCode(0), "");
134 ASSERT_NO_FATAL_FAILURE(TestProtDenied(fd, size, protFlags[1-i]));
135 }
136}
137
138TEST(AshmemTest, ForkMultiRegionTest) {
139 constexpr size_t size = PAGE_SIZE;
140 uint8_t data[size];
141 FillData(data, size);
142
143 constexpr int nRegions = 16;
144 unique_fd fd[nRegions];
145 for (int i = 0; i < nRegions; i++) {
146 ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd[i], PROT_READ | PROT_WRITE));
147 void *region;
148 ASSERT_NO_FATAL_FAILURE(TestMmap(fd[i], size, PROT_READ | PROT_WRITE, &region));
149 memcpy(region, &data, size);
150 ASSERT_EQ(0, memcmp(region, &data, size));
151 EXPECT_EQ(0, munmap(region, size));
152 }
153
154 ASSERT_EXIT({
155 for (int i = 0; i < nRegions; i++) {
156 void *region = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd[i], 0);
157 if (region == MAP_FAILED) {
158 _exit(1);
159 }
160 if (memcmp(region, &data, size) != 0) {
161 munmap(region, size);
162 _exit(2);
163 }
164 memset(region, 0, size);
165 munmap(region, size);
166 }
167 _exit(0);
168 }, ::testing::ExitedWithCode(0), "");
169
170 memset(&data, 0, size);
171 for (int i = 0; i < nRegions; i++) {
172 void *region;
173 ASSERT_NO_FATAL_FAILURE(TestMmap(fd[i], size, PROT_READ | PROT_WRITE, &region));
174 ASSERT_EQ(0, memcmp(region, &data, size));
175 EXPECT_EQ(0, munmap(region, size));
176 }
177}