1af69d88dSmrg/*
2af69d88dSmrg * Mesa 3-D graphics library
3af69d88dSmrg *
4af69d88dSmrg * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
5af69d88dSmrg *
6af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
7af69d88dSmrg * copy of this software and associated documentation files (the "Software"),
8af69d88dSmrg * to deal in the Software without restriction, including without limitation
9af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the
11af69d88dSmrg * Software is furnished to do so, subject to the following conditions:
12af69d88dSmrg *
13af69d88dSmrg * The above copyright notice and this permission notice shall be included
14af69d88dSmrg * in all copies or substantial portions of the Software.
15af69d88dSmrg *
16af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17af69d88dSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE.
23af69d88dSmrg */
24af69d88dSmrg
25af69d88dSmrg
26af69d88dSmrg/**
27af69d88dSmrg * \file glapi_execmem.c
28af69d88dSmrg *
29af69d88dSmrg * Function for allocating executable memory for dispatch stubs.
30af69d88dSmrg *
31af69d88dSmrg * Copied from main/execmem.c and simplified for dispatch stubs.
32af69d88dSmrg */
33af69d88dSmrg
34af69d88dSmrg
3501e04c3fSmrg#include "c99_compat.h"
3601e04c3fSmrg#include "c11/threads.h"
37af69d88dSmrg#include "u_execmem.h"
38af69d88dSmrg
39af69d88dSmrg
40af69d88dSmrg#define EXEC_MAP_SIZE (4*1024)
41af69d88dSmrg
42af69d88dSmrgstatic mtx_t exec_mutex = _MTX_INITIALIZER_NP;
43af69d88dSmrg
44af69d88dSmrgstatic unsigned int head = 0;
45af69d88dSmrg
46af69d88dSmrgstatic unsigned char *exec_mem = (unsigned char *)0;
47af69d88dSmrg
48af69d88dSmrg
497ec681f3Smrg#if defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun) || defined(__HAIKU__)
50af69d88dSmrg
51af69d88dSmrg#include <unistd.h>
52af69d88dSmrg#include <sys/mman.h>
53af69d88dSmrg
54af69d88dSmrg#ifdef MESA_SELINUX
55af69d88dSmrg#include <selinux/selinux.h>
56af69d88dSmrg#endif
57af69d88dSmrg
58af69d88dSmrg
59af69d88dSmrg#ifndef MAP_ANONYMOUS
60af69d88dSmrg#define MAP_ANONYMOUS MAP_ANON
61af69d88dSmrg#endif
62af69d88dSmrg
63af69d88dSmrg
64af69d88dSmrg/*
65af69d88dSmrg * Dispatch stubs are of fixed size and never freed. Thus, we do not need to
66af69d88dSmrg * overlay a heap, we just mmap a page and manage through an index.
67af69d88dSmrg */
68af69d88dSmrg
69af69d88dSmrgstatic int
70af69d88dSmrginit_map(void)
71af69d88dSmrg{
72af69d88dSmrg#ifdef MESA_SELINUX
73af69d88dSmrg   if (is_selinux_enabled()) {
74af69d88dSmrg      if (!security_get_boolean_active("allow_execmem") ||
75af69d88dSmrg	  !security_get_boolean_pending("allow_execmem"))
76af69d88dSmrg         return 0;
77af69d88dSmrg   }
78af69d88dSmrg#endif
79af69d88dSmrg
80af69d88dSmrg   if (!exec_mem)
81af69d88dSmrg      exec_mem = mmap(NULL, EXEC_MAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE,
82af69d88dSmrg		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
83af69d88dSmrg
84af69d88dSmrg   return (exec_mem != MAP_FAILED);
85af69d88dSmrg}
86af69d88dSmrg
87af69d88dSmrg
88af69d88dSmrg#elif defined(_WIN32)
89af69d88dSmrg
90af69d88dSmrg#include <windows.h>
91af69d88dSmrg
92af69d88dSmrg
93af69d88dSmrg/*
94af69d88dSmrg * Avoid Data Execution Prevention.
95af69d88dSmrg */
96af69d88dSmrg
97af69d88dSmrgstatic int
98af69d88dSmrginit_map(void)
99af69d88dSmrg{
100af69d88dSmrg   exec_mem = VirtualAlloc(NULL, EXEC_MAP_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
101af69d88dSmrg
102af69d88dSmrg   return (exec_mem != NULL);
103af69d88dSmrg}
104af69d88dSmrg
105af69d88dSmrg
106af69d88dSmrg#else
107af69d88dSmrg
108af69d88dSmrg#include <stdlib.h>
109af69d88dSmrg
110af69d88dSmrgstatic int
111af69d88dSmrginit_map(void)
112af69d88dSmrg{
113af69d88dSmrg   exec_mem = malloc(EXEC_MAP_SIZE);
114af69d88dSmrg
115af69d88dSmrg   return (exec_mem != NULL);
116af69d88dSmrg}
117af69d88dSmrg
118af69d88dSmrg
119af69d88dSmrg#endif
120af69d88dSmrg
121af69d88dSmrgvoid *
122af69d88dSmrgu_execmem_alloc(unsigned int size)
123af69d88dSmrg{
1247ec681f3Smrg#ifndef MESA_EXECMEM
1257ec681f3Smrg   (void)size;
1267ec681f3Smrg   return NULL;
1277ec681f3Smrg#else
128af69d88dSmrg   void *addr = NULL;
129af69d88dSmrg
130af69d88dSmrg   mtx_lock(&exec_mutex);
131af69d88dSmrg
132af69d88dSmrg   if (!init_map())
133af69d88dSmrg      goto bail;
134af69d88dSmrg
135af69d88dSmrg   /* free space check, assumes no integer overflow */
136af69d88dSmrg   if (head + size > EXEC_MAP_SIZE)
137af69d88dSmrg      goto bail;
138af69d88dSmrg
139af69d88dSmrg   /* allocation, assumes proper addr and size alignement */
140af69d88dSmrg   addr = exec_mem + head;
141af69d88dSmrg   head += size;
142af69d88dSmrg
143af69d88dSmrgbail:
144af69d88dSmrg   mtx_unlock(&exec_mutex);
145af69d88dSmrg
146af69d88dSmrg   return addr;
1477ec681f3Smrg#endif /* MESA_EXECMEM */
148af69d88dSmrg}
149af69d88dSmrg
150af69d88dSmrg
151