PowerPC64, sanity check r_offset in relocate_section

Message ID YTix3P9iUK9OoEsA@squeak.grove.modra.org
State New
Headers show
Series
  • PowerPC64, sanity check r_offset in relocate_section
Related show

Commit Message

Alan Modra via Binutils Sept. 8, 2021, 12:51 p.m.
This hardens the powerpc64 linker code transformations.

	* elf64-ppc.c (is_8byte_reloc, offset_in_range): New functions.
	(ppc64_elf_relocate_section): Sanity check r_offset before
	accessing section contents for various code transformations.


-- 
Alan Modra
Australia Development Lab, IBM

Patch

diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index aa997bb42ab..4ebacbd9945 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -4601,6 +4601,26 @@  is_plt_seq_reloc (enum elf_ppc64_reloc_type r_type)
 	  || r_type == R_PPC64_PLTSEQ_NOTOC);
 }
 
+/* Of relocs which might appear paired with TLSGD and TLSLD marker
+   relocs, return true for those that operate on a dword.  */
+
+static bool
+is_8byte_reloc (enum elf_ppc64_reloc_type r_type)
+{
+  return (r_type == R_PPC64_PLT_PCREL34
+	  || r_type == R_PPC64_PLT_PCREL34_NOTOC
+	  || r_type == R_PPC64_PLTCALL);
+}
+
+/* Like bfd_reloc_offset_in_range but without a howto.  Return true
+   iff a field of SIZE bytes at OFFSET is within SEC limits.  */
+
+static bool
+offset_in_range (asection *sec, bfd_vma offset, size_t size)
+{
+  return offset <= sec->size && size <= sec->size - offset;
+}
+
 /* Look through the relocs for a section during the first phase, and
    calculate needed space in the global offset table, procedure
    linkage table, and dynamic reloc sections.  */
@@ -15222,13 +15242,18 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	  break;
 
 	case R_PPC64_LO_DS_OPT:
-	  insn = bfd_get_32 (input_bfd, contents + rel->r_offset - d_offset);
-	  if ((insn & (0x3fu << 26)) != 58u << 26)
-	    abort ();
-	  insn += (14u << 26) - (58u << 26);
-	  bfd_put_32 (input_bfd, insn, contents + rel->r_offset - d_offset);
-	  r_type = R_PPC64_TOC16_LO;
-	  rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+	  if (offset_in_range (input_section, rel->r_offset - d_offset, 4))
+	    {
+	      insn = bfd_get_32 (input_bfd,
+				 contents + rel->r_offset - d_offset);
+	      if ((insn & (0x3fu << 26)) != 58u << 26)
+		abort ();
+	      insn += (14u << 26) - (58u << 26);
+	      bfd_put_32 (input_bfd, insn,
+			  contents + rel->r_offset - d_offset);
+	      r_type = R_PPC64_TOC16_LO;
+	      rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+	    }
 	  break;
 
 	case R_PPC64_TOC16:
@@ -15280,7 +15305,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	case R_PPC64_GOT_TPREL16_HI:
 	case R_PPC64_GOT_TPREL16_HA:
 	  if ((tls_mask & TLS_TLS) != 0
-	      && (tls_mask & TLS_TPREL) == 0)
+	      && (tls_mask & TLS_TPREL) == 0
+	      && offset_in_range (input_section, rel->r_offset - d_offset, 4))
 	    {
 	      rel->r_offset -= d_offset;
 	      bfd_put_32 (input_bfd, NOP, contents + rel->r_offset);
@@ -15292,7 +15318,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	case R_PPC64_GOT_TPREL16_DS:
 	case R_PPC64_GOT_TPREL16_LO_DS:
 	  if ((tls_mask & TLS_TLS) != 0
-	      && (tls_mask & TLS_TPREL) == 0)
+	      && (tls_mask & TLS_TPREL) == 0
+	      && offset_in_range (input_section, rel->r_offset - d_offset, 4))
 	    {
 	    toctprel:
 	      insn = bfd_get_32 (input_bfd,
@@ -15317,7 +15344,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 
 	case R_PPC64_GOT_TPREL_PCREL34:
 	  if ((tls_mask & TLS_TLS) != 0
-	      && (tls_mask & TLS_TPREL) == 0)
+	      && (tls_mask & TLS_TPREL) == 0
+	      && offset_in_range (input_section, rel->r_offset, 8))
 	    {
 	      /* pld ra,sym@got@tprel@pcrel -> paddi ra,r13,sym@tprel  */
 	      pinsn = bfd_get_32 (input_bfd, contents + rel->r_offset);
@@ -15336,7 +15364,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 
 	case R_PPC64_TLS:
 	  if ((tls_mask & TLS_TLS) != 0
-	      && (tls_mask & TLS_TPREL) == 0)
+	      && (tls_mask & TLS_TPREL) == 0
+	      && offset_in_range (input_section, rel->r_offset & ~3, 4))
 	    {
 	      insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
 	      insn = _bfd_elf_ppc_at_tls_transform (insn, 13);
@@ -15387,13 +15416,15 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	case R_PPC64_GOT_TLSGD16_HI:
 	case R_PPC64_GOT_TLSGD16_HA:
 	  tls_gd = TLS_GDIE;
-	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0)
+	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0
+	      && offset_in_range (input_section, rel->r_offset & ~3, 4))
 	    goto tls_gdld_hi;
 	  break;
 
 	case R_PPC64_GOT_TLSLD16_HI:
 	case R_PPC64_GOT_TLSLD16_HA:
