diff --git a/elf/dl-load.c b/elf/dl-load.c index 2923b1141d..ffaf722f5f 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -88,6 +89,10 @@ struct filebuf #define STRING(x) __STRING (x) +#ifndef PT_GNU_SFRAME +#define PT_GNU_SFRAME 0x6474e554 +#endif + int __stack_prot attribute_hidden attribute_relro #if _STACK_GROWS_DOWN && defined PROT_GROWSDOWN @@ -1213,6 +1218,10 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, l->l_relro_addr = ph->p_vaddr; l->l_relro_size = ph->p_memsz; break; + + case PT_GNU_SFRAME: + l->l_sframe_addr = ph->p_vaddr; + break; } if (__glibc_unlikely (nloadcmds == 0)) @@ -1376,6 +1385,13 @@ cannot enable executable stack as shared object requires"); break; } +#define PR_ADD_SFRAME 74 + if (l->l_sframe_addr != 0) + { + l->l_sframe_addr += l->l_addr; + __prctl(PR_ADD_SFRAME, l->l_sframe_addr, NULL, NULL, NULL); + } + /* We are done mapping in the file. We no longer need the descriptor. */ if (__glibc_unlikely (__close_nocancel (fd) != 0)) { diff --git a/elf/dl-unmap-segments.h b/elf/dl-unmap-segments.h index 1ec507e887..c4a7e9e0ed 100644 --- a/elf/dl-unmap-segments.h +++ b/elf/dl-unmap-segments.h @@ -21,14 +21,20 @@ #include #include +#include /* _dl_map_segments ensures that any whole pages in gaps between segments are filled in with PROT_NONE mappings. So we can just unmap the whole range in one fell swoop. */ +#define PR_REMOVE_SFRAME 75 + static __always_inline void _dl_unmap_segments (struct link_map *l) { + if (l->l_sframe_addr != 0) + __prctl(PR_REMOVE_SFRAME, l->l_sframe_addr, NULL, NULL, NULL); + __munmap ((void *) l->l_map_start, l->l_map_end - l->l_map_start); } diff --git a/include/link.h b/include/link.h index c6af095d87..36ac75680f 100644 --- a/include/link.h +++ b/include/link.h @@ -348,6 +348,8 @@ struct link_map ElfW(Addr) l_relro_addr; size_t l_relro_size; + ElfW(Addr) l_sframe_addr; + unsigned long long int l_serial; };