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]
Message-ID: <75b6fec7-f168-4bc3-9479-8a089bb4e033@xen0n.name>
Date: Tue, 21 Jan 2025 21:35:06 +0800
From: WANG Xuerui <kernel@...0n.name>
To: Tiezhu Yang <yangtiezhu@...ngson.cn>, Huacai Chen <chenhuacai@...nel.org>
Cc: loongarch@...ts.linux.dev, linux-kernel@...r.kernel.org
Subject: Re: [PATCH 2/2] LoongArch: Extend the maximum number of watchpoints

Hi,

On 1/21/25 15:06, Tiezhu Yang wrote:
> The maximum number of load/store watchpoints and fetch instruction
> watchpoints is 14 each according to LoongArch Reference Manual, so
> extend the maximum number of watchpoints from 8 to 14 for ptrace.
> 
> By the way, just simply change 8 to 14 for the definition in struct
> user_watch_state at the beginning, but it may corrupt uapi, then add
> a new struct user_watch_state_v2 directly.
> 
> As far as I can tell, the only users for this struct in the userspace
> are GDB and LLDB, there are no any problems of software compatibility
> between the application and kernel according to the analysis.

But it seems something is indeed corrupted by this patch...

For example, it's entirely appropriate to mix-match debuggers and 
kernels of different UAPI revision. In this case, some kind of version 
marker must be present in the UAPI structure to prevent out-of-bounds 
accesses by the kernel. But according to the changes...

> Link: https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#control-and-status-registers-related-to-watchpoints
> Fixes: 1a69f7a161a7 ("LoongArch: ptrace: Expose hardware breakpoints to debuggers")
> Signed-off-by: Tiezhu Yang <yangtiezhu@...ngson.cn>
> ---
>   arch/loongarch/include/uapi/asm/ptrace.h | 10 ++++++++++
>   arch/loongarch/kernel/ptrace.c           |  6 +++---
>   2 files changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/loongarch/include/uapi/asm/ptrace.h b/arch/loongarch/include/uapi/asm/ptrace.h
> index ac915f841650..aafb3cd9e943 100644
> --- a/arch/loongarch/include/uapi/asm/ptrace.h
> +++ b/arch/loongarch/include/uapi/asm/ptrace.h
> @@ -72,6 +72,16 @@ struct user_watch_state {
>   	} dbg_regs[8];
>   };
>   
> +struct user_watch_state_v2 {
> +	uint64_t dbg_info;
> +	struct {
> +		uint64_t    addr;
> +		uint64_t    mask;
> +		uint32_t    ctrl;
> +		uint32_t    pad;
> +	} dbg_regs[14];
> +};

there seems no indication of any "version marker" field ("revision" or 
"sizeof(input)" or something like that), so...

> +
>   #define PTRACE_SYSEMU			0x1f
>   #define PTRACE_SYSEMU_SINGLESTEP	0x20
>   
> diff --git a/arch/loongarch/kernel/ptrace.c b/arch/loongarch/kernel/ptrace.c
> index 19dc6eff45cc..5e2402cfcab0 100644
> --- a/arch/loongarch/kernel/ptrace.c
> +++ b/arch/loongarch/kernel/ptrace.c
> @@ -720,7 +720,7 @@ static int hw_break_set(struct task_struct *target,
>   	unsigned int note_type = regset->core_note_type;
>   
>   	/* Resource info */
> -	offset = offsetof(struct user_watch_state, dbg_regs);
> +	offset = offsetof(struct user_watch_state_v2, dbg_regs);
>   	user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
>   
>   	/* (address, mask, ctrl) registers */
> @@ -920,7 +920,7 @@ static const struct user_regset loongarch64_regsets[] = {
>   #ifdef CONFIG_HAVE_HW_BREAKPOINT
>   	[REGSET_HW_BREAK] = {
>   		.core_note_type = NT_LOONGARCH_HW_BREAK,
> -		.n = sizeof(struct user_watch_state) / sizeof(u32),
> +		.n = sizeof(struct user_watch_state_v2) / sizeof(u32),

one cannot account for older (in fact, *every existing*) clients 
expecting the old UAPI, hence providing a smaller buffer than struct 
user_watch_state_v2. In which case the kernel will happily write 
out-of-bounds if the client asks for the current watchpoint state. This 
is not acceptable I'm afraid.

>   		.size = sizeof(u32),
>   		.align = sizeof(u32),
>   		.regset_get = hw_break_get,
> @@ -928,7 +928,7 @@ static const struct user_regset loongarch64_regsets[] = {
>   	},
>   	[REGSET_HW_WATCH] = {
>   		.core_note_type = NT_LOONGARCH_HW_WATCH,
> -		.n = sizeof(struct user_watch_state) / sizeof(u32),
> +		.n = sizeof(struct user_watch_state_v2) / sizeof(u32),
>   		.size = sizeof(u32),
>   		.align = sizeof(u32),
>   		.regset_get = hw_break_get,


-- 
WANG "xen0n" Xuerui

Linux/LoongArch mailing list: https://lore.kernel.org/loongarch/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