-	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0)
+	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0
+	      && offset_in_range (input_section, rel->r_offset & ~3, 4))
 	    {
 	    tls_gdld_hi:
 	      if ((tls_mask & tls_gd) != 0)
@@ -15412,13 +15443,15 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	case R_PPC64_GOT_TLSGD16:
 	case R_PPC64_GOT_TLSGD16_LO:
 	  tls_gd = TLS_GDIE;
-	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0)
+	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0
+	      && offset_in_range (input_section, rel->r_offset & ~3, 4))
 	    goto tls_ldgd_opt;
 	  break;
 
 	case R_PPC64_GOT_TLSLD16:
 	case R_PPC64_GOT_TLSLD16_LO:
-	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0)
+	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0
+	      && offset_in_range (input_section, rel->r_offset & ~3, 4))
 	    {
 	      unsigned int insn1, insn2;
 
@@ -15488,10 +15521,11 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 		}
 	      bfd_put_32 (input_bfd, insn1,
 			  contents + rel->r_offset - d_offset);
-	      if (offset != (bfd_vma) -1)
+	      if (offset != (bfd_vma) -1
+		  && offset_in_range (input_section, offset, 4))
 		{
 		  bfd_put_32 (input_bfd, insn2, contents + offset);
-		  if (offset + 8 <= input_section->size)
+		  if (offset_in_range (input_section, offset + 4, 4))
 		    {
 		      insn2 = bfd_get_32 (input_bfd, contents + offset + 4);
 		      if (insn2 == LD_R2_0R1 + STK_TOC (htab))
@@ -15509,7 +15543,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	  break;
 
 	case R_PPC64_GOT_TLSGD_PCREL34:
-	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0)
+	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0
+	      && offset_in_range (input_section, rel->r_offset, 8))
 	    {
 	      pinsn = bfd_get_32 (input_bfd, contents + rel->r_offset);
 	      pinsn <<= 32;
@@ -15535,7 +15570,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	  break;
 
 	case R_PPC64_GOT_TLSLD_PCREL34:
-	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0)
+	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0
+	      && offset_in_range (input_section, rel->r_offset, 8))
 	    {
 	      pinsn = bfd_get_32 (input_bfd, contents + rel->r_offset);
 	      pinsn <<= 32;
@@ -15555,7 +15591,10 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 
 	case R_PPC64_TLSGD:
 	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0
-	      && rel + 1 < relend)
+	      && rel + 1 < relend
+	      && offset_in_range (input_section, rel->r_offset,
+				  is_8byte_reloc (ELF64_R_TYPE (rel[1].r_info))
+				  ? 8 : 4))
 	    {
 	      unsigned int insn2;
 	      enum elf_ppc64_reloc_type r_type1 = ELF64_R_TYPE (rel[1].r_info);
@@ -15571,7 +15610,7 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 		  break;
 		}
 
