1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ----------------------------------------------------------------------- 2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closures.c - Copyright (c) 2007 Red Hat, Inc. 3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Copyright (C) 2007 Free Software Foundation, Inc 4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Code to allocate and deallocate memory for closures. 6a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 7a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Permission is hereby granted, free of charge, to any person obtaining 8a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project a copy of this software and associated documentation files (the 9a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ``Software''), to deal in the Software without restriction, including 10a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project without limitation the rights to use, copy, modify, merge, publish, 11a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project distribute, sublicense, and/or sell copies of the Software, and to 12a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project permit persons to whom the Software is furnished to do so, subject to 13a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the following conditions: 14a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 15a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project The above copyright notice and this permission notice shall be included 16a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project in all copies or substantial portions of the Software. 17a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 18a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 19a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project DEALINGS IN THE SOFTWARE. 26a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ----------------------------------------------------------------------- */ 27a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 28a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined __linux__ && !defined _GNU_SOURCE 29a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define _GNU_SOURCE 1 30a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 31a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 32a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi.h> 33a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi_common.h> 34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifndef FFI_MMAP_EXEC_WRIT 36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# if __gnu_linux__ 37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* This macro indicates it may be forbidden to map anonymous memory 38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project with both write and execute permission. Code compiled when this 39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project option is defined will attempt to map such pages once, but if it 40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project fails, it falls back to creating a temporary file in a writable and 41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project executable filesystem and mapping pages from it into separate 42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project locations in the virtual memory space, one location writable and 43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project another executable. */ 44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# define FFI_MMAP_EXEC_WRIT 1 45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# endif 46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX 49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# ifdef __linux__ 50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* When defined to 1 check for SELinux and if SELinux is active, 51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that 52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project might cause audit messages. */ 53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# define FFI_MMAP_EXEC_SELINUX 1 54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# endif 55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if FFI_CLOSURES 58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# if FFI_MMAP_EXEC_WRIT 60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define USE_LOCKS 1 62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define USE_DL_PREFIX 1 63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define USE_BUILTIN_FFS 1 64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* We need to use mmap, not sbrk. */ 66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define HAVE_MORECORE 0 67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* We could, in theory, support mremap, but it wouldn't buy us anything. */ 69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define HAVE_MREMAP 0 70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* We have no use for this, so save some code and data. */ 72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define NO_MALLINFO 1 73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* We need all allocations to be in regular segments, otherwise we 75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project lose track of the corresponding code address. */ 76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T 77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Don't allocate more than a page unless needed. */ 79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize) 80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if FFI_CLOSURE_TEST 82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Don't release single pages, to avoid a worst-case scenario of 83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project continuously allocating and releasing single pages, but release 84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project pairs of pages, which should do just as well given that allocations 85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project are likely to be small. */ 86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize) 87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <sys/types.h> 90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <sys/stat.h> 91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <fcntl.h> 92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <errno.h> 93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <unistd.h> 94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <string.h> 95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdio.h> 96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <mntent.h> 97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <sys/param.h> 98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <pthread.h> 99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* We don't want sys/mman.h to be included after we redefine mmap and 101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project dlmunmap. */ 102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <sys/mman.h> 103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define LACKS_SYS_MMAN_H 1 104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if FFI_MMAP_EXEC_SELINUX 106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <sys/statfs.h> 107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdlib.h> 108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int selinux_enabled = -1; 110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int 112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectselinux_enabled_check (void) 113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project struct statfs sfs; 115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FILE *f; 116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *buf = NULL; 117a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project size_t len = 0; 118a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 119a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (statfs ("/selinux", &sfs) >= 0 120a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project && (unsigned int) sfs.f_type == 0xf97cff8cU) 121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return 1; 122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project f = fopen ("/proc/mounts", "r"); 123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (f == NULL) 124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return 0; 125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project while (getline (&buf, &len, f) >= 0) 126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *p = strchr (buf, ' '); 128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (p == NULL) 129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p = strchr (p + 1, ' '); 131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (p == NULL) 132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (strncmp (p + 1, "selinuxfs ", 10) != 0) 134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project free (buf); 136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project fclose (f); 137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return 1; 138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project free (buf); 141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project fclose (f); 142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return 0; 143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define is_selinux_enabled() (selinux_enabled >= 0 ? selinux_enabled \ 146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project : (selinux_enabled = selinux_enabled_check ())) 147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else 149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define is_selinux_enabled() 0 151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Declare all functions defined in dlmalloc.c as static. */ 155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void *dlmalloc(size_t); 156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void dlfree(void*); 157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void *dlcalloc(size_t, size_t) MAYBE_UNUSED; 158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void *dlrealloc(void *, size_t) MAYBE_UNUSED; 159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void *dlmemalign(size_t, size_t) MAYBE_UNUSED; 160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void *dlvalloc(size_t) MAYBE_UNUSED; 161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int dlmallopt(int, int) MAYBE_UNUSED; 162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic size_t dlmalloc_footprint(void) MAYBE_UNUSED; 163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic size_t dlmalloc_max_footprint(void) MAYBE_UNUSED; 164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void** dlindependent_calloc(size_t, size_t, void**) MAYBE_UNUSED; 165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void** dlindependent_comalloc(size_t, size_t*, void**) MAYBE_UNUSED; 166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void *dlpvalloc(size_t) MAYBE_UNUSED; 167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int dlmalloc_trim(size_t) MAYBE_UNUSED; 168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic size_t dlmalloc_usable_size(void*) MAYBE_UNUSED; 169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void dlmalloc_stats(void) MAYBE_UNUSED; 170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Use these for mmap and munmap within dlmalloc.c. */ 172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void *dlmmap(void *, size_t, int, int, int, off_t); 173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int dlmunmap(void *, size_t); 174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define mmap dlmmap 176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define munmap dlmunmap 177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include "dlmalloc.c" 179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#undef mmap 181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#undef munmap 182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* A mutex used to synchronize access to *exec* variables in this file. */ 184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER; 185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* A file descriptor of a temporary file from which we'll map 187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project executable pages. */ 188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int execfd = -1; 189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* The amount of space already allocated from the temporary file. */ 191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic size_t execsize = 0; 192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Open a temporary file name, and immediately unlink it. */ 194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int 195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectopen_temp_exec_file_name (char *name) 196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int fd = mkstemp (name); 198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (fd != -1) 200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unlink (name); 201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return fd; 203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Open a temporary file in the named directory. */ 206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int 207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectopen_temp_exec_file_dir (const char *dir) 208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project static const char suffix[] = "/ffiXXXXXX"; 210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int lendir = strlen (dir); 211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *tempname = __builtin_alloca (lendir + sizeof (suffix)); 212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (!tempname) 214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return -1; 215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy (tempname, dir, lendir); 217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy (tempname + lendir, suffix, sizeof (suffix)); 218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return open_temp_exec_file_name (tempname); 220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 222a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Open a temporary file in the directory in the named environment 223a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project variable. */ 224a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int 225a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectopen_temp_exec_file_env (const char *envvar) 226a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 227a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project const char *value = getenv (envvar); 228a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 229a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (!value) 230a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return -1; 231a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 232a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return open_temp_exec_file_dir (value); 233a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 234a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 235a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Open a temporary file in an executable and writable mount point 236a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project listed in the mounts file. Subsequent calls with the same mounts 237a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project keep searching for mount points in the same file. Providing NULL 238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project as the mounts file closes the file. */ 239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int 240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectopen_temp_exec_file_mnt (const char *mounts) 241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project static const char *last_mounts; 243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project static FILE *last_mntent; 244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (mounts != last_mounts) 246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (last_mntent) 248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project endmntent (last_mntent); 249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project last_mounts = mounts; 251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (mounts) 253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project last_mntent = setmntent (mounts, "r"); 254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project last_mntent = NULL; 256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (!last_mntent) 259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return -1; 260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project for (;;) 262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int fd; 264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project struct mntent mnt; 265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char buf[MAXPATHLEN * 3]; 266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (getmntent_r (last_mntent, &mnt, buf, sizeof (buf))) 268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return -1; 269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (hasmntopt (&mnt, "ro") 271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project || hasmntopt (&mnt, "noexec") 272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project || access (mnt.mnt_dir, W_OK)) 273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project continue; 274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project fd = open_temp_exec_file_dir (mnt.mnt_dir); 276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (fd != -1) 278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return fd; 279a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 280a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 281a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 282a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Instructions to look for a location to hold a temporary file that 283a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project can be mapped in for execution. */ 284a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic struct 285a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 286a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int (*func)(const char *); 287a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project const char *arg; 288a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int repeat; 289a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} open_temp_exec_file_opts[] = { 290a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { open_temp_exec_file_env, "TMPDIR", 0 }, 291a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { open_temp_exec_file_dir, "/tmp", 0 }, 292a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { open_temp_exec_file_dir, "/var/tmp", 0 }, 293a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { open_temp_exec_file_dir, "/dev/shm", 0 }, 294a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { open_temp_exec_file_env, "HOME", 0 }, 295a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { open_temp_exec_file_mnt, "/etc/mtab", 1 }, 296a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { open_temp_exec_file_mnt, "/proc/mounts", 1 }, 297a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}; 298a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 299a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Current index into open_temp_exec_file_opts. */ 300a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int open_temp_exec_file_opts_idx = 0; 301a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 302a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Reset a current multi-call func, then advances to the next entry. 303a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project If we're at the last, go back to the first and return nonzero, 304a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project otherwise return zero. */ 305a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int 306a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectopen_temp_exec_file_opts_next (void) 307a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 308a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat) 309a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func (NULL); 310a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 311a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project open_temp_exec_file_opts_idx++; 312a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (open_temp_exec_file_opts_idx 313a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project == (sizeof (open_temp_exec_file_opts) 314a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project / sizeof (*open_temp_exec_file_opts))) 315a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 316a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project open_temp_exec_file_opts_idx = 0; 317a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return 1; 318a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 319a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 320a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return 0; 321a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 322a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 323a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Return a file descriptor of a temporary zero-sized file in a 324a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project writable and exexutable filesystem. */ 325a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int 326a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectopen_temp_exec_file (void) 327a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 328a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int fd; 329a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 330a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project do 331a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 332a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project fd = open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func 333a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].arg); 334a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 335a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (!open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat 336a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project || fd == -1) 337a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 338a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (open_temp_exec_file_opts_next ()) 339a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 340a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 341a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 342a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project while (fd == -1); 343a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 344a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return fd; 345a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 346a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 347a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Map in a chunk of memory from the temporary exec file into separate 348a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project locations in the virtual memory address space, one writable and one 349a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project executable. Returns the address of the writable portion, after 350a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project storing an offset to the corresponding executable portion at the 351a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project last word of the requested chunk. */ 352a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void * 353a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectdlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset) 354a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 355a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *ptr; 356a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 357a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (execfd == -1) 358a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 359a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project open_temp_exec_file_opts_idx = 0; 360a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project retry_open: 361a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project execfd = open_temp_exec_file (); 362a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (execfd == -1) 363a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return MFAIL; 364a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 365a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 366a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project offset = execsize; 367a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 368a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (ftruncate (execfd, offset + length)) 369a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return MFAIL; 370a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 371a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS); 372a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project flags |= MAP_SHARED; 373a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 374a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ptr = mmap (NULL, length, (prot & ~PROT_WRITE) | PROT_EXEC, 375a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project flags, execfd, offset); 376a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (ptr == MFAIL) 377a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 378a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (!offset) 379a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 380a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project close (execfd); 381a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project goto retry_open; 382a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 383a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ftruncate (execfd, offset); 384a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return MFAIL; 385a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 386a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (!offset 387a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project && open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat) 388a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project open_temp_exec_file_opts_next (); 389a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 390a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project start = mmap (start, length, prot, flags, execfd, offset); 391a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 392a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (start == MFAIL) 393a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 394a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project munmap (ptr, length); 395a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ftruncate (execfd, offset); 396a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return start; 397a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 398a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 399a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project mmap_exec_offset ((char *)start, length) = (char*)ptr - (char*)start; 400a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 401a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project execsize += length; 402a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 403a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return start; 404a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 405a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 406a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Map in a writable and executable chunk of memory if possible. 407a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Failing that, fall back to dlmmap_locked. */ 408a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void * 409a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectdlmmap (void *start, size_t length, int prot, 410a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int flags, int fd, off_t offset) 411a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 412a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *ptr; 413a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 414a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project assert (start == NULL && length % malloc_getpagesize == 0 415a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project && prot == (PROT_READ | PROT_WRITE) 416a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project && flags == (MAP_PRIVATE | MAP_ANONYMOUS) 417a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project && fd == -1 && offset == 0); 418a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 419a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if FFI_CLOSURE_TEST 420a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project printf ("mapping in %zi\n", length); 421a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 422a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 423a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (execfd == -1 && !is_selinux_enabled ()) 424a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 425a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset); 426a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 427a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (ptr != MFAIL || (errno != EPERM && errno != EACCES)) 428a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Cool, no need to mess with separate segments. */ 429a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return ptr; 430a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 431a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* If MREMAP_DUP is ever introduced and implemented, try mmap 432a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project with ((prot & ~PROT_WRITE) | PROT_EXEC) and mremap with 433a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project MREMAP_DUP and prot at this point. */ 434a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 435a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 436a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (execsize == 0 || execfd == -1) 437a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 438a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project pthread_mutex_lock (&open_temp_exec_file_mutex); 439a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ptr = dlmmap_locked (start, length, prot, flags, offset); 440a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project pthread_mutex_unlock (&open_temp_exec_file_mutex); 441a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 442a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return ptr; 443a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 444a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 445a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return dlmmap_locked (start, length, prot, flags, offset); 446a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 447a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 448a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Release memory at the given address, as well as the corresponding 449a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project executable page if it's separate. */ 450a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int 451a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectdlmunmap (void *start, size_t length) 452a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 453a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* We don't bother decreasing execsize or truncating the file, since 454a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project we can't quite tell whether we're unmapping the end of the file. 455a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project We don't expect frequent deallocation anyway. If we did, we 456a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project could locate pages in the file by writing to the pages being 457a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project deallocated and checking that the file contents change. 458a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Yuck. */ 459a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project msegmentptr seg = segment_holding (gm, start); 460a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *code; 461a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 462a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if FFI_CLOSURE_TEST 463a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project printf ("unmapping %zi\n", length); 464a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 465a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 466a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (seg && (code = add_segment_exec_offset (start, seg)) != start) 467a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 468a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int ret = munmap (code, length); 469a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (ret) 470a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return ret; 471a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 472a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 473a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return munmap (start, length); 474a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 475a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 476a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if FFI_CLOSURE_FREE_CODE 477a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Return segment holding given code address. */ 478a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic msegmentptr 479a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectsegment_holding_code (mstate m, char* addr) 480a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 481a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project msegmentptr sp = &m->seg; 482a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project for (;;) { 483a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (addr >= add_segment_exec_offset (sp->base, sp) 484a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project && addr < add_segment_exec_offset (sp->base, sp) + sp->size) 485a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return sp; 486a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ((sp = sp->next) == 0) 487a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return 0; 488a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 489a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 490a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 491a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 492a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Allocate a chunk of memory with the given size. Returns a pointer 493a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project to the writable address, and sets *CODE to the executable 494a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project corresponding virtual address. */ 495a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid * 496a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_alloc (size_t size, void **code) 497a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 498a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *ptr; 499a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 500a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (!code) 501a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return NULL; 502a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 503a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ptr = dlmalloc (size); 504a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 505a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (ptr) 506a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 507a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project msegmentptr seg = segment_holding (gm, ptr); 508a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 509a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *code = add_segment_exec_offset (ptr, seg); 510a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 511a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 512a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return ptr; 513a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 514a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 515a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Release a chunk of memory allocated with ffi_closure_alloc. If 516a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the 517a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project writable or the executable address given. Otherwise, only the 518a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project writable address can be provided here. */ 519a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid 520a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_free (void *ptr) 521a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 522a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if FFI_CLOSURE_FREE_CODE 523a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project msegmentptr seg = segment_holding_code (gm, ptr); 524a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 525a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (seg) 526a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ptr = sub_segment_exec_offset (ptr, seg); 527a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 528a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 529a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project dlfree (ptr); 530a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 531a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 532a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 533a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if FFI_CLOSURE_TEST 534a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Do some internal sanity testing to make sure allocation and 535a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project deallocation of pages are working as intended. */ 536a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectint main () 537a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 538a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *p[3]; 539a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0) 540a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0) 541a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project GET (0, malloc_getpagesize / 2); 542a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*)); 543a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project PUT (1); 544a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project GET (1, 2 * malloc_getpagesize); 545a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project GET (2, malloc_getpagesize / 2); 546a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project PUT (1); 547a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project PUT (0); 548a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project PUT (2); 549a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return 0; 550a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 551a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* FFI_CLOSURE_TEST */ 552a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# else /* ! FFI_MMAP_EXEC_WRIT */ 553a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 554a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* On many systems, memory returned by malloc is writable and 555a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project executable, so just use it. */ 556a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 557a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdlib.h> 558a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 559a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid * 560a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_alloc (size_t size, void **code) 561a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 562a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (!code) 563a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return NULL; 564a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 565a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return *code = malloc (size); 566a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 567a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 568a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid 569a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_free (void *ptr) 570a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 571a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project free (ptr); 572a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 573a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 574a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# endif /* ! FFI_MMAP_EXEC_WRIT */ 575a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* FFI_CLOSURES */ 576