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