lkml.org 
[lkml]   [2018]   [Nov]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 2/2] objtool: Fix seg fault in .cold detection with -ffunction-sections
    Date
    From: Artem Savkov <asavkov@redhat.com>

    Because find_symbol_by_name() traverses the same lists as
    read_symbols(), changing sym->name in place without copying it affects
    the result of find_symbol_by_name(). In the case where a ".cold"
    function precedes its parent in sec->symbol_list, it can result in a
    function being considered a parent of itself. This leads to function
    length being set to 0 and other consequent side-effects including a
    segfault in add_switch_table(). The effects of this bug are only
    visible when building with -ffunction-sections in KCFLAGS.

    Fix by copying the search string instead of modifying it in place.

    Fixes: 13810435b9a7 ("objtool: Support GCC 8's cold subfunctions")
    Signed-off-by: Artem Savkov <asavkov@redhat.com>
    Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
    ---
    tools/objtool/elf.c | 17 ++++++++++++++---
    1 file changed, 14 insertions(+), 3 deletions(-)

    diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
    index e7a7ac40e045..b8f3cca8e58b 100644
    --- a/tools/objtool/elf.c
    +++ b/tools/objtool/elf.c
    @@ -31,6 +31,8 @@
    #include "elf.h"
    #include "warn.h"

    +#define MAX_NAME_LEN 128
    +
    struct section *find_section_by_name(struct elf *elf, const char *name)
    {
    struct section *sec;
    @@ -298,6 +300,8 @@ static int read_symbols(struct elf *elf)
    /* Create parent/child links for any cold subfunctions */
    list_for_each_entry(sec, &elf->sections, list) {
    list_for_each_entry(sym, &sec->symbol_list, list) {
    + char pname[MAX_NAME_LEN + 1];
    + size_t pnamelen;
    if (sym->type != STT_FUNC)
    continue;
    sym->pfunc = sym->cfunc = sym;
    @@ -305,9 +309,16 @@ static int read_symbols(struct elf *elf)
    if (!coldstr)
    continue;

    - coldstr[0] = '\0';
    - pfunc = find_symbol_by_name(elf, sym->name);
    - coldstr[0] = '.';
    + pnamelen = coldstr - sym->name;
    + if (pnamelen > MAX_NAME_LEN) {
    + WARN("%s(): parent function name exceeds maximum length of %d characters",
    + sym->name, MAX_NAME_LEN);
    + return -1;
    + }
    +
    + strncpy(pname, sym->name, pnamelen);
    + pname[pnamelen] = '\0';
    + pfunc = find_symbol_by_name(elf, pname);

    if (!pfunc) {
    WARN("%s(): can't find parent function",
    --
    2.17.2
    \
     
     \ /
      Last update: 2018-11-20 18:54    [W:5.409 / U:0.136 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site