From patchwork Sat Dec 24 00:23:14 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 18679 Received: (qmail 39049 invoked by alias); 24 Dec 2016 00:23:32 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 39030 invoked by uid 89); 24 Dec 2016 00:23:32 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=relocating, *output_bfd, asection, sk:_bfd_el X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-pf0-f195.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=Y4+u791nrywce4mYBZ3xZT0SVU/0VzMfvzf6pla9cHU=; b=qvqdUTTdxnvJkWDXE1BjcD6+/P8eFsC1eYPFMoHp4W7Jm3l/VcCrsoMl3FcW9E4wnM 6jGc/Dh2N+B9ftxBhZdoylfh2TjxMLnw+cDs0IJZP6DSUwN3WoQFJt30ULy7bN2Q8ils LvM/vn8Y5EW61CA0+uuNssdYJ9vZ8RymIlWcGmKJ81UphlB1Ot7ClkV1F06j8c1JFoEY URmpC59x7xq6OtRGR4Kx6/+MM1Rl6SUv0bJdGTASanCWdiohfbnOGmP6fmhmJ+bvaTgB G4r5i9LS7FLyFzKluSQAufCvIDpsUd462n53KhEfaiYd7OQ+NFS6p/ObfkPerHrD/1hd h8pg== X-Gm-Message-State: AIkVDXKvuxvw0douy1idm4gIUL0HqIglvlJFsf1g6MwLyudJe/1Z7xOaCveyE6OvNDyZlQ== X-Received: by 10.84.218.197 with SMTP id g5mr34342439plm.173.1482539000290; Fri, 23 Dec 2016 16:23:20 -0800 (PST) Date: Sat, 24 Dec 2016 10:53:14 +1030 From: Alan Modra To: Florian Weimer Cc: Mathias Payer , binutils@sourceware.org, libc-alpha@sourceware.org, Xinyang Ge , Trent Jaeger Subject: Re: Read-only data in ELF libraries may be remapped writable at runtime (upcoming NDSS'17 paper) Message-ID: <20161224002314.GH2896@bubble.grove.modra.org> References: <5bb116b9-2633-bb9d-bd93-edece2fc56ec@redhat.com> <20161223143554.GG2896@bubble.grove.modra.org> <1f4b9a13-3d00-9782-1190-23dc6eb0d804@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1f4b9a13-3d00-9782-1190-23dc6eb0d804@redhat.com> User-Agent: Mutt/1.5.24 (2015-08-30) On Fri, Dec 23, 2016 at 08:02:22PM +0100, Florian Weimer wrote: > On 12/23/2016 07:32 PM, Mathias Payer wrote: > > > > > >On December 23, 2016 7:18:29 PM GMT+01:00, Florian Weimer wrote: > >>On 12/23/2016 07:04 PM, Mathias Payer wrote: > >> > >>>At the linker level you likely don't know if the referenced symbol is > >>RO > >>>or not (as it could come from any object) -- only the runtime loader > >>has > >>>this knowledge and at that time it is too late as PIE uses relative > >>>addressing inside the object. > >> > >>The static linker necessarily sees a definition, otherwise it cannot > >>produce a copy relocation because copy relocations must refer to > >>objects > >>of known size. > > > >Agreed. The static linker knows about the symbol and size but not the permission. That information is discarded after compilation. > > That's not quite true. At least in the vtable case, the vtable is emitted > in the .data.rel.ro section, and this information is definitely available to > the static linker. I believe that should be the case for all dynamic symbols of interest. Here's a prototype patch for powerpc64. Obviously there's a lot more work to do yet to fix all the other backends. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 2f0aaf6..e1f4566 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -595,6 +595,10 @@ struct elf_link_hash_table asection *srelgot; asection *splt; asection *srelplt; + asection *sdynbss; + asection *srelbss; + asection *sdynrelro; + asection *srelro; asection *igotplt; asection *iplt; asection *irelplt; diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index ae014e5..b9cb378 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -93,7 +93,7 @@ static bfd_vma opd_entry_value #define elf_backend_grok_prstatus ppc64_elf_grok_prstatus #define elf_backend_grok_psinfo ppc64_elf_grok_psinfo #define elf_backend_write_core_note ppc64_elf_write_core_note -#define elf_backend_create_dynamic_sections ppc64_elf_create_dynamic_sections +#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections #define elf_backend_copy_indirect_symbol ppc64_elf_copy_indirect_symbol #define elf_backend_add_symbol_hook ppc64_elf_add_symbol_hook #define elf_backend_check_directives ppc64_elf_before_check_relocs @@ -4084,8 +4084,6 @@ struct ppc_link_hash_table struct ppc_link_hash_entry *dot_syms; /* Shortcuts to get to dynamic linker sections. */ - asection *dynbss; - asection *relbss; asection *glink; asection *sfpr; asection *brlt; @@ -4669,31 +4667,6 @@ create_got_section (bfd *abfd, struct bfd_link_info *info) return TRUE; } -/* Create the dynamic sections, and set up shortcuts. */ - -static bfd_boolean -ppc64_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) -{ - struct ppc_link_hash_table *htab; - - if (!_bfd_elf_create_dynamic_sections (dynobj, info)) - return FALSE; - - htab = ppc_hash_table (info); - if (htab == NULL) - return FALSE; - - htab->dynbss = bfd_get_linker_section (dynobj, ".dynbss"); - if (!bfd_link_pic (info)) - htab->relbss = bfd_get_linker_section (dynobj, ".rela.bss"); - - if (!htab->elf.sgot || !htab->elf.splt || !htab->elf.srelplt || !htab->dynbss - || (!bfd_link_pic (info) && !htab->relbss)) - abort (); - - return TRUE; -} - /* Follow indirect and warning symbol links. */ static inline struct bfd_link_hash_entry * @@ -7311,7 +7284,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h) { struct ppc_link_hash_table *htab; - asection *s; + asection *s, *srel; htab = ppc_hash_table (info); if (htab == NULL) @@ -7441,14 +7414,22 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info, to copy the initial value out of the dynamic object and into the runtime process image. We need to remember the offset into the .rela.bss section we are going to use. */ + if ((h->root.u.def.section->flags & SEC_READONLY) != 0) + { + s = htab->elf.sdynrelro; + srel = htab->elf.srelro; + } + else + { + s = htab->elf.sdynbss; + srel = htab->elf.srelbss; + } if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0) { - htab->relbss->size += sizeof (Elf64_External_Rela); + srel->size += sizeof (Elf64_External_Rela); h->needs_copy = 1; } - s = htab->dynbss; - return _bfd_elf_adjust_dynamic_copy (info, h, s); } @@ -10278,7 +10259,8 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, || s == htab->elf.splt || s == htab->elf.iplt || s == htab->glink - || s == htab->dynbss) + || s == htab->elf.sdynbss + || s == htab->elf.sdynrelro) { /* Strip this section if we don't need it; see the comment below. */ @@ -10331,7 +10313,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, but this way if it does we get a R_PPC64_NONE reloc in .rela sections instead of garbage. We also rely on the section contents being zero when writing - the GOT. */ + the GOT and .dynrelro. */ s->contents = bfd_zalloc (dynobj, s->size); if (s->contents == NULL) return FALSE; @@ -15615,11 +15597,13 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd, if (h->needs_copy) { /* This symbol needs a copy reloc. Set it up. */ + asection *srel; if (h->dynindx == -1 || (h->root.type != bfd_link_hash_defined && h->root.type != bfd_link_hash_defweak) - || htab->relbss == NULL) + || htab->elf.srelbss == NULL + || htab->elf.srelro == NULL) abort (); rela.r_offset = (h->root.u.def.value @@ -15627,8 +15611,12 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd, + h->root.u.def.section->output_offset); rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_COPY); rela.r_addend = 0; - loc = htab->relbss->contents; - loc += htab->relbss->reloc_count++ * sizeof (Elf64_External_Rela); + if ((h->root.u.def.section->flags & SEC_READONLY) != 0) + srel = htab->elf.srelro; + else + srel = htab->elf.srelbss; + loc = srel->contents; + loc += srel->reloc_count++ * sizeof (Elf64_External_Rela); bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); } diff --git a/bfd/elflink.c b/bfd/elflink.c index 42bb837..a10ed07 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -427,6 +427,17 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) (SEC_ALLOC | SEC_LINKER_CREATED)); if (s == NULL) return FALSE; + htab->sdynbss = s; + + /* Similarly, but for symbols that were originally in read-only + sections. */ + s = bfd_make_section_anyway_with_flags (abfd, ".dynrelro", + (SEC_ALLOC | SEC_READONLY + | SEC_HAS_CONTENTS + | SEC_LINKER_CREATED)); + if (s == NULL) + return FALSE; + htab->sdynrelro = s; /* The .rel[a].bss section holds copy relocs. This section is not normally needed. We need to create it here, though, so that the @@ -448,6 +459,16 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; + htab->srelbss = s; + + s = bfd_make_section_anyway_with_flags (abfd, + (bed->rela_plts_and_copies_p + ? ".rela.ro" : ".rel.ro"), + flags | SEC_READONLY); + if (s == NULL + || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) + return FALSE; + htab->srelro = s; } } diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc index f0c6439..12cfe8b 100644 --- a/ld/scripttempl/elf.sc +++ b/ld/scripttempl/elf.sc @@ -169,7 +169,7 @@ RELA_IPLT=".rela.iplt ${RELOCATING-0} : }" DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }" RODATA=".${RODATA_NAME} ${RELOCATING-0} : { *(.${RODATA_NAME}${RELOCATING+ .${RODATA_NAME}.* .gnu.linkonce.r.*}) }" -DATARELRO=".data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }" +DATARELRO=".data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) *(.dynrelro) }" DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }" if test -z "${NO_SMALL_DATA}"; then SBSS=".${SBSS_NAME} ${RELOCATING-0} :