1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker *
4*8d67ca89SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker *
8*8d67ca89SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker *
10*8d67ca89SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker */
16*8d67ca89SAndroid Build Coastguard Worker
17*8d67ca89SAndroid Build Coastguard Worker #include <fcntl.h>
18*8d67ca89SAndroid Build Coastguard Worker #include <sys/mman.h>
19*8d67ca89SAndroid Build Coastguard Worker #include <sys/user.h>
20*8d67ca89SAndroid Build Coastguard Worker #include <sys/types.h>
21*8d67ca89SAndroid Build Coastguard Worker #include <unistd.h>
22*8d67ca89SAndroid Build Coastguard Worker
23*8d67ca89SAndroid Build Coastguard Worker #include <android-base/file.h>
24*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
25*8d67ca89SAndroid Build Coastguard Worker
26*8d67ca89SAndroid Build Coastguard Worker #include "utils.h"
27*8d67ca89SAndroid Build Coastguard Worker
28*8d67ca89SAndroid Build Coastguard Worker static const size_t kPageSize = getpagesize();
29*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mmap_std)30*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mmap_std) {
31*8d67ca89SAndroid Build Coastguard Worker void* map = mmap(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
32*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
33*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, munmap(map, 4096));
34*8d67ca89SAndroid Build Coastguard Worker }
35*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mmap64_std)36*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mmap64_std) {
37*8d67ca89SAndroid Build Coastguard Worker void* map = mmap64(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
38*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
39*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, munmap(map, 4096));
40*8d67ca89SAndroid Build Coastguard Worker }
41*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mmap_file_bad_offset)42*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mmap_file_bad_offset) {
43*8d67ca89SAndroid Build Coastguard Worker TemporaryFile tf;
44*8d67ca89SAndroid Build Coastguard Worker
45*8d67ca89SAndroid Build Coastguard Worker void* map = mmap(nullptr, 100, PROT_READ, MAP_SHARED, tf.fd, 1);
46*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(MAP_FAILED, map);
47*8d67ca89SAndroid Build Coastguard Worker }
48*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mmap64_file_bad_offset)49*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mmap64_file_bad_offset) {
50*8d67ca89SAndroid Build Coastguard Worker TemporaryFile tf;
51*8d67ca89SAndroid Build Coastguard Worker
52*8d67ca89SAndroid Build Coastguard Worker void* map = mmap64(nullptr, 100, PROT_READ, MAP_SHARED, tf.fd, 1);
53*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(MAP_FAILED, map);
54*8d67ca89SAndroid Build Coastguard Worker }
55*8d67ca89SAndroid Build Coastguard Worker
56*8d67ca89SAndroid Build Coastguard Worker #define STR_SSIZE(str) static_cast<ssize_t>(sizeof(str))
57*8d67ca89SAndroid Build Coastguard Worker
58*8d67ca89SAndroid Build Coastguard Worker #define STRING_MSG "012345678\nabcdefgh\n"
59*8d67ca89SAndroid Build Coastguard Worker #define INITIAL_MSG "000000000\n00000000\n"
60*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mmap_file_read)61*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mmap_file_read) {
62*8d67ca89SAndroid Build Coastguard Worker TemporaryFile tf;
63*8d67ca89SAndroid Build Coastguard Worker
64*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(STR_SSIZE(STRING_MSG), write(tf.fd, STRING_MSG, sizeof(STRING_MSG)));
65*8d67ca89SAndroid Build Coastguard Worker
66*8d67ca89SAndroid Build Coastguard Worker void* map = mmap(nullptr, sizeof(STRING_MSG), PROT_READ, MAP_SHARED, tf.fd, 0);
67*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
68*8d67ca89SAndroid Build Coastguard Worker
69*8d67ca89SAndroid Build Coastguard Worker char* data = reinterpret_cast<char*>(map);
70*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(STRING_MSG, data);
71*8d67ca89SAndroid Build Coastguard Worker
72*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, munmap(map, sizeof(STRING_MSG)));
73*8d67ca89SAndroid Build Coastguard Worker }
74*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mmap_file_write)75*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mmap_file_write) {
76*8d67ca89SAndroid Build Coastguard Worker TemporaryFile tf;
77*8d67ca89SAndroid Build Coastguard Worker
78*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(STR_SSIZE(INITIAL_MSG), write(tf.fd, INITIAL_MSG, sizeof(INITIAL_MSG)));
79*8d67ca89SAndroid Build Coastguard Worker lseek(tf.fd, 0, SEEK_SET);
80*8d67ca89SAndroid Build Coastguard Worker
81*8d67ca89SAndroid Build Coastguard Worker void* map = mmap(nullptr, sizeof(STRING_MSG), PROT_WRITE, MAP_SHARED, tf.fd, 0);
82*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
83*8d67ca89SAndroid Build Coastguard Worker close(tf.fd);
84*8d67ca89SAndroid Build Coastguard Worker
85*8d67ca89SAndroid Build Coastguard Worker memcpy(map, STRING_MSG, sizeof(STRING_MSG));
86*8d67ca89SAndroid Build Coastguard Worker
87*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, munmap(map, sizeof(STRING_MSG)));
88*8d67ca89SAndroid Build Coastguard Worker
89*8d67ca89SAndroid Build Coastguard Worker tf.fd = open(tf.path, O_RDWR);
90*8d67ca89SAndroid Build Coastguard Worker char buf[sizeof(STRING_MSG)];
91*8d67ca89SAndroid Build Coastguard Worker memset(buf, 0, sizeof(STRING_MSG));
92*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(STR_SSIZE(STRING_MSG), read(tf.fd, buf, sizeof(STRING_MSG)));
93*8d67ca89SAndroid Build Coastguard Worker
94*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(STRING_MSG, buf);
95*8d67ca89SAndroid Build Coastguard Worker }
96*8d67ca89SAndroid Build Coastguard Worker
97*8d67ca89SAndroid Build Coastguard Worker #define PAGE0_MSG "00PAGE00"
98*8d67ca89SAndroid Build Coastguard Worker #define PAGE1_MSG "111PAGE111"
99*8d67ca89SAndroid Build Coastguard Worker #define PAGE2_MSG "2222PAGE2222"
100*8d67ca89SAndroid Build Coastguard Worker #define END_MSG "E"
101*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mmap_file_read_at_offset)102*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mmap_file_read_at_offset) {
103*8d67ca89SAndroid Build Coastguard Worker TemporaryFile tf;
104*8d67ca89SAndroid Build Coastguard Worker size_t pagesize = sysconf(_SC_PAGESIZE);
105*8d67ca89SAndroid Build Coastguard Worker
106*8d67ca89SAndroid Build Coastguard Worker // Create the file with three pages worth of data.
107*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(STR_SSIZE(PAGE0_MSG), write(tf.fd, PAGE0_MSG, sizeof(PAGE0_MSG)));
108*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(-1, lseek(tf.fd, pagesize, SEEK_SET));
109*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(STR_SSIZE(PAGE1_MSG), write(tf.fd, PAGE1_MSG, sizeof(PAGE1_MSG)));
110*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(-1, lseek(tf.fd, 2 * pagesize, SEEK_SET));
111*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(STR_SSIZE(PAGE2_MSG), write(tf.fd, PAGE2_MSG, sizeof(PAGE2_MSG)));
112*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(-1, lseek(tf.fd, 3 * pagesize - sizeof(END_MSG), SEEK_SET));
113*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(STR_SSIZE(END_MSG), write(tf.fd, END_MSG, sizeof(END_MSG)));
114*8d67ca89SAndroid Build Coastguard Worker
115*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(-1, lseek(tf.fd, 0, SEEK_SET));
116*8d67ca89SAndroid Build Coastguard Worker
117*8d67ca89SAndroid Build Coastguard Worker void* map = mmap(nullptr, pagesize, PROT_READ, MAP_SHARED, tf.fd, pagesize);
118*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
119*8d67ca89SAndroid Build Coastguard Worker
120*8d67ca89SAndroid Build Coastguard Worker char* data = reinterpret_cast<char*>(map);
121*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(PAGE1_MSG, data);
122*8d67ca89SAndroid Build Coastguard Worker
123*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, munmap(map, pagesize));
124*8d67ca89SAndroid Build Coastguard Worker
125*8d67ca89SAndroid Build Coastguard Worker map = mmap(nullptr, pagesize, PROT_READ, MAP_SHARED, tf.fd, 2 * pagesize);
126*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
127*8d67ca89SAndroid Build Coastguard Worker
128*8d67ca89SAndroid Build Coastguard Worker data = reinterpret_cast<char*>(map);
129*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(PAGE2_MSG, data);
130*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(END_MSG, data+pagesize-sizeof(END_MSG));
131*8d67ca89SAndroid Build Coastguard Worker
132*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, munmap(map, pagesize));
133*8d67ca89SAndroid Build Coastguard Worker }
134*8d67ca89SAndroid Build Coastguard Worker
135*8d67ca89SAndroid Build Coastguard Worker #define NEWPAGE1_MSG "1NEW1PAGE1"
136*8d67ca89SAndroid Build Coastguard Worker #define NEWPAGE2_MSG "22NEW22PAGE22"
137*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mmap_file_write_at_offset)138*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mmap_file_write_at_offset) {
139*8d67ca89SAndroid Build Coastguard Worker TemporaryFile tf;
140*8d67ca89SAndroid Build Coastguard Worker size_t pagesize = sysconf(_SC_PAGESIZE);
141*8d67ca89SAndroid Build Coastguard Worker
142*8d67ca89SAndroid Build Coastguard Worker // Create the file with three pages worth of data.
143*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(STR_SSIZE(PAGE0_MSG), write(tf.fd, PAGE0_MSG, sizeof(PAGE0_MSG)));
144*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(-1, lseek(tf.fd, pagesize, SEEK_SET));
145*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(STR_SSIZE(PAGE1_MSG), write(tf.fd, PAGE1_MSG, sizeof(PAGE1_MSG)));
146*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(-1, lseek(tf.fd, 2 * pagesize, SEEK_SET));
147*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(STR_SSIZE(PAGE2_MSG), write(tf.fd, PAGE2_MSG, sizeof(PAGE2_MSG)));
148*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(-1, lseek(tf.fd, 3 * pagesize - sizeof(END_MSG), SEEK_SET));
149*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(STR_SSIZE(END_MSG), write(tf.fd, END_MSG, sizeof(END_MSG)));
150*8d67ca89SAndroid Build Coastguard Worker
151*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(-1, lseek(tf.fd, 0, SEEK_SET));
152*8d67ca89SAndroid Build Coastguard Worker
153*8d67ca89SAndroid Build Coastguard Worker void* map = mmap(nullptr, pagesize, PROT_WRITE, MAP_SHARED, tf.fd, pagesize);
154*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
155*8d67ca89SAndroid Build Coastguard Worker close(tf.fd);
156*8d67ca89SAndroid Build Coastguard Worker
157*8d67ca89SAndroid Build Coastguard Worker memcpy(map, NEWPAGE1_MSG, sizeof(NEWPAGE1_MSG));
158*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, munmap(map, pagesize));
159*8d67ca89SAndroid Build Coastguard Worker
160*8d67ca89SAndroid Build Coastguard Worker tf.fd = open(tf.path, O_RDWR);
161*8d67ca89SAndroid Build Coastguard Worker map = mmap(nullptr, pagesize, PROT_WRITE, MAP_SHARED, tf.fd, 2 * pagesize);
162*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
163*8d67ca89SAndroid Build Coastguard Worker close(tf.fd);
164*8d67ca89SAndroid Build Coastguard Worker
165*8d67ca89SAndroid Build Coastguard Worker memcpy(map, NEWPAGE2_MSG, sizeof(NEWPAGE2_MSG));
166*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, munmap(map, pagesize));
167*8d67ca89SAndroid Build Coastguard Worker
168*8d67ca89SAndroid Build Coastguard Worker tf.fd = open(tf.path, O_RDWR);
169*8d67ca89SAndroid Build Coastguard Worker char buf[pagesize];
170*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<ssize_t>(pagesize), read(tf.fd, buf, pagesize));
171*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(PAGE0_MSG, buf);
172*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(-1, lseek(tf.fd, pagesize, SEEK_SET));
173*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<ssize_t>(pagesize), read(tf.fd, buf, pagesize));
174*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(NEWPAGE1_MSG, buf);
175*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(-1, lseek(tf.fd, 2 * pagesize, SEEK_SET));
176*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<ssize_t>(pagesize), read(tf.fd, buf, pagesize));
177*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(NEWPAGE2_MSG, buf);
178*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(END_MSG, buf+pagesize-sizeof(END_MSG));
179*8d67ca89SAndroid Build Coastguard Worker }
180*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,posix_madvise)181*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, posix_madvise) {
182*8d67ca89SAndroid Build Coastguard Worker TemporaryFile tempfile;
183*8d67ca89SAndroid Build Coastguard Worker size_t pagesize = sysconf(_SC_PAGESIZE);
184*8d67ca89SAndroid Build Coastguard Worker char buf[pagesize];
185*8d67ca89SAndroid Build Coastguard Worker
186*8d67ca89SAndroid Build Coastguard Worker // Prepare environment.
187*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<ssize_t>(pagesize), write(tempfile.fd, buf, pagesize));
188*8d67ca89SAndroid Build Coastguard Worker void* map = mmap(nullptr, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, tempfile.fd, 0);
189*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
190*8d67ca89SAndroid Build Coastguard Worker
191*8d67ca89SAndroid Build Coastguard Worker // Verify different options of posix_madvise.
192*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_NORMAL));
193*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_SEQUENTIAL));
194*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_RANDOM));
195*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_WILLNEED));
196*8d67ca89SAndroid Build Coastguard Worker
197*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, munmap(map, pagesize));
198*8d67ca89SAndroid Build Coastguard Worker }
199*8d67ca89SAndroid Build Coastguard Worker
200*8d67ca89SAndroid Build Coastguard Worker // Verify that memory can still access after posix_madvise(POSIX_MADV_DONTNEED).
201*8d67ca89SAndroid Build Coastguard Worker // We should test on MAP_ANONYMOUS memory to verify whether the memory is discarded,
202*8d67ca89SAndroid Build Coastguard Worker // because the content of non MAP_ANONYMOUS memory can be reread from file.
TEST(sys_mman,posix_madvise_POSIX_MADV_DONTNEED)203*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, posix_madvise_POSIX_MADV_DONTNEED) {
204*8d67ca89SAndroid Build Coastguard Worker size_t pagesize = sysconf(_SC_PAGESIZE);
205*8d67ca89SAndroid Build Coastguard Worker
206*8d67ca89SAndroid Build Coastguard Worker void* map = mmap(nullptr, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
207*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
208*8d67ca89SAndroid Build Coastguard Worker
209*8d67ca89SAndroid Build Coastguard Worker int* int_ptr = reinterpret_cast<int*>(map);
210*8d67ca89SAndroid Build Coastguard Worker for (int i = 0; i < static_cast<int>(pagesize / sizeof(int)); ++i) {
211*8d67ca89SAndroid Build Coastguard Worker *int_ptr++ = i;
212*8d67ca89SAndroid Build Coastguard Worker }
213*8d67ca89SAndroid Build Coastguard Worker
214*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_DONTNEED));
215*8d67ca89SAndroid Build Coastguard Worker
216*8d67ca89SAndroid Build Coastguard Worker int_ptr = reinterpret_cast<int*>(map);
217*8d67ca89SAndroid Build Coastguard Worker for (int i = 0; i < static_cast<int>(pagesize / sizeof(int)); ++i) {
218*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(i, *int_ptr++);
219*8d67ca89SAndroid Build Coastguard Worker }
220*8d67ca89SAndroid Build Coastguard Worker
221*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, munmap(map, pagesize));
222*8d67ca89SAndroid Build Coastguard Worker }
223*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mremap)224*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mremap) {
225*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic push
226*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wnonnull"
227*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(MAP_FAILED, mremap(nullptr, 0, 0, 0));
228*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic pop
229*8d67ca89SAndroid Build Coastguard Worker }
230*8d67ca89SAndroid Build Coastguard Worker
231*8d67ca89SAndroid Build Coastguard Worker constexpr size_t kHuge = size_t(PTRDIFF_MAX) + 1;
232*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mmap_PTRDIFF_MAX)233*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mmap_PTRDIFF_MAX) {
234*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(MAP_FAILED, mmap(nullptr, kHuge, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
235*8d67ca89SAndroid Build Coastguard Worker }
236*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mremap_PTRDIFF_MAX)237*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mremap_PTRDIFF_MAX) {
238*8d67ca89SAndroid Build Coastguard Worker void* map = mmap(nullptr, kPageSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
239*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
240*8d67ca89SAndroid Build Coastguard Worker
241*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(MAP_FAILED, mremap(map, kPageSize, kHuge, MREMAP_MAYMOVE));
242*8d67ca89SAndroid Build Coastguard Worker
243*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, munmap(map, kPageSize));
244*8d67ca89SAndroid Build Coastguard Worker }
245*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mremap_MREMAP_FIXED)246*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mremap_MREMAP_FIXED) {
247*8d67ca89SAndroid Build Coastguard Worker // We're not trying to test the kernel here; that's external/ltp's job.
248*8d67ca89SAndroid Build Coastguard Worker // We just want to check that optional argument (mremap() is varargs)
249*8d67ca89SAndroid Build Coastguard Worker // gets passed through in an MREMAP_FIXED call.
250*8d67ca89SAndroid Build Coastguard Worker void* vma1 = mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
251*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, vma1);
252*8d67ca89SAndroid Build Coastguard Worker
253*8d67ca89SAndroid Build Coastguard Worker void* vma2 = mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
254*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, vma2);
255*8d67ca89SAndroid Build Coastguard Worker
256*8d67ca89SAndroid Build Coastguard Worker void* vma3 = mremap(vma1, getpagesize(), getpagesize(), MREMAP_FIXED | MREMAP_MAYMOVE, vma2);
257*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(vma2, vma3);
258*8d67ca89SAndroid Build Coastguard Worker }
259*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mmap_bug_27265969)260*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mmap_bug_27265969) {
261*8d67ca89SAndroid Build Coastguard Worker char* base = reinterpret_cast<char*>(
262*8d67ca89SAndroid Build Coastguard Worker mmap(nullptr, kPageSize * 2, PROT_EXEC | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
263*8d67ca89SAndroid Build Coastguard Worker // Some kernels had bugs that would cause segfaults here...
264*8d67ca89SAndroid Build Coastguard Worker __builtin___clear_cache(base, base + (kPageSize * 2));
265*8d67ca89SAndroid Build Coastguard Worker }
266*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mlock)267*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mlock) {
268*8d67ca89SAndroid Build Coastguard Worker void* map = mmap(nullptr, kPageSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
269*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
270*8d67ca89SAndroid Build Coastguard Worker
271*8d67ca89SAndroid Build Coastguard Worker // Not really anything we can assert about this.
272*8d67ca89SAndroid Build Coastguard Worker mlock(map, kPageSize);
273*8d67ca89SAndroid Build Coastguard Worker
274*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, munmap(map, kPageSize));
275*8d67ca89SAndroid Build Coastguard Worker }
276*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,mlock2)277*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, mlock2) {
278*8d67ca89SAndroid Build Coastguard Worker #if defined(__GLIBC__)
279*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "needs glibc 2.27";
280*8d67ca89SAndroid Build Coastguard Worker #else
281*8d67ca89SAndroid Build Coastguard Worker void* map = mmap(nullptr, kPageSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
282*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
283*8d67ca89SAndroid Build Coastguard Worker
284*8d67ca89SAndroid Build Coastguard Worker // Not really anything we can assert about this.
285*8d67ca89SAndroid Build Coastguard Worker mlock2(map, kPageSize, MLOCK_ONFAULT);
286*8d67ca89SAndroid Build Coastguard Worker
287*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, munmap(map, kPageSize));
288*8d67ca89SAndroid Build Coastguard Worker #endif
289*8d67ca89SAndroid Build Coastguard Worker }
290*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mman,memfd_create)291*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mman, memfd_create) {
292*8d67ca89SAndroid Build Coastguard Worker #if defined(__GLIBC__)
293*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "needs glibc 2.27";
294*8d67ca89SAndroid Build Coastguard Worker #else
295*8d67ca89SAndroid Build Coastguard Worker // Is the MFD_CLOEXEC flag obeyed?
296*8d67ca89SAndroid Build Coastguard Worker errno = 0;
297*8d67ca89SAndroid Build Coastguard Worker int fd = memfd_create("doesn't matter", 0);
298*8d67ca89SAndroid Build Coastguard Worker if (fd == -1 && errno == ENOSYS) GTEST_SKIP() << "no memfd_create() in this kernel";
299*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(-1, fd) << strerror(errno);
300*8d67ca89SAndroid Build Coastguard Worker
301*8d67ca89SAndroid Build Coastguard Worker int f = fcntl(fd, F_GETFD);
302*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(-1, f);
303*8d67ca89SAndroid Build Coastguard Worker ASSERT_FALSE(f & FD_CLOEXEC);
304*8d67ca89SAndroid Build Coastguard Worker close(fd);
305*8d67ca89SAndroid Build Coastguard Worker
306*8d67ca89SAndroid Build Coastguard Worker errno = 0;
307*8d67ca89SAndroid Build Coastguard Worker fd = memfd_create("doesn't matter", MFD_CLOEXEC);
308*8d67ca89SAndroid Build Coastguard Worker f = fcntl(fd, F_GETFD);
309*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(-1, f);
310*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(f & FD_CLOEXEC);
311*8d67ca89SAndroid Build Coastguard Worker
312*8d67ca89SAndroid Build Coastguard Worker // Can we read and write?
313*8d67ca89SAndroid Build Coastguard Worker std::string expected("hello, world!");
314*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteStringToFd(expected, fd));
315*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, lseek(fd, 0, SEEK_SET));
316*8d67ca89SAndroid Build Coastguard Worker std::string actual;
317*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFdToString(fd, &actual));
318*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(expected, actual);
319*8d67ca89SAndroid Build Coastguard Worker
320*8d67ca89SAndroid Build Coastguard Worker close(fd);
321*8d67ca89SAndroid Build Coastguard Worker #endif
322*8d67ca89SAndroid Build Coastguard Worker }
323*8d67ca89SAndroid Build Coastguard Worker
TEST(sys_mseal,mseal)324*8d67ca89SAndroid Build Coastguard Worker TEST(sys_mseal, mseal) {
325*8d67ca89SAndroid Build Coastguard Worker #if defined(__GLIBC__)
326*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "needs glibc 2.40";
327*8d67ca89SAndroid Build Coastguard Worker #else
328*8d67ca89SAndroid Build Coastguard Worker void* map = mmap(nullptr, kPageSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
329*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(MAP_FAILED, map);
330*8d67ca89SAndroid Build Coastguard Worker
331*8d67ca89SAndroid Build Coastguard Worker #if defined(__LP64__)
332*8d67ca89SAndroid Build Coastguard Worker int rc = mseal(map, kPageSize, 0);
333*8d67ca89SAndroid Build Coastguard Worker if (rc == -1) {
334*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(ENOSYS);
335*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "needs kernel with mseal(2)";
336*8d67ca89SAndroid Build Coastguard Worker }
337*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(-1, mprotect(map, kPageSize, PROT_READ));
338*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EPERM);
339*8d67ca89SAndroid Build Coastguard Worker #else
340*8d67ca89SAndroid Build Coastguard Worker // No mseal() for ILP32.
341*8d67ca89SAndroid Build Coastguard Worker errno = 0;
342*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(-1, mseal(map, kPageSize, 0));
343*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(ENOSYS);
344*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "mseal(2) is LP64-only";
345*8d67ca89SAndroid Build Coastguard Worker #endif
346*8d67ca89SAndroid Build Coastguard Worker
347*8d67ca89SAndroid Build Coastguard Worker // We can't munmap() our test mapping if mseal() actually succeeded :-)
348*8d67ca89SAndroid Build Coastguard Worker #endif
349*8d67ca89SAndroid Build Coastguard Worker }
350