linux-trace-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v1 0/1] Call forget_syscall() if different than execve*()
@ 2022-05-09 15:19 Francis Laniel
  2022-05-09 15:19 ` [RFC PATCH v1 1/1] arm64: Forget syscall if different from execve*() Francis Laniel
  0 siblings, 1 reply; 7+ messages in thread
From: Francis Laniel @ 2022-05-09 15:19 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-trace-devel, Francis Laniel, Catalin Marinas, Will Deacon,
	Peter Collingbourne, Mark Brown, Mark Rutland, Daniel Kiss,
	Kees Cook, linux-kernel

Hi.


First, I hope you are fine and the same for your relatives.

With this contribution, I enabled using syscalls:sys_exit_execve and
syscalls:sys_exit_execveat as tracepoints on arm64.
Indeed, before this contribution, the above tracepoint would not print their
information as syscall number was set to -1 by calling forget_syscall().

Now, forget_syscall() is called only if previous syscall number was different
than __NR_execve and __NR_execveat.
I tested it by compiling a kernel for arm64 and running it within a VM:
# Perf was compiled with linux kernel source.
root@vm-arm64:~# perf record -ag -e 'syscalls:sys_exit_execve' -e 'syscalls:sys_enter_execve' &
[1] 263
root@vm-arm64:~# ls
perf.data  share
root@vm-arm64:~# fg
perf record -ag -e 'syscalls:sys_exit_execve' -e 'syscalls:sys_enter_execve'
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.061 MB perf.data (2 samples) ]
root@vm-arm64:~# perf script
bash   264 [000]    66.220187: syscalls:sys_enter_execve: filename: 0xaaab05d9d
...
# Below line does not appear with this patch.
ls   264 [000]    66.226848:  syscalls:sys_exit_execve: 0x0
...

Nonetheless, this contribution is not perfect, hence I marked it as RFC.
First, I am not really sure if this is safe to not call forget_syscall() all the
time, even though I did not have problem while testing it.
Then, by including <asm-generic/unistd.h> to the modified file I ended with
some warnings at compile time:

So, if you see any way to improve this contribution, feel free to share!

Francis Laniel (1):
  arm64: Forget syscall if different from execve*()

 arch/arm64/include/asm/processor.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)


Best regards and thank you in advance.
-- 
2.25.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC PATCH v1 1/1] arm64: Forget syscall if different from execve*()
  2022-05-09 15:19 [RFC PATCH v1 0/1] Call forget_syscall() if different than execve*() Francis Laniel
@ 2022-05-09 15:19 ` Francis Laniel
  2022-05-10 10:59   ` Will Deacon
  0 siblings, 1 reply; 7+ messages in thread
From: Francis Laniel @ 2022-05-09 15:19 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-trace-devel, Francis Laniel, Catalin Marinas, Will Deacon,
	Mark Brown, Peter Collingbourne, Mark Rutland, Kees Cook,
	Daniel Kiss, linux-kernel

This patch enables exeve*() to be traced by syscalls:sys_exit_execve
tracepoint.
Previously, calling forget_syscall() would set syscall to -1, which impedes
this tracepoint to prints its information.
So, this patch makes call to forget_syscall() conditional by only calling
it when syscall number is not execve() or execveat().

Signed-off-by: Francis Laniel <flaniel@linux.microsoft.com>
---
 arch/arm64/include/asm/processor.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 73e38d9a540c..e12ceb363d6a 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -34,6 +34,8 @@
 
 #include <vdso/processor.h>
 
+#include <asm-generic/unistd.h>
+
 #include <asm/alternative.h>
 #include <asm/cpufeature.h>
 #include <asm/hw_breakpoint.h>
@@ -250,8 +252,12 @@ void tls_preserve_current_state(void);
 
 static inline void start_thread_common(struct pt_regs *regs, unsigned long pc)
 {
+	s32 previous_syscall = regs->syscallno;
 	memset(regs, 0, sizeof(*regs));
-	forget_syscall(regs);
+	if (previous_syscall == __NR_execve || previous_syscall == __NR_execveat)
+		regs->syscallno = previous_syscall;
+	else
+		forget_syscall(regs);
 	regs->pc = pc;
 
 	if (system_uses_irq_prio_masking())
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH v1 1/1] arm64: Forget syscall if different from execve*()
  2022-05-09 15:19 ` [RFC PATCH v1 1/1] arm64: Forget syscall if different from execve*() Francis Laniel
