PR30657, gprof heap buffer overflow

PR 30657
	* cg_arcs.c (cg_assemble): Sanity check find_call addresses.
	* i386.c (i386_find_call): Don't access past end of core_text_space.
	* aarch64.c (aarch64_find_call): Round up lowpc, round down highpc.
	* alpha.c (alpha_find_call): Likewise.
	* mips.c (mips_find_call): Likewise.
	* sparc.c (sparc_find_call): Likewise.
	* vax.c (vax_find_call): Sanity check core_text_space accesses.
This commit is contained in:
Alan Modra
2023-07-26 09:54:03 +09:30
parent eb14a8b4bf
commit 477c9f2ba2
7 changed files with 37 additions and 10 deletions

View File

@@ -54,7 +54,8 @@ aarch64_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
DBG (CALLDEBUG, printf ("[find_call] %s: 0x%lx to 0x%lx\n", DBG (CALLDEBUG, printf ("[find_call] %s: 0x%lx to 0x%lx\n",
parent->name, (unsigned long) p_lowpc, parent->name, (unsigned long) p_lowpc,
(unsigned long) p_highpc)); (unsigned long) p_highpc));
p_lowpc = (p_lowpc + 3) & ~3;
p_highpc &= ~3;
for (pc = p_lowpc; pc < p_highpc; pc += 4) for (pc = p_lowpc; pc < p_highpc; pc += 4)
{ {

View File

@@ -107,7 +107,9 @@ alpha_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"), DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"),
parent->name, (unsigned long) p_lowpc, parent->name, (unsigned long) p_lowpc,
(unsigned long) p_highpc)); (unsigned long) p_highpc));
for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4) p_lowpc = (p_lowpc + 3) & ~3;
p_highpc &= ~3;
for (pc = p_lowpc; pc < p_highpc; pc += 4)
{ {
insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space
+ pc - core_text_sect->vma)); + pc - core_text_sect->vma));

View File

@@ -37,6 +37,7 @@
#include "cg_print.h" #include "cg_print.h"
#include "utils.h" #include "utils.h"
#include "sym_ids.h" #include "sym_ids.h"
#include "corefile.h"
static int cmp_topo (const void *, const void *); static int cmp_topo (const void *, const void *);
static void propagate_time (Sym *); static void propagate_time (Sym *);
@@ -622,7 +623,11 @@ cg_assemble (void)
parent->cg.cyc.num = 0; parent->cg.cyc.num = 0;
parent->cg.cyc.head = parent; parent->cg.cyc.head = parent;
parent->cg.cyc.next = 0; parent->cg.cyc.next = 0;
if (ignore_direct_calls) if (ignore_direct_calls
&& parent->addr >= core_text_sect->vma
&& parent->addr < core_text_sect->vma + core_text_sect->size
&& (parent + 1)->addr >= core_text_sect->vma
&& (parent + 1)->addr <= core_text_sect->vma + core_text_sect->size)
find_call (parent, parent->addr, (parent + 1)->addr); find_call (parent, parent->addr, (parent + 1)->addr);
} }

View File

