Skip to content

Commit 066c738

Browse files
committed
ppc: sanity check writing relocs
Check for output buffer overruns. * elf32-ppc.c (swap_reloc_out, count_and_swap_reloc_out): New functions. Use throughout file. * elf64-ppc.c (swap_reloc_out, count_and_swap_reloc_out): Likewise.
1 parent ae33771 commit 066c738

File tree

2 files changed

+72
-61
lines changed

2 files changed

+72
-61
lines changed

bfd/elf32-ppc.c

+37-26
Original file line numberDiff line numberDiff line change
@@ -6935,6 +6935,23 @@ is_insn_dq_form (unsigned int insn)
69356935
&& (insn & 3) == 1));
69366936
}
69376937

6938+
static bool
6939+
swap_reloc_out (bfd *obfd, Elf_Internal_Rela *rel, bfd_byte *loc, asection *s)
6940+
{
6941+
if ((size_t) (loc - s->contents) >= s->size)
6942+
return false;
6943+
bfd_elf32_swap_reloca_out (obfd, rel, loc);
6944+
return true;
6945+
}
6946+
6947+
static bool
6948+
count_and_swap_reloc_out (bfd *obfd, Elf_Internal_Rela *rel, asection *s)
6949+
{
6950+
bfd_byte *loc = s->contents;
6951+
loc += s->reloc_count++ * sizeof (Elf32_External_Rela);
6952+
return swap_reloc_out (obfd, rel, loc, s);
6953+
}
6954+
69386955
/* The RELOCATE_SECTION function is called by the ELF backend linker
69396956
to handle the relocations for a section.
69406957
@@ -7806,7 +7823,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
78067823
: sym->st_shndx != SHN_ABS)))
78077824
{
78087825
asection *rsec = htab->elf.srelgot;
7809-
bfd_byte * loc;
78107826

78117827
if (ifunc != NULL)
78127828
{
@@ -7825,11 +7841,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
78257841
outrel.r_info = ELF32_R_INFO (indx, R_PPC_DTPMOD32);
78267842
if (tls_ty == (TLS_TLS | TLS_GD))
78277843
{
7828-
loc = rsec->contents;
7829-
loc += (rsec->reloc_count++
7830-
* sizeof (Elf32_External_Rela));
7831-
bfd_elf32_swap_reloca_out (output_bfd,
7832-
&outrel, loc);
7844+
BFD_ASSERT (count_and_swap_reloc_out (output_bfd,
7845+
&outrel,
7846+
rsec));
78337847
outrel.r_offset += 4;
78347848
outrel.r_info
78357849
= ELF32_R_INFO (indx, R_PPC_DTPREL32);
@@ -7856,10 +7870,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
78567870
outrel.r_addend -= htab->elf.tls_sec->vma;
78577871
}
78587872
}
7859-
loc = rsec->contents;
7860-
loc += (rsec->reloc_count++
7861-
* sizeof (Elf32_External_Rela));
7862-
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
7873+
BFD_ASSERT (count_and_swap_reloc_out (output_bfd,
7874+
&outrel, rsec));
78637875
}
78647876

78657877
/* Init the .got section contents if we're not
@@ -8089,7 +8101,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
80898101
&& h->dyn_relocs != NULL))
80908102
{
80918103
int skip;
8092-
bfd_byte *loc;
80938104
asection *sreloc;
80948105
long indx = 0;
80958106

@@ -8221,9 +8232,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
82218232
if (sreloc == NULL)
82228233
return false;
82238234

8224-
loc = sreloc->contents;
8225-
loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
8226-
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
8235+
BFD_ASSERT (count_and_swap_reloc_out (output_bfd, &outrel,
8236+
sreloc));
82278237

82288238
if (skip == -1)
82298239
goto copy_reloc;
@@ -9573,7 +9583,8 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
95739583
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
95749584
R_PPC_ADDR16_HA);
95759585
rela.r_addend = got_offset;
9576-
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
9586+
BFD_ASSERT (swap_reloc_out (info->output_bfd, &rela, loc,
9587+
htab->srelplt2));
95779588
loc += sizeof (Elf32_External_Rela);
95789589

95799590
/* Provide the @l relocation for the second instruction. */
@@ -9583,7 +9594,8 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
95839594
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
95849595
R_PPC_ADDR16_LO);
95859596
rela.r_addend = got_offset;
9586-
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
9597+
BFD_ASSERT (swap_reloc_out (info->output_bfd, &rela, loc,
9598+
htab->srelplt2));
95879599
loc += sizeof (Elf32_External_Rela);
95889600

