xref: /netbsd-src/external/gpl3/gcc.old/dist/libgcc/enable-execute-stack-mprotect.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Implement __enable_execute_stack using mprotect(2).
2*8feb0f0bSmrg    Copyright (C) 2011-2020 Free Software Foundation, Inc.
31debfc3dSmrg 
41debfc3dSmrg    This file is part of GCC.
51debfc3dSmrg 
61debfc3dSmrg    GCC is free software; you can redistribute it and/or modify it under
71debfc3dSmrg    the terms of the GNU General Public License as published by the Free
81debfc3dSmrg    Software Foundation; either version 3, or (at your option) any later
91debfc3dSmrg    version.
101debfc3dSmrg 
111debfc3dSmrg    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
121debfc3dSmrg    WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
141debfc3dSmrg    for more details.
151debfc3dSmrg 
161debfc3dSmrg    Under Section 7 of GPL version 3, you are granted additional
171debfc3dSmrg    permissions described in the GCC Runtime Library Exception, version
181debfc3dSmrg    3.1, as published by the Free Software Foundation.
191debfc3dSmrg 
201debfc3dSmrg    You should have received a copy of the GNU General Public License and
211debfc3dSmrg    a copy of the GCC Runtime Library Exception along with this program;
221debfc3dSmrg    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
231debfc3dSmrg    <http://www.gnu.org/licenses/>.  */
241debfc3dSmrg 
251debfc3dSmrg #include <sys/mman.h>
261debfc3dSmrg #include <unistd.h>
271debfc3dSmrg #include <stdlib.h>
281debfc3dSmrg 
291debfc3dSmrg #define STACK_PROT_RWX (PROT_READ | PROT_WRITE | PROT_EXEC)
301debfc3dSmrg 
311debfc3dSmrg static int need_enable_exec_stack;
321debfc3dSmrg 
331debfc3dSmrg static void check_enabling (void) __attribute__ ((unused));
341debfc3dSmrg extern void __enable_execute_stack (void *);
351debfc3dSmrg 
361debfc3dSmrg #if defined __sun__ && defined __svr4__
371debfc3dSmrg static void __attribute__ ((constructor))
check_enabling(void)381debfc3dSmrg check_enabling (void)
391debfc3dSmrg {
401debfc3dSmrg   int prot = (int) sysconf (_SC_STACK_PROT);
411debfc3dSmrg 
421debfc3dSmrg   if (prot != STACK_PROT_RWX)
431debfc3dSmrg     need_enable_exec_stack = 1;
441debfc3dSmrg }
451debfc3dSmrg #else
461debfc3dSmrg /* There is no way to query the execute permission of the stack, so
471debfc3dSmrg    we always issue the mprotect() call.  */
481debfc3dSmrg 
491debfc3dSmrg static int need_enable_exec_stack = 1;
501debfc3dSmrg #endif
511debfc3dSmrg 
521debfc3dSmrg /* Attempt to turn on access permissions for the stack.  Unfortunately it
531debfc3dSmrg    is not possible to make this namespace-clean.*/
541debfc3dSmrg 
551debfc3dSmrg void
__enable_execute_stack(void * addr)561debfc3dSmrg __enable_execute_stack (void *addr)
571debfc3dSmrg {
581debfc3dSmrg   if (!need_enable_exec_stack)
591debfc3dSmrg     return;
601debfc3dSmrg   else
611debfc3dSmrg     {
621debfc3dSmrg       static long size, mask;
631debfc3dSmrg 
641debfc3dSmrg       if (size == 0) {
651debfc3dSmrg 	size = getpagesize ();
661debfc3dSmrg 	mask = ~(size - 1);
671debfc3dSmrg       }
681debfc3dSmrg 
691debfc3dSmrg       char *page = (char *) (((long) addr) & mask);
701debfc3dSmrg       char *end  = (char *)
711debfc3dSmrg 	((((long) (addr + __LIBGCC_TRAMPOLINE_SIZE__)) & mask) + size);
721debfc3dSmrg 
731debfc3dSmrg       if (mprotect (page, end - page, STACK_PROT_RWX) < 0)
741debfc3dSmrg 	/* Note that no errors should be emitted by this code; it is
751debfc3dSmrg 	   considered dangerous for library calls to send messages to
761debfc3dSmrg 	   stdout/stderr.  */
771debfc3dSmrg 	abort ();
781debfc3dSmrg     }
791debfc3dSmrg }
80