From patchwork Wed Mar 4 23:26:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 5465 Received: (qmail 4462 invoked by alias); 4 Mar 2015 23:26:16 -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 4424 invoked by uid 89); 4 Mar 2015 23:26:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=2.7 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, KAM_FROM_URIBL_PCCC, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-oi0-f41.google.com MIME-Version: 1.0 X-Received: by 10.202.191.194 with SMTP id p185mr4700023oif.128.1425511570560; Wed, 04 Mar 2015 15:26:10 -0800 (PST) Date: Wed, 4 Mar 2015 15:26:10 -0800 Message-ID: Subject: RFC: PATCHES: Properly handle reference to protected data on x86 From: "H.J. Lu" To: GCC Patches , GNU C Library , Binutils Protected symbol means that it can't be pre-emptied. It doesn't mean its address won't be external. This is true for pointer to protected function. With copy relocation, address of protected data defined in the shared library may also be external. We only know that for sure at run-time. Here are patches for glibc, binutils and GCC to handle it properly. Any comments? Thanks. From ced505c47a961691e3f1e252ba5ea2aec4152397 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 4 Mar 2015 08:57:30 -0800 Subject: [PATCH] Add extern_protected_data and set it for x86 With copy relocation, address of protected data defined in the shared library may be external. This patch adds extern_protected_data and changes _bfd_elf_symbol_refs_local_p to return false for protecteddata if extern_protected_data is true. --- bfd/elf-bfd.h | 4 ++++ bfd/elf32-i386.c | 1 + bfd/elf64-x86-64.c | 1 + bfd/elflink.c | 9 ++++++--- bfd/elfxx-target.h | 6 +++++- ld/testsuite/ld-i386/protected3.d | 3 ++- ld/testsuite/ld-i386/protected3.s | 3 ++- ld/testsuite/ld-x86-64/protected3.d | 3 ++- ld/testsuite/ld-x86-64/protected3.s | 3 ++- 9 files changed, 25 insertions(+), 8 deletions(-) diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 156eec7..13c32e0 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1359,6 +1359,10 @@ struct elf_backend_data in length rather than sec->size in length, if sec->rawsize is non-zero and smaller than sec->size. */ unsigned caches_rawsize : 1; + + /* Address of protected data defined in the shared library may be + external, i.e., due to copy relocation. */ + unsigned extern_protected_data : 1; }; /* Information about reloc sections associated with a bfd_elf_section_data diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 3f16fc1..52f4d33 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -5292,6 +5292,7 @@ elf_i386_add_symbol_hook (bfd * abfd, #define elf_backend_want_plt_sym 0 #define elf_backend_got_header_size 12 #define elf_backend_plt_alignment 4 +#define elf_backend_extern_protected_data 1 /* Support RELA for objdump of prelink objects. */ #define elf_info_to_howto elf_i386_info_to_howto_rel diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index a4974ce..74d1d06 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -5868,6 +5868,7 @@ static const struct bfd_elf_special_section #define elf_backend_got_header_size (GOT_ENTRY_SIZE*3) #define elf_backend_rela_normal 1 #define elf_backend_plt_alignment 4 +#define elf_backend_extern_protected_data 1 #define elf_info_to_howto elf_x86_64_info_to_howto diff --git a/bfd/elflink.c b/bfd/elflink.c index ec1e4df..6ee6499 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -2671,7 +2671,9 @@ _bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info, /* Increment the size of DYNBSS to make room for the symbol. */ dynbss->size += h->size; - if (h->protected_def) + /* No error if extern_protected_data is true. */ + if (h->protected_def + && !get_elf_backend_data (dynbss->owner)->extern_protected_data) { info->callbacks->einfo (_("%P: copy reloc against protected `%T' is invalid\n"), @@ -2835,8 +2837,9 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h, bed = get_elf_backend_data (hash_table->dynobj); - /* STV_PROTECTED non-function symbols are local. */ - if (!bed->is_function_type (h->type)) + /* If extern_protected_data is false, STV_PROTECTED non-function + symbols are local. */ + if (!bed->extern_protected_data && !bed->is_function_type (h->type)) return TRUE; /* Function pointer equality tests may require that STV_PROTECTED diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index 211c0a1..9760db4 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -117,6 +117,9 @@ #ifndef elf_backend_caches_rawsize #define elf_backend_caches_rawsize 0 #endif +#ifndef elf_backend_extern_protected_data +#define elf_backend_extern_protected_data 0 +#endif #ifndef elf_backend_stack_align #define elf_backend_stack_align 16 #endif @@ -801,7 +804,8 @@ static struct elf_backend_data elfNN_bed = elf_backend_want_dynbss, elf_backend_want_p_paddr_set_to_zero, elf_backend_default_execstack, - elf_backend_caches_rawsize + elf_backend_caches_rawsize, + elf_backend_extern_protected_data }; /* Forward declaration for use when initialising alternative_target field. */ diff --git a/ld/testsuite/ld-i386/protected3.d b/ld/testsuite/ld-i386/protected3.d index aafa2d8..47ab4e1 100644 --- a/ld/testsuite/ld-i386/protected3.d +++ b/ld/testsuite/ld-i386/protected3.d @@ -8,6 +8,7 @@ Disassembly of section .text: 0+[a-f0-9]+ : -[ ]*[a-f0-9]+: 8b 81 [a-f0-9][a-f0-9] [a-f0-9][a-f0-9] 00 00 mov 0x[a-f0-9]+\(%ecx\),%eax +[ ]*[a-f0-9]+: 8b 81 [a-f0-9][a-f0-9] [a-f0-9][a-f0-9] ff ff mov -0x[a-f0-9]+\(%ecx\),%eax +[ ]*[a-f0-9]+: 8b 00 mov \(%eax\),%eax [ ]*[a-f0-9]+: c3 ret #pass diff --git a/ld/testsuite/ld-i386/protected3.s b/ld/testsuite/ld-i386/protected3.s index 7a605a2..4dd2115 100644 --- a/ld/testsuite/ld-i386/protected3.s +++ b/ld/testsuite/ld-i386/protected3.s @@ -10,6 +10,7 @@ foo: .globl bar .type bar, @function bar: - movl foo@GOTOFF(%ecx), %eax + movl foo@GOT(%ecx), %eax + movl (%eax), %eax ret .size bar, .-bar diff --git a/ld/testsuite/ld-x86-64/protected3.d b/ld/testsuite/ld-x86-64/protected3.d index 22a36ac..d8f09da 100644 --- a/ld/testsuite/ld-x86-64/protected3.d +++ b/ld/testsuite/ld-x86-64/protected3.d @@ -8,6 +8,7 @@ Disassembly of section .text: 0+[a-f0-9]+ : -[ ]*[a-f0-9]+: 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%eax # [a-f0-9]+ +[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+> +[ ]*[a-f0-9]+: 8b 00 mov \(%rax\),%eax [ ]*[a-f0-9]+: c3 retq * #pass diff --git a/ld/testsuite/ld-x86-64/protected3.s b/ld/testsuite/ld-x86-64/protected3.s index e4af6e7..7538050 100644 --- a/ld/testsuite/ld-x86-64/protected3.s +++ b/ld/testsuite/ld-x86-64/protected3.s @@ -10,6 +10,7 @@ foo: .globl bar .type bar, @function bar: - movl foo(%rip), %eax + movq foo@GOTPCREL(%rip), %rax + movl (%rax), %eax ret .size bar, .-bar -- 1.9.3