95899601
/* Provide a relocation for the GOT entry corresponding to this
@@ -9594,7 +9606,8 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
95949606
rela.r_info = ELF32_R_INFO (htab->elf.hplt->indx,
95959607
R_PPC_ADDR32);
95969608
rela.r_addend = ent->plt.offset + 16;
9597-
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
9609+
BFD_ASSERT (swap_reloc_out (info->output_bfd, &rela, loc,
9610+
htab->srelplt2));
95989611
}
95999612

96009613
/* VxWorks uses non-standard semantics for R_PPC_JMP_SLOT.
@@ -9676,7 +9689,8 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
96769689
if (h->type == STT_GNU_IFUNC && is_static_defined (h))
96779690
htab->maybe_local_ifunc_resolver = 1;
96789691
}
9679-
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
9692+
BFD_ASSERT (swap_reloc_out (info->output_bfd, &rela,
9693+
loc, relplt));
96809694
}
96819695
doneone = true;
96829696
}
@@ -9793,9 +9807,8 @@ ppc_finish_symbols (struct bfd_link_info *info)
97939807
+ plt->output_offset
97949808
+ plt->output_section->vma);
97959809
rela.r_addend = val;
9796-
loc = relplt->contents + (relplt->reloc_count++
9797-
* sizeof (Elf32_External_Rela));
9798-
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
9810+
BFD_ASSERT (count_and_swap_reloc_out (info->output_bfd, &rela,
9811+
relplt));
97999812

98009813
p = (unsigned char *) htab->glink->contents + ent->glink_offset;
98019814
write_glink_stub (NULL, ent, htab->elf.iplt, p, info);
@@ -9879,7 +9892,6 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
98799892
{
98809893
asection *s;
98819894
Elf_Internal_Rela rela;
9882-
bfd_byte *loc;
98839895

98849896
/* This symbols needs a copy reloc. Set it up. */
98859897

@@ -9900,8 +9912,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
99009912
rela.r_offset = SYM_VAL (h);
99019913
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY);
99029914
rela.r_addend = 0;
9903-
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
9904-
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
9915+
BFD_ASSERT (count_and_swap_reloc_out (output_bfd, &rela, s));
99059916
}
99069917

99079918
#ifdef DEBUG
@@ -10105,7 +10116,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
1010510116
+ 2);
1010610117
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_HA);
1010710118
rela.r_addend = 0;
10108-
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
10119+
BFD_ASSERT (swap_reloc_out (output_bfd, &rela, loc, htab->srelplt2));
1010910120
loc += sizeof (Elf32_External_Rela);
1011010121

1011110122
/* Output the @l relocation for the second instruction. */
@@ -10114,7 +10125,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
1011410125
+ 6);
1011510126
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_LO);
1011610127
rela.r_addend = 0;
10117-
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
10128+
BFD_ASSERT (swap_reloc_out (output_bfd, &rela, loc, htab->srelplt2));
1011810129
loc += sizeof (Elf32_External_Rela);
1011910130

1012010131
/* Fix up the remaining relocations. They may have the wrong

bfd/elf64-ppc.c

+35-35
Original file line numberDiff line numberDiff line change
@@ -11569,6 +11569,24 @@ get_relocs (asection *sec, int count)
1156911569
return relocs;
1157011570
}
1157111571

11572+
static bool
11573+
swap_reloc_out (bfd *obfd, Elf_Internal_Rela *rel, bfd_byte *loc, asection *s)
11574+
{
11575+
if ((size_t) (loc - s->contents) >= s->size)
11576+
return false;
11577+
bfd_elf64_swap_reloca_out (obfd, rel, loc);
11578+
return true;
11579+
}
11580+
11581+
static bool
11582+
count_and_swap_reloc_out (bfd *obfd, Elf_Internal_Rela *rel, asection *s)
11583+
{
11584+
bfd_byte *loc = s->contents;
11585+
loc += s->reloc_count++ * sizeof (Elf64_External_Rela);
11586+
return swap_reloc_out (obfd, rel, loc, s);
11587+
}
11588+
11589+
1157211590
/* Convert the relocs R[0] thru R[-NUM_REL+1], which are all no-symbol
1157311591
forms, to the equivalent relocs against the global symbol given by
1157411592
STUB_ENTRY->H. */
@@ -11847,18 +11865,15 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
1184711865
{
1184811866
/* Create a reloc for the branch lookup table entry. */
1184911867
Elf_Internal_Rela rela;
11850-
bfd_byte *rl;
1185111868

1185211869
rela.r_offset = (br_entry->offset
1185311870
+ htab->brlt->output_offset
1185411871
+ htab->brlt->output_section->vma);
1185511872
rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
1185611873
rela.r_addend = targ;
1185711874

11858-
rl = htab->relbrlt->contents;
11859-
rl += (htab->relbrlt->reloc_count++
11860-
* sizeof (Elf64_External_Rela));
11861-
bfd_elf64_swap_reloca_out (htab->relbrlt->owner, &rela, rl);
11875+
BFD_ASSERT (count_and_swap_reloc_out (htab->relbrlt->owner, &rela,
11876+
htab->relbrlt));
1186211877
}
1186311878
else if (info->emitrelocations)
1186411879
{
@@ -14652,9 +14667,8 @@ build_global_entry_stubs_and_plt (struct elf_link_hash_entry *h, void *inf)
1465214667
rela.r_offset = (plt->output_section->vma
1465314668
+ plt->output_offset
1465414669
+ ent->plt.offset);
14655-
loc = relplt->contents + (relplt->reloc_count++
14656-
* sizeof (Elf64_External_Rela));
14657-
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
14670+
BFD_ASSERT (count_and_swap_reloc_out (info->output_bfd, &rela,
14671+
relplt));
1465814672
}
1465914673
}
1466014674
else
@@ -14669,7 +14683,8 @@ build_global_entry_stubs_and_plt (struct elf_link_hash_entry *h, void *inf)
1466914683
/ PLT_ENTRY_SIZE (htab) * sizeof (Elf64_External_Rela)));
1467014684
if (h->type == STT_GNU_IFUNC && is_static_defined (h))
1467114685
htab->elf.ifunc_resolvers = true;
14672-
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
14686+
BFD_ASSERT (swap_reloc_out (info->output_bfd, &rela,
14687+
loc, htab->elf.srelplt));
1467314688
}
1467414689
}
1467514690

