Skip to contentSkip to conversation

ptrace breakage

parisc Al Viro 2 participants 3 messages Dec 9, 2012 PA-RISC architecture

lore
Share & tools
lore

Al Viro

author
#0 lore raw

1) PTRACE_SYSCALL doesn't work for 64bit process on parisc64.
Compat syscall table is used instead of 64bit one. IMO we should either refuse to allow PTRACE_SYSCALL for 64bit processes or duplicate the logics choosing the right syscall table into .Ltracesys.

2) if you have let the tracee run with PTRACE_SYSCALL and
it had stopped, you can use PTRACE_POKEUSR to modify syscall number (r20) and arguments 1--4 (r26--r23). Modifications will have effect. However, modifying arguments 5 and 6 (r22 and r21 resp.) works only when process (32bit one) runs on 64bit host - on 32bit one it has no effect. AFAICS, the diff below should fix that one.

Comments?

arch/parisc/kernel/syscall.S +4 -1
index 86742df..5e05524 100644
@@ -309,10 +309,13 @@ tracesys_next:
 	LDREG   TASK_PT_GR25(%r1), %r25
 	LDREG   TASK_PT_GR24(%r1), %r24
 	LDREG   TASK_PT_GR23(%r1), %r23
-#ifdef CONFIG_64BIT
 	LDREG   TASK_PT_GR22(%r1), %r22
 	LDREG   TASK_PT_GR21(%r1), %r21
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29			/* Reference param save area */
+#else
+	stw     %r22, -52(%r30)                 /* 5th argument */
+	stw     %r21, -56(%r30)                 /* 6th argument */
 #endif
 
 	comiclr,>>=	__NR_Linux_syscalls, %r20, %r0
maintainer
#1 lore raw
Quoted 4 lines · Al Viro

1) PTRACE_SYSCALL doesn't work for 64bit process on parisc64.
Compat syscall table is used instead of 64bit one. IMO we should either refuse to allow PTRACE_SYSCALL for 64bit processes or duplicate the logics choosing the right syscall table into .Ltracesys.

We don't have a 64 bit userspace (except for a toy one I created to test out a few thing), so I'd be happy returning -ENOSYS.

Quoted 16 lines

2) if you have let the tracee run with PTRACE_SYSCALL and
it had stopped, you can use PTRACE_POKEUSR to modify syscall number (r20) and arguments 1--4 (r26--r23). Modifications will have effect. However, modifying arguments 5 and 6 (r22 and r21 resp.) works only when process (32bit one) runs on 64bit host - on 32bit one it has no effect. AFAICS, the diff below should fix that one.

Comments?

arch/parisc/kernel/syscall.S +0 -0
index 86742df..5e05524 100644
@@ -309,10 +309,13 @@ tracesys_next:
 	LDREG   TASK_PT_GR25(%r1), %r25
 	LDREG   TASK_PT_GR24(%r1), %r24

arch/parisc/kernel/syscall.S tracesys_next: · line 319

Quoted 10 lines
arch/parisc/kernel/syscall.S +4 -1
 	LDREG   TASK_PT_GR23(%r1), %r23
-#ifdef CONFIG_64BIT
 	LDREG   TASK_PT_GR22(%r1), %r22
 	LDREG   TASK_PT_GR21(%r1), %r21
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29			/* Reference param save area */
+#else
+	stw     %r22, -52(%r30)                 /* 5th argument */
+	stw     %r21, -56(%r30)                 /* 6th argument */
 #endif

I'll defer to the glibc guys on this. The code before you modified it is correct according to the ABI, but it does look like gate calls are done with 8 args in registers on 32 bit in which case the above would be correct.

James

author
#2 lore raw
Quoted 23 lines · James Bottomley
Quoted 23 lines

2) if you have let the tracee run with PTRACE_SYSCALL and
it had stopped, you can use PTRACE_POKEUSR to modify syscall number (r20) and arguments 1--4 (r26--r23). Modifications will have effect. However, modifying arguments 5 and 6 (r22 and r21 resp.) works only when process (32bit one) runs on 64bit host - on 32bit one it has no effect. AFAICS, the diff below should fix that one.

Comments?

arch/parisc/kernel/syscall.S +2 -1
index 86742df..5e05524 100644
@@ -309,10 +309,13 @@ tracesys_next:
 	LDREG   TASK_PT_GR25(%r1), %r25
 	LDREG   TASK_PT_GR24(%r1), %r24
 	LDREG   TASK_PT_GR23(%r1), %r23
-#ifdef CONFIG_64BIT
 	LDREG   TASK_PT_GR22(%r1), %r22
 	LDREG   TASK_PT_GR21(%r1), %r21
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29			/* Reference param save area */
+#else
Quoted 8 lines

arch/parisc/kernel/syscall.S tracesys_next: · line 319

Quoted 3 lines
arch/parisc/kernel/syscall.S +2 -0
+	stw     %r22, -52(%r30)                 /* 5th argument */
+	stw     %r21, -56(%r30)                 /* 6th argument */
 #endif

I'll defer to the glibc guys on this. The code before you modified it is correct according to the ABI, but it does look like gate calls are done with 8 args in registers on 32 bit in which case the above would be correct.

Er... What happens on PTRACE_SYSCALL path is that we reload the registers clobbered by do_syscall_trace_enter(). Sure, on 32bit we'd already pushed the arguments 5 and 6 on stack (originally from r22/r21), so they are not clobbered. However, this reload has a side effect - if whoever's tracing us does PTRACE_POKEUSER to modify pt_regs, we end up with changed value reloaded. What this patch does is making this behaviour consistent between 32bit and 64bit hosts.

BTW, note that if we e.g. end up restarting the syscall, the changes to r22 and r21 *will* have effect on the second pass on 32bit. With the current kernel. The registers will be restored from pt_regs on the way out.