Re: [RFC] weird crap with vdso on uml/i386

Al Viro
2011-08-21T06:34:58Z

On Sat, Aug 20, 2011 at 05:40:03PM -0400, Andrew Lutomirski wrote:

> will cause iret (if iret happens) to restore the original rbp in rcx
> (why? -- it seems okay if syscall is hit in __kernel_vsyscall but not
> if something else does the syscall). I don't see what saves rbp to
> the stack frame.

Far more interesting question is how the hell does that thing manage to
work in face of syscall restarts? As the matter of fact, how does it
(and sysenter-based variant) play with ptrace() *and* restarts?

Suppose we have a traced process. foo6() is called and the thing it
stopped before the sys_foo6() is reached kernel-side. The sixth argument
is on stack, ebp is set to user esp. SYSENTER happens, we read the
6th argument from userland stack and put it along with the rest into
pt_regs. tracer examines the arguments, modifies them (including the last
one) and lets the tracee run free - e.g. detaches from the tracee.

What should happen if we happen to get a signal that would restart that
sucker? Granted, it's not going to happen with mmap() - it doesn't, AFAICS,
do anything of that kind. However, I wouldn't bet a dime on other 6-argument
syscalls not stepping on that. sendto() and recvfrom(), in particular...

OK, we return to userland. The sixth argument is placed into %ebp. Linus'
"pig and proud of that" trick works and we end up slapping userland
%esp into %ebp and hitting SYSENTER again. Only one problem, though -
the sixth argument on user stack is completely unaffected by what tracer
had done. Unlike the rest of arguments, that *are* changed.

We could deal with that in case of SYSENTER if we e.g. replaced that
jmp .Lenter_kernel
with
jmp .Lrestart
and added
.Lrestart:
movl %ebp, (%esp)
jmp .Lenter_kernel
but in case of SYSCALL it seems to be even messier... Comments?

... and there I thought that last year session of asm glue sniffing couldn't
be topped by anything more unpleasant ;-/