Re: [PATCH] s390/ptrace: Preserve ILC when updating system call number

From: Sven Schnelle

Date: Mon Oct 12 2026 - 02:12:20 EST


Heiko Carstens <hca@xxxxxxxxxxxxx> writes:

> When an attached debugger changes gpr2 via PTRACE_POKEUSR while the
> traced process has PIF_SYSCALL set, the int_code in pt_regs is also
> updated. In case of an svc it contains the instruction length code
> (ILC), as well as the system call number.
>
> The ptrace code sets the ILC unconditionally to a value which matches the
> svc instruction. However the svc instruction also may have been executed
> via the execute or execute relative long instruction, which have a
> different length. Therefore preserve the ILC and only change the system
> call number using syscall_set_nr().
>
> This makes sure that in case of a PSW rewind the instruction address
> points to the correct instruction.
>
> Fixes: 56e62a737028 ("s390: convert to generic entry")
> Signed-off-by: Heiko Carstens <hca@xxxxxxxxxxxxx>
> ---
> arch/s390/kernel/ptrace.c | 9 ++++-----
> 1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
> index 125ca4c4e30c..d8d5e843859c 100644
> --- a/arch/s390/kernel/ptrace.c
> +++ b/arch/s390/kernel/ptrace.c
> @@ -34,6 +34,7 @@
> #include <asm/ptrace.h>
> #include <asm/rwonce.h>
> #include <asm/fpu.h>
> +#include <asm/syscall.h>
>
> #include "entry.h"
>
> @@ -345,11 +346,9 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
> return -EINVAL;
> }
>
> - if (test_pt_regs_flag(regs, PIF_SYSCALL) &&
> - addr == offsetof(struct user, regs.gprs[2])) {
> - struct pt_regs *regs = task_pt_regs(child);
> -
> - regs->int_code = 0x20000 | (data & 0xffff);
> + if (addr == offsetof(struct user, regs.gprs[2])) {
> + if (test_pt_regs_flag(regs, PIF_SYSCALL))
> + syscall_set_nr(child, regs, data);
> }
> *(addr_t *)((addr_t) &regs->psw + addr) = data;
> } else if (addr < offsetof(struct user, regs.orig_gpr2)) {

Reviewed-by: Sven Schnelle <svens@xxxxxxxxxxxxx>