"Fossies" - the Fresh Open Source Software Archive

Member "pcre2-10.36/src/sljit/sljitWXExecAllocator.c" (27 Aug 2020, 6765 Bytes) of package /linux/misc/pcre2-10.36.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sljitWXExecAllocator.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  *    Stack-less Just-In-Time compiler
    3  *
    4  *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without modification, are
    7  * permitted provided that the following conditions are met:
    8  *
    9  *   1. Redistributions of source code must retain the above copyright notice, this list of
   10  *      conditions and the following disclaimer.
   11  *
   12  *   2. Redistributions in binary form must reproduce the above copyright notice, this list
   13  *      of conditions and the following disclaimer in the documentation and/or other materials
   14  *      provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
   17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
   19  * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
   21  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
   22  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 /*
   28    This file contains a simple W^X executable memory allocator for POSIX
   29    like systems and Windows
   30 
   31    In *NIX, MAP_ANON is required (that is considered a feature) so make
   32    sure to set the right availability macros for your system or the code
   33    will fail to build.
   34 
   35    If your system doesn't support mapping of anonymous pages (ex: IRIX) it
   36    is also likely that it doesn't need this allocator and should be using
   37    the standard one instead.
   38 
   39    It allocates a separate map for each code block and may waste a lot of
   40    memory, because whatever was requested, will be rounded up to the page
   41    size (minimum 4KB, but could be even bigger).
   42 
   43    It changes the page permissions (RW <-> RX) as needed and therefore, if you
   44    will be updating the code after it has been generated, need to make sure to
   45    block any concurrent execution, or could result in a SIGBUS, that could
   46    even manifest itself at a different address than the one that was being
   47    modified.
   48 
   49    Only use if you are unable to use the regular allocator because of security
   50    restrictions and adding exceptions to your application or the system are
   51    not possible.
   52 */
   53 
   54 #define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \
   55     sljit_update_wx_flags((from), (to), (enable_exec))
   56 
   57 #ifndef _WIN32
   58 #include <sys/types.h>
   59 #include <sys/mman.h>
   60 
   61 #ifdef __NetBSD__
   62 #if defined(PROT_MPROTECT)
   63 #define check_se_protected(ptr, size) (0)
   64 #define SLJIT_PROT_WX PROT_MPROTECT(PROT_EXEC)
   65 #else /* !PROT_MPROTECT */
   66 #ifdef _NETBSD_SOURCE
   67 #include <sys/param.h>
   68 #else /* !_NETBSD_SOURCE */
   69 typedef unsigned int    u_int;
   70 #define devmajor_t sljit_s32
   71 #endif /* _NETBSD_SOURCE */
   72 #include <sys/sysctl.h>
   73 #include <unistd.h>
   74 
   75 #define check_se_protected(ptr, size) netbsd_se_protected()
   76 
   77 static SLJIT_INLINE int netbsd_se_protected(void)
   78 {
   79     int mib[3];
   80     int paxflags;
   81     size_t len = sizeof(paxflags);
   82 
   83     mib[0] = CTL_PROC;
   84     mib[1] = getpid();
   85     mib[2] = PROC_PID_PAXFLAGS;
   86 
   87     if (SLJIT_UNLIKELY(sysctl(mib, 3, &paxflags, &len, NULL, 0) < 0))
   88         return -1;
   89 
   90     return (paxflags & CTL_PROC_PAXFLAGS_MPROTECT) ? -1 : 0;
   91 }
   92 #endif /* PROT_MPROTECT */
   93 #else /* POSIX */
   94 #define check_se_protected(ptr, size) generic_se_protected(ptr, size)
   95 
   96 static SLJIT_INLINE int generic_se_protected(void *ptr, sljit_uw size)
   97 {
   98     if (SLJIT_LIKELY(!mprotect(ptr, size, PROT_EXEC)))
   99         return mprotect(ptr, size, PROT_READ | PROT_WRITE);
  100 
  101     return -1;
  102 }
  103 #endif /* NetBSD */
  104 
  105 #if defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED
  106 #define SLJIT_SE_LOCK()
  107 #define SLJIT_SE_UNLOCK()
  108 #else /* !SLJIT_SINGLE_THREADED */
  109 #include <pthread.h>
  110 #define SLJIT_SE_LOCK() pthread_mutex_lock(&se_lock)
  111 #define SLJIT_SE_UNLOCK()   pthread_mutex_unlock(&se_lock)
  112 #endif /* SLJIT_SINGLE_THREADED */
  113 
  114 #ifndef SLJIT_PROT_WX
  115 #define SLJIT_PROT_WX 0
  116 #endif /* !SLJIT_PROT_WX */
  117 
  118 SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
  119 {
  120 #if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
  121     static pthread_mutex_t se_lock = PTHREAD_MUTEX_INITIALIZER;
  122 #endif
  123     static int se_protected = !SLJIT_PROT_WX;
  124     sljit_uw* ptr;
  125 
  126     if (SLJIT_UNLIKELY(se_protected < 0))
  127         return NULL;
  128 
  129     size += sizeof(sljit_uw);
  130     ptr = (sljit_uw*)mmap(NULL, size, PROT_READ | PROT_WRITE | SLJIT_PROT_WX,
  131                 MAP_PRIVATE | MAP_ANON, -1, 0);
  132 
  133     if (ptr == MAP_FAILED)
  134         return NULL;
  135 
  136     if (SLJIT_UNLIKELY(se_protected > 0)) {
  137         SLJIT_SE_LOCK();
  138         se_protected = check_se_protected(ptr, size);
  139         SLJIT_SE_UNLOCK();
  140         if (SLJIT_UNLIKELY(se_protected < 0)) {
  141             munmap((void *)ptr, size);
  142             return NULL;
  143         }
  144     }
  145 
  146     *ptr++ = size;
  147     return ptr;
  148 }
  149 
  150 #undef SLJIT_PROT_WX
  151 #undef SLJIT_SE_UNLOCK
  152 #undef SLJIT_SE_LOCK
  153 
  154 SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
  155 {
  156     sljit_uw *start_ptr = ((sljit_uw*)ptr) - 1;
  157     munmap((void*)start_ptr, *start_ptr);
  158 }
  159 
  160 static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec)
  161 {
  162     sljit_uw page_mask = (sljit_uw)get_page_alignment();
  163     sljit_uw start = (sljit_uw)from;
  164     sljit_uw end = (sljit_uw)to;
  165     int prot = PROT_READ | (enable_exec ? PROT_EXEC : PROT_WRITE);
  166 
  167     SLJIT_ASSERT(start < end);
  168 
  169     start &= ~page_mask;
  170     end = (end + page_mask) & ~page_mask;
  171 
  172     mprotect((void*)start, end - start, prot);
  173 }
  174 
  175 #else /* windows */
  176 
  177 SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
  178 {
  179     sljit_uw *ptr;
  180 
  181     size += sizeof(sljit_uw);
  182     ptr = (sljit_uw*)VirtualAlloc(NULL, size,
  183                 MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  184 
  185     if (!ptr)
  186         return NULL;
  187 
  188     *ptr++ = size;
  189 
  190     return ptr;
  191 }
  192 
  193 SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
  194 {
  195     sljit_uw start = (sljit_uw)ptr - sizeof(sljit_uw);
  196 #if defined(SLJIT_DEBUG) && SLJIT_DEBUG
  197     sljit_uw page_mask = (sljit_uw)get_page_alignment();
  198 
  199     SLJIT_ASSERT(!(start & page_mask));
  200 #endif
  201     VirtualFree((void*)start, 0, MEM_RELEASE);
  202 }
  203 
  204 static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec)
  205 {
  206     DWORD oldprot;
  207     sljit_uw page_mask = (sljit_uw)get_page_alignment();
  208     sljit_uw start = (sljit_uw)from;
  209     sljit_uw end = (sljit_uw)to;
  210     DWORD prot = enable_exec ? PAGE_EXECUTE : PAGE_READWRITE;
  211 
  212     SLJIT_ASSERT(start < end);
  213 
  214     start &= ~page_mask;
  215     end = (end + page_mask) & ~page_mask;
  216 
  217     VirtualProtect((void*)start, end - start, prot, &oldprot);
  218 }
  219 
  220 #endif /* !windows */
  221 
  222 SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
  223 {
  224     /* This allocator does not keep unused memory for future allocations. */
  225 }