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