From: Jeff Dike <[EMAIL PROTECTED]> The 32-bit sysenter entry point mangles the sixth system call argument for both 32-bit and 64-bit ptrace. In both cases, strace shows the frame pointer (ebp) as the sixth argument.
Here's a snippet of a 64-bit strace of a 32-bit test program which calls mmap through sysenter: mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0xfff00fcc) = 0xfffffffff7f7a000 fstat64(0x1, 0xfff008d8) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0xfff0089c) = 0xfffffffff7f79000 write(1, "mmap returns 0xf7f7a000\n", 24mmap returns 0xf7f7a000 ) = 24 Here's a 32-bit strace of the same program: mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0xffc224ec) = 0xf7fcb000 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0xffc21dbc) = 0xf7fca000 write(1, "mmap returns 0xf7fcb000\n", 24mmap returns 0xf7fcb000 ) = 24 The first mmap is the one made by the test - its final argument (the offset) is 0, but strace shows 0xfff00fcc, which is the value of ebp. The second is a guilty bystander which is also showing the bug. The patch below copies %r9 (where the sixth argument has been stashed) into the RBP slot of pt_regs before syscall_trace_enter is called. This fixes ptrace. To allow a successful return to userspace, the original value of rbp must be restored. This is done by storing the current value of rbp into the RBP slot of pt_regs before the RESTORE_REST. With this patch, the straces now look like this: 64-bit: mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfffffffff7f5a000 fstat64(0x1, 0xff926ee8) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfffffffff7f59000 write(1, "mmap returns 0xf7f5a000\n", 24mmap returns 0xf7f5a000 ) = 24 32-bit: mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7fa9000 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7fa8000 write(1, "mmap returns 0xf7fa9000\n", 24mmap returns 0xf7fa9000 ) = 24 Signed-off-by: Jeff Dike <[EMAIL PROTECTED]> Signed-off-by: Andi Kleen <[EMAIL PROTECTED]> Cc: Andi Kleen <[EMAIL PROTECTED]> Signed-off-by: Andrew Morton <[EMAIL PROTECTED]> --- arch/x86_64/ia32/ia32entry.S | 12 ++++++++++++ 1 file changed, 12 insertions(+) Index: linux/arch/x86_64/ia32/ia32entry.S =================================================================== --- linux.orig/arch/x86_64/ia32/ia32entry.S +++ linux/arch/x86_64/ia32/ia32entry.S @@ -148,11 +148,23 @@ sysenter_do_call: sysenter_tracesys: CFI_RESTORE_STATE SAVE_REST + /* + * We need the 6th system call argument to be in regs->rbp at + * this point so that ptrace will see it. It's in r9 now, so copy + * it to the rbp slot now. + */ + movq %r9, RBP(%rsp) CLEAR_RREGS movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ + /* + * Now, we need the correct value of rbp to be restored. It + * was never munged, so we can save it to the rbp slot and + * just have it restored. + */ + movq %rbp, RBP(%rsp) RESTORE_REST movl %ebp, %ebp /* no need to do an access_ok check here because rbp has been - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/