lkml.org 
[lkml]   [2021]   [Mar]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 157/176] module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
    Date
    From: Fangrui Song <maskray@google.com>

    commit ebfac7b778fac8b0e8e92ec91d0b055f046b4604 upstream.

    clang-12 -fno-pic (since
    https://github.com/llvm/llvm-project/commit/a084c0388e2a59b9556f2de0083333232da3f1d6)
    can emit `call __stack_chk_fail@PLT` instead of `call __stack_chk_fail`
    on x86. The two forms should have identical behaviors on x86-64 but the
    former causes GNU as<2.37 to produce an unreferenced undefined symbol
    _GLOBAL_OFFSET_TABLE_.

    (On x86-32, there is an R_386_PC32 vs R_386_PLT32 difference but the
    linker behavior is identical as far as Linux kernel is concerned.)

    Simply ignore _GLOBAL_OFFSET_TABLE_ for now, like what
    scripts/mod/modpost.c:ignore_undef_symbol does. This also fixes the
    problem for gcc/clang -fpie and -fpic, which may emit `call foo@PLT` for
    external function calls on x86.

    Note: ld -z defs and dynamic loaders do not error for unreferenced
    undefined symbols so the module loader is reading too much. If we ever
    need to ignore more symbols, the code should be refactored to ignore
    unreferenced symbols.

    Cc: <stable@vger.kernel.org>
    Link: https://github.com/ClangBuiltLinux/linux/issues/1250
    Link: https://sourceware.org/bugzilla/show_bug.cgi?id=27178
    Reported-by: Marco Elver <elver@google.com>
    Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
    Reviewed-by: Nathan Chancellor <natechancellor@gmail.com>
    Tested-by: Marco Elver <elver@google.com>
    Signed-off-by: Fangrui Song <maskray@google.com>
    Signed-off-by: Jessica Yu <jeyu@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    kernel/module.c | 21 +++++++++++++++++++--
    1 file changed, 19 insertions(+), 2 deletions(-)

    --- a/kernel/module.c
    +++ b/kernel/module.c
    @@ -2247,6 +2247,21 @@ static int verify_export_symbols(struct
    return 0;
    }

    +static bool ignore_undef_symbol(Elf_Half emachine, const char *name)
    +{
    + /*
    + * On x86, PIC code and Clang non-PIC code may have call foo@PLT. GNU as
    + * before 2.37 produces an unreferenced _GLOBAL_OFFSET_TABLE_ on x86-64.
    + * i386 has a similar problem but may not deserve a fix.
    + *
    + * If we ever have to ignore many symbols, consider refactoring the code to
    + * only warn if referenced by a relocation.
    + */
    + if (emachine == EM_386 || emachine == EM_X86_64)
    + return !strcmp(name, "_GLOBAL_OFFSET_TABLE_");
    + return false;
    +}
    +
    /* Change all symbols so that st_value encodes the pointer directly. */
    static int simplify_symbols(struct module *mod, const struct load_info *info)
    {
    @@ -2292,8 +2307,10 @@ static int simplify_symbols(struct modul
    break;
    }

    - /* Ok if weak. */
    - if (!ksym && ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
    + /* Ok if weak or ignored. */
    + if (!ksym &&
    + (ELF_ST_BIND(sym[i].st_info) == STB_WEAK ||
    + ignore_undef_symbol(info->hdr->e_machine, name)))
    break;

    pr_warn("%s: Unknown symbol %s (err %li)\n",

    \
     
     \ /
      Last update: 2021-03-01 20:38    [W:4.386 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site