1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * System utilities. 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "DexFile.h" 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "SysUtil.h" 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h> 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdio.h> 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h> 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <string.h> 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_POSIX_FILEMAP 2864896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden# include <sys/mman.h> 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <limits.h> 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h> 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3364896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden#include <JNIHelp.h> // TEMP_FAILURE_RETRY may or may not be in unistd 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create an anonymous shared memory segment large enough to hold "length" 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bytes. The actual segment may be larger because mmap() operates on 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * page boundaries (usually 4K). 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void* sysCreateAnonShmem(size_t length) 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_POSIX_FILEMAP 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* ptr; 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ptr = mmap(NULL, length, PROT_READ | PROT_WRITE, 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MAP_SHARED | MAP_ANON, -1, 0); 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (ptr == MAP_FAILED) { 49e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("mmap(%d, RW, SHARED|ANON) failed: %s", (int) length, 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project strerror(errno)); 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ptr; 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 56c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("sysCreateAnonShmem not implemented."); 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 6199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project/* 6299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Create a private anonymous storage area. 6399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project */ 6499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Projectint sysCreatePrivateMap(size_t length, MemMapping* pMap) 6599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project{ 6699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project void* memPtr; 6799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project 6899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project memPtr = sysCreateAnonShmem(length); 6999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project if (memPtr == NULL) 7099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project return -1; 7199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project 7299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project pMap->addr = pMap->baseAddr = memPtr; 7399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project pMap->length = pMap->baseLength = length; 7499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project return 0; 7599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project} 7699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project 7799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project/* 7899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Determine the current offset and remaining length of the open file. 7999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project */ 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int getFileStartAndLength(int fd, off_t *start_, size_t *length_) 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project off_t start, end; 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t length; 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(start_ != NULL); 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(length_ != NULL); 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = lseek(fd, 0L, SEEK_CUR); 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project end = lseek(fd, 0L, SEEK_END); 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (void) lseek(fd, start, SEEK_SET); 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (start == (off_t) -1 || end == (off_t) -1) { 93c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("could not determine length of file"); 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project length = end - start; 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (length == 0) { 99c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("file is empty"); 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *start_ = start; 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *length_ = length; 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 0; 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 109518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden#ifndef HAVE_POSIX_FILEMAP 110518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFaddenint sysFakeMapFile(int fd, MemMapping* pMap) 111518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden{ 112518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden /* No MMAP, just fake it by copying the bits. 113518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden For Win32 we could use MapViewOfFile if really necessary 114518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden (see libs/utils/FileMap.cpp). 115518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden */ 116518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden off_t start; 117518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden size_t length; 118518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden void* memPtr; 119518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden 120518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden assert(pMap != NULL); 121518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden 122518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden if (getFileStartAndLength(fd, &start, &length) < 0) 123518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden return -1; 124518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden 125518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden memPtr = malloc(length); 126518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden if (read(fd, memPtr, length) < 0) { 127e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("read(fd=%d, start=%d, length=%d) failed: %s", (int) length, 128518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden fd, (int) start, strerror(errno)); 129518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden return -1; 130518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden } 131518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden 132518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden pMap->baseAddr = pMap->addr = memPtr; 133518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden pMap->baseLength = pMap->length = length; 134518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden 135518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden return 0; 136518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden} 137518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden#endif 138518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 140b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden * Map a file (from fd's current offset) into a private, read-write memory 141b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden * segment that will be marked read-only (a/k/a "writable read-only"). The 142b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden * file offset must be a multiple of the system page size. 143b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden * 144b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden * In some cases the mapping will be fully writable (e.g. for files on 145b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden * FAT filesystems). 146b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden * 147b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden * On success, returns 0 and fills out "pMap". On failure, returns a nonzero 148b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden * value and does not disturb "pMap". 149b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden */ 150b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFaddenint sysMapFileInShmemWritableReadOnly(int fd, MemMapping* pMap) 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_POSIX_FILEMAP 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project off_t start; 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t length; 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* memPtr; 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(pMap != NULL); 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (getFileStartAndLength(fd, &start, &length) < 0) 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 16296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden memPtr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE, 16396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden fd, start); 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (memPtr == MAP_FAILED) { 165e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("mmap(%d, R/W, FILE|PRIVATE, %d, %d) failed: %s", (int) length, 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fd, (int) start, strerror(errno)); 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 16996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (mprotect(memPtr, length, PROT_READ) < 0) { 170b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden /* this fails with EACCESS on FAT filesystems, e.g. /sdcard */ 171b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden int err = errno; 17292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("mprotect(%p, %d, PROT_READ) failed: %s", 173b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden memPtr, length, strerror(err)); 174062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("mprotect(RO) failed (%d), file will remain read-write", err); 17596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pMap->baseAddr = pMap->addr = memPtr; 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pMap->baseLength = pMap->length = length; 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 0; 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 182518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden return sysFakeMapFile(fd, pMap); 183b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden#endif 184b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden} 185b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1878911f7a2222124ba724a4a9281555b74d0e098e2Andy McFadden * Map part of a file into a shared, read-only memory segment. The "start" 1888911f7a2222124ba724a4a9281555b74d0e098e2Andy McFadden * offset is absolute, not relative. 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On success, returns 0 and fills out "pMap". On failure, returns a nonzero 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * value and does not disturb "pMap". 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1938911f7a2222124ba724a4a9281555b74d0e098e2Andy McFaddenint sysMapFileSegmentInShmem(int fd, off_t start, size_t length, 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MemMapping* pMap) 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_POSIX_FILEMAP 1978911f7a2222124ba724a4a9281555b74d0e098e2Andy McFadden size_t actualLength; 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project off_t actualStart; 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int adjust; 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* memPtr; 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(pMap != NULL); 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* adjust to be page-aligned */ 20564896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden adjust = start % SYSTEM_PAGE_SIZE; 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project actualStart = start - adjust; 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project actualLength = length + adjust; 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memPtr = mmap(NULL, actualLength, PROT_READ, MAP_FILE | MAP_SHARED, 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fd, actualStart); 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (memPtr == MAP_FAILED) { 212e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("mmap(%d, R, FILE|SHARED, %d, %d) failed: %s", 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (int) actualLength, fd, (int) actualStart, strerror(errno)); 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pMap->baseAddr = memPtr; 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pMap->baseLength = actualLength; 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pMap->addr = (char*)memPtr + adjust; 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pMap->length = length; 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 222614dca3bb487f17ef8ea37a82a22dd6c4abc027eDan Bornstein LOGVV("mmap seg (st=%d ln=%d): bp=%p bl=%d ad=%p ln=%d", 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (int) start, (int) length, 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pMap->baseAddr, (int) pMap->baseLength, 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pMap->addr, (int) pMap->length); 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 0; 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 229c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("sysMapFileSegmentInShmem not implemented."); 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 23596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Change the access rights on one or more pages to read-only or read-write. 23696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 23796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns 0 on success. 23896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 23996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenint sysChangeMapAccess(void* addr, size_t length, int wantReadWrite, 24096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden MemMapping* pMap) 24196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 242518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden#ifdef HAVE_POSIX_FILEMAP 24396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden /* 24496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Verify that "addr" is part of this mapping file. 24596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 24696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (addr < pMap->baseAddr || 24796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden (u1*)addr >= (u1*)pMap->baseAddr + pMap->baseLength) 24896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden { 249c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Attempted to change %p; map is %p - %p", 25096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden addr, pMap->baseAddr, (u1*)pMap->baseAddr + pMap->baseLength); 25196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return -1; 25296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 25396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 25496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden /* 25596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Align "addr" to a page boundary and adjust "length" appropriately. 25696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * (The address must be page-aligned, the length doesn't need to be, 25796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * but we do need to ensure we cover the same range.) 25896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 259b210a9f9c7ae17e2028a86d9a4e9a3b35472862aSangWook Han u1* alignAddr = (u1*) ((uintptr_t) addr & ~(SYSTEM_PAGE_SIZE-1)); 26096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden size_t alignLength = length + ((u1*) addr - alignAddr); 26196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 2624308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block //ALOGI("%p/%zd --> %p/%zd", addr, length, alignAddr, alignLength); 26396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden int prot = wantReadWrite ? (PROT_READ|PROT_WRITE) : (PROT_READ); 26496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (mprotect(alignAddr, alignLength, prot) != 0) { 26596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden int err = errno; 26692c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("mprotect (%p,%zd,%d) failed: %s", 26796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden alignAddr, alignLength, prot, strerror(errno)); 26896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return (errno != 0) ? errno : -1; 26996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 270518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden#endif 27196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 272518925b0103405fd0fa03cde1b9e58acf76a6a64Andy McFadden /* for "fake" mapping, no need to do anything */ 27396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return 0; 27496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 27596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 27696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Release a memory mapping. 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid sysReleaseShmem(MemMapping* pMap) 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_POSIX_FILEMAP 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pMap->baseAddr == NULL && pMap->baseLength == 0) 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (munmap(pMap->baseAddr, pMap->baseLength) < 0) { 286e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("munmap(%p, %d) failed: %s", 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pMap->baseAddr, (int)pMap->baseLength, strerror(errno)); 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 28992c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("munmap(%p, %d) succeeded", pMap->baseAddr, pMap->baseLength); 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pMap->baseAddr = NULL; 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pMap->baseLength = 0; 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Free the bits allocated by sysMapFileInShmem. */ 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pMap->baseAddr != NULL) { 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pMap->baseAddr); 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pMap->baseAddr = NULL; 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pMap->baseLength = 0; 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Make a copy of a MemMapping. 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid sysCopyMap(MemMapping* dst, const MemMapping* src) 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memcpy(dst, src, sizeof(MemMapping)); 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 31164896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden/* 31264896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden * Write until all bytes have been written. 31364896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden * 31464896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden * Returns 0 on success, or an errno value on failure. 31564896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden */ 31664896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFaddenint sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg) 31764896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden{ 31864896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden while (count != 0) { 31964896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden ssize_t actual = TEMP_FAILURE_RETRY(write(fd, buf, count)); 32064896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden if (actual < 0) { 32164896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden int err = errno; 322c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("%s: write failed: %s", logMsg, strerror(err)); 32364896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden return err; 32464896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden } else if (actual != (ssize_t) count) { 325062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("%s: partial write (will retry): (%d of %zd)", 32664896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden logMsg, (int) actual, count); 32764896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden buf = (const void*) (((const u1*) buf) + actual); 32864896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden } 32964896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden count -= actual; 33064896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden } 33164896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden 33264896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden return 0; 33364896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden} 334650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein 335650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein/* See documentation comment in header file. */ 336650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornsteinint sysCopyFileToFile(int outFd, int inFd, size_t count) 337650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein{ 338650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein const size_t kBufSize = 32768; 339650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein unsigned char buf[kBufSize]; 340650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein 341650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein while (count != 0) { 342650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein size_t getSize = (count > kBufSize) ? kBufSize : count; 343650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein 344650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein ssize_t actual = TEMP_FAILURE_RETRY(read(inFd, buf, getSize)); 345650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein if (actual != (ssize_t) getSize) { 346e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("sysCopyFileToFile: copy read failed (%d vs %zd)", 347650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein (int) actual, getSize); 348650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein return -1; 349650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein } 350650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein 351650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein if (sysWriteFully(outFd, buf, getSize, "sysCopyFileToFile") != 0) 352650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein return -1; 353650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein 354650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein count -= getSize; 355650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein } 356650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein 357650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein return 0; 358650177ee24fbe07cdd9ad9d8913fbf44cf44be13Dan Bornstein} 359