@@ -14790,7 +14805,6 @@ write_plt_relocs_for_local_syms (struct bfd_link_info *info)
1479014805
Elf_Internal_Sym *sym;
1479114806
asection *sym_sec;
1479214807
asection *plt, *relplt;
14793-
bfd_byte *loc;
1479414808
bfd_vma val;
1479514809

1479614810
if (!get_sym_h (NULL, &sym, &sym_sec, NULL, &local_syms,
@@ -14822,7 +14836,7 @@ write_plt_relocs_for_local_syms (struct bfd_link_info *info)
1482214836

1482314837
if (relplt == NULL)
1482414838
{
14825-
loc = plt->contents + ent->plt.offset;
14839+
bfd_byte *loc = plt->contents + ent->plt.offset;
1482614840
bfd_put_64 (info->output_bfd, val, loc);
1482714841
if (htab->opd_abi)
1482814842
{
@@ -14851,9 +14865,8 @@ write_plt_relocs_for_local_syms (struct bfd_link_info *info)
1485114865
rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
1485214866
}
1485314867
rela.r_addend = val;
14854-
loc = relplt->contents + (relplt->reloc_count++
14855-
* sizeof (Elf64_External_Rela));
14856-
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
14868+
BFD_ASSERT (count_and_swap_reloc_out (info->output_bfd,
14869+
&rela, relplt));
1485714870
}
1485814871
}
1485914872

@@ -16991,11 +17004,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
1699117004
outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPMOD64);
1699217005
if (tls_type == (TLS_TLS | TLS_GD))
1699317006
{
16994-
loc = relgot->contents;
16995-
loc += (relgot->reloc_count++
16996-
* sizeof (Elf64_External_Rela));
16997-
bfd_elf64_swap_reloca_out (output_bfd,
16998-
&outrel, loc);
17007+
BFD_ASSERT (count_and_swap_reloc_out (output_bfd,
17008+
&outrel,
17009+
relgot));
1699917010
outrel.r_offset += 8;
1700017011
outrel.r_addend = orig_rel.r_addend;
1700117012
outrel.r_info
@@ -17035,12 +17046,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
1703517046
}
1703617047
if (!(info->enable_dt_relr
1703717048
&& ELF64_R_TYPE (outrel.r_info) == R_PPC64_RELATIVE))
17038-
{
17039-
loc = relgot->contents;
17040-
loc += (relgot->reloc_count++
17041-
* sizeof (Elf64_External_Rela));
17042-
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
17043-
}
17049+
BFD_ASSERT (count_and_swap_reloc_out (output_bfd,
17050+
&outrel, relgot));
1704417051
}
1704517052

1704617053
/* Init the .got section contents here if we're not
@@ -17526,12 +17533,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
1752617533
if (sreloc == NULL)
1752717534
abort ();
1752817535

17529-
if (sreloc->reloc_count * sizeof (Elf64_External_Rela)
17530-
>= sreloc->size)
17531-
abort ();
17532-
loc = sreloc->contents;
17533-
loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
17534-
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
17536+
BFD_ASSERT (count_and_swap_reloc_out (output_bfd, &outrel,
17537+
sreloc));
1753517538
}
1753617539

1753717540
if (!warned_dynamic
@@ -18164,7 +18167,6 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
1816418167
/* This symbol needs a copy reloc. Set it up. */
1816518168
Elf_Internal_Rela rela;
1816618169
asection *srel;
18167-
bfd_byte *loc;
1816818170

1816918171
if (h->dynindx == -1)
1817018172
abort ();
@@ -18176,9 +18178,7 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
1817618178
srel = htab->elf.sreldynrelro;
1817718179
else
1817818180
srel = htab->elf.srelbss;
18179-
loc = srel->contents;
18180-
loc += srel->reloc_count++ * sizeof (Elf64_External_Rela);
18181-
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
18181+
BFD_ASSERT (count_and_swap_reloc_out (output_bfd, &rela, srel));
1818218182
}
1818318183

1818418184
return true;

0 commit comments

Comments
 (0)