/*1* Mesa 3-D graphics library2*3* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the "Software"),7* to deal in the Software without restriction, including without limitation8* the rights to use, copy, modify, merge, publish, distribute, sublicense,9* and/or sell copies of the Software, and to permit persons to whom the10* Software is furnished to do so, subject to the following conditions:11*12* The above copyright notice and this permission notice shall be included13* in all copies or substantial portions of the Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS16* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR19* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,20* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR21* OTHER DEALINGS IN THE SOFTWARE.22*/232425/**26* \file glapi_execmem.c27*28* Function for allocating executable memory for dispatch stubs.29*30* Copied from main/execmem.c and simplified for dispatch stubs.31*/323334#include "c99_compat.h"35#include "c11/threads.h"36#include "u_execmem.h"373839#define EXEC_MAP_SIZE (4*1024)4041static mtx_t exec_mutex = _MTX_INITIALIZER_NP;4243static unsigned int head = 0;4445static unsigned char *exec_mem = (unsigned char *)0;464748#if defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun) || defined(__HAIKU__)4950#include <unistd.h>51#include <sys/mman.h>5253#ifdef MESA_SELINUX54#include <selinux/selinux.h>55#endif565758#ifndef MAP_ANONYMOUS59#define MAP_ANONYMOUS MAP_ANON60#endif616263/*64* Dispatch stubs are of fixed size and never freed. Thus, we do not need to65* overlay a heap, we just mmap a page and manage through an index.66*/6768static int69init_map(void)70{71#ifdef MESA_SELINUX72if (is_selinux_enabled()) {73if (!security_get_boolean_active("allow_execmem") ||74!security_get_boolean_pending("allow_execmem"))75return 0;76}77#endif7879if (!exec_mem)80exec_mem = mmap(NULL, EXEC_MAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE,81MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);8283return (exec_mem != MAP_FAILED);84}858687#elif defined(_WIN32)8889#include <windows.h>909192/*93* Avoid Data Execution Prevention.94*/9596static int97init_map(void)98{99exec_mem = VirtualAlloc(NULL, EXEC_MAP_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);100101return (exec_mem != NULL);102}103104105#else106107#include <stdlib.h>108109static int110init_map(void)111{112exec_mem = malloc(EXEC_MAP_SIZE);113114return (exec_mem != NULL);115}116117118#endif119120void *121u_execmem_alloc(unsigned int size)122{123#ifndef MESA_EXECMEM124(void)size;125return NULL;126#else127void *addr = NULL;128129mtx_lock(&exec_mutex);130131if (!init_map())132goto bail;133134/* free space check, assumes no integer overflow */135if (head + size > EXEC_MAP_SIZE)136goto bail;137138/* allocation, assumes proper addr and size alignement */139addr = exec_mem + head;140head += size;141142bail:143mtx_unlock(&exec_mutex);144145return addr;146#endif /* MESA_EXECMEM */147}148149150151152