1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "crazy_linker_ashmem.h" 6 7 #include <fcntl.h> 8 #include <string.h> 9 #include <sys/ioctl.h> 10 #include <sys/stat.h> 11 #include <sys/types.h> 12 #include <unistd.h> 13 14 #include <linux/ashmem.h> 15 16 #include "crazy_linker_system.h" 17 #include "crazy_linker_memory_mapping.h" 18 19 namespace crazy { 20 Allocate(size_t region_size,const char * region_name)21 bool AshmemRegion::Allocate(size_t region_size, const char* region_name) { 22 int fd = TEMP_FAILURE_RETRY(open("/dev/ashmem", O_RDWR)); 23 if (fd < 0) 24 return false; 25 26 if (ioctl(fd, ASHMEM_SET_SIZE, region_size) < 0) 27 goto ERROR; 28 29 if (region_name) { 30 char buf[256]; 31 strlcpy(buf, region_name, sizeof(buf)); 32 if (ioctl(fd, ASHMEM_SET_NAME, buf) < 0) 33 goto ERROR; 34 } 35 36 Reset(fd); 37 return true; 38 39 ERROR: 40 ::close(fd); 41 return false; 42 } 43 SetProtectionFlags(int prot)44 bool AshmemRegion::SetProtectionFlags(int prot) { 45 return ioctl(fd_, ASHMEM_SET_PROT_MASK, prot) == 0; 46 } 47 48 // static CheckFileDescriptorIsReadOnly(int fd)49 bool AshmemRegion::CheckFileDescriptorIsReadOnly(int fd) { 50 const size_t map_size = PAGE_SIZE; 51 ScopedMemoryMapping map; 52 53 // First, check that trying to map a page of the region with PROT_WRITE 54 // fails with EPERM. 55 if (map.Allocate(NULL, map_size, MemoryMapping::CAN_WRITE, fd)) { 56 LOG("%s: Region could be mapped writable. Should not happen.\n", 57 __FUNCTION__); 58 errno = EPERM; 59 return false; 60 } 61 if (errno != EPERM) { 62 LOG_ERRNO("%s: Region failed writable mapping with unexpected error", 63 __FUNCTION__); 64 return false; 65 } 66 67 // Second, check that it can be mapped PROT_READ, but cannot be remapped 68 // with PROT_READ | PROT_WRITE through mprotect(). 69 if (!map.Allocate(NULL, map_size, MemoryMapping::CAN_READ, fd)) { 70 LOG_ERRNO("%s: Failed to map region read-only", __FUNCTION__); 71 return false; 72 } 73 if (map.SetProtection(MemoryMapping::CAN_READ_WRITE)) { 74 LOG_ERRNO("%s: Region could be remapped read-write. Should not happen.\n", 75 __FUNCTION__); 76 return false; 77 } 78 if (errno != EACCES) { 79 LOG_ERRNO( 80 "%s: Region failed to be remapped read-write with unexpected error", 81 __FUNCTION__); 82 return false; 83 } 84 85 // Everything's good. 86 return true; 87 } 88 89 } // namespace crazy 90