lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Mon, 8 Apr 2024 11:29:04 +0800
From: Zheng Yejian <zhengyejian1@...wei.com>
To: "Masami Hiramatsu (Google)" <mhiramat@...nel.org>
CC: <naveen.n.rao@...ux.ibm.com>, <anil.s.keshavamurthy@...el.com>,
	<davem@...emloft.net>, <linux-kernel@...r.kernel.org>,
	<linux-trace-kernel@...r.kernel.org>
Subject: Re: [PATCH] kprobes: Fix possible warn in __arm_kprobe_ftrace()

On 2024/4/8 10:50, Masami Hiramatsu (Google) wrote:
> On Sun, 7 Apr 2024 11:59:04 +0800
> Zheng Yejian <zhengyejian1@...wei.com> wrote:
> 
>> There is once warn in __arm_kprobe_ftrace() on:
>>
>>   ret = ftrace_set_filter_ip(ops, (unsigned long)p->addr, 0, 0);
>>   if (WARN_ONCE(..., "Failed to arm kprobe-ftrace at %pS (error %d)\n", ...)
>>     return ret;
>>
>> This warning is due to 'p->addr' is not a valid ftrace_location and
>> that invalid 'p->addr' was bypassed in check_kprobe_address_safe():
> 
> Ah, this is a guard warning to detect changes on ftrace_set_filter() and/or
> preparation steps. (A kind of debug message.)
> The ftrace address check is done by check_ftrace_location() at the beginning of
> check_kprobe_address_safe(). At that point, ftrace_location(addr) == addr should
> return true if the module is loaded. But there is a small window that we check
> the ftrace_location() and get the module refcount, even if the "addr" was ftrace
> location, the module is unloaded and failed to get the module refcount and fail
> to register the kprobe.

Thanks, I'll complete the description in V2.

> 
>>     check_kprobe_address_safe() {
>>       ...
>>       // 1. p->addr is in some module, this check passed
>>       is_module_text_address((unsigned long) p->addr)
>>       ...
>>       // 2. If the moudle is removed, the *probed_mod is NULL, but then
>>       //    the return value would still be 0 !!!
>>       *probed_mod = __module_text_address((unsigned long) p->addr);
>>       ...
>>     }
>>
>> So adjust the module text check to fix it.
> 
> This seems just optimizing code (skip the 2nd module search), right?

Yes, optimze more than fix, but this can still avoid latter warn like in
__arm_kprobe_ftrace()

> Also some comments needs to be updated.

Will do in V2.

> 
>>
>> Signed-off-by: Zheng Yejian <zhengyejian1@...wei.com>
>> ---
>>   kernel/kprobes.c | 13 +++++++++----
>>   1 file changed, 9 insertions(+), 4 deletions(-)
>>
>> diff --git a/kernel/kprobes.c b/kernel/kprobes.c
>> index 9d9095e81792..e0612cc3e2a3 100644
>> --- a/kernel/kprobes.c
>> +++ b/kernel/kprobes.c
>> @@ -1567,10 +1567,16 @@ static int check_kprobe_address_safe(struct kprobe *p,
>>   	jump_label_lock();
>>   	preempt_disable();
>>
> 
> 	/* Ensure the address is in a text area, and find a module if exists. */
>    
>> +	*probed_mod = NULL;
>> +	if (!core_kernel_text((unsigned long) p->addr)) {
>> +		*probed_mod = __module_text_address((unsigned long) p->addr);
>> +		if (!(*probed_mod)) {
>> +			ret = -EINVAL;
>> +			goto out;
>> +		}
> 
> nit: this should get the module refcount soon after getting probed_mod.
> (I think this should be an atomic operation, but we don't have such interface.)

Yes, it's better to get the module refcount right here, but suppose the
module is expected to be unloaded soon, we don't really need to make the 
registration succeed.

> 
>> +	}
> 
>>   	/* Ensure it is not in reserved area nor out of text */
> 
> 	/* Ensure it is not in reserved area. */
> 
>> -	if (!(core_kernel_text((unsigned long) p->addr) ||
>> -	    is_module_text_address((unsigned long) p->addr)) ||
> 
> Note that this part is doing same thing. If the probe address is !kernel_text
> and !module_text, it will be rejected.
> 

Yes.

>> -	    in_gate_area_no_mm((unsigned long) p->addr) ||
>> +	if (in_gate_area_no_mm((unsigned long) p->addr) ||
>>   	    within_kprobe_blacklist((unsigned long) p->addr) ||
>>   	    jump_label_text_reserved(p->addr, p->addr) ||
>>   	    static_call_text_reserved(p->addr, p->addr) ||
>> @@ -1581,7 +1587,6 @@ static int check_kprobe_address_safe(struct kprobe *p,
>>   	}
>>   
>>   	/* Check if 'p' is probing a module. */
> 
> 	/* Get module refcount and reject __init functions for loaded modules. */
> 
>> -	*probed_mod = __module_text_address((unsigned long) p->addr);
>>   	if (*probed_mod) {
>>   		/*
>>   		 * We must hold a refcount of the probed module while updating
>> -- 
>> 2.25.1
>>
> 
> Thank you,
> 

--

Thank you,
Zheng Yejian


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