-	      if (ELF64_R_TYPE (rel[1].r_info) == R_PPC64_PLTCALL)
+	      if (r_type1 == R_PPC64_PLTCALL)
 		bfd_put_32 (output_bfd, NOP, contents + offset + 4);
 
 	      if ((tls_mask & TLS_GDIE) != 0)
@@ -15615,7 +15654,10 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 
 	case R_PPC64_TLSLD:
 	  if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0
-	      && rel + 1 < relend)
+	      && rel + 1 < relend
+	      && offset_in_range (input_section, rel->r_offset,
+				  is_8byte_reloc (ELF64_R_TYPE (rel[1].r_info))
+				  ? 8 : 4))
 	    {
 	      unsigned int insn2;
 	      enum elf_ppc64_reloc_type r_type1 = ELF64_R_TYPE (rel[1].r_info);
@@ -15631,7 +15673,7 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 		  break;
 		}
 
-	      if (ELF64_R_TYPE (rel[1].r_info) == R_PPC64_PLTCALL)
+	      if (r_type1 == R_PPC64_PLTCALL)
 		bfd_put_32 (output_bfd, NOP, contents + offset + 4);
 
 	      if (r_type1 == R_PPC64_REL24_NOTOC
@@ -15663,7 +15705,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	      && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64)
 	      && rel[1].r_offset == rel->r_offset + 8)
 	    {
-	      if ((tls_mask & TLS_GD) == 0)
+	      if ((tls_mask & TLS_GD) == 0
+		  && offset_in_range (input_section, rel->r_offset, 8))
 		{
 		  rel[1].r_info = ELF64_R_INFO (r_symndx, R_PPC64_NONE);
 		  if ((tls_mask & TLS_GDIE) != 0)
@@ -15678,7 +15721,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	    }
 	  else
 	    {
-	      if ((tls_mask & TLS_LD) == 0)
+	      if ((tls_mask & TLS_LD) == 0
+		  && offset_in_range (input_section, rel->r_offset, 8))
 		{
 		  bfd_put_64 (output_bfd, 1, contents + rel->r_offset);
 		  r_type = R_PPC64_NONE;
@@ -15699,7 +15743,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	  relocation = TOCstart + htab->sec_info[input_section->id].toc_off;
 	  if (!bfd_link_pic (info)
 	      && !info->traditional_format
-	      && relocation + 0x80008000 <= 0xffffffff)
+	      && relocation + 0x80008000 <= 0xffffffff
+	      && offset_in_range (input_section, rel->r_offset, 8))
 	    {
 	      unsigned int insn1, insn2;
 
@@ -15721,7 +15766,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	      relocation -= (rel->r_offset
 			     + input_section->output_offset
 			     + input_section->output_section->vma);
-	      if (relocation + 0x80008000 <= 0xffffffff)
+	      if (relocation + 0x80008000 <= 0xffffffff
+		  && offset_in_range (input_section, rel->r_offset, 8))
 		{
 		  unsigned int insn1, insn2;
 
@@ -15758,7 +15804,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	      && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_REL16_LO)
 	      && rel[1].r_offset == rel->r_offset + 4
 	      && rel[1].r_addend == rel->r_addend + 4
-	      && relocation + 0x80008000 <= 0xffffffff)
+	      && relocation + 0x80008000 <= 0xffffffff
+	      && offset_in_range (input_section, rel->r_offset - d_offset, 8))
 	    {
 	      unsigned int insn1, insn2;
 	      offset = rel->r_offset - d_offset;
@@ -15793,7 +15840,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 				      + input_section->output_offset
 				      + input_section->output_section->vma)
 	      && tocsave_find (htab, NO_INSERT,
-			       &local_syms, rel, input_bfd))
+			       &local_syms, rel, input_bfd)
+	      && offset_in_range (input_section, rel->r_offset, 4))
 	    {
 	      insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
 	      if (insn == NOP
@@ -15813,6 +15861,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	  /* Branch not taken prediction relocations.  */
 	case R_PPC64_ADDR14_BRNTAKEN:
 	case R_PPC64_REL14_BRNTAKEN:
+	  if (!offset_in_range (input_section, rel->r_offset, 4))
+	    break;
 	  insn |= bfd_get_32 (input_bfd,
 			      contents + rel->r_offset) & ~(0x01 << 21);
 	  /* Fall through.  */
@@ -15873,7 +15923,7 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	      /* All of these stubs may modify r2, so there must be a
 		 branch and link followed by a nop.  The nop is
 		 replaced by an insn to restore r2.  */
-	      else if (rel->r_offset + 8 <= input_section->size)
+	      else if (offset_in_range (input_section, rel->r_offset, 8))
 		{
 		  unsigned long br;
 
@@ -16111,7 +16161,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 		   && (r_type == R_PPC64_REL24
 		       || r_type == R_PPC64_REL24_NOTOC)
 		   && relocation == 0
-		   && addend == 0)
+		   && addend == 0
+		   && offset_in_range (input_section, rel->r_offset, 4))
 	    {
 	      bfd_put_32 (input_bfd, NOP, contents + rel->r_offset);
 	      goto copy_reloc;
@@ -16127,7 +16178,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	      && sec != NULL
 	      && sec->output_section != NULL
 	      && !discarded_section (sec)
-	      && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, &h->elf)))
+	      && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, &h->elf))
+	      && offset_in_range (input_section, rel->r_offset & ~3, 4))
 	    {
 	      insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
 	      if ((insn & (0x3fu << 26 | 0x3)) == 58u << 26 /* ld */)
@@ -16150,7 +16202,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	      && sec != NULL
 	      && sec->output_section != NULL
 	      && !discarded_section (sec)
-	      && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, &h->elf)))
+	      && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, &h->elf))
+	      && offset_in_range (input_section, rel->r_offset & ~3, 4))
 	    {
 	      insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
 	      if (r_type == R_PPC64_GOT16_LO_DS
@@ -16181,7 +16234,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 		&& sec != NULL
 		&& sec->output_section != NULL
 		&& !discarded_section (sec)
-		&& (h == NULL || SYMBOL_REFERENCES_LOCAL (info, &h->elf))))
+		&& (h == NULL || SYMBOL_REFERENCES_LOCAL (info, &h->elf))
+		&& offset_in_range (input_section, rel->r_offset, 8)))
 	    break;
 
 	  offset = rel->r_offset;
