[pulseaudio-tickets] [Bug 99066] Pulseaudio segfaults when ORC is used on x32

bugzilla-daemon at freedesktop.org bugzilla-daemon at freedesktop.org
Sat Feb 4 18:53:36 UTC 2017


https://bugs.freedesktop.org/show_bug.cgi?id=99066

--- Comment #14 from Tanu Kaskinen <tanuk at iki.fi> ---
I was asked for more information about the cpuid crash, so here we go:

This is the code that GCC generates for get_cpuid() on x32:

0xf7b6a270 <get_cpuid>          push   %rbp
0xf7b6a271 <get_cpuid+1>        mov    %esp,%ebp
0xf7b6a273 <get_cpuid+3>        mov    %edi,-0x4(%ebp)
0xf7b6a277 <get_cpuid+7>        mov    %rcx,%rax
0xf7b6a27a <get_cpuid+10>       mov    %r8,%rcx
0xf7b6a27d <get_cpuid+13>       mov    %esi,-0x8(%ebp)
0xf7b6a281 <get_cpuid+17>       mov    %edx,-0xc(%ebp)
0xf7b6a285 <get_cpuid+21>       mov    %eax,-0x10(%ebp)
0xf7b6a289 <get_cpuid+25>       mov    %ecx,-0x14(%ebp)
0xf7b6a28d <get_cpuid+29>       mov    -0x4(%ebp),%eax      [breakpoint]
0xf7b6a291 <get_cpuid+33>       push   %rbx
0xf7b6a292 <get_cpuid+34>       cpuid
0xf7b6a294 <get_cpuid+36>       mov    %ebx,%esi
0xf7b6a296 <get_cpuid+38>       pop    %rbx
0xf7b6a297 <get_cpuid+39>       mov    -0x8(%ebp),%edi
0xf7b6a29b <get_cpuid+43>       mov    %eax,(%edi)          [segfault]
0xf7b6a29e <get_cpuid+46>       mov    -0xc(%ebp),%eax
0xf7b6a2a2 <get_cpuid+50>       mov    %esi,(%eax)
0xf7b6a2a5 <get_cpuid+53>       mov    -0x10(%ebp),%eax
0xf7b6a2a9 <get_cpuid+57>       mov    %ecx,(%eax)
0xf7b6a2ac <get_cpuid+60>       mov    -0x14(%ebp),%eax

"[breakpoint]" marks the place where the execution stops if you set a
breakpoint with "break get_cpuid". "[segfault]" marks the place where the crash
happens.

Before the breakpoint there's the code that copies the function parameters to
the stack as follows:

%edi is the "op" parameter. It's saved to -0x4(%ebp).
%rcx is the "c" parameter. It's moved to %rax and from %rax to -0x10(%ebp).
%r8 is the "d" parameter. It's moved to %rcx and from %rcx to -0x14(%ebp).
%esi is the "a" parameter. It's saved to -0x8(%ebp).
%edx is the "b" parameter. It's saved to -0xc(%ebp).

The stack pointer is not updated when the parameters are saved to the stack.
Since the stack pointer points to the beginning of the frame, the push
instruction overwrites 8 bytes from the beginning of the frame, overwriting the
"op" and "a" parameters.

I think the push is done, because the %rbx register is special in that it must
always have the same value when returning from a function as it had when the
function started. The cpuid instruction modifies the %rbx register, so that's
why we need to save and restore the %rbx register.

After the pop, this happens:

0xf7b6a297 <get_cpuid+39>       mov    -0x8(%ebp),%edi

This reads the stack from the position where the "a" parameter was saved. The
compiler seems to assume that it has the same value that was written there in
the beginning of the function, but the push instruction has written some random
garbage there.

0xf7b6a29b <get_cpuid+43>       mov    %eax,(%edi)          [segfault]

This is supposed to save the return value (well, one part of the return value)
of the cpuid instruction to the address stored in %edi, but we just wrote
garbage to %edi, so we end up dereferencing using garbage as the pointer (in my
tests the value in %edi was 1).

-- 
You are receiving this mail because:
You are the QA Contact for the bug.
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/pulseaudio-bugs/attachments/20170204/cdb769e1/attachment-0001.html>


More information about the pulseaudio-bugs mailing list