All of lore.kernel.org
 help / color / mirror / Atom feed
From: Will Deacon <will@kernel.org>
To: Liam Howlett <liam.howlett@oracle.com>, ebiederm@xmission.com
Cc: Catalin Marinas <catalin.marinas@arm.com>,
	Julien Grall <julien.grall@arm.com>,
	Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>,
	"linux-arm-kernel@lists.infradead.org" 
	<linux-arm-kernel@lists.infradead.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"netdev@vger.kernel.org" <netdev@vger.kernel.org>,
	"bpf@vger.kernel.org" <bpf@vger.kernel.org>
Subject: Re: [PATCH 2/3] arm64: signal: sigreturn() and rt_sigreturn() sometime returns the wrong signals
Date: Thu, 22 Apr 2021 13:48:50 +0100	[thread overview]
Message-ID: <20210422124849.GA1521@willie-the-truck> (raw)
In-Reply-To: <20210420165001.3790670-2-Liam.Howlett@Oracle.com>

[+Eric as he actually understands how this is supposed to work]

On Tue, Apr 20, 2021 at 04:50:13PM +0000, Liam Howlett wrote:
> arm64_notify_segfault() was used to force a SIGSEGV in all error cases
> in sigreturn() and rt_sigreturn() to avoid writing a new sig handler.
> There is now a better sig handler to use which does not search the VMA
> address space and return a slightly incorrect error code.  Restore the
> older and correct si_code of SI_KERNEL by using arm64_notify_die().  In
> the case of !access_ok(), simply return SIGSEGV with si_code
> SEGV_ACCERR.
> 
> This change requires exporting arm64_notfiy_die() to the arm64 traps.h
> 
> Fixes: f71016a8a8c5 (arm64: signal: Call arm64_notify_segfault when
> failing to deliver signal)
> Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
> ---
>  arch/arm64/include/asm/traps.h |  2 ++
>  arch/arm64/kernel/signal.c     |  8 ++++++--
>  arch/arm64/kernel/signal32.c   | 18 ++++++++++++++----
>  3 files changed, 22 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
> index 54f32a0675df..9b76144fcba6 100644
> --- a/arch/arm64/include/asm/traps.h
> +++ b/arch/arm64/include/asm/traps.h
> @@ -29,6 +29,8 @@ void arm64_notify_segfault(unsigned long addr);
>  void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *str);
>  void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str);
>  void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, const char *str);
> +void arm64_notify_die(const char *str, struct pt_regs *regs, int signo,
> +		      int sicode, unsigned long far, int err);
>  
>  /*
>   * Move regs->pc to next instruction and do necessary setup before it
> diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
> index 6237486ff6bb..9fde6dc760c3 100644
> --- a/arch/arm64/kernel/signal.c
> +++ b/arch/arm64/kernel/signal.c
> @@ -544,7 +544,7 @@ SYSCALL_DEFINE0(rt_sigreturn)
>  	frame = (struct rt_sigframe __user *)regs->sp;
>  
>  	if (!access_ok(frame, sizeof (*frame)))
> -		goto badframe;
> +		goto e_access;
>  
>  	if (restore_sigframe(regs, frame))
>  		goto badframe;
> @@ -555,7 +555,11 @@ SYSCALL_DEFINE0(rt_sigreturn)
>  	return regs->regs[0];
>  
>  badframe:
> -	arm64_notify_segfault(regs->sp);
> +	arm64_notify_die("Bad frame", regs, SIGSEGV, SI_KERNEL, regs->sp, 0);
> +	return 0;
> +
> +e_access:
> +	force_signal_inject(SIGSEGV, SEGV_ACCERR, regs->sp, 0);
>  	return 0;

This seems really error-prone to me, but maybe I'm just missing some
context. What's the rule for reporting an si_code of SI_KERNEL vs
SEGV_ACCERR, and is the former actually valid for SIGSEGV?

With this change, pointing the (signal) stack to a kernel address will
result in SEGV_ACCERR but pointing it to something like a PROT_NONE user
address will give SI_KERNEL (well, assuming that we manage to deliver
the SEGV somehow). I'm having a hard time seeing why that's a useful
distinction to make..

If it's important to get this a particular way around, please can you
add some selftests?

Will

WARNING: multiple messages have this Message-ID (diff)
From: Will Deacon <will@kernel.org>
To: Liam Howlett <liam.howlett@oracle.com>, ebiederm@xmission.com
Cc: Catalin Marinas <catalin.marinas@arm.com>,
	Julien Grall <julien.grall@arm.com>,
	Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>,
	 "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"netdev@vger.kernel.org" <netdev@vger.kernel.org>,
	"bpf@vger.kernel.org" <bpf@vger.kernel.org>
Subject: Re: [PATCH 2/3] arm64: signal: sigreturn() and rt_sigreturn() sometime returns the wrong signals
Date: Thu, 22 Apr 2021 13:48:50 +0100	[thread overview]
Message-ID: <20210422124849.GA1521@willie-the-truck> (raw)
In-Reply-To: <20210420165001.3790670-2-Liam.Howlett@Oracle.com>

[+Eric as he actually understands how this is supposed to work]

On Tue, Apr 20, 2021 at 04:50:13PM +0000, Liam Howlett wrote:
> arm64_notify_segfault() was used to force a SIGSEGV in all error cases
> in sigreturn() and rt_sigreturn() to avoid writing a new sig handler.
> There is now a better sig handler to use which does not search the VMA
> address space and return a slightly incorrect error code.  Restore the
> older and correct si_code of SI_KERNEL by using arm64_notify_die().  In
> the case of !access_ok(), simply return SIGSEGV with si_code
> SEGV_ACCERR.
> 
> This change requires exporting arm64_notfiy_die() to the arm64 traps.h
> 
> Fixes: f71016a8a8c5 (arm64: signal: Call arm64_notify_segfault when
> failing to deliver signal)
> Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
> ---
>  arch/arm64/include/asm/traps.h |  2 ++
>  arch/arm64/kernel/signal.c     |  8 ++++++--
>  arch/arm64/kernel/signal32.c   | 18 ++++++++++++++----
>  3 files changed, 22 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
> index 54f32a0675df..9b76144fcba6 100644
> --- a/arch/arm64/include/asm/traps.h
> +++ b/arch/arm64/include/asm/traps.h
> @@ -29,6 +29,8 @@ void arm64_notify_segfault(unsigned long addr);
>  void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *str);
>  void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str);
>  void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, const char *str);
> +void arm64_notify_die(const char *str, struct pt_regs *regs, int signo,
> +		      int sicode, unsigned long far, int err);
>  
>  /*
>   * Move regs->pc to next instruction and do necessary setup before it
> diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
> index 6237486ff6bb..9fde6dc760c3 100644
> --- a/arch/arm64/kernel/signal.c
> +++ b/arch/arm64/kernel/signal.c
> @@ -544,7 +544,7 @@ SYSCALL_DEFINE0(rt_sigreturn)
>  	frame = (struct rt_sigframe __user *)regs->sp;
>  
>  	if (!access_ok(frame, sizeof (*frame)))
> -		goto badframe;
> +		goto e_access;
>  
>  	if (restore_sigframe(regs, frame))
>  		goto badframe;
> @@ -555,7 +555,11 @@ SYSCALL_DEFINE0(rt_sigreturn)
>  	return regs->regs[0];
>  
>  badframe:
> -	arm64_notify_segfault(regs->sp);
> +	arm64_notify_die("Bad frame", regs, SIGSEGV, SI_KERNEL, regs->sp, 0);
> +	return 0;
> +
> +e_access:
> +	force_signal_inject(SIGSEGV, SEGV_ACCERR, regs->sp, 0);
>  	return 0;

This seems really error-prone to me, but maybe I'm just missing some
context. What's the rule for reporting an si_code of SI_KERNEL vs
SEGV_ACCERR, and is the former actually valid for SIGSEGV?

With this change, pointing the (signal) stack to a kernel address will
result in SEGV_ACCERR but pointing it to something like a PROT_NONE user
address will give SI_KERNEL (well, assuming that we manage to deliver
the SEGV somehow). I'm having a hard time seeing why that's a useful
distinction to make..

If it's important to get this a particular way around, please can you
add some selftests?

Will

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2021-04-22 12:49 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-20 16:50 [PATCH 1/3] arm64: armv8_deprecated: Fix swp_handler() signal generation Liam Howlett
2021-04-20 16:50 ` Liam Howlett
2021-04-20 16:50 ` [PATCH 2/3] arm64: signal: sigreturn() and rt_sigreturn() sometime returns the wrong signals Liam Howlett
2021-04-20 16:50   ` Liam Howlett
2021-04-22 12:48   ` Will Deacon [this message]
2021-04-22 12:48     ` Will Deacon
2021-04-22 18:22     ` Eric W. Biederman
2021-04-22 18:22       ` Eric W. Biederman
2021-04-22 19:24       ` Liam Howlett
2021-04-22 19:24         ` Liam Howlett
2021-04-23 18:17         ` Eric W. Biederman
2021-04-23 18:17           ` Eric W. Biederman
2021-04-23 20:03           ` Liam Howlett
2021-04-23 20:03             ` Liam Howlett
2021-04-29 17:52             ` Eric W. Biederman
2021-04-29 17:52               ` Eric W. Biederman
2021-04-30 18:48               ` Liam Howlett
2021-04-30 18:48                 ` Liam Howlett
2021-04-30 19:57                 ` Eric W. Biederman
2021-04-30 19:57                   ` Eric W. Biederman
2021-04-30 20:31                   ` Liam Howlett
2021-04-30 20:31                     ` Liam Howlett
2021-04-20 16:50 ` [PATCH 3/3] arch/arm64/kernel/traps: Use find_vma_intersection() in traps for setting si_code Liam Howlett
2021-04-20 16:50   ` Liam Howlett
2021-04-22 12:53   ` Will Deacon
2021-04-22 12:53     ` Will Deacon
2021-04-22 18:56     ` Liam Howlett
2021-04-22 18:56       ` Liam Howlett
2021-04-20 21:22 ` [PATCH 1/3] arm64: armv8_deprecated: Fix swp_handler() signal generation kernel test robot
2021-04-20 21:22   ` kernel test robot
2021-04-21 15:47   ` Liam Howlett
2021-04-21 15:47     ` Liam Howlett
2021-04-21 15:47     ` Liam Howlett
2021-04-22 12:59 ` Will Deacon
2021-04-22 12:59   ` Will Deacon
2021-04-23  1:00   ` Liam Howlett
2021-04-23  1:00     ` Liam Howlett

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=20210422124849.GA1521@willie-the-truck \
    --to=will@kernel.org \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=daniel@iogearbox.net \
    --cc=ebiederm@xmission.com \
    --cc=julien.grall@arm.com \
    --cc=liam.howlett@oracle.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    /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.