@ 2022-05-10 10:59   ` Will Deacon
  2022-05-10 14:00     ` Francis Laniel
  0 siblings, 1 reply; 7+ messages in thread
From: Will Deacon @ 2022-05-10 10:59 UTC (permalink / raw)
  To: Francis Laniel
  Cc: linux-arm-kernel, linux-trace-devel, Catalin Marinas, Mark Brown,
	Peter Collingbourne, Mark Rutland, Kees Cook, Daniel Kiss,
	linux-kernel

On Mon, May 09, 2022 at 04:19:57PM +0100, Francis Laniel wrote:
> This patch enables exeve*() to be traced by syscalls:sys_exit_execve
> tracepoint.
> Previously, calling forget_syscall() would set syscall to -1, which impedes
> this tracepoint to prints its information.
> So, this patch makes call to forget_syscall() conditional by only calling
> it when syscall number is not execve() or execveat().
> 
> Signed-off-by: Francis Laniel <flaniel@linux.microsoft.com>
> ---
>  arch/arm64/include/asm/processor.h | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
> index 73e38d9a540c..e12ceb363d6a 100644
> --- a/arch/arm64/include/asm/processor.h
> +++ b/arch/arm64/include/asm/processor.h
> @@ -34,6 +34,8 @@
>  
>  #include <vdso/processor.h>
>  
> +#include <asm-generic/unistd.h>
> +
>  #include <asm/alternative.h>
>  #include <asm/cpufeature.h>
>  #include <asm/hw_breakpoint.h>
> @@ -250,8 +252,12 @@ void tls_preserve_current_state(void);
>  
>  static inline void start_thread_common(struct pt_regs *regs, unsigned long pc)
>  {
> +	s32 previous_syscall = regs->syscallno;
>  	memset(regs, 0, sizeof(*regs));
> -	forget_syscall(regs);
> +	if (previous_syscall == __NR_execve || previous_syscall == __NR_execveat)
> +		regs->syscallno = previous_syscall;
> +	else
> +		forget_syscall(regs);

Hmm, this really looks like a bodge and it doesn't handle the compat case
either.

How do other architectures handle this?

Will

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH v1 1/1] arm64: Forget syscall if different from execve*()
  2022-05-10 10:59   ` Will Deacon
@ 2022-05-10 14:00     ` Francis Laniel
  2022-05-10 14:03       ` Will Deacon
  0 siblings, 1 reply; 7+ messages in thread
From: Francis Laniel @ 2022-05-10 14:00 UTC (permalink / raw)
  To: Will Deacon
  Cc: linux-arm-kernel, linux-trace-devel, Catalin Marinas, Mark Brown,
	Peter Collingbourne, Mark Rutland, Kees Cook, Daniel Kiss,
	linux-kernel

Hi.

Le mardi 10 mai 2022, 11:59:48 BST Will Deacon a écrit :
> On Mon, May 09, 2022 at 04:19:57PM +0100, Francis Laniel wrote:
> > This patch enables exeve*() to be traced by syscalls:sys_exit_execve
> > tracepoint.
> > Previously, calling forget_syscall() would set syscall to -1, which
> > impedes
> > this tracepoint to prints its information.
> > So, this patch makes call to forget_syscall() conditional by only calling
> > it when syscall number is not execve() or execveat().
> > 
> > Signed-off-by: Francis Laniel <flaniel@linux.microsoft.com>
> > ---
> > 
> >  arch/arm64/include/asm/processor.h | 8 +++++++-
> >  1 file changed, 7 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm64/include/asm/processor.h
> > b/arch/arm64/include/asm/processor.h index 73e38d9a540c..e12ceb363d6a
> > 100644
> > --- a/arch/arm64/include/asm/processor.h
> > +++ b/arch/arm64/include/asm/processor.h
> > @@ -34,6 +34,8 @@
> > 
> >  #include <vdso/processor.h>
> > 
> > +#include <asm-generic/unistd.h>
> > +
> > 
> >  #include <asm/alternative.h>
> >  #include <asm/cpufeature.h>
> >  #include <asm/hw_breakpoint.h>
> > 
> > @@ -250,8 +252,12 @@ void tls_preserve_current_state(void);
> > 
> >  static inline void start_thread_common(struct pt_regs *regs, unsigned
> >  long pc) {
> > 
> > +	s32 previous_syscall = regs->syscallno;
> > 
> >  	memset(regs, 0, sizeof(*regs));
> > 
> > -	forget_syscall(regs);
> > +	if (previous_syscall == __NR_execve || previous_syscall ==
> > __NR_execveat)
> > +		regs->syscallno = previous_syscall;
> > +	else
> > +		forget_syscall(regs);
> 
> Hmm, this really looks like a bodge and it doesn't handle the compat case
> either.
> 
> How do other architectures handle this?

My understanding of others architectures is quite limited, but here are my 
findings and understanding of some of them:
* arm (32 bits) EABI: start_thread() sets r7 to previous r7 for ELF FDPIC  and 
to 0 for other binfmts [1].
* arm (32 bits) OABI: syscall number is set to -1 if 
ptrace_report_syscall_entry() failed [2].
* mips: start_thread() does not modify current_thread_info->syscall which is 
taken directly from v0 [3, 4].
* riscv: start_thread() does not modify a7 [5].
* x86_64: start_thread_common() does not touch orig_ax which seems to contain 
the syscall number [6].

> Will

Best regards.
---
[1] https://elixir.bootlin.com/linux/v5.18-rc6/source/arch/arm/include/asm/
processor.h#L52
[2] https://elixir.bootlin.com/linux/v5.18-rc6/source/arch/arm/kernel/
ptrace.c#L847
[3] https://elixir.bootlin.com/linux/v5.18-rc6/source/arch/mips/kernel/
process.c#L52
[4] https://elixir.bootlin.com/linux/v5.18-rc6/source/arch/mips/kernel/
scall64-n64.S#L85
[5] https://elixir.bootlin.com/linux/v5.18-rc6/source/arch/riscv/kernel/
process.c#L87
[6] https://elixir.bootlin.com/linux/v5.18-rc6/source/arch/x86/kernel/
process_64.c#L505



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH v1 1/1] arm64: Forget syscall if different from execve*()
  2022-05-10 14:00     ` Francis Laniel
