lkml.org 
[lkml]   [2019]   [Aug]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.2 016/135] arm64: ftrace: Ensure module ftrace trampoline is coherent with I-side
    Date
    From: Will Deacon <will@kernel.org>

    commit b6143d10d23ebb4a77af311e8b8b7f019d0163e6 upstream.

    The initial support for dynamic ftrace trampolines in modules made use
    of an indirect branch which loaded its target from the beginning of
    a special section (e71a4e1bebaf7 ("arm64: ftrace: add support for far
    branches to dynamic ftrace")). Since no instructions were being patched,
    no cache maintenance was needed. However, later in be0f272bfc83 ("arm64:
    ftrace: emit ftrace-mod.o contents through code") this code was reworked
    to output the trampoline instructions directly into the PLT entry but,
    unfortunately, the necessary cache maintenance was overlooked.

    Add a call to __flush_icache_range() after writing the new trampoline
    instructions but before patching in the branch to the trampoline.

    Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
    Cc: James Morse <james.morse@arm.com>
    Cc: <stable@vger.kernel.org>
    Fixes: be0f272bfc83 ("arm64: ftrace: emit ftrace-mod.o contents through code")
    Signed-off-by: Will Deacon <will@kernel.org>
    Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    arch/arm64/kernel/ftrace.c | 22 +++++++++++++---------
    1 file changed, 13 insertions(+), 9 deletions(-)

    diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
    index 1285c7b2947fa..1717732579742 100644
    --- a/arch/arm64/kernel/ftrace.c
    +++ b/arch/arm64/kernel/ftrace.c
    @@ -73,7 +73,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)

    if (offset < -SZ_128M || offset >= SZ_128M) {
    #ifdef CONFIG_ARM64_MODULE_PLTS
    - struct plt_entry trampoline;
    + struct plt_entry trampoline, *dst;
    struct module *mod;

    /*
    @@ -106,23 +106,27 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
    * to check if the actual opcodes are in fact identical,
    * regardless of the offset in memory so use memcmp() instead.
    */
    - trampoline = get_plt_entry(addr, mod->arch.ftrace_trampoline);
    - if (memcmp(mod->arch.ftrace_trampoline, &trampoline,
    - sizeof(trampoline))) {
    - if (plt_entry_is_initialized(mod->arch.ftrace_trampoline)) {
    + dst = mod->arch.ftrace_trampoline;
    + trampoline = get_plt_entry(addr, dst);
    + if (memcmp(dst, &trampoline, sizeof(trampoline))) {
    + if (plt_entry_is_initialized(dst)) {
    pr_err("ftrace: far branches to multiple entry points unsupported inside a single module\n");
    return -EINVAL;
    }

    /* point the trampoline to our ftrace entry point */
    module_disable_ro(mod);
    - *mod->arch.ftrace_trampoline = trampoline;
    + *dst = trampoline;
    module_enable_ro(mod, true);

    - /* update trampoline before patching in the branch */
    - smp_wmb();
    + /*
    + * Ensure updated trampoline is visible to instruction
    + * fetch before we patch in the branch.
    + */
    + __flush_icache_range((unsigned long)&dst[0],
    + (unsigned long)&dst[1]);
    }
    - addr = (unsigned long)(void *)mod->arch.ftrace_trampoline;
    + addr = (unsigned long)dst;
    #else /* CONFIG_ARM64_MODULE_PLTS */
    return -EINVAL;
    #endif /* CONFIG_ARM64_MODULE_PLTS */
    --
    2.20.1
    \
     
     \ /
      Last update: 2019-08-22 19:26    [W:5.208 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site