This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC][PATCH] make PowerPC64 default to nonexecutable stack


Currently GLIBC upstream defaults to an executable stack for all
platforms and relies on the compiler emitting the PT_GNU_STACK header to
mark a shared object or executable as having a nonexecutable stack.

In order for this to work on PowerPC64 Linux distributions currently
carry a patch against GCC which makes GCC emit the PT_GNU_STACK section
on PowerPC64.  Upstream GCC actually doesn't do this for PowerPC64 and
hasn't for about 6 years.

An executable stack is not necessary on PowerPC64, which is why GCC
doesn't emit the PT_GNU_STACK header by default (because it isn't
needed).

This patch abstracts the stack permissions flags into the stackinfo.h
file.  On PowerPC64 this defaults the stack to nonexecutable.  A
compiler continuing to emit PT_GNU_STACK shouldn't be problematic if the
stack defaults to nonexecutable.

I've added a powerpc64 override testcase.  The
sysdeps/powerpc/powerpc64/configure.in fragment will now test the CC
compiler to see if it defaults to PT_GNU_STACK and will either invoke
the sysdeps/powerpc/powerpc64/check-execstack.c testcase or the default
in elf/check-execstack.c.

elf/Makefile had to be modified so that the $(objpfx)check-execstack:
rule searched for check-execstack in the sysdep dirs before falling back
to the version in elf/.

I've built and tested this on x86, PowerPC64 (upstream GCC with no
PT_GNU_STACK header), PowerPC64 (Linux distro GCC with PT_GNU_STACK
header), and PowerPC32.

We're carrying it in the ibm/2.12/master branch under commit:
ac02cf3af6f46706a29f21fc762f7099a7a546cc

Ryan S. Arnold
IBM Linux Technology Center
Linux Toolchain Development

2010-10-26  Ryan S. Arnold  <rsa@us.ibm.com>

	* config.h.in: Added HAVE_PPC64_PT_GNU_STACK which is set during a
	configure test to determine whether the the $(CC) compiler defaults to
	PT_GNU_STACK support for PPC64.
	* elf/Makefile (($objpfx)check-execstac:): Replaced $(native-compile)
	with an operation which does the same thing but searches sysdeps/ for
	the testcase before settling on elf/check-execstack.c.  This allows
	overriding in sysdeps/powerpc/powerpc64/check-execstack.c.
	* elf/dl-load.c (_dl_map_object_from_fd): Replace PF_R|RF_W|PF_X with
	_STACK_FLAGS, defined in stackinfo.h.
	* elf/dl-support.c (_dl_stack_flags): Likewise.
	* elf/rtld.c (_rtld_global): Likewise.
	* sysdeps/generic/stackinfo.h: Define _STACK_FLAGS = PF_R|PF_W|PF_X.
	Define _STACKINFO_H.
	* sysdeps/i386/stackinfo.h: Include <sysdeps/generic/stackinfo.h> and
	remove #define _STACKINFO_H.
	* sysdeps/ia64/stackinfo.h: Likewise.
	* sysdeps/s390/stackinfo.h: Likewise.
	* sysdeps/sh/stackinfo.h: Likewise.
	* sysdeps/sparc/stackinfo.h: Likewise.
	* sysdeps/x86_64/stackinfo.h: Likewise.
	* sysdeps/powerpc/stackinfo.h: Define _STACK_FLAGS as PF_R|PF_W, i.e.,
	nonexecutable, on PowerPC64, but PF_R|PF_W|PF_X on PowerPC32.
	* sysdeps/powerpc/powerpc64/check-execstack.c: New file which checks
	the test executable to make sure it doesn't have PT_GNU_STACK set and
	then checks the executable to see if the mapfile indicates that
	the [stack] is nonexecutable.
	* sysdeps/powerpc/powerpc64/configure: Regenerated.
	* sysdeps/powerpc/powerpc64/configure.in: Added fragment to test for
	PT_GNU_STACK default in the compiler.  It sets HAVE_PPC64_PT_GNU_STACK.

diff --git a/config.h.in b/config.h.in
index 18bf01a..6cd3dc1 100644
--- a/config.h.in
+++ b/config.h.in
@@ -195,6 +195,9 @@
 /* Define if your compiler defaults to -msecure-plt mode on ppc.  */
 #undef HAVE_PPC_SECURE_PLT
 
+/* Define if your compiler emits a PT_GNU_STACK header for ppc64.  */
+#undef HAVE_PPC64_PT_GNU_STACK
+
 /* Define if __stack_chk_guard canary should be randomized at program startup.  */
 #undef ENABLE_STACKGUARD_RANDOMIZE
 
