diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/Makefile | 139 | ||||
-rw-r--r-- | elf/check-execstack.c | 162 | ||||
-rw-r--r-- | elf/check-localplt.c | 298 | ||||
-rw-r--r-- | elf/check-textrel.c | 198 | ||||
-rw-r--r-- | elf/dl-close.c | 15 | ||||
-rw-r--r-- | elf/dl-deps.c | 13 | ||||
-rw-r--r-- | elf/dl-fini.c | 8 | ||||
-rw-r--r-- | elf/dl-libc.c | 9 | ||||
-rw-r--r-- | elf/dl-load.c | 5 | ||||
-rw-r--r-- | elf/dl-lookup.c | 3 | ||||
-rw-r--r-- | elf/dl-minimal.c | 40 | ||||
-rw-r--r-- | elf/dl-open.c | 8 | ||||
-rw-r--r-- | elf/dl-reloc.c | 6 | ||||
-rw-r--r-- | elf/dl-support.c | 6 | ||||
-rw-r--r-- | elf/dl-sysdep.c | 15 | ||||
-rw-r--r-- | elf/dynamic-link.h | 69 | ||||
-rw-r--r-- | elf/elf.h | 4 | ||||
-rw-r--r-- | elf/ldconfig.c | 6 | ||||
-rw-r--r-- | elf/pldd-xx.c | 18 | ||||
-rw-r--r-- | elf/rtld-Rules | 5 | ||||
-rw-r--r-- | elf/rtld.c | 28 | ||||
-rw-r--r-- | elf/stackguard-macros.h | 30 | ||||
-rw-r--r-- | elf/tls-macros.h | 16 | ||||
-rw-r--r-- | elf/tst-auditmod1.c | 2 | ||||
-rw-r--r-- | elf/tst-auditmod3b.c | 2 | ||||
-rw-r--r-- | elf/tst-auditmod4b.c | 2 | ||||
-rw-r--r-- | elf/tst-auditmod5b.c | 2 | ||||
-rw-r--r-- | elf/tst-auditmod6b.c | 2 | ||||
-rw-r--r-- | elf/tst-auditmod6c.c | 2 | ||||
-rw-r--r-- | elf/tst-auditmod7b.c | 2 | ||||
-rw-r--r-- | elf/tst-execstack.c | 71 | ||||
-rw-r--r-- | elf/tst-relsort1.c | 2 |
32 files changed, 311 insertions, 877 deletions
diff --git a/elf/Makefile b/elf/Makefile index 59a3936a1b..0c26ce545a 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1995-2011, 2012 Free Software Foundation, Inc. +# Copyright (C) 1995-2012 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 @@ -80,15 +80,14 @@ install-rootsbin += ldconfig ldconfig-modules := cache readlib xmalloc xstrdup chroot_canon extra-objs += $(ldconfig-modules:=.o) +endif +endif pldd-modules := xmalloc # To find xmalloc.c and xstrdup.c vpath %.c ../locale/programs -endif -endif - ifeq ($(have-ksh)$(build-shared),yesyes) extra-objs += sotruss-lib.os sotruss-lib.so install-others += $(inst_auditdir)/sotruss-lib.so @@ -156,7 +155,9 @@ tests += tst-audit6 tst-audit7 endif endif endif +ifeq ($(cross-compiling),no) tests: $(objpfx)tst-leaks1-mem $(objpfx)noload-mem +endif tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 tlsmod18a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 tlsmod17a-modules = $(addprefix tst-tlsmod17a, $(tlsmod17a-suffixes)) @@ -419,8 +420,10 @@ CFLAGS-ldconfig.c = $(SYSCONF-FLAGS) -D'LIBDIR="$(libdir)"' \ -D'SLIBDIR="$(slibdir)"' -DIS_IN_ldconfig=1 CFLAGS-dl-cache.c = $(SYSCONF-FLAGS) CFLAGS-cache.c = $(SYSCONF-FLAGS) +CFLAGS-rtld.c = $(SYSCONF-FLAGS) -CPPFLAGS-.os += $(if $(filter $(@F),$(patsubst %,%.os,$(all-rtld-routines))),-DNOT_IN_libc=1 -DIS_IN_rtld=1) +CPPFLAGS-.os += $(if $(filter $(@F),$(patsubst %,%.os,$(all-rtld-routines))),\ + -DNOT_IN_libc=1 -DIS_IN_rtld=1 -DIN_LIB=rtld) test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(strip $(modules-names)))) generated += $(addsuffix .so,$(strip $(modules-names))) @@ -497,6 +500,18 @@ $(objpfx)tst-initordera3.so: $(objpfx)tst-initorderb2.so $(objpfx)tst-initorderb $(objpfx)tst-initordera4.so: $(objpfx)tst-initordera3.so $(objpfx)tst-initorder: $(objpfx)tst-initordera4.so $(objpfx)tst-initordera1.so $(objpfx)tst-initorderb2.so +LDFLAGS-nodel2mod3.so = $(no-as-needed) +LDFLAGS-reldepmod5.so = $(no-as-needed) +LDFLAGS-reldep6mod1.so = $(no-as-needed) +LDFLAGS-reldep6mod4.so = $(no-as-needed) +LDFLAGS-reldep8mod3.so = $(no-as-needed) +LDFLAGS-unload4mod1.so = $(no-as-needed) +LDFLAGS-unload4mod2.so = $(no-as-needed) +LDFLAGS-tst-initorder = $(no-as-needed) +LDFLAGS-tst-initordera2.so = $(no-as-needed) +LDFLAGS-tst-initordera3.so = $(no-as-needed) +LDFLAGS-tst-initordera4.so = $(no-as-needed) +LDFLAGS-tst-initorderb2.so = $(no-as-needed) LDFLAGS-tst-tlsmod5.so = -nostdlib LDFLAGS-tst-tlsmod6.so = -nostdlib @@ -630,7 +645,7 @@ $(objpfx)vismain.out: $(addprefix $(objpfx),vismod3.so) vismain-ENV = LD_PRELOAD=$(addprefix $(objpfx),vismod3.so) $(objpfx)noload: $(objpfx)testobj1.so $(common-objpfx)dlfcn/libdl.so -LDFLAGS-noload = -rdynamic +LDFLAGS-noload = -rdynamic $(no-as-needed) $(objpfx)noload.out: $(objpfx)testobj5.so $(objpfx)noload-mem: $(objpfx)noload.out @@ -675,6 +690,7 @@ $(objpfx)reldep4: $(libdl) $(objpfx)reldep4.out: $(objpfx)reldep4mod1.so $(objpfx)reldep4mod2.so $(objpfx)next: $(objpfx)nextmod1.so $(objpfx)nextmod2.so $(libdl) +LDFLAGS-next = $(no-as-needed) $(objpfx)unload2: $(libdl) $(objpfx)unload2.out: $(objpfx)unload2mod.so $(objpfx)unload2dep.so @@ -869,45 +885,64 @@ CFLAGS-tst-pie1.c += $(pie-ccflag) $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so -check-textrel-CFLAGS = -O -Wall -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -$(objpfx)check-textrel: check-textrel.c - $(native-compile) +ifeq (yes,$(build-shared)) +tests: $(objpfx)check-textrel.out $(objpfx)check-execstack.out -check-execstack-CFLAGS = -O -Wall -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -std=gnu99 \ - $(objpfx:%/=-I%) -$(objpfx)check-execstack: check-execstack.c $(objpfx)check-execstack.h - $(native-compile) -$(objpfx)check-execstack.h: $(first-word $(wildcard $(sysdirs:%=%/stackinfo.h))) - $(make-target-directory) - { echo '#include <stackinfo.h>'; echo '@@@DEFAULT_STACK_PERMS@@@'; } | \ - $(CC) $(CFLAGS) $(CPPFLAGS) -E -x c-header - | \ - sed -n -e 's/^@@@\(.*\)@@@/#define DEFAULT_STACK_PERMS \1/p' > $@T - mv -f $@T $@ -generated += check-execstack.h +all-built-dso := $(common-objpfx)libc.so \ + $(filter-out $(common-objpfx)linkobj/libc.so, \ + $(sort $(wildcard $(addprefix $(common-objpfx), \ + */lib*.so \ + iconvdata/*.so)))) -check-localplt-CFLAGS = -O -Wall -D_GNU_SOURCE -std=gnu99 -$(objpfx)check-localplt: check-localplt.c - $(native-compile) +$(all-built-dso:=.dyn): %.dyn: % + @rm -f $@T + LC_ALL=C $(READELF) -W -d $< > $@T + test -s $@T + mv -f $@T $@ +common-generated += $(all-built-dso:$(common-objpfx)%=%.dyn) -ifeq (yes,$(build-shared)) -tests: $(objpfx)check-textrel.out $(objpfx)check-execstack.out +$(objpfx)check-textrel.out: $(..)scripts/check-textrel.awk \ + $(all-built-dso:=.dyn) + LC_ALL=C $(AWK) -f $^ > $@ +generated += check-textrel.out -all-built-dso = $(common-objpfx)libc.so \ - $(filter-out $(common-objpfx)linkobj/libc.so, \ - $(sort $(wildcard $(common-objpfx)*/lib*.so \ - $(common-objpfx)iconvdata/*.so))) +$(objpfx)execstack-default: $(first-word $(wildcard $(sysdirs:%=%/stackinfo.h))) + $(make-target-directory) + { echo '#include <elf.h>'; \ + echo '#include <stackinfo.h>'; \ + echo '#if (DEFAULT_STACK_PERMS & PF_X) == 0'; \ + echo '@@@execstack-no@@@'; \ + echo '#else'; \ + echo '@@@execstack-yes@@@'; \ + echo '#endif'; } | \ + $(CC) $(CFLAGS) $(CPPFLAGS) -E -x c-header - | \ + sed -n -e 's/^@@@\(.*\)@@@/\1/p' > $@T + mv -f $@T $@ +generated += execstack-default -$(objpfx)check-textrel.out: $(objpfx)check-textrel $(all-built-dso) - $(dir $<)$(notdir $<) $(filter-out $<, $^) > $@ -generated += check-textrel check-textrel.out +$(all-built-dso:=.phdr): %.phdr: % + @rm -f $@T + LC_ALL=C $(READELF) -W -l $< > $@T + test -s $@T + mv -f $@T $@ +common-generated += $(all-built-dso:$(common-objpfx)%=%.phdr) -$(objpfx)check-execstack.out: $(objpfx)check-execstack $(all-built-dso) - $(dir $<)$(notdir $<) $(filter-out $<, $^) > $@ -generated += check-execstack check-execstack.out +$(objpfx)check-execstack.out: $(..)scripts/check-execstack.awk \ + $(objpfx)execstack-default \ + $(all-built-dso:=.phdr) + LC_ALL=C $(AWK) -f $^ > $@ +generated += check-execstack.out $(objpfx)tst-dlmodcount: $(libdl) $(objpfx)tst-dlmodcount.out: $(test-modules) +$(all-built-dso:=.jmprel): %.jmprel: % Makefile + @rm -f $@T + LC_ALL=C $(READELF) -W -S -d -r $< > $@T + test -s $@T + mv -f $@T $@ +common-generated += $(all-built-dso:$(common-objpfx)%=%.jmprel) + check-data := $(firstword $(wildcard \ $(foreach D,$(add-ons) scripts,\ $(patsubst %,$(..)$D/data/localplt-%.data,\ @@ -919,21 +954,25 @@ check-data := $(firstword $(wildcard \ tests: $(objpfx)check-localplt.out +localplt-built-dso := $(addprefix $(common-objpfx),\ + libc.so \ + math/libm.so \ + rt/librt.so \ + dlfcn/libdl.so \ + resolv/libresolv.so \ + crypt/libcrypt.so \ + ) ifeq ($(have-thread-library),yes) -thread-dso := $(filter-out %_nonshared.a, $(shared-thread-library)) +localplt-built-dso += $(filter-out %_nonshared.a, $(shared-thread-library)) endif -$(objpfx)check-localplt.out: $(objpfx)check-localplt \ - $(common-objpfx)libc.so \ - $(common-objpfx)math/libm.so $(thread-dso) \ - $(common-objpfx)rt/librt.so \ - $(common-objpfx)dlfcn/libdl.so \ - $(common-objpfx)resolv/libresolv.so \ - $(common-objpfx)crypt/libcrypt.so \ +$(objpfx)check-localplt.out: $(..)scripts/check-localplt.awk \ + $(..)scripts/localplt.awk \ + $(localplt-built-dso:=.jmprel) \ $(check-data) - $(dir $<)$(notdir $<) $(filter-out $< $(check-data),$^) | \ - LC_ALL=C sort | \ - diff -u $(check-data) - > $@ + LC_ALL=C $(AWK) -f $(filter-out $< $(check-data),$^) | \ + LC_ALL=C $(AWK) -f $< $(check-data) - \ + > $@ endif $(objpfx)tst-dlopenrpathmod.so: $(libdl) @@ -999,6 +1038,8 @@ $(objpfx)order2mod1.so: $(objpfx)order2mod4.so $(objpfx)order2mod4.so: $(objpfx)order2mod3.so $(objpfx)order2mod2.so: $(objpfx)order2mod3.so order2mod2.so-no-z-defs = yes +LDFLAGS-order2mod1.so = $(no-as-needed) +LDFLAGS-order2mod2.so = $(no-as-needed) tst-stackguard1-ARGS = --command "$(built-program-cmd) --child" tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child" @@ -1087,6 +1128,10 @@ $(objpfx)tst-initorder2: $(objpfx)tst-initorder2a.so $(objpfx)tst-initorder2d.so $(objpfx)tst-initorder2a.so: $(objpfx)tst-initorder2b.so $(objpfx)tst-initorder2b.so: $(objpfx)tst-initorder2c.so $(objpfx)tst-initorder2c.so: $(objpfx)tst-initorder2d.so +LDFLAGS-tst-initorder2 = $(no-as-needed) +LDFLAGS-tst-initorder2a.so = $(no-as-needed) +LDFLAGS-tst-initorder2b.so = $(no-as-needed) +LDFLAGS-tst-initorder2c.so = $(no-as-needed) define o-iterator-doit $(objpfx)tst-initorder2$o.os: tst-initorder2.c; \ $$(compile-command.c) -DNAME=\"$o\" @@ -1119,7 +1164,9 @@ $(objpfx)tst-relsort1mod2.so: $(libm) $(objpfx)tst-relsort1.out: $(objpfx)tst-relsort1mod1.so \ $(objpfx)tst-relsort1mod2.so +ifeq ($(cross-compiling),no) tests: $(objpfx)tst-unused-dep.out +endif $(objpfx)tst-unused-dep.out: $(objpfx)testobj1.so LD_TRACE_LOADED_OBJECTS=1 \ diff --git a/elf/check-execstack.c b/elf/check-execstack.c deleted file mode 100644 index 6a5c4d9b9a..0000000000 --- a/elf/check-execstack.c +++ /dev/null @@ -1,162 +0,0 @@ -/* Check for executable stacks in DSOs. - Copyright (C) 2009, 2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contribute by Ulrich Drepper <drepper@redhat.com>. 2009. - - 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, see - <http://www.gnu.org/licenses/>. */ - -#include <byteswap.h> -#include <elf.h> -#include <endian.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include "check-execstack.h" - - -#ifdef BITS - -# define AB(name) _AB (name, BITS) -# define _AB(name, bits) __AB (name, bits) -# define __AB(name, bits) name##bits -# 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; }) - - -static int -AB(handle_file) (const char *fname, int fd) -{ - E(Ehdr) ehdr; - - if (pread (fd, &ehdr, sizeof (ehdr), 0) != sizeof (ehdr)) - { - read_error: - printf ("%s: read error: %m\n", fname); - return 1; - } - - 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 the PT_GNU_STACK entry. */ - for (size_t cnt = 0; cnt < phnum; ++cnt) - if (SWAP (phdr[cnt].p_type) == PT_GNU_STACK) - { - unsigned int flags = SWAP(phdr[cnt].p_flags); - if (flags & PF_X) - { - printf ("%s: executable stack signaled\n", fname); - return 1; - } - - return 0; - } - - if (DEFAULT_STACK_PERMS & PF_X) - { - printf ("%s: no PT_GNU_STACK entry\n", fname); - return 1; - } - - return 0; -} - -# undef BITS -#else - -# define BITS 32 -# include "check-execstack.c" - -# define BITS 64 -# include "check-execstack.c" - - -static int -handle_file (const char *fname) -{ - int fd = open (fname, O_RDONLY); - if (fd == -1) - { - printf ("cannot open %s: %m\n", fname); - return 1; - } - - /* Read was 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) - { - printf ("%s: read error: %m\n", fname); - close (fd); - return 1; - } - - if (memcmp (&ident[EI_MAG0], ELFMAG, SELFMAG) != 0) - { - printf ("%s: not an ELF file\n", fname); - close (fd); - return 1; - } - - int result; - if (ident[EI_CLASS] == ELFCLASS64) - result = handle_file64 (fname, fd); - else - result = handle_file32 (fname, fd); - - close (fd); - - return result; -} - - -int -main (int argc, char *argv[]) -{ - int cnt; - int result = 0; - - for (cnt = 1; cnt < argc; ++cnt) - result |= handle_file (argv[cnt]); - return result; -} -#endif diff --git a/elf/check-localplt.c b/elf/check-localplt.c deleted file mode 100644 index edab1d2d0a..0000000000 --- a/elf/check-localplt.c +++ /dev/null @@ -1,298 +0,0 @@ -/* Show local PLT use in DSOs. - Copyright (C) 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contribute by Ulrich Drepper <drepper@redhat.com>. 2006. - - 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, see - <http://www.gnu.org/licenses/>. */ - -#include <byteswap.h> -#include <elf.h> -#include <endian.h> -#include <fcntl.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - - -#ifdef BITS - -# define AB(name) _AB (name, BITS) -# define _AB(name, bits) __AB (name, bits) -# define __AB(name, bits) name##bits -# define E(name) _E (name, BITS) -# define _E(name, bits) __E (name, bits) -# define __E(name, bits) Elf##bits##_##name -# define EE(name) _EE (name, BITS) -# define _EE(name, bits) __EE (name, bits) -# define __EE(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; }) - - -static int -AB(handle_file) (const char *fname, int fd) -{ - E(Ehdr) ehdr; - - if (pread (fd, &ehdr, sizeof (ehdr), 0) != sizeof (ehdr)) - { - read_error: - printf ("%s: read error: %m\n", fname); - return 1; - } - - 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 the PT_DYNAMIC entry. */ - size_t cnt; - E(Phdr) *dynphdr = NULL; - for (cnt = 0; cnt < phnum; ++cnt) - if (SWAP (phdr[cnt].p_type) == PT_DYNAMIC) - { - dynphdr = &phdr[cnt]; - break; - } - - if (dynphdr == NULL) - { - printf ("%s: no DYNAMIC segment found\n", fname); - return 1; - } - - /* Read the dynamic segment. */ - size_t pmemsz = SWAP(dynphdr->p_memsz); - E(Dyn) *dyn = alloca (pmemsz); - if (pread64 (fd, dyn, pmemsz, SWAP(dynphdr->p_offset)) != pmemsz) - goto read_error; - - /* Search for an DT_PLTREL, DT_JMPREL, DT_PLTRELSZ, DT_STRTAB, - DT_STRSZ, and DT_SYMTAB entries. */ - size_t pltrel_idx = SIZE_MAX; - size_t jmprel_idx = SIZE_MAX; - size_t pltrelsz_idx = SIZE_MAX; - size_t strtab_idx = SIZE_MAX; - size_t strsz_idx = SIZE_MAX; - size_t symtab_idx = SIZE_MAX; - for (cnt = 0; (cnt + 1) * sizeof (E(Dyn)) - 1 < pmemsz; ++cnt) - { - unsigned int tag = SWAP (dyn[cnt].d_tag); - - if (tag == DT_NULL) - /* We reached the end. */ - break; - - if (tag == DT_PLTREL) - pltrel_idx = cnt; - else if (tag == DT_JMPREL) - jmprel_idx = cnt; - else if (tag == DT_PLTRELSZ) - pltrelsz_idx = cnt; - else if (tag == DT_STRTAB) - strtab_idx = cnt; - else if (tag == DT_STRSZ) - strsz_idx = cnt; - else if (tag == DT_SYMTAB) - symtab_idx = cnt; - } - - if (pltrel_idx == SIZE_MAX || jmprel_idx == SIZE_MAX - || pltrelsz_idx == SIZE_MAX || strtab_idx == SIZE_MAX - || strsz_idx == SIZE_MAX || symtab_idx == SIZE_MAX) - { - puts ("not all PLT information found"); - return 1; - } - - E(Xword) relsz = SWAP (dyn[pltrelsz_idx].d_un.d_val); - - void *relmem = NULL; - char *strtab = NULL; - E(Xword) symtab_offset = 0; - - /* Find the offset of DT_JMPREL and load the data. */ - for (cnt = 0; cnt < phnum; ++cnt) - if (SWAP (phdr[cnt].p_type) == PT_LOAD) - { - E(Addr) vaddr = SWAP (phdr[cnt].p_vaddr); - E(Xword) memsz = SWAP (phdr[cnt].p_memsz); - - if (vaddr <= SWAP (dyn[jmprel_idx].d_un.d_val) - && vaddr + memsz >= SWAP (dyn[jmprel_idx].d_un.d_val) + relsz) - { - relmem = alloca (SWAP (dyn[pltrelsz_idx].d_un.d_val)); - if (pread64 (fd, relmem, relsz, - SWAP (phdr[cnt].p_offset) - + SWAP (dyn[jmprel_idx].d_un.d_val) - vaddr) - != relsz) - { - puts ("cannot read JMPREL"); - return 1; - } - } - - if (vaddr <= SWAP (dyn[symtab_idx].d_un.d_val) - && vaddr + memsz > SWAP (dyn[symtab_idx].d_un.d_val)) - symtab_offset = (SWAP (phdr[cnt].p_offset) - + SWAP (dyn[symtab_idx].d_un.d_val) - vaddr); - - if (vaddr <= SWAP (dyn[strtab_idx].d_un.d_val) - && vaddr + memsz >= (SWAP (dyn[strtab_idx].d_un.d_val) - + SWAP(dyn[strsz_idx].d_un.d_val))) - { - strtab = alloca (SWAP(dyn[strsz_idx].d_un.d_val)); - if (pread64 (fd, strtab, SWAP(dyn[strsz_idx].d_un.d_val), - SWAP (phdr[cnt].p_offset) - + SWAP (dyn[strtab_idx].d_un.d_val) - vaddr) - != SWAP(dyn[strsz_idx].d_un.d_val)) - { - puts ("cannot read STRTAB"); - return 1; - } - } - } - - if (relmem == NULL || strtab == NULL || symtab_offset == 0) - { - puts ("couldn't load PLT data"); - return 1; - } - - if (SWAP (dyn[pltrel_idx].d_un.d_val) == DT_RELA) - for (E(Rela) *rela = relmem; (char *) rela - (char *) relmem < relsz; - ++rela) - { - E(Sym) sym; - - if (pread64 (fd, &sym, sizeof (sym), - symtab_offset - + EE(R_SYM) (SWAP (rela->r_info)) * sizeof (sym)) - != sizeof (sym)) - { - puts ("cannot read symbol"); - return 1; - } - - if (sym.st_value != 0) - /* This symbol is locally defined. */ - printf ("%s: %s\n", basename (fname), strtab + SWAP (sym.st_name)); - } - else - for (E(Rel) *rel = relmem; (char *) rel - (char *) relmem < relsz; ++rel) - { - E(Sym) sym; - - if (pread64 (fd, &sym, sizeof (sym), - symtab_offset - + EE(R_SYM) (SWAP (rel->r_info)) * sizeof (sym)) - != sizeof (sym)) - { - puts ("cannot read symbol"); - return 1; - } - - if (sym.st_value != 0) - /* This symbol is locally defined. */ - printf ("%s: %s\n", basename (fname), strtab + SWAP (sym.st_name)); - } - - return 0; -} - -# undef BITS -#else - -# define BITS 32 -# include "check-localplt.c" - -# define BITS 64 -# include "check-localplt.c" - - -static int -handle_file (const char *fname) -{ - int fd = open (fname, O_RDONLY); - if (fd == -1) - { - printf ("cannot open %s: %m\n", fname); - return 1; - } - - /* Read was 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) - { - printf ("%s: read error: %m\n", fname); - close (fd); - return 1; - } - - if (memcmp (&ident[EI_MAG0], ELFMAG, SELFMAG) != 0) - { - printf ("%s: not an ELF file\n", fname); - close (fd); - return 1; - } - - int result; - if (ident[EI_CLASS] == ELFCLASS64) - result = handle_file64 (fname, fd); - else - result = handle_file32 (fname, fd); - - close (fd); - - return result; -} - - -int -main (int argc, char *argv[]) -{ - int cnt; - int result = 0; - - for (cnt = 1; cnt < argc; ++cnt) - result |= handle_file (argv[cnt]); - - return result; -} -#endif diff --git a/elf/check-textrel.c b/elf/check-textrel.c deleted file mode 100644 index 6372019a9c..0000000000 --- a/elf/check-textrel.c +++ /dev/null @@ -1,198 +0,0 @@ -/* Check for text relocations in DSOs. - Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contribute by Ulrich Drepper <drepper@redhat.com>. 2002. - - 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, see - <http://www.gnu.org/licenses/>. */ - -#include <byteswap.h> -#include <elf.h> -#include <endian.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - - -#ifdef BITS - -# define AB(name) _AB (name, BITS) -# define _AB(name, bits) __AB (name, bits) -# define __AB(name, bits) name##bits -# 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; }) - - -static int -AB(handle_file) (const char *fname, int fd) -{ - E(Ehdr) ehdr; - - if (pread (fd, &ehdr, sizeof (ehdr), 0) != sizeof (ehdr)) - { - read_error: - printf ("%s: read error: %m\n", fname); - return 1; - } - - 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 the PT_DYNAMIC entry. */ - size_t cnt; - E(Phdr) *dynphdr = NULL; - for (cnt = 0; cnt < phnum; ++cnt) - if (SWAP (phdr[cnt].p_type) == PT_DYNAMIC) - dynphdr = &phdr[cnt]; - else if (SWAP (phdr[cnt].p_type) == PT_LOAD - && (SWAP (phdr[cnt].p_flags) & (PF_X | PF_W)) == (PF_X | PF_W)) - { - printf ("%s: segment %zu is executable and writable\n", - fname, cnt); -#if !defined __sparc__ \ - && !defined __alpha__ \ - && (!defined __powerpc__ || defined __powerpc64__ || defined HAVE_PPC_SECURE_PLT) - /* sparc, sparc64, alpha and powerpc32 (the last one only when using - -mbss-plt) are expected to have PF_X | PF_W segment containing .plt - section, it is part of their ABI. It is bad security wise, nevertheless - this test shouldn't fail because of this. */ - return 1; -#endif - } - - if (dynphdr == NULL) - { - printf ("%s: no DYNAMIC segment found\n", fname); - return 1; - } - - /* Read the dynamic segment. */ - size_t pmemsz = SWAP(dynphdr->p_memsz); - E(Dyn) *dyn = alloca (pmemsz); - if (pread (fd, dyn, pmemsz, SWAP(dynphdr->p_offset)) != pmemsz) - goto read_error; - - /* Search for an DT_TEXTREL entry of DT_FLAGS with the DF_TEXTREL - bit set. */ - for (cnt = 0; (cnt + 1) * sizeof (E(Dyn)) - 1 < pmemsz; ++cnt) - { - unsigned int tag = SWAP (dyn[cnt].d_tag); - - if (tag == DT_NULL) - /* We reached the end. */ - break; - - if (tag == DT_TEXTREL - || (tag == DT_FLAGS - && (SWAP (dyn[cnt].d_un.d_val) & DF_TEXTREL) != 0)) - { - /* Urgh! The DSO has text relocations. */ - printf ("%s: text relocations used\n", fname); - return 1; - } - } - - printf ("%s: OK\n", fname); - - return 0; -} - -# undef BITS -#else - -# define BITS 32 -# include "check-textrel.c" - -# define BITS 64 -# include "check-textrel.c" - - -static int -handle_file (const char *fname) -{ - int fd = open (fname, O_RDONLY); - if (fd == -1) - { - printf ("cannot open %s: %m\n", fname); - return 1; - } - - /* Read was 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) - { - printf ("%s: read error: %m\n", fname); - close (fd); - return 1; - } - - if (memcmp (&ident[EI_MAG0], ELFMAG, SELFMAG) != 0) - { - printf ("%s: not an ELF file\n", fname); - close (fd); - return 1; - } - - int result; - if (ident[EI_CLASS] == ELFCLASS64) - result = handle_file64 (fname, fd); - else - result = handle_file32 (fname, fd); - - close (fd); - - return result; -} - - -int -main (int argc, char *argv[]) -{ - int cnt; - int result = 0; - - for (cnt = 1; cnt < argc; ++cnt) - result |= handle_file (argv[cnt]); - - return result; -} -#endif diff --git a/elf/dl-close.c b/elf/dl-close.c index d232294665..a250ea5e3e 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -1,5 +1,5 @@ /* Close a shared object opened by `_dl_open'. - Copyright (C) 1996-2007, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1996-2012 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 @@ -118,17 +118,8 @@ _dl_close_worker (struct link_map *map) if (map->l_direct_opencount > 0 || map->l_type != lt_loaded || dl_close_state != not_pending) { - if (map->l_direct_opencount == 0) - { - if (map->l_type == lt_loaded) - dl_close_state = rerun; - else if (map->l_type == lt_library) - { - struct link_map **oldp = map->l_initfini; - map->l_initfini = map->l_orig_initfini; - _dl_scope_free (oldp); - } - } + if (map->l_direct_opencount == 0 && map->l_type == lt_loaded) + dl_close_state = rerun; /* There are still references to this object. Do nothing more. */ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0)) diff --git a/elf/dl-deps.c b/elf/dl-deps.c index fb1c3058c0..2ae496d7b5 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -1,6 +1,5 @@ /* Load the dependencies of a mapped object. - Copyright (C) 1996-2003, 2004, 2005, 2006, 2007, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1996-2012 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 @@ -488,6 +487,7 @@ _dl_map_object_deps (struct link_map *map, nneeded * sizeof needed[0]); atomic_write_barrier (); l->l_initfini = l_initfini; + l->l_free_initfini = 1; } /* If we have no auxiliary objects just go on to the next map. */ @@ -632,7 +632,7 @@ Filters not supported with LD_TRACE_PRELINKING")); /* We can skip looking for the binary itself which is at the front of the search list. */ i = 1; - char seen[nlist]; + uint16_t seen[nlist]; memset (seen, 0, nlist * sizeof (seen[0])); while (1) { @@ -658,13 +658,13 @@ Filters not supported with LD_TRACE_PRELINKING")); (k - i) * sizeof (l_initfini[0])); l_initfini[k] = thisp; - if (seen[i + 1] > 1) + if (seen[i + 1] > nlist - i) { ++i; goto next_clear; } - char this_seen = seen[i]; + uint16_t this_seen = seen[i]; memmove (&seen[i], &seen[i + 1], (k - i) * sizeof (seen[0])); seen[k] = this_seen; @@ -688,6 +688,7 @@ Filters not supported with LD_TRACE_PRELINKING")); l_initfini[nlist] = NULL; atomic_write_barrier (); map->l_initfini = l_initfini; + map->l_free_initfini = 1; if (l_reldeps != NULL) { atomic_write_barrier (); @@ -696,7 +697,7 @@ Filters not supported with LD_TRACE_PRELINKING")); _dl_scope_free (old_l_reldeps); } if (old_l_initfini != NULL) - map->l_orig_initfini = old_l_initfini; + _dl_scope_free (old_l_initfini); if (errno_reason) _dl_signal_error (errno_reason == -1 ? 0 : errno_reason, objname, diff --git a/elf/dl-fini.c b/elf/dl-fini.c index 05146b3795..87cf2f1d33 100644 --- a/elf/dl-fini.c +++ b/elf/dl-fini.c @@ -1,5 +1,5 @@ /* Call the termination functions of loaded shared objects. - Copyright (C) 1995,96,1998-2002,2004-2005,2009,2011 + Copyright (C) 1995, 1996, 1998-2002, 2004-2005, 2009, 2011-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -38,7 +38,7 @@ _dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns) /* We can skip looking for the binary itself which is at the front of the search list for the main namespace. */ unsigned int i = ns == LM_ID_BASE; - char seen[nmaps]; + uint16_t seen[nmaps]; memset (seen, 0, nmaps * sizeof (seen[0])); while (1) { @@ -78,13 +78,13 @@ _dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns) used[k] = here_used; } - if (seen[i + 1] > 1) + if (seen[i + 1] > nmaps - i) { ++i; goto next_clear; } - char this_seen = seen[i]; + uint16_t this_seen = seen[i]; memmove (&seen[i], &seen[i + 1], (k - i) * sizeof (seen[0])); seen[k] = this_seen; diff --git a/elf/dl-libc.c b/elf/dl-libc.c index a58e2164f6..af2e663737 100644 --- a/elf/dl-libc.c +++ b/elf/dl-libc.c @@ -1,6 +1,5 @@ /* Handle loading and unloading shared objects for internal libc purposes. - Copyright (C) 1999-2002,2004-2006,2009,2010,2011 - Free Software Foundation, Inc. + Copyright (C) 1999-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999. @@ -269,13 +268,13 @@ libc_freeres_fn (free_mem) for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) { - /* Remove all additional names added to the objects. */ for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) { struct libname_list *lnp = l->l_libname->next; l->l_libname->next = NULL; + /* Remove all additional names added to the objects. */ while (lnp != NULL) { struct libname_list *old = lnp; @@ -283,6 +282,10 @@ libc_freeres_fn (free_mem) if (! old->dont_free) free (old); } + + /* Free the initfini dependency list. */ + if (l->l_free_initfini) + free (l->l_initfini); } if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0 diff --git a/elf/dl-load.c b/elf/dl-load.c index 41d48ee138..fe83f87eb9 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1,5 +1,5 @@ /* Map in a shared object's segments from the file. - Copyright (C) 1995-2007, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1995-2012 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 @@ -2194,7 +2194,8 @@ _dl_map_object (struct link_map *loader, const char *name, if (fd == -1 && (__builtin_expect (! (mode & __RTLD_SECURE), 1) - || ! INTUSE(__libc_enable_secure))) + || ! INTUSE(__libc_enable_secure)) + && __builtin_expect (GLRO(dl_inhibit_cache) == 0, 1)) { /* Check the list of libraries in the file /etc/ld.so.cache, for compatibility with Linux's ldconfig program. */ diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 839dd3a4fc..a2a699b48f 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -769,7 +769,8 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, if (__builtin_expect (current_value.s == NULL, 0)) { if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) - && skip_map == NULL) + && skip_map == NULL + && !(GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)) { /* We could find no value for a strong reference. */ const char *reference_name = undef_map ? undef_map->l_name : ""; diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c index 316de99b8f..a8b2d4f339 100644 --- a/elf/dl-minimal.c +++ b/elf/dl-minimal.c @@ -1,6 +1,5 @@ /* Minimal replacements for basic facilities used in the dynamic linker. - Copyright (C) 1995-1998,2000-2002,2004-2006,2007,2009 - Free Software Foundation, Inc. + Copyright (C) 1995-2012 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 @@ -232,6 +231,7 @@ __strtoul_internal (const char *nptr, char **endptr, int base, int group) { unsigned long int result = 0; long int sign = 1; + unsigned max_digit; while (*nptr == ' ' || *nptr == '\t') ++nptr; @@ -253,6 +253,7 @@ __strtoul_internal (const char *nptr, char **endptr, int base, int group) assert (base == 0); base = 10; + max_digit = 9; if (*nptr == '0') { if (nptr[1] == 'x' || nptr[1] == 'X') @@ -261,14 +262,31 @@ __strtoul_internal (const char *nptr, char **endptr, int base, int group) nptr += 2; } else - base = 8; + { + base = 8; + max_digit = 7; + } } - while (*nptr >= '0' && *nptr <= '9') + while (1) { - unsigned long int digval = *nptr - '0'; - if (result > ULONG_MAX / 10 - || (result == ULONG_MAX / 10 && digval > ULONG_MAX % 10)) + unsigned long int digval; + if (*nptr >= '0' && *nptr <= '0' + max_digit) + digval = *nptr - '0'; + else if (base == 16) + { + if (*nptr >= 'a' && *nptr <= 'f') + digval = *nptr - 'a' + 10; + else if (*nptr >= 'A' && *nptr <= 'F') + digval = *nptr - 'A' + 10; + else + break; + } + else + break; + + if (result > ULONG_MAX / base + || (result == ULONG_MAX / base && digval > ULONG_MAX % base)) { errno = ERANGE; if (endptr != NULL) @@ -297,12 +315,10 @@ _itoa (value, buflim, base, upper_case) unsigned int base; int upper_case; { - extern const char INTUSE(_itoa_lower_digits)[] attribute_hidden; - assert (! upper_case); do - *--buflim = INTUSE(_itoa_lower_digits)[value % base]; + *--buflim = _itoa_lower_digits[value % base]; while ((value /= base) != 0); return buflim; @@ -362,5 +378,5 @@ rtld_hidden_def (__chk_fail) /* The '_itoa_lower_digits' variable in libc.so is able to handle bases up to 36. We don't need this here. */ -const char INTUSE(_itoa_lower_digits)[16] attribute_hidden - = "0123456789abcdef"; +const char _itoa_lower_digits[16] = "0123456789abcdef"; +rtld_hidden_data_def (_itoa_lower_digits) diff --git a/elf/dl-open.c b/elf/dl-open.c index 570c5f8791..9fe0a7ff6a 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -1,5 +1,5 @@ /* Load a shared object at runtime, relocate it, and run its initializer. - Copyright (C) 1996-2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + Copyright (C) 1996-2007, 2009-2012 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 @@ -325,7 +325,7 @@ dl_open_worker (void *a) while (l != NULL); if (nmaps > 1) { - char seen[nmaps]; + uint16_t seen[nmaps]; memset (seen, '\0', nmaps); size_t i = 0; while (1) @@ -351,13 +351,13 @@ dl_open_worker (void *a) (k - i) * sizeof (maps[0])); maps[k] = thisp; - if (seen[i + 1] > 1) + if (seen[i + 1] > nmaps - i) { ++i; goto next_clear; } - char this_seen = seen[i]; + uint16_t this_seen = seen[i]; memmove (&seen[i], &seen[i + 1], (k - i) * sizeof (seen[0])); seen[k] = this_seen; diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index 97d2f6f779..e6968a4456 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -1,5 +1,5 @@ /* Relocate a shared object and resolve its references to other loaded objects. - Copyright (C) 1995-2006, 2008-2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1995-2012 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 @@ -24,6 +24,7 @@ #include <sys/mman.h> #include <sys/param.h> #include <sys/types.h> +#include <_itoa.h> #include "dynamic-link.h" /* Statistics function. */ @@ -338,8 +339,7 @@ void internal_function __attribute_noinline__ _dl_reloc_bad_type (struct link_map *map, unsigned int type, int plt) { - extern const char INTUSE(_itoa_lower_digits)[] attribute_hidden; -#define DIGIT(b) INTUSE(_itoa_lower_digits)[(b) & 0xf]; +#define DIGIT(b) _itoa_lower_digits[(b) & 0xf]; /* XXX We cannot translate these messages. */ static const char msg[2][32 diff --git a/elf/dl-support.c b/elf/dl-support.c index e7008078f5..644f3d4622 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -1,5 +1,5 @@ /* Support for dynamic linking code in static libc. - Copyright (C) 1996-2008,2009,2010,2011 Free Software Foundation, Inc. + Copyright (C) 1996-2012 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 @@ -107,6 +107,8 @@ void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls; size_t _dl_pagesize = /* EXEC_PAGESIZE */ 4096; +int _dl_inhibit_cache; + unsigned int _dl_osversion; /* All known directories in sorted order. */ @@ -123,6 +125,7 @@ int _dl_debug_fd = STDERR_FILENO; int _dl_correct_cache_id = _DL_CACHE_DEFAULT_ID; +ElfW(auxv_t) *_dl_auxv; ElfW(Phdr) *_dl_phdr; size_t _dl_phnum; uint64_t _dl_hwcap __attribute__ ((nocommon)); @@ -185,6 +188,7 @@ _dl_aux_init (ElfW(auxv_t) *av) uid_t uid = 0; gid_t gid = 0; + _dl_auxv = av; for (; av->a_type != AT_NULL; ++av) switch (av->a_type) { diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c index 1cb4460a02..e2a9d935ab 100644 --- a/elf/dl-sysdep.c +++ b/elf/dl-sysdep.c @@ -1,5 +1,5 @@ /* Operating system support for run-time dynamic linker. Generic Unix version. - Copyright (C) 1995-1998,2000-2008,2009,2010 + Copyright (C) 1995-1998,2000-2010,2012 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -61,7 +61,6 @@ int __libc_multiple_libcs = 0; /* Defining this here avoids the inclusion /* This variable contains the lowest stack address ever used. */ void *__libc_stack_end attribute_relro = NULL; rtld_hidden_data_def(__libc_stack_end) -static ElfW(auxv_t) *_dl_auxv attribute_relro; void *_dl_random attribute_relro = NULL; #ifndef DL_FIND_ARG_COMPONENTS @@ -111,12 +110,12 @@ _dl_sysdep_start (void **start_argptr, __libc_stack_end = DL_STACK_END (start_argptr); DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, INTUSE(_dl_argv), _environ, - _dl_auxv); + GLRO(dl_auxv)); user_entry = (ElfW(Addr)) ENTRY_POINT; GLRO(dl_platform) = NULL; /* Default to nothing known about the platform. */ - for (av = _dl_auxv; av->a_type != AT_NULL; set_seen (av++)) + for (av = GLRO(dl_auxv); av->a_type != AT_NULL; set_seen (av++)) switch (av->a_type) { case AT_PHDR: @@ -240,7 +239,7 @@ _dl_sysdep_start (void **start_argptr, if (__builtin_expect (INTUSE(__libc_enable_secure), 0)) __libc_check_standard_fds (); - (*dl_main) (phdr, phnum, &user_entry, _dl_auxv); + (*dl_main) (phdr, phnum, &user_entry, GLRO(dl_auxv)); return user_entry; } @@ -265,7 +264,7 @@ _dl_show_auxv (void) close by (otherwise the array will be too large). In case we have to support a platform where these requirements are not fulfilled some alternative implementation has to be used. */ - for (av = _dl_auxv; av->a_type != AT_NULL; ++av) + for (av = GLRO(dl_auxv); av->a_type != AT_NULL; ++av) { static const struct { @@ -303,7 +302,9 @@ _dl_show_auxv (void) }; unsigned int idx = (unsigned int) (av->a_type - 2); - if ((unsigned int) av->a_type < 2u || auxvars[idx].form == ignore) + if ((unsigned int) av->a_type < 2u + || (idx < sizeof (auxvars) / sizeof (auxvars[0]) + && auxvars[idx].form == ignore)) continue; assert (AT_NULL == 0); diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index aa7122738b..44f53b3c70 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -251,53 +251,13 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) /* On some machines, notably SPARC, DT_REL* includes DT_JMPREL in its range. Note that according to the ELF spec, this is completely legal! - But conditionally define things so that on machines we know this will - not happen we do something more optimal. */ -# ifdef ELF_MACHINE_PLTREL_OVERLAP -# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \ - do { \ - struct { ElfW(Addr) start, size; \ - __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; } \ - ranges[3]; \ - int ranges_index; \ - \ - ranges[0].lazy = ranges[2].lazy = 0; \ - ranges[1].lazy = 1; \ - ranges[0].size = ranges[1].size = ranges[2].size = 0; \ - ranges[0].nrelative = ranges[1].nrelative = ranges[2].nrelative = 0; \ - \ - if ((map)->l_info[DT_##RELOC]) \ - { \ - ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \ - ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \ - if (map->l_info[VERSYMIDX (DT_##RELOC##COUNT)] != NULL) \ - ranges[0].nrelative \ - = MIN (map->l_info[VERSYMIDX (DT_##RELOC##COUNT)]->d_un.d_val, \ - ranges[0].size / sizeof (ElfW(reloc))); \ - } \ - \ - if ((do_lazy) \ - && (map)->l_info[DT_PLTREL] \ - && (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \ - { \ - ranges[1].start = D_PTR ((map), l_info[DT_JMPREL]); \ - ranges[1].size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \ - ranges[2].start = ranges[1].start + ranges[1].size; \ - ranges[2].size = ranges[0].start + ranges[0].size - ranges[2].start; \ - ranges[0].size = ranges[1].start - ranges[0].start; \ - } \ - \ - for (ranges_index = 0; ranges_index < 3; ++ranges_index) \ - elf_dynamic_do_##reloc ((map), \ - ranges[ranges_index].start, \ - ranges[ranges_index].size, \ - ranges[ranges_index].nrelative, \ - ranges[ranges_index].lazy, \ - skip_ifunc); \ - } while (0) -# else -# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \ + We are guarenteed that we have one of three situations. Either DT_JMPREL + comes immediately after DT_REL*, or there is overlap and DT_JMPREL + consumes precisely the very end of the DT_REL*, or DT_JMPREL and DT_REL* + are completely separate and there is a gap between them. */ + +# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \ do { \ struct { ElfW(Addr) start, size; \ __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; } \ @@ -316,24 +276,20 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) && (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \ { \ ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]); \ + ElfW(Addr) size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \ \ - if (! ELF_DURING_STARTUP \ - && ((do_lazy) \ - /* This test does not only detect whether the relocation \ - sections are in the right order, it also checks whether \ - there is a DT_REL/DT_RELA section. */ \ - || __builtin_expect (ranges[0].start + ranges[0].size \ - != start, 0))) \ + if (ranges[0].start + ranges[0].size == (start + size)) \ + ranges[0].size -= size; \ + if (! ELF_DURING_STARTUP && ((do_lazy) || ranges[0].size == 0)) \ { \ ranges[1].start = start; \ - ranges[1].size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \ + ranges[1].size = size; \ ranges[1].lazy = (do_lazy); \ } \ else \ { \ /* Combine processing the sections. */ \ - assert (ranges[0].start + ranges[0].size == start); \ - ranges[0].size += (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \ + ranges[0].size += size; \ } \ } \ \ @@ -352,7 +308,6 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) skip_ifunc); \ } \ } while (0) -# endif # if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA # define _ELF_CHECK_REL 0 @@ -1327,6 +1327,7 @@ typedef struct #define R_SPARC_H34 85 #define R_SPARC_SIZE32 86 #define R_SPARC_SIZE64 87 +#define R_SPARC_WDISP10 88 #define R_SPARC_JMP_IREL 248 #define R_SPARC_IRELATIVE 249 #define R_SPARC_GNU_VTINHERIT 250 @@ -2702,8 +2703,9 @@ typedef Elf32_Addr Elf32_Conflict; descriptor. */ #define R_X86_64_TLSDESC 36 /* TLS descriptor. */ #define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ +#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */ -#define R_X86_64_NUM 38 +#define R_X86_64_NUM 39 /* AM33 relocations. */ diff --git a/elf/ldconfig.c b/elf/ldconfig.c index aa97213cc2..8d6e77f8ec 100644 --- a/elf/ldconfig.c +++ b/elf/ldconfig.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999-2011, 2012 Free Software Foundation, Inc. +/* Copyright (C) 1999-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Jaeger <aj@suse.de>, 1999. @@ -1061,7 +1061,9 @@ parse_conf (const char *filename, bool do_chroot) if (file == NULL) { - error (0, errno, _("Can't open configuration file %s"), canon); + error (0, errno, _("\ +Warning: ignoring configuration file that cannot be opened: %s"), + canon); if (canon != filename) free ((char *) canon); return; diff --git a/elf/pldd-xx.c b/elf/pldd-xx.c index 6a9edcbd4a..cf49c57b13 100644 --- a/elf/pldd-xx.c +++ b/elf/pldd-xx.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Free Software Foundation, Inc. +/* Copyright (C) 2011-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@gmail.com>, 2011. @@ -23,7 +23,7 @@ #define EW_(e, w, t) EW__(e, w, _##t) #define EW__(e, w, t) e##w##t -#define static_assert(name, exp) \ +#define pldd_assert(name, exp) \ typedef int __assert_##name[((exp) != 0) - 1] @@ -39,11 +39,11 @@ struct E(link_map) EW(Addr) l_libname; }; #if CLASS == __ELF_NATIVE_CLASS -static_assert (l_addr, (offsetof (struct link_map, l_addr) +pldd_assert (l_addr, (offsetof (struct link_map, l_addr) == offsetof (struct E(link_map), l_addr))); -static_assert (l_name, (offsetof (struct link_map, l_name) +pldd_assert (l_name, (offsetof (struct link_map, l_name) == offsetof (struct E(link_map), l_name))); -static_assert (l_next, (offsetof (struct link_map, l_next) +pldd_assert (l_next, (offsetof (struct link_map, l_next) == offsetof (struct E(link_map), l_next))); #endif @@ -54,9 +54,9 @@ struct E(libname_list) EW(Addr) next; }; #if CLASS == __ELF_NATIVE_CLASS -static_assert (name, (offsetof (struct libname_list, name) +pldd_assert (name, (offsetof (struct libname_list, name) == offsetof (struct E(libname_list), name))); -static_assert (next, (offsetof (struct libname_list, next) +pldd_assert (next, (offsetof (struct libname_list, next) == offsetof (struct E(libname_list), next))); #endif @@ -69,9 +69,9 @@ struct E(r_debug) EW(Addr) r_map; }; #if CLASS == __ELF_NATIVE_CLASS -static_assert (r_version, (offsetof (struct r_debug, r_version) +pldd_assert (r_version, (offsetof (struct r_debug, r_version) == offsetof (struct E(r_debug), r_version))); -static_assert (r_map, (offsetof (struct r_debug, r_map) +pldd_assert (r_map, (offsetof (struct r_debug, r_map) == offsetof (struct E(r_debug), r_map))); #endif diff --git a/elf/rtld-Rules b/elf/rtld-Rules index 6526aec19a..1e03332ca1 100644 --- a/elf/rtld-Rules +++ b/elf/rtld-Rules @@ -1,7 +1,6 @@ # Subroutine makefile for compiling libc modules linked into dynamic linker. -# Copyright (C) 2002,2003,2005,2006,2008,2010,2011 -# Free Software Foundation, Inc. +# Copyright (C) 2002-2012 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 @@ -130,6 +129,6 @@ ifdef rtld-depfiles endif # This here is the whole point of all the shenanigans. -rtld-CPPFLAGS := -DNOT_IN_libc=1 -DIS_IN_rtld=1 +rtld-CPPFLAGS := -DNOT_IN_libc=1 -DIS_IN_rtld=1 -DIN_LIB=rtld endif diff --git a/elf/rtld.c b/elf/rtld.c index 800f172848..00496a7fda 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -161,6 +161,7 @@ struct rtld_global_ro _rtld_global_ro attribute_relro = ._dl_fpu_control = _FPU_DEFAULT, ._dl_pointer_guard = 1, ._dl_pagesize = /* EXEC_PAGESIZE */ 4096, + ._dl_inhibit_cache = 0, /* Function pointers. */ ._dl_debug_printf = _dl_debug_printf, @@ -973,6 +974,13 @@ dl_main (const ElfW(Phdr) *phdr, --_dl_argc; ++INTUSE(_dl_argv); } + else if (! strcmp (INTUSE(_dl_argv)[1], "--inhibit-cache")) + { + GLRO(dl_inhibit_cache) = 1; + ++_dl_skip_args; + --_dl_argc; + ++INTUSE(_dl_argv); + } else if (! strcmp (INTUSE(_dl_argv)[1], "--library-path") && _dl_argc > 2) { @@ -1022,6 +1030,7 @@ of this helper program; chances are you did not intend to run this program.\n\ --list list all dependencies and how they are resolved\n\ --verify verify that given object really is a dynamically linked\n\ object we can handle\n\ + --inhibit-cache Do not use " LD_SO_CACHE "\n\ --library-path PATH use given PATH instead of content of the environment\n\ variable LD_LIBRARY_PATH\n\ --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\ @@ -1423,7 +1432,7 @@ of this helper program; chances are you did not intend to run this program.\n\ #endif #ifdef DL_SYSDEP_OSCHECK - DL_SYSDEP_OSCHECK (dl_fatal); + DL_SYSDEP_OSCHECK (_dl_fatal_printf); #endif /* Initialize the data structures for the search paths for shared @@ -1967,7 +1976,12 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", if (dyn->d_tag == DT_NEEDED) { l = l->l_next; - +#if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO + /* Skip the VDSO since it's not part of the list + of objects we brought in via DT_NEEDED entries. */ + if (l == GLRO(dl_sysinfo_map)) + l = l->l_next; +#endif if (!l->l_used) { if (first) @@ -2278,6 +2292,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", lnp->dont_free = 1; lnp = lnp->next; } + /* Also allocated with the fake malloc(). */ + l->l_free_initfini = 0; if (l != &GL(dl_rtld_map)) _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0, @@ -2500,6 +2516,14 @@ warning: debug option `%s' unknown; try LD_DEBUG=help\n", copy); ++dl_debug; } + if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) + { + /* In order to get an accurate picture of whether a particular + DT_NEEDED entry is actually used we have to process both + the PLT and non-PLT relocation entries. */ + GLRO(dl_lazy) = 0; + } + if (GLRO(dl_debug_mask) & DL_DEBUG_HELP) { size_t cnt; diff --git a/elf/stackguard-macros.h b/elf/stackguard-macros.h deleted file mode 100644 index a9889cf7b2..0000000000 --- a/elf/stackguard-macros.h +++ /dev/null @@ -1,30 +0,0 @@ -#include <stdint.h> - -#ifdef __i386__ -# define STACK_CHK_GUARD \ - ({ uintptr_t x; asm ("movl %%gs:0x14, %0" : "=r" (x)); x; }) -#elif defined __x86_64__ -# define STACK_CHK_GUARD \ - ({ uintptr_t x; asm ("movq %%fs:0x28, %0" : "=r" (x)); x; }) -#elif defined __powerpc64__ -# define STACK_CHK_GUARD \ - ({ uintptr_t x; asm ("ld %0,-28688(13)" : "=r" (x)); x; }) -#elif defined __powerpc__ -# define STACK_CHK_GUARD \ - ({ uintptr_t x; asm ("lwz %0,-28680(2)" : "=r" (x)); x; }) -#elif defined __sparc__ && defined __arch64__ -# define STACK_CHK_GUARD \ - ({ uintptr_t x; asm ("ldx [%%g7+0x28], %0" : "=r" (x)); x; }) -#elif defined __sparc__ -# define STACK_CHK_GUARD \ - ({ uintptr_t x; asm ("ld [%%g7+0x14], %0" : "=r" (x)); x; }) -#elif defined __s390x__ -# define STACK_CHK_GUARD \ - ({ uintptr_t x; asm ("ear %0,%%a0; sllg %0,%0,32; ear %0,%%a1; lg %0,0x28(%0)" : "=a" (x)); x; }) -#elif defined __s390__ -# define STACK_CHK_GUARD \ - ({ uintptr_t x; asm ("ear %0,%%a0; l %0,0x14(%0)" : "=a" (x)); x; }) -#elif !defined STACK_CHK_GUARD -extern uintptr_t __stack_chk_guard; -# define STACK_CHK_GUARD __stack_chk_guard -#endif diff --git a/elf/tls-macros.h b/elf/tls-macros.h index ea6f14f56b..e753d5ccaf 100644 --- a/elf/tls-macros.h +++ b/elf/tls-macros.h @@ -101,15 +101,15 @@ # define TLS_LE(x) \ ({ int *__l; \ - asm ("movq %%fs:0,%0\n\t" \ - "leaq " #x "@tpoff(%0), %0" \ + asm ("mov %%fs:0,%0\n\t" \ + "lea " #x "@tpoff(%0), %0" \ : "=r" (__l)); \ __l; }) # define TLS_IE(x) \ ({ int *__l; \ - asm ("movq %%fs:0,%0\n\t" \ - "addq " #x "@gottpoff(%%rip),%0" \ + asm ("mov %%fs:0,%0\n\t" \ + "add " #x "@gottpoff(%%rip),%0" \ : "=r" (__l)); \ __l; }) @@ -122,9 +122,15 @@ : : "rdi", "rsi", "r8", "r9", "r10", "r11"); \ __l; }) +# ifdef __ILP32__ +# define TLS_GD_PREFIX +# else +# define TLS_GD_PREFIX ".byte 0x66\n\t" +# endif + # define TLS_GD(x) \ ({ int *__l, __c, __d; \ - asm (".byte 0x66\n\t" \ + asm (TLS_GD_PREFIX \ "leaq " #x "@tlsgd(%%rip),%%rdi\n\t" \ ".word 0x6666\n\t" \ "rex64\n\t" \ diff --git a/elf/tst-auditmod1.c b/elf/tst-auditmod1.c index 67fc758ac3..108d6ded59 100644 --- a/elf/tst-auditmod1.c +++ b/elf/tst-auditmod1.c @@ -109,7 +109,7 @@ la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, # define La_retval La_i86_retval # define int_retval lrv_eax #elif defined __x86_64__ -# ifdef __LP64__ +# ifndef __ILP32__ # define pltenter la_x86_64_gnu_pltenter # define pltexit la_x86_64_gnu_pltexit # define La_regs La_x86_64_regs diff --git a/elf/tst-auditmod3b.c b/elf/tst-auditmod3b.c index 921eaca55a..a9bb0e22c3 100644 --- a/elf/tst-auditmod3b.c +++ b/elf/tst-auditmod3b.c @@ -105,7 +105,7 @@ la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, return sym->st_value; } -#ifdef __LP64__ +# ifndef __ILP32__ # define pltenter la_x86_64_gnu_pltenter # define pltexit la_x86_64_gnu_pltexit # define La_regs La_x86_64_regs diff --git a/elf/tst-auditmod4b.c b/elf/tst-auditmod4b.c index 75e85582bd..7778d6a172 100644 --- a/elf/tst-auditmod4b.c +++ b/elf/tst-auditmod4b.c @@ -94,7 +94,7 @@ la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, return sym->st_value; } -#ifdef __LP64__ +# ifndef __ILP32__ # define pltenter la_x86_64_gnu_pltenter # define pltexit la_x86_64_gnu_pltexit # define La_regs La_x86_64_regs diff --git a/elf/tst-auditmod5b.c b/elf/tst-auditmod5b.c index d2443c8d20..3a4221536c 100644 --- a/elf/tst-auditmod5b.c +++ b/elf/tst-auditmod5b.c @@ -95,7 +95,7 @@ la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, return sym->st_value; } -#ifdef __LP64__ +# ifndef __ILP32__ # define pltenter la_x86_64_gnu_pltenter # define pltexit la_x86_64_gnu_pltexit # define La_regs La_x86_64_regs diff --git a/elf/tst-auditmod6b.c b/elf/tst-auditmod6b.c index b00dcd7c2e..a9fe5dcadc 100644 --- a/elf/tst-auditmod6b.c +++ b/elf/tst-auditmod6b.c @@ -94,7 +94,7 @@ la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, return sym->st_value; } -#ifdef __LP64__ +# ifndef __ILP32__ # define pltenter la_x86_64_gnu_pltenter # define pltexit la_x86_64_gnu_pltexit # define La_regs La_x86_64_regs diff --git a/elf/tst-auditmod6c.c b/elf/tst-auditmod6c.c index a78c913963..9b1063b23f 100644 --- a/elf/tst-auditmod6c.c +++ b/elf/tst-auditmod6c.c @@ -94,7 +94,7 @@ la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, return sym->st_value; } -#ifdef __LP64__ +# ifndef __ILP32__ # define pltenter la_x86_64_gnu_pltenter # define pltexit la_x86_64_gnu_pltexit # define La_regs La_x86_64_regs diff --git a/elf/tst-auditmod7b.c b/elf/tst-auditmod7b.c index d761149a2f..1ae9e72769 100644 --- a/elf/tst-auditmod7b.c +++ b/elf/tst-auditmod7b.c @@ -94,7 +94,7 @@ la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, return sym->st_value; } -#ifdef __LP64__ +#ifndef __ILP32__ # define pltenter la_x86_64_gnu_pltenter # define pltexit la_x86_64_gnu_pltexit # define La_regs La_x86_64_regs diff --git a/elf/tst-execstack.c b/elf/tst-execstack.c index 6632e53367..02cc270d80 100644 --- a/elf/tst-execstack.c +++ b/elf/tst-execstack.c @@ -7,6 +7,7 @@ #include <string.h> #include <unistd.h> #include <error.h> +#include <stackinfo.h> static void print_maps (void) @@ -46,7 +47,6 @@ waiter_thread (void *arg) } #endif - static bool allow_execstack = true; @@ -107,6 +107,35 @@ do_test (void) print_maps (); +#if USE_PTHREADS + void *old_stack_addr, *new_stack_addr; + size_t stack_size; + pthread_t me = pthread_self (); + pthread_attr_t attr; + int ret = 0; + + ret = pthread_getattr_np (me, &attr); + if (ret) + { + printf ("before execstack: pthread_getattr_np returned error: %s\n", + strerror (ret)); + return 1; + } + + ret = pthread_attr_getstack (&attr, &old_stack_addr, &stack_size); + if (ret) + { + printf ("before execstack: pthread_attr_getstack returned error: %s\n", + strerror (ret)); + return 1; + } +# if _STACK_GROWS_DOWN + old_stack_addr += stack_size; +# else + old_stack_addr -= stack_size; +# endif +#endif + /* Loading this module should force stacks to become executable. */ void *h = dlopen ("tst-execstack-mod.so", RTLD_LAZY); if (h == NULL) @@ -129,6 +158,46 @@ do_test (void) print_maps (); +#if USE_PTHREADS + ret = pthread_getattr_np (me, &attr); + if (ret) + { + printf ("after execstack: pthread_getattr_np returned error: %s\n", + strerror (ret)); + return 1; + } + + ret = pthread_attr_getstack (&attr, &new_stack_addr, &stack_size); + if (ret) + { + printf ("after execstack: pthread_attr_getstack returned error: %s\n", + strerror (ret)); + return 1; + } + +# if _STACK_GROWS_DOWN + new_stack_addr += stack_size; +# else + new_stack_addr -= stack_size; +# endif + + /* It is possible that the dlopen'd module may have been mmapped just below + the stack. The stack size is taken as MIN(stack rlimit size, end of last + vma) in pthread_getattr_np. If rlimit is set high enough, it is possible + that the size may have changed. A subsequent call to + pthread_attr_getstack returns the size and (bottom - size) as the + stacksize and stackaddr respectively. If the size changes due to the + above, then both stacksize and stackaddr can change, but the stack bottom + should remain the same, which is computed as stackaddr + stacksize. */ + if (old_stack_addr != new_stack_addr) + { + printf ("Stack end changed, old: %p, new: %p\n", + old_stack_addr, new_stack_addr); + return 1; + } + printf ("Stack address remains the same: %p\n", old_stack_addr); +#endif + /* Test that growing the stack region gets new executable pages too. */ deeper ((void (*) (void)) f); diff --git a/elf/tst-relsort1.c b/elf/tst-relsort1.c index 972100c0e9..a87b138280 100644 --- a/elf/tst-relsort1.c +++ b/elf/tst-relsort1.c @@ -3,7 +3,7 @@ static int -do_test () +do_test (void) { const char lib[] = "$ORIGIN/tst-relsort1mod1.so"; void *h = dlopen (lib, RTLD_NOW); |