@@ -16205,7 +16259,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	      && rel + 1 < relend
 	      && rel[1].r_offset == rel->r_offset
 	      && rel[1].r_info == ELF64_R_INFO (0, R_PPC64_PCREL_OPT)
-	      && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, &h->elf)))
+	      && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, &h->elf))
+	      && offset_in_range (input_section, rel->r_offset, 8))
 	    {
 	      offset = rel->r_offset;
 	      pinsn = bfd_get_32 (input_bfd, contents + offset);
@@ -16220,7 +16275,7 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 		    /* zero means next insn.  */
 		    off2 = 8;
 		  off2 += offset;
-		  if (off2 + 4 <= input_section->size)
+		  if (offset_in_range (input_section, off2, 4))
 		    {
 		      uint64_t pinsn2;
 		      bfd_signed_vma addend_off;
@@ -16228,7 +16283,7 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 		      pinsn2 <<= 32;
 		      if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
 			{
-			  if (off2 + 8 > input_section->size)
+			  if (!offset_in_range (input_section, off2, 8))
 			    break;
 			  pinsn2 |= bfd_get_32 (input_bfd,
 						contents + off2 + 4);
@@ -16659,7 +16714,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	case R_PPC64_TPREL16_HIGHESTA:
 	  if (h != NULL
 	      && h->elf.root.type == bfd_link_hash_undefweak
-	      && h->elf.dynindx == -1)
+	      && h->elf.dynindx == -1
+	      && offset_in_range (input_section, rel->r_offset - d_offset, 4))
 	    {
 	      /* Make this relocation against an undefined weak symbol
 		 resolve to zero.  This is really just a tweak, since
@@ -17041,7 +17097,9 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	    htab->notoc_plt = 1;
 	  /* Fall through.  */
 	case R_PPC64_PLTCALL:
-	  if (unresolved_reloc)
+	  if (unresolved_reloc
+	      && offset_in_range (input_section, rel->r_offset,
+				  r_type == R_PPC64_PLTCALL ? 8 : 4))
 	    {
 	      /* No plt entry.  Make this into a direct call.  */
 	      bfd_byte *p = contents + rel->r_offset;
@@ -17069,7 +17127,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	    htab->notoc_plt = 1;
 	  /* Fall through.  */
 	case R_PPC64_PLT_PCREL34:
-	  if (unresolved_reloc)
+	  if (unresolved_reloc
+	      && offset_in_range (input_section, rel->r_offset, 8))
 	    {
 	      bfd_byte *p = contents + rel->r_offset;
 	      bfd_put_32 (input_bfd, PNOP >> 32, p);
@@ -17097,9 +17156,12 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	    {
 	      bfd_byte *p;
 	    nop_it:
-	      p = contents + (rel->r_offset & ~3);
-	      bfd_put_32 (input_bfd, NOP, p);
-	      goto copy_reloc;
+	      if (offset_in_range (input_section, rel->r_offset & ~3, 4))
+		{
+		  p = contents + (rel->r_offset & ~3);
+		  bfd_put_32 (input_bfd, NOP, p);
+		  goto copy_reloc;
+		}
 	    }
 	  break;
 
@@ -17120,7 +17182,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	case R_PPC64_TOC16_LO:
 	case R_PPC64_TOC16_LO_DS:
 	  if (htab->do_toc_opt && relocation + addend + 0x8000 < 0x10000
-	      && !ppc64_elf_tdata (input_bfd)->unexpected_toc_insn)
+	      && !ppc64_elf_tdata (input_bfd)->unexpected_toc_insn
+	      && offset_in_range (input_section, rel->r_offset & ~3, 4))
 	    {
 	      bfd_byte *p = contents + (rel->r_offset & ~3);
 	      insn = bfd_get_32 (input_bfd, p);
@@ -17140,7 +17203,9 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	  break;
 
 	case R_PPC64_TPREL16_HA:
-	  if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+	  if (htab->do_tls_opt
+	      && relocation + addend + 0x8000 < 0x10000
+	      && offset_in_range (input_section, rel->r_offset & ~3, 4))
 	    {
 	      bfd_byte *p = contents + (rel->r_offset & ~3);
 	      bfd_put_32 (input_bfd, NOP, p);
@@ -17150,7 +17215,9 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 
 	case R_PPC64_TPREL16_LO:
 	case R_PPC64_TPREL16_LO_DS:
-	  if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+	  if (htab->do_tls_opt
+	      && relocation + addend + 0x8000 < 0x10000
+	      && offset_in_range (input_section, rel->r_offset & ~3, 4))
 	    {
 	      bfd_byte *p = contents + (rel->r_offset & ~3);
 	      insn = bfd_get_32 (input_bfd, p);
@@ -17234,6 +17301,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	case R_PPC64_TPREL16_LO_DS:
 	case R_PPC64_DTPREL16_DS:
 	case R_PPC64_DTPREL16_LO_DS:
+	  if (!offset_in_range (input_section, rel->r_offset & ~3, 4))
+	    break;
 	  insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
 	  mask = 3;
 	  /* If this reloc is against an lq, lxv, or stxv insn, then
@@ -17287,7 +17356,8 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	 have different reloc types.  */
       if (howto->complain_on_overflow != complain_overflow_dont
 	  && howto->dst_mask == 0xffff
-	  && (input_section->flags & SEC_CODE) != 0)
+	  && (input_section->flags & SEC_CODE) != 0
+	  && offset_in_range (input_section, rel->r_offset & ~3, 4))
 	{
 	  enum complain_overflow complain = complain_overflow_signed;
 
@@ -17329,7 +17399,7 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	case R_PPC64_PLT_PCREL34_NOTOC:
 	case R_PPC64_D28:
 	case R_PPC64_PCREL28:
-	  if (rel->r_offset + 8 > input_section->size)
+	  if (!offset_in_range (input_section, rel->r_offset, 8))
 	    r = bfd_reloc_outofrange;
 	  else
 	    {
@@ -17358,7 +17428,7 @@  ppc64_elf_relocate_section (bfd *output_bfd,
 	  break;
 
 	case R_PPC64_REL16DX_HA:
-	  if (rel->r_offset + 4 > input_section->size)
+	  if (!offset_in_range (input_section, rel->r_offset, 4))
 	    r = bfd_reloc_outofrange;
 	  else
 	    {