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#include "safe_copy.h" 18 19#include "common_runtime_test.h" 20 21#include <errno.h> 22#include <string.h> 23#include <sys/mman.h> 24#include <sys/user.h> 25 26namespace art { 27 28#if defined(__linux__) 29 30TEST(SafeCopyTest, smoke) { 31 // Map four pages, mark the second one as PROT_NONE, unmap the last one. 32 void* map = mmap(nullptr, PAGE_SIZE * 4, PROT_READ | PROT_WRITE, 33 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 34 ASSERT_NE(MAP_FAILED, map); 35 char* page1 = static_cast<char*>(map); 36 char* page2 = page1 + PAGE_SIZE; 37 char* page3 = page2 + PAGE_SIZE; 38 char* page4 = page3 + PAGE_SIZE; 39 ASSERT_EQ(0, mprotect(page1 + PAGE_SIZE, PAGE_SIZE, PROT_NONE)); 40 ASSERT_EQ(0, munmap(page4, PAGE_SIZE)); 41 42 page1[0] = 'a'; 43 page1[PAGE_SIZE - 1] = 'z'; 44 45 page3[0] = 'b'; 46 page3[PAGE_SIZE - 1] = 'y'; 47 48 char buf[PAGE_SIZE]; 49 50 // Completely valid read. 51 memset(buf, 0xCC, sizeof(buf)); 52 EXPECT_EQ(static_cast<ssize_t>(PAGE_SIZE), SafeCopy(buf, page1, PAGE_SIZE)) << strerror(errno); 53 EXPECT_EQ(0, memcmp(buf, page1, PAGE_SIZE)); 54 55 // Reading into a guard page. 56 memset(buf, 0xCC, sizeof(buf)); 57 EXPECT_EQ(static_cast<ssize_t>(PAGE_SIZE - 1), SafeCopy(buf, page1 + 1, PAGE_SIZE)); 58 EXPECT_EQ(0, memcmp(buf, page1 + 1, PAGE_SIZE - 1)); 59 60 // Reading from a guard page into a real page. 61 memset(buf, 0xCC, sizeof(buf)); 62 EXPECT_EQ(0, SafeCopy(buf, page2 + PAGE_SIZE - 1, PAGE_SIZE)); 63 64 // Reading off of the end of a mapping. 65 memset(buf, 0xCC, sizeof(buf)); 66 EXPECT_EQ(static_cast<ssize_t>(PAGE_SIZE), SafeCopy(buf, page3, PAGE_SIZE * 2)); 67 EXPECT_EQ(0, memcmp(buf, page3, PAGE_SIZE)); 68 69 // Completely invalid. 70 EXPECT_EQ(0, SafeCopy(buf, page1 + PAGE_SIZE, PAGE_SIZE)); 71 72 // Clean up. 73 ASSERT_EQ(0, munmap(map, PAGE_SIZE * 3)); 74} 75 76TEST(SafeCopyTest, alignment) { 77 // Copy the middle of a mapping to the end of another one. 78 void* src_map = mmap(nullptr, PAGE_SIZE * 3, PROT_READ | PROT_WRITE, 79 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 80 ASSERT_NE(MAP_FAILED, src_map); 81 82 // Add a guard page to make sure we don't write past the end of the mapping. 83 void* dst_map = mmap(nullptr, PAGE_SIZE * 4, PROT_READ | PROT_WRITE, 84 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 85 ASSERT_NE(MAP_FAILED, dst_map); 86 87 char* src = static_cast<char*>(src_map); 88 char* dst = static_cast<char*>(dst_map); 89 ASSERT_EQ(0, mprotect(dst + 3 * PAGE_SIZE, PAGE_SIZE, PROT_NONE)); 90 91 src[512] = 'a'; 92 src[PAGE_SIZE * 3 - 512 - 1] = 'z'; 93 94 EXPECT_EQ(static_cast<ssize_t>(PAGE_SIZE * 3 - 1024), 95 SafeCopy(dst + 1024, src + 512, PAGE_SIZE * 3 - 1024)); 96 EXPECT_EQ(0, memcmp(dst + 1024, src + 512, PAGE_SIZE * 3 - 1024)); 97 98 ASSERT_EQ(0, munmap(src_map, PAGE_SIZE * 3)); 99 ASSERT_EQ(0, munmap(dst_map, PAGE_SIZE * 4)); 100} 101 102#endif // defined(__linux__) 103 104} // namespace art 105