diff --git a/elf/Makefile b/elf/Makefile
index e600cc3..50c46c6 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -899,8 +899,13 @@ $(objpfx)check-textrel: check-textrel.c
 	$(native-compile)
 
 check-execstack-CFLAGS = -O -Wall -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -std=gnu99
+# Perform the same operation as $(native-compile) but search sysdeps/ for a
+# matching testcase file before settling for the testcase in elf/.
 $(objpfx)check-execstack: check-execstack.c
-	$(native-compile)
+	$(make-target-directory)
+	$(patsubst %/,cd % &&,$(objpfx)) \
+	$(BUILD_CC) $($(basename $(<F))-CFLAGS) $(ALL_BUILD_CFLAGS) \
+	$(firstword $(wildcard $(addsuffix /$<,$(addprefix $(shell pwd)/,$(sysdirs)) $(shell pwd)))) -o $(@F)
 
 check-localplt-CFLAGS = -O -Wall -D_GNU_SOURCE -std=gnu99
 $(objpfx)check-localplt: check-localplt.c
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 0adddf5..899973c 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -999,8 +999,10 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
 	}
     }
 
-  /* Presumed absent PT_GNU_STACK.  */
-  uint_fast16_t stack_flags = PF_R|PF_W|PF_X;
+  /* On most architectures presume that PT_GNU_STACK is absent and the stack is
+   * executable.  Other architectures default to a nonexecutable stack and don't
+   * need PT_GNU_STACK to do so.  */
+  uint_fast16_t stack_flags = _STACK_FLAGS;
 
   {
     /* Scan the program header table, collecting its load commands.  */
diff --git a/elf/dl-support.c b/elf/dl-support.c
index f94d2c4..0e2cccf 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -32,6 +32,7 @@
 #include <dl-procinfo.h>
 #include <unsecvars.h>
 #include <hp-timing.h>
+#include <stackinfo.h>
 
 extern char *__progname;
 char **_dl_argv = &__progname;	/* This is checked for some error messages.  */
@@ -134,8 +135,9 @@ uint64_t _dl_hwcap __attribute__ ((nocommon));
    setting _dl_hwcap nonzero below, but we do anyway.  */
 uint64_t _dl_hwcap_mask __attribute__ ((nocommon));
 
-/* Prevailing state of the stack, PF_X indicating it's executable.  */
-ElfW(Word) _dl_stack_flags = PF_R|PF_W|PF_X;
+/* Prevailing state of the stack.  Generally this includes PF_X, indicating it's
+ * executable but this isn't true for all architectures.  */
+ElfW(Word) _dl_stack_flags = _STACK_FLAGS;
 
 /* If loading a shared object requires that we make the stack executable
    when it was not, we do it by calling this function.
diff --git a/elf/rtld.c b/elf/rtld.c
index d03aa04..f03c6c0 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -40,6 +40,7 @@
 #include <dl-osinfo.h>
 #include <dl-procinfo.h>
 #include <tls.h>
+#include <stackinfo.h>
 
 #include <assert.h>
 
@@ -122,8 +123,9 @@ INTVARDEF(_dl_starting_up)
    (except those which cannot be added for some reason).  */
 struct rtld_global _rtld_global =
   {
-    /* Default presumption without further information is executable stack.  */
-    ._dl_stack_flags = PF_R|PF_W|PF_X,
+    /* Generally the default presumption without further information is an
+     * executable stack but this is not true on all architectures.  */
+    ._dl_stack_flags = _STACK_FLAGS,
 #ifdef _LIBC_REENTRANT
     ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
     ._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
diff --git a/sysdeps/generic/stackinfo.h b/sysdeps/generic/stackinfo.h
index 7c43801..af613f9 100644
--- a/sysdeps/generic/stackinfo.h
+++ b/sysdeps/generic/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -16,6 +16,14 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-/* This file contains a bit of information about the stack allocation
-   of the processor.  Since there is no general truth we can't say
-   anything here.  */
+/* This file contains generic information about the stack allocation.  */
+
+#ifndef _STACKINFO_H
+#define _STACKINFO_H	1
+#include <elf.h>
+
+/* Default to an executable stack.  PF_X can be overridden if PT_GNU_STACK is
+ * present, but it is presumed absent.  */
+#define _STACK_FLAGS	(PF_R|PF_W|PF_X)
+
+#endif /* stackinfo.h  */
diff --git a/sysdeps/i386/stackinfo.h b/sysdeps/i386/stackinfo.h
index 2530ea7..38fd1f1 100644
--- a/sysdeps/i386/stackinfo.h
+++ b/sysdeps/i386/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2009, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -20,7 +20,9 @@
    of the processor.  */
 
 #ifndef _STACKINFO_H
-#define _STACKINFO_H	1
+
+/* Pick up the default definition for _STACK_FLAGS and define _STACKINFO_H.  */
+#include <sysdeps/generic/stackinfo.h>
 
 /* On x86 the stack grows down.  */
 #define _STACK_GROWS_DOWN	1
diff --git a/sysdeps/ia64/stackinfo.h b/sysdeps/ia64/stackinfo.h
index b7dc5d9..4d3f827 100644
--- a/sysdeps/ia64/stackinfo.h
+++ b/sysdeps/ia64/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -20,7 +20,9 @@
    of the processor.  */
 
 #ifndef _STACKINFO_H
-#define _STACKINFO_H	1
+
+/* Pick up the default definition for _STACK_FLAGS and define _STACKINFO_H.  */
+#include <sysdeps/generic/stackinfo.h>
 
 /* On IA-64 the stack grows down.  The register stack is of no concern
    here.  */
diff --git a/sysdeps/powerpc/powerpc64/check-execstack.c b/sysdeps/powerpc/powerpc64/check-execstack.c
new file mode 100644
index 0000000..8194789
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/check-execstack.c
@@ -0,0 +1,195 @@
+/* Verify nonexecutable stack in test app when linked against GLIBC.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contribute by Ryan S. Arnold <rsa@us.ibm.com>. 2010.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#if defined HAVE_PPC64_PT_GNU_STACK
+
+/* If the compiler defaults to emitting PT_GNU_STACK for PPC64 then we should
+ * use the standard check-execstack.c test case which checks the shared objects
+ * generated by GLIBC for the GNU_STACK header.  */
+#include "../../../elf/check-execstack.c"
+
+#else
+
+/* The original test in elf/check-execstack.c supposedly checks for no-exec
+ * stack but what it really does is check if the compiler used to to build GLIBC
+ * creates a PT_GNU_STACK header in the elf info for each shared object.  The
+ * only way to check whether the stack is executable is to build and link an app
+ * with the recently built GLIBC and check the exec bits.  */
+
+#include <stdio.h>
+#include <byteswap.h>
+#include <elf.h>
+#include <endian.h>
+#include <linux/limits.h> /* Pick up PATH_MAX.  */
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <alloca.h>
+
+/* Macros taken from elf/check-execstack.c because it works.  */
+# define BITS 64
+# define E(name) _E (name, BITS)
+# define _E(name, bits) __E (name, bits)
+# define __E(name, bits) Elf##bits##_##name
+# define SWAP(val) \
+  ({ __typeof (val) __res;						      \
+     if (((ehdr.e_ident[EI_DATA] == ELFDATA2MSB				      \
+	   && BYTE_ORDER == LITTLE_ENDIAN)				      \
+	  || (ehdr.e_ident[EI_DATA] == ELFDATA2LSB			      \
+	      && BYTE_ORDER == BIG_ENDIAN))				      \
+	 && sizeof (val) != 1)						      \
+       {								      \
+	 if (sizeof (val) == 2)						      \
+	   __res = bswap_16 (val);					      \
+	 else if (sizeof (val) == 4)					      \
+	   __res = bswap_32 (val);					      \
+	 else								      \
+	   __res = bswap_64 (val);					      \
+       }								      \
+     else								      \
+       __res = (val);							      \
+     __res; })
+
+/* Make sure this binary doesn't have PT_GNU_STACK set (which it shouldn't if
+ * the configure test which left HAVE_PPC64_PT_GNU_STACK unset was correct) and
+ * make sure that this test case didn't inherit PT_GNU_STACK, and that the stack
+ * defaults to non-executable anyway.  */
+
+int
+main (int argc, char *argv[])
+{
+
+  char *argv0 = argv[0]; /* testcase binary.  */
+  int fd = open (argv0, O_RDONLY);
+
+  if (fd == -1)
+    {
+      printf("Cannot open file image %s for reading.\n", argv0);
+    }
+
+  /* Read whats is supposed to be the ELF header.  Read the initial
+     bytes to determine whether this is a 32 or 64 bit file.  */
+  char ident[EI_NIDENT];
+  if (read (fd, ident, EI_NIDENT) != EI_NIDENT)
+    {
+    read_error:
+      printf("%s: read error\n", argv0);
+      close (fd);
+      return 1;
+    }
+
+  if (memcmp (&ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
+    {
+      printf("%s: not an ELF file\n", argv0);
+      close (fd);
+      return 1;
+    }
+
+  /* Only operate on a 64-bit file.  */
+  if (ident[EI_CLASS] == ELFCLASS32)
+    {
+      printf("%s is not a 64-bit binary.\n",argv0);
+      close (fd);
+      return 1;
+  }
+
+  /* Now verify that this binary doesn't have a PT_GNU_STACK header.  */
+  E(Ehdr) ehdr;
+
+  if (pread (fd, &ehdr, sizeof (ehdr), 0) != sizeof (ehdr))
+    goto read_error;
+
+  const size_t phnum = SWAP (ehdr.e_phnum);
+  const size_t phentsize = SWAP (ehdr.e_phentsize);
+
+  /* Read the program header.  */
+  E(Phdr) *phdr = alloca (phentsize * phnum);
+  if (pread (fd, phdr, phentsize * phnum, SWAP (ehdr.e_phoff))
+      != phentsize * phnum)
+    goto read_error;
+
+  /* Search for an unwanted PT_GNU_STACK entry.  */
+  for (size_t cnt = 0; cnt < phnum; ++cnt)
+    if (SWAP (phdr[cnt].p_type) == PT_GNU_STACK)
+      {
+	printf("%s: Found unwanted PT_GNU_STACK header.\n", argv0);
+	close (fd);
+	return 1;
+      }
+
+  close(fd);
+
+  /* Now make sure the stack is marked non-executable by reading
+   * /proc/self/maps and looking for the memory permissions on the [stack]
+   * region.  */
+
+  FILE *mapfd = fopen ("/proc/self/maps", "r");
+  if (mapfd == NULL)
+    {
+      /* We don't have a solution for older systems that don't support
+       * /proc/self/maps.  Just return a false success since the situation is
+       * kind of ridiculous (really old kernel + glibc 2.13+).  */
+      printf("fopen of /proc/self/maps failed.\n");
+      return 0;
+    }
+
+  char line[PATH_MAX + 128];
+  const char delimiters[] = " ";
+  char *token;
+  const char stack[] = "[stack]";
+  while ((fgets(line, PATH_MAX + 128, mapfd)) != NULL)
+    {
+      char *perms = NULL;
+      int field = 0;
+      token = strtok(line,delimiters);
+      while(token != NULL) {
+	if (field == 1) /* The second field is the perms field.  */
+	  perms = token; /* Save this until we find [stack].  */
+	if (field == 5) /* The sixth field is the pathname field.  */
+	  {
+	    /* If we find "[stack]" as the pathname check the permissions.  */
+	    if (!strncmp(stack,token,strlen(stack)))
+	      {
+		if (perms[2] == 'x')
+		  {
+		    printf("found executable stack for %s.\n", argv0);
+		    printf("%s %s %s\n",line,perms,token);
+		    fclose(mapfd);
+		    return 1;
+		  }
+		else
+		  {
+		    printf("found noexec stack in:\n");
+		    printf("%s %s %s\n",line,perms,token);
+		    fclose(mapfd);
+		    return 0;
+		  }
+	      }
+	    break;
+	  }
+	token = strtok(NULL,delimiters);
+	field++;
+      }
+    }
+  printf("didn't find [stack] pathname for %s in /proc/self/maps.\n", argv0);
+  fclose(mapfd);
+  return 1;
+}
+#endif
diff --git a/sysdeps/powerpc/powerpc64/configure b/sysdeps/powerpc/powerpc64/configure
index a9b6722..8976d34 100644
--- a/sysdeps/powerpc/powerpc64/configure
+++ b/sysdeps/powerpc/powerpc64/configure
@@ -3,10 +3,10 @@
 
 # The Aix ld uses global .symbol_names instead of symbol_names
 # and unfortunately early Linux PPC64 linkers use it as well.
-{ $as_echo "$as_me:$LINENO: checking for support for omitting dot symbols" >&5
-$as_echo_n "checking for support for omitting dot symbols... " >&6; }
+{ echo "$as_me:$LINENO: checking for support for omitting dot symbols" >&5
+echo $ECHO_N "checking for support for omitting dot symbols... $ECHO_C" >&6; }
 if test "${libc_cv_omit_dot_syms+set}" = set; then
-  $as_echo_n "(cached) " >&6
+  echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   libc_cv_omit_dot_syms=no
 echo 'void foo (void) {}' > conftest.c
@@ -14,7 +14,7 @@ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S conftest.c -o conftest.s 1>&5'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   if grep -w '\.foo' conftest.s > /dev/null; then
     :
@@ -25,8 +25,8 @@ fi
 rm -f conftest.c conftest.s
 
 fi
-{ $as_echo "$as_me:$LINENO: result: $libc_cv_omit_dot_syms" >&5
-$as_echo "$libc_cv_omit_dot_syms" >&6; }
+{ echo "$as_me:$LINENO: result: $libc_cv_omit_dot_syms" >&5
+echo "${ECHO_T}$libc_cv_omit_dot_syms" >&6; }
 if test x$libc_cv_omit_dot_syms != xyes; then
   cat >>confdefs.h <<\_ACEOF
 #define HAVE_ASM_GLOBAL_DOT_NAME 1
@@ -34,10 +34,10 @@ _ACEOF
 
 fi
 
-{ $as_echo "$as_me:$LINENO: checking for linker support for overlapping .opd entries" >&5
-$as_echo_n "checking for linker support for overlapping .opd entries... " >&6; }
+{ echo "$as_me:$LINENO: checking for linker support for overlapping .opd entries" >&5
+echo $ECHO_N "checking for linker support for overlapping .opd entries... $ECHO_C" >&6; }
 if test "${libc_cv_overlapping_opd+set}" = set; then
-  $as_echo_n "(cached) " >&6
+  echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   libc_cv_overlapping_opd=no
 echo 'void foo (void) {}' > conftest.c
@@ -45,7 +45,7 @@ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S conftest.c -o conftest.s 1>&5'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   if grep '\.TOC\.@tocbase' conftest.s > /dev/null; then
     if grep '\.TOC\.@tocbase[ 	]*,[ 	]*0' conftest.s > /dev/null; then
@@ -58,11 +58,45 @@ fi
 rm -f conftest.c conftest.s
 
 fi
-{ $as_echo "$as_me:$LINENO: result: $libc_cv_overlapping_opd" >&5
-$as_echo "$libc_cv_overlapping_opd" >&6; }
+{ echo "$as_me:$LINENO: result: $libc_cv_overlapping_opd" >&5
+echo "${ECHO_T}$libc_cv_overlapping_opd" >&6; }
 if test x$libc_cv_overlapping_opd = xyes; then
   cat >>confdefs.h <<\_ACEOF
 #define USE_PPC64_OVERLAPPING_OPD 1
 _ACEOF
 
 fi
+
+# Some compilers have been configured to emit PT_GNU_STACK on PowerPC64 even
+# though this isn't necessary.  If it is present then which check-execstack is
+# tested should be changed.
+{ echo "$as_me:$LINENO: checking if PT_GNU_STACK ELF program header is emitted by the compiler on PowerPC64" >&5
+echo $ECHO_N "checking if PT_GNU_STACK ELF program header is emitted by the compiler on PowerPC64... $ECHO_C" >&6; }
+if test "${libc_cv_ppc64_pt_gnu_stack+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  echo 'int main (void) { return 0; }' > conftest.c
+libc_cv_ppc64_pt_gnu_stack=no
+  if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -o conftest
+		     conftest.c 1>&5'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }
+  then
+    if readelf -l conftest | fgrep GNU_STACK > /dev/null; then
+      libc_cv_ppc64_pt_gnu_stack=yes
+    fi
+  fi
+  rm -f conftest*
+fi
+{ echo "$as_me:$LINENO: result: $libc_cv_ppc64_pt_gnu_stack" >&5
+echo "${ECHO_T}$libc_cv_ppc64_pt_gnu_stack" >&6; }
+#AC_SUBST(libc_cv_ppc64_pt_gnu_stack)
+if test $libc_cv_ppc64_pt_gnu_stack = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_PPC64_PT_GNU_STACK 1
+_ACEOF
+
+fi
diff --git a/sysdeps/powerpc/powerpc64/configure.in b/sysdeps/powerpc/powerpc64/configure.in
index 67aac66..9c236ad 100644
--- a/sysdeps/powerpc/powerpc64/configure.in
+++ b/sysdeps/powerpc/powerpc64/configure.in
@@ -40,3 +40,22 @@ rm -f conftest.c conftest.s
 if test x$libc_cv_overlapping_opd = xyes; then
   AC_DEFINE(USE_PPC64_OVERLAPPING_OPD)
 fi
+
+# Some compilers have been configured to emit PT_GNU_STACK on PowerPC64 even
+# though this isn't necessary.  If it is present then which check-execstack is
+# tested should be changed.
+AC_CACHE_CHECK(if PT_GNU_STACK ELF program header is emitted by the compiler on PowerPC64, libc_cv_ppc64_pt_gnu_stack, [dnl
+echo 'int main (void) { return 0; }' > conftest.c
+libc_cv_ppc64_pt_gnu_stack=no
+  if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -o conftest
+		     conftest.c 1>&AS_MESSAGE_LOG_FD])
+  then
+    if readelf -l conftest | fgrep GNU_STACK > /dev/null; then
+      libc_cv_ppc64_pt_gnu_stack=yes
+    fi
+  fi
+  rm -f conftest*])
+#AC_SUBST(libc_cv_ppc64_pt_gnu_stack)
+if test $libc_cv_ppc64_pt_gnu_stack = yes; then
+  AC_DEFINE(HAVE_PPC64_PT_GNU_STACK)
+fi
diff --git a/sysdeps/powerpc/stackinfo.h b/sysdeps/powerpc/stackinfo.h
index 839758a..c46ec7c 100644
--- a/sysdeps/powerpc/stackinfo.h
+++ b/sysdeps/powerpc/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -25,4 +25,13 @@
 /* On PPC the stack grows down.  */
 #define _STACK_GROWS_DOWN	1
 
+#if __WORDSIZE == 64
+/* PPC64 doesn't need an executable stack and doesn't need PT_GNU_STACK
+ * to make the stack nonexecutable.  */
+# define _STACK_FLAGS	(PF_R|PF_W)
+#else
+/* PF_X can be overridden if PT_GNU_STACK is present but is presumed absent.  */
+# define _STACK_FLAGS	(PF_R|PF_W|PF_X)
+#endif
+
 #endif	/* stackinfo.h */
diff --git a/sysdeps/s390/stackinfo.h b/sysdeps/s390/stackinfo.h
index 7e09c85..b41a6f4 100644
--- a/sysdeps/s390/stackinfo.h
+++ b/sysdeps/s390/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -20,7 +20,9 @@
    of the processor.  */
 
 #ifndef _STACKINFO_H
-#define _STACKINFO_H	1
+
+/* Pick up the default definition for _STACK_FLAGS and define _STACKINFO_H.  */
+#include <sysdeps/generic/stackinfo.h>
 
 /* On s390 the stack grows down.  */
 #define _STACK_GROWS_DOWN	1
diff --git a/sysdeps/sh/stackinfo.h b/sysdeps/sh/stackinfo.h
index e65338f..4b0eb95 100644
--- a/sysdeps/sh/stackinfo.h
+++ b/sysdeps/sh/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -20,7 +20,9 @@
    of the processor.  */
 
 #ifndef _STACKINFO_H
-#define _STACKINFO_H	1
+
+/* Pick up the default definition for _STACK_FLAGS and define _STACKINFO_H.  */
+#include <sysdeps/generic/stackinfo.h>
 
 /* On SH the stack grows down.  */
 #define _STACK_GROWS_DOWN	1
diff --git a/sysdeps/sparc/stackinfo.h b/sysdeps/sparc/stackinfo.h
index fd34e2d..5f02a2b 100644
--- a/sysdeps/sparc/stackinfo.h
+++ b/sysdeps/sparc/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -20,7 +20,9 @@
    of the processor.  */
 
 #ifndef _STACKINFO_H
-#define _STACKINFO_H	1
+
+/* Pick up the default definition for _STACK_FLAGS and define _STACKINFO_H.  */
+#include <sysdeps/generic/stackinfo.h>
 
 /* On sparc the stack grows down.  */
 #define _STACK_GROWS_DOWN	1
diff --git a/sysdeps/x86_64/stackinfo.h b/sysdeps/x86_64/stackinfo.h
index b11849d..3f09019 100644
--- a/sysdeps/x86_64/stackinfo.h
+++ b/sysdeps/x86_64/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -20,7 +20,9 @@
    of the processor.  */
 
 #ifndef _STACKINFO_H
-#define _STACKINFO_H	1
+
+/* Pick up the default definition for _STACK_FLAGS and define _STACKINFO_H.  */
+#include <sysdeps/generic/stackinfo.h>
 
 /* On x86_64 the stack grows down.  */
 #define _STACK_GROWS_DOWN	1



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]