15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Mesa 3-D graphics library
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version:  6.5
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copy of this software and associated documentation files (the "Software"),
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to deal in the Software without restriction, including without limitation
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the rights to use, copy, modify, merge, publish, distribute, sublicense,
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and/or sell copies of the Software, and to permit persons to whom the
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Software is furnished to do so, subject to the following conditions:
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) * The above copyright notice and this permission notice shall be included
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * in all copies or substantial portions of the Software.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * \file glapi_execmem.c
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Function for allocating executable memory for dispatch stubs.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copied from main/execmem.c and simplified for dispatch stubs.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "u_compiler.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "u_thread.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "u_execmem.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define EXEC_MAP_SIZE (4*1024)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)u_mutex_declare_static(exec_mutex);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned int head = 0;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned char *exec_mem = (unsigned char *)0;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__linux__) || defined(__OpenBSD__) || defined(_NetBSD__) || defined(__sun)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/mman.h>
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef MESA_SELINUX
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <selinux/selinux.h>
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MAP_ANONYMOUS
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAP_ANONYMOUS MAP_ANON
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Dispatch stubs are of fixed size and never freed. Thus, we do not need to
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * overlay a heap, we just mmap a page and manage through an index.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)init_map(void)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef MESA_SELINUX
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (is_selinux_enabled()) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!security_get_boolean_active("allow_execmem") ||
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  !security_get_boolean_pending("allow_execmem"))
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         return 0;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!exec_mem)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      exec_mem = mmap(NULL, EXEC_MAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return (exec_mem != MAP_FAILED);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(_WIN32)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Avoid Data Execution Prevention.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
97static int
98init_map(void)
99{
100   exec_mem = VirtualAlloc(NULL, EXEC_MAP_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
101
102   return (exec_mem != NULL);
103}
104
105
106#else
107
108#include <stdlib.h>
109
110static int
111init_map(void)
112{
113   exec_mem = malloc(EXEC_MAP_SIZE);
114
115   return (exec_mem != NULL);
116}
117
118
119#endif
120
121void *
122u_execmem_alloc(unsigned int size)
123{
124   void *addr = NULL;
125
126   u_mutex_lock(exec_mutex);
127
128   if (!init_map())
129      goto bail;
130
131   /* free space check, assumes no integer overflow */
132   if (head + size > EXEC_MAP_SIZE)
133      goto bail;
134
135   /* allocation, assumes proper addr and size alignement */
136   addr = exec_mem + head;
137   head += size;
138
139bail:
140   u_mutex_unlock(exec_mutex);
141
142   return addr;
143}
144
145
146