@ 2022-05-10 14:03       ` Will Deacon
  2022-05-10 14:12         ` Francis Laniel
  2022-05-18 13:32         ` Catalin Marinas
  0 siblings, 2 replies; 7+ messages in thread
From: Will Deacon @ 2022-05-10 14:03 UTC (permalink / raw)
  To: Francis Laniel
  Cc: linux-arm-kernel, linux-trace-devel, Catalin Marinas, Mark Brown,
	Peter Collingbourne, Mark Rutland, Kees Cook, Daniel Kiss,
	linux-kernel

On Tue, May 10, 2022 at 03:00:11PM +0100, Francis Laniel wrote:
> Le mardi 10 mai 2022, 11:59:48 BST Will Deacon a écrit :
> > On Mon, May 09, 2022 at 04:19:57PM +0100, Francis Laniel wrote:
> > > diff --git a/arch/arm64/include/asm/processor.h
> > > b/arch/arm64/include/asm/processor.h index 73e38d9a540c..e12ceb363d6a
> > > 100644
> > > --- a/arch/arm64/include/asm/processor.h
> > > +++ b/arch/arm64/include/asm/processor.h
> > > @@ -34,6 +34,8 @@
> > > 
> > >  #include <vdso/processor.h>
> > > 
> > > +#include <asm-generic/unistd.h>
> > > +
> > > 
> > >  #include <asm/alternative.h>
> > >  #include <asm/cpufeature.h>
> > >  #include <asm/hw_breakpoint.h>
> > > 
> > > @@ -250,8 +252,12 @@ void tls_preserve_current_state(void);
> > > 
> > >  static inline void start_thread_common(struct pt_regs *regs, unsigned
> > >  long pc) {
> > > 
> > > +	s32 previous_syscall = regs->syscallno;
> > > 
> > >  	memset(regs, 0, sizeof(*regs));
> > > 
> > > -	forget_syscall(regs);
> > > +	if (previous_syscall == __NR_execve || previous_syscall ==
> > > __NR_execveat)
> > > +		regs->syscallno = previous_syscall;
> > > +	else
> > > +		forget_syscall(regs);
> > 
> > Hmm, this really looks like a bodge and it doesn't handle the compat case
> > either.
> > 
> > How do other architectures handle this?
> 
> My understanding of others architectures is quite limited, but here are my 
> findings and understanding of some of them:
> * arm (32 bits) EABI: start_thread() sets r7 to previous r7 for ELF FDPIC  and 
> to 0 for other binfmts [1].
> * arm (32 bits) OABI: syscall number is set to -1 if 
> ptrace_report_syscall_entry() failed [2].
> * mips: start_thread() does not modify current_thread_info->syscall which is 
> taken directly from v0 [3, 4].
> * riscv: start_thread() does not modify a7 [5].
> * x86_64: start_thread_common() does not touch orig_ax which seems to contain 
> the syscall number [6].

Hmm, so the million dollar question is why on Earth we have that
forget_syscall() call to start with. Amusingly I've, err, forgotten;
forget_forget_syscall() perhaps?

Catalin? It's been there since day one afaict.

Will

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH v1 1/1] arm64: Forget syscall if different from execve*()
  2022-05-10 14:03       ` Will Deacon
