Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0583a65f authored by Sergei Trofimovich's avatar Sergei Trofimovich Committed by Greg Kroah-Hartman
Browse files

ia64: fix user_stack_pointer() for ptrace()

commit 7ad1e366167837daeb93d0bacb57dee820b0b898 upstream.

ia64 has two stacks:

 - memory stack (or stack), pointed at by by r12

 - register backing store (register stack), pointed at by
   ar.bsp/ar.bspstore with complications around dirty
   register frame on CPU.

In [1] Dmitry noticed that PTRACE_GET_SYSCALL_INFO returns the register
stack instead memory stack.

The bug comes from the fact that user_stack_pointer() and
current_user_stack_pointer() don't return the same register:

  ulong user_stack_pointer(struct pt_regs *regs) { return regs->ar_bspstore; }
  #define current_user_stack_pointer() (current_pt_regs()->r12)

The change gets both back in sync.

I think ptrace(PTRACE_GET_SYSCALL_INFO) is the only affected user by
this bug on ia64.

The change fixes 'rt_sigreturn.gen.test' strace test where it was
observed initially.

Link: https://bugs.gentoo.org/769614 [1]
Link: https://lkml.kernel.org/r/20210331084447.2561532-1-slyfox@gentoo.org


Signed-off-by: default avatarSergei Trofimovich <slyfox@gentoo.org>
Reported-by: default avatarDmitry V. Levin <ldv@altlinux.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent cfb476f1
Loading
Loading
Loading
Loading
+1 −7
Original line number Diff line number Diff line
@@ -53,8 +53,7 @@

static inline unsigned long user_stack_pointer(struct pt_regs *regs)
{
	/* FIXME: should this be bspstore + nr_dirty regs? */
	return regs->ar_bspstore;
	return regs->r12;
}

static inline int is_syscall_success(struct pt_regs *regs)
@@ -78,11 +77,6 @@ static inline long regs_return_value(struct pt_regs *regs)
	unsigned long __ip = instruction_pointer(regs);			\
	(__ip & ~3UL) + ((__ip & 3UL) << 2);				\
})
/*
 * Why not default?  Because user_stack_pointer() on ia64 gives register
 * stack backing store instead...
 */
#define current_user_stack_pointer() (current_pt_regs()->r12)

  /* given a pointer to a task_struct, return the user's pt_regs */
# define task_pt_regs(t)		(((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1)