@@ -57,6 +57,9 @@ i386_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
parent->name, (unsigned long) p_lowpc, parent->name, (unsigned long) p_lowpc,
(unsigned long) p_highpc)); (unsigned long) p_highpc));
if (p_highpc < 5)
return;
p_highpc -= 5;
for (pc = p_lowpc; pc < p_highpc; ++pc) for (pc = p_lowpc; pc < p_highpc; ++pc)
{ {
instructp = (unsigned char *) core_text_space + pc - core_text_sect->vma; instructp = (unsigned char *) core_text_space + pc - core_text_sect->vma;

View File

@@ -59,6 +59,8 @@ mips_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"), DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"),
parent->name, (unsigned long) p_lowpc, parent->name, (unsigned long) p_lowpc,
(unsigned long) p_highpc)); (unsigned long) p_highpc));
p_lowpc = (p_lowpc + 3) & ~3;
p_highpc &= ~3;
for (pc = p_lowpc; pc < p_highpc; pc += 4) for (pc = p_lowpc; pc < p_highpc; pc += 4)
{ {
op = bfd_get_32 (core_bfd, ((unsigned char *)core_text_space op = bfd_get_32 (core_bfd, ((unsigned char *)core_text_space

View File

@@ -51,7 +51,9 @@ sparc_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
DBG (CALLDEBUG, printf ("[find_call] %s: 0x%lx to 0x%lx\n", DBG (CALLDEBUG, printf ("[find_call] %s: 0x%lx to 0x%lx\n",
parent->name, (unsigned long) p_lowpc, parent->name, (unsigned long) p_lowpc,
(unsigned long) p_highpc)); (unsigned long) p_highpc));
for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4) p_lowpc = (p_lowpc + 3) & ~3;
p_highpc &= ~3;
for (pc = p_lowpc; pc < p_highpc; pc += 4)
{ {
insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space
+ pc - core_text_sect->vma)); + pc - core_text_sect->vma));

View File

@@ -252,6 +252,8 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
(unsigned long) p_highpc)); (unsigned long) p_highpc));
for (pc = p_lowpc; pc < p_highpc; pc += length) for (pc = p_lowpc; pc < p_highpc; pc += length)
{ {
unsigned char *operand;
length = 1; length = 1;
instructp = ((unsigned char *) core_text_space instructp = ((unsigned char *) core_text_space
+ pc - core_text_sect->vma); + pc - core_text_sect->vma);
@@ -263,7 +265,10 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
*/ */
DBG (CALLDEBUG, DBG (CALLDEBUG,
printf ("[findcall]\t0x%lx:calls", (unsigned long) pc)); printf ("[findcall]\t0x%lx:calls", (unsigned long) pc));
firstmode = vax_operandmode (instructp + length); if (pc - core_text_sect->vma + length >= core_text_sect->size)
goto botched;
operand = instructp + length;
firstmode = vax_operandmode (operand);
switch (firstmode) switch (firstmode)
{ {
case literal: case literal:
@@ -272,8 +277,11 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
default: default:
goto botched; goto botched;
} }
length += vax_operandlength (instructp + length); length += vax_operandlength (operand);
mode = vax_operandmode (instructp + length); if (pc - core_text_sect->vma + length >= core_text_sect->size)
goto botched;
operand = instructp + length;
mode = vax_operandmode (operand);
DBG (CALLDEBUG, DBG (CALLDEBUG,
printf ("\tfirst operand is %s", vax_operandname (firstmode)); printf ("\tfirst operand is %s", vax_operandname (firstmode));
printf ("\tsecond operand is %s\n", vax_operandname (mode))); printf ("\tsecond operand is %s\n", vax_operandname (mode)));
@@ -294,8 +302,10 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
* [are there others that we miss?, * [are there others that we miss?,
* e.g. arrays of pointers to functions???] * e.g. arrays of pointers to functions???]
*/ */
length += vax_operandlength (operand);
if (pc - core_text_sect->vma + length > core_text_sect->size)
goto botched;
arc_add (parent, &indirectchild, (unsigned long) 0); arc_add (parent, &indirectchild, (unsigned long) 0);
length += vax_operandlength (instructp + length);
continue; continue;
case byterel: case byterel:
case wordrel: case wordrel:
@@ -305,7 +315,10 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
* check that this is the address of * check that this is the address of
* a function. * a function.
*/ */
destpc = pc + vax_offset (instructp + length); length += vax_operandlength (operand);
if (pc - core_text_sect->vma + length > core_text_sect->size)
goto botched;
destpc = pc + vax_offset (operand);
if (hist_check_address (destpc)) if (hist_check_address (destpc))
{ {
child = sym_lookup (&symtab, destpc); child = sym_lookup (&symtab, destpc);
@@ -324,7 +337,6 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
* a hit * a hit
*/ */
arc_add (parent, child, (unsigned long) 0); arc_add (parent, child, (unsigned long) 0);
length += vax_operandlength (instructp + length);
continue; continue;
} }
} }