@ 2022-05-10 14:12         ` Francis Laniel
  2022-05-18 13:32         ` Catalin Marinas
  1 sibling, 0 replies; 7+ messages in thread
From: Francis Laniel @ 2022-05-10 14:12 UTC (permalink / raw)
  To: Will Deacon
  Cc: linux-arm-kernel, linux-trace-devel, Catalin Marinas, Mark Brown,
	Peter Collingbourne, Mark Rutland, Kees Cook, Daniel Kiss,
	linux-kernel

Le mardi 10 mai 2022, 15:03:33 BST Will Deacon a écrit :
> On Tue, May 10, 2022 at 03:00:11PM +0100, Francis Laniel wrote:
> > Le mardi 10 mai 2022, 11:59:48 BST Will Deacon a écrit :
> > > On Mon, May 09, 2022 at 04:19:57PM +0100, Francis Laniel wrote:
> > > > diff --git a/arch/arm64/include/asm/processor.h
> > > > b/arch/arm64/include/asm/processor.h index 73e38d9a540c..e12ceb363d6a
> > > > 100644
> > > > --- a/arch/arm64/include/asm/processor.h
> > > > +++ b/arch/arm64/include/asm/processor.h
> > > > @@ -34,6 +34,8 @@
> > > > 
> > > >  #include <vdso/processor.h>
> > > > 
> > > > +#include <asm-generic/unistd.h>
> > > > +
> > > > 
> > > >  #include <asm/alternative.h>
> > > >  #include <asm/cpufeature.h>
> > > >  #include <asm/hw_breakpoint.h>
> > > > 
> > > > @@ -250,8 +252,12 @@ void tls_preserve_current_state(void);
> > > > 
> > > >  static inline void start_thread_common(struct pt_regs *regs, unsigned
> > > >  long pc) {
> > > > 
> > > > +	s32 previous_syscall = regs->syscallno;
> > > > 
> > > >  	memset(regs, 0, sizeof(*regs));
> > > > 
> > > > -	forget_syscall(regs);
> > > > +	if (previous_syscall == __NR_execve || previous_syscall ==
> > > > __NR_execveat)
> > > > +		regs->syscallno = previous_syscall;
> > > > +	else
> > > > +		forget_syscall(regs);
> > > 
> > > Hmm, this really looks like a bodge and it doesn't handle the compat
> > > case
> > > either.
> > > 
> > > How do other architectures handle this?
> > 
> > My understanding of others architectures is quite limited, but here are my
> > findings and understanding of some of them:
> > * arm (32 bits) EABI: start_thread() sets r7 to previous r7 for ELF FDPIC 
> > and to 0 for other binfmts [1].
> > * arm (32 bits) OABI: syscall number is set to -1 if
> > ptrace_report_syscall_entry() failed [2].
> > * mips: start_thread() does not modify current_thread_info->syscall which
> > is taken directly from v0 [3, 4].
> > * riscv: start_thread() does not modify a7 [5].
> > * x86_64: start_thread_common() does not touch orig_ax which seems to
> > contain the syscall number [6].
> 
> Hmm, so the million dollar question is why on Earth we have that
> forget_syscall() call to start with. Amusingly I've, err, forgotten;
> forget_forget_syscall() perhaps?

I think this is maybe tied to this comment [1]:
The de-facto standard way to skip a system call using ptrace 
is to set the system call to -1 (NO_SYSCALL)

But I will let the original author explain as his/her explaination will be 
better than mine.

> Catalin? It's been there since day one afaict.
> 
> Will

---
[1] https://elixir.bootlin.com/linux/v5.18-rc6/source/arch/arm64/kernel/
syscall.c#L121



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH v1 1/1] arm64: Forget syscall if different from execve*()
  2022-05-10 14:03       ` Will Deacon
  2022-05-10 14:12         ` Francis Laniel
