On Wed, Mar 17, 2021 at 01:45:57PM +0100, Peter Zijlstra wrote:
> On Wed, Mar 17, 2021 at 05:25:48PM +0530, Sumit Garg wrote:
> > Thanks Peter for this fix. It does work for me on qemu for x86. Can
> > you turn this into a proper fix patch? BTW, feel free to add:
> 
> Per the below, the original patch ought to be fixed as well, to not use
> static_call() in __exit.
> 
> ---
> Subject: objtool,static_call: Don't emit static_call_site for .exit.text
> From: Peter Zijlstra <pet...@infradead.org>
> Date: Wed Mar 17 13:35:05 CET 2021
> 
> Functions marked __exit are (somewhat surprisingly) discarded at
> runtime when built-in. This means that static_call(), when used in
> __exit functions, will generate static_call_site entries that point
> into reclaimed space.
> 
> Simply skip such sites and emit a WARN about it. By not emitting a
> static_call_site the site will remain pointed at the trampoline, which
> is also maintained, so things will work as expected, albeit with the
> extra indirection.
> 
> The WARN is so that people are aware of this; and arguably it simply
> isn't a good idea to use static_call() in __exit code anyway, since
> module unload is never a performance critical path.
> 
> Reported-by: Sumit Garg <sumit.g...@linaro.org>
> Signed-off-by: Peter Zijlstra (Intel) <pet...@infradead.org>
> Tested-by: Sumit Garg <sumit.g...@linaro.org>


Reviewed-by: Jarkko Sakkinen <jar...@kernel.org>

/Jarkko

> ---
>  tools/objtool/check.c |   32 ++++++++++++++++++++------------
>  1 file changed, 20 insertions(+), 12 deletions(-)
> 
> --- a/tools/objtool/check.c
> +++ b/tools/objtool/check.c
> @@ -850,6 +850,22 @@ static int add_ignore_alternatives(struc
>       return 0;
>  }
>  
> +static inline void static_call_add(struct instruction *insn,
> +                                struct objtool_file *file)
> +{
> +     if (!insn->call_dest->static_call_tramp)
> +             return;
> +
> +     if (!strcmp(insn->sec->name, ".exit.text")) {
> +             WARN_FUNC("static_call in .exit.text, skipping inline patching",
> +                       insn->sec, insn->offset);
> +             return;
> +     }
> +
> +     list_add_tail(&insn->static_call_node,
> +                   &file->static_call_list);
> +}
> +
>  /*
>   * Find the destination instructions for all jumps.
>   */
> @@ -888,10 +904,7 @@ static int add_jump_destinations(struct
>               } else if (insn->func) {
>                       /* internal or external sibling call (with reloc) */
>                       insn->call_dest = reloc->sym;
> -                     if (insn->call_dest->static_call_tramp) {
> -                             list_add_tail(&insn->static_call_node,
> -                                           &file->static_call_list);
> -                     }
> +                     static_call_add(insn, file);
>                       continue;
>               } else if (reloc->sym->sec->idx) {
>                       dest_sec = reloc->sym->sec;
> @@ -950,10 +963,7 @@ static int add_jump_destinations(struct
>  
>                               /* internal sibling call (without reloc) */
>                               insn->call_dest = insn->jump_dest->func;
> -                             if (insn->call_dest->static_call_tramp) {
> -                                     list_add_tail(&insn->static_call_node,
> -                                                   &file->static_call_list);
> -                             }
> +                             static_call_add(insn, file);
>                       }
>               }
>       }
> @@ -2746,10 +2756,8 @@ static int validate_branch(struct objtoo
>                       if (dead_end_function(file, insn->call_dest))
>                               return 0;
>  
> -                     if (insn->type == INSN_CALL && 
> insn->call_dest->static_call_tramp) {
> -                             list_add_tail(&insn->static_call_node,
> -                                           &file->static_call_list);
> -                     }
> +                     if (insn->type == INSN_CALL)
> +                             static_call_add(insn, file);
>  
>                       break;
>  
> 

Reply via email to