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