@ 2022-05-18 13:32         ` Catalin Marinas
  1 sibling, 0 replies; 7+ messages in thread
From: Catalin Marinas @ 2022-05-18 13:32 UTC (permalink / raw)
  To: Will Deacon
  Cc: Francis Laniel, linux-arm-kernel, linux-trace-devel, Mark Brown,
	Peter Collingbourne, Mark Rutland, Kees Cook, Daniel Kiss,
	linux-kernel, James Morse

On Tue, May 10, 2022 at 03:03:33PM +0100, Will Deacon wrote:
> On Tue, May 10, 2022 at 03:00:11PM +0100, Francis Laniel wrote:
> > Le mardi 10 mai 2022, 11:59:48 BST Will Deacon a �crit :
> > > On Mon, May 09, 2022 at 04:19:57PM +0100, Francis Laniel wrote:
> > > > diff --git a/arch/arm64/include/asm/processor.h
> > > > b/arch/arm64/include/asm/processor.h index 73e38d9a540c..e12ceb363d6a
> > > > 100644
> > > > --- a/arch/arm64/include/asm/processor.h
> > > > +++ b/arch/arm64/include/asm/processor.h
> > > > @@ -34,6 +34,8 @@
> > > > 
> > > >  #include <vdso/processor.h>
> > > > 
> > > > +#include <asm-generic/unistd.h>
> > > > +
> > > > 
> > > >  #include <asm/alternative.h>
> > > >  #include <asm/cpufeature.h>
> > > >  #include <asm/hw_breakpoint.h>
> > > > 
> > > > @@ -250,8 +252,12 @@ void tls_preserve_current_state(void);
> > > > 
> > > >  static inline void start_thread_common(struct pt_regs *regs, unsigned
> > > >  long pc) {
> > > > 
> > > > +	s32 previous_syscall = regs->syscallno;
> > > > 
> > > >  	memset(regs, 0, sizeof(*regs));
> > > > 
> > > > -	forget_syscall(regs);
> > > > +	if (previous_syscall == __NR_execve || previous_syscall ==
> > > > __NR_execveat)
> > > > +		regs->syscallno = previous_syscall;
> > > > +	else
> > > > +		forget_syscall(regs);
> > > 
> > > Hmm, this really looks like a bodge and it doesn't handle the compat case
> > > either.
> > > 
> > > How do other architectures handle this?
> > 
> > My understanding of others architectures is quite limited, but here are my 
> > findings and understanding of some of them:
> > * arm (32 bits) EABI: start_thread() sets r7 to previous r7 for ELF FDPIC  and 
> > to 0 for other binfmts [1].
> > * arm (32 bits) OABI: syscall number is set to -1 if 
> > ptrace_report_syscall_entry() failed [2].
> > * mips: start_thread() does not modify current_thread_info->syscall which is 
> > taken directly from v0 [3, 4].
> > * riscv: start_thread() does not modify a7 [5].
> > * x86_64: start_thread_common() does not touch orig_ax which seems to contain 
> > the syscall number [6].
> 
> Hmm, so the million dollar question is why on Earth we have that
> forget_syscall() call to start with. Amusingly I've, err, forgotten;
> forget_forget_syscall() perhaps?
> 
> Catalin? It's been there since day one afaict.

Looking at the old logs, this appeared somewhere between day 0 and 1. We
had a memset(regs, 0) with a pt_regs of 36 registers but moved to
dedicated names for syscallno etc. and that's where I changed it from 0
to ~0UL.

A few weeks ago James Morse (cc'ed) came across this issue and even sent
a patch internally to remove forget_syscall() here. But that looks like
a bodge and James' suggestion was that maybe the core code can preserve
the syscallno and this would fix it for all architectures.

-- 
Catalin

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-05-18 13:33 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-09 15:19 [RFC PATCH v1 0/1] Call forget_syscall() if different than execve*() Francis Laniel
2022-05-09 15:19 ` [RFC PATCH v1 1/1] arm64: Forget syscall if different from execve*() Francis Laniel
2022-05-10 10:59   ` Will Deacon
2022-05-10 14:00     ` Francis Laniel
2022-05-10 14:03       ` Will Deacon
2022-05-10 14:12         ` Francis Laniel
2022-05-18 13:32         ` Catalin Marinas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).