All of lore.kernel.org
 help / color / mirror / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: Zheng Yejian <zhengyejian1@huawei.com>
Cc: <mhiramat@kernel.org>, <mark.rutland@arm.com>,
	<mathieu.desnoyers@efficios.com>, <linux-kernel@vger.kernel.org>,
	<linux-trace-kernel@vger.kernel.org>
Subject: Re: [PATCH] ftrace: Fix use-after-free issue in ftrace_location()
Date: Wed, 10 Apr 2024 11:28:23 -0400	[thread overview]
Message-ID: <20240410112823.1d084c8f@gandalf.local.home> (raw)
In-Reply-To: <20240401125543.1282845-1-zhengyejian1@huawei.com>

On Mon, 1 Apr 2024 20:55:43 +0800
Zheng Yejian <zhengyejian1@huawei.com> wrote:

> KASAN reports a bug:
> 
>   BUG: KASAN: use-after-free in ftrace_location+0x90/0x120
>   Read of size 8 at addr ffff888141d40010 by task insmod/424
>   CPU: 8 PID: 424 Comm: insmod Tainted: G        W          6.9.0-rc2+ #213
>   [...]
>   Call Trace:
>    <TASK>
>    dump_stack_lvl+0x68/0xa0
>    print_report+0xcf/0x610
>    kasan_report+0xb5/0xe0
>    ftrace_location+0x90/0x120
>    register_kprobe+0x14b/0xa40
>    kprobe_init+0x2d/0xff0 [kprobe_example]
>    do_one_initcall+0x8f/0x2d0
>    do_init_module+0x13a/0x3c0
>    load_module+0x3082/0x33d0
>    init_module_from_file+0xd2/0x130
>    __x64_sys_finit_module+0x306/0x440
>    do_syscall_64+0x68/0x140
>    entry_SYSCALL_64_after_hwframe+0x71/0x79
> 
> The root cause is that when lookup_rec() is lookuping ftrace record of
> an address in some module, and at the same time in ftrace_release_mod(),
> the memory that saving ftrace records has been freed as that module is
> being deleted.
> 
>   register_kprobes() {
>     check_kprobe_address_safe() {
>       arch_check_ftrace_location() {
>         ftrace_location() {
>           lookup_rec()  // access memory that has been freed by
>                         // ftrace_release_mod() !!!
> 
> It seems that the ftrace_lock is required when lookuping records in
> ftrace_location(), so is ftrace_location_range().
> 
> Fixes: ae6aa16fdc16 ("kprobes: introduce ftrace based optimization")
> Signed-off-by: Zheng Yejian <zhengyejian1@huawei.com>
> ---
>  kernel/trace/ftrace.c | 28 ++++++++++++++++++----------
>  1 file changed, 18 insertions(+), 10 deletions(-)
> 
> diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
> index da1710499698..838d175709c1 100644
> --- a/kernel/trace/ftrace.c
> +++ b/kernel/trace/ftrace.c
> @@ -1581,7 +1581,7 @@ static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end)
>  }
>  
>  /**
> - * ftrace_location_range - return the first address of a traced location
> + * ftrace_location_range_locked - return the first address of a traced location
>   *	if it touches the given ip range
>   * @start: start of range to search.
>   * @end: end of range to search (inclusive). @end points to the last byte
> @@ -1592,7 +1592,7 @@ static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end)
>   * that is either a NOP or call to the function tracer. It checks the ftrace
>   * internal tables to determine if the address belongs or not.
>   */
> -unsigned long ftrace_location_range(unsigned long start, unsigned long end)
> +static unsigned long ftrace_location_range_locked(unsigned long start, unsigned long end)
>  {
>  	struct dyn_ftrace *rec;
>  
> @@ -1603,6 +1603,17 @@ unsigned long ftrace_location_range(unsigned long start, unsigned long end)
>  	return 0;
>  }
>  
> +unsigned long ftrace_location_range(unsigned long start, unsigned long end)
> +{
> +	unsigned long loc;
> +
> +	mutex_lock(&ftrace_lock);
> +	loc = ftrace_location_range_locked(start, end);
> +	mutex_unlock(&ftrace_lock);

I'm not so sure we can take a mutex in all places that call this function.

What about using RCU?

	rcu_read_lock();
	loc = ftrace_location_range_rcu(start, end);
	rcu_read_unlock();

Then in ftrace_release_mod() we can have:

 out_unlock:
	mutex_unlock();

	/* Need to synchronize with ftrace_location() */
	if (tmp_pages)
		synchronize_rcu();

-- Steve


> +
> +	return loc;
> +}
> +
>  /**
>   * ftrace_location - return the ftrace location
>   * @ip: the instruction pointer to check
> @@ -1614,25 +1625,22 @@ unsigned long ftrace_location_range(unsigned long start, unsigned long end)
>   */
>  unsigned long ftrace_location(unsigned long ip)
>  {
> -	struct dyn_ftrace *rec;
> +	unsigned long loc;
>  	unsigned long offset;
>  	unsigned long size;
>  
> -	rec = lookup_rec(ip, ip);
> -	if (!rec) {
> +	loc = ftrace_location_range(ip, ip);
> +	if (!loc) {
>  		if (!kallsyms_lookup_size_offset(ip, &size, &offset))
>  			goto out;
>  
>  		/* map sym+0 to __fentry__ */
>  		if (!offset)
> -			rec = lookup_rec(ip, ip + size - 1);
> +			loc = ftrace_location_range(ip, ip + size - 1);
>  	}
>  
> -	if (rec)
> -		return rec->ip;
> -
>  out:
> -	return 0;
> +	return loc;
>  }
>  
>  /**


  reply	other threads:[~2024-04-10 15:25 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-01 12:55 [PATCH] ftrace: Fix use-after-free issue in ftrace_location() Zheng Yejian
2024-04-10 15:28 ` Steven Rostedt [this message]
2024-04-11  1:48   ` Zheng Yejian
2024-04-16 11:24 ` [PATCH v2] ftrace: Fix possible " Zheng Yejian
2024-04-16 15:57   ` Markus Elfring
2024-04-17  3:28 ` [PATCH v3] " Zheng Yejian
2024-05-02 21:07   ` Steven Rostedt
2024-05-09  1:39     ` Zheng Yejian
2024-05-09 19:28 ` [PATCH v4] " Zheng Yejian

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240410112823.1d084c8f@gandalf.local.home \
    --to=rostedt@goodmis.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=mhiramat@kernel.org \
    --cc=zhengyejian1@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.