[BZ,#18508] S390: Fix "backtrace() returns infinitely deep stack frames with makecontext()".

Message ID mnj3c8$npj$1@ger.gmane.org
State Dropped
Headers

Commit Message

Stefan Liebler July 8, 2015, noon UTC
  On 07/07/2015 09:02 PM, Carlos O'Donell wrote:
> On 07/07/2015 01:47 PM, H.J. Lu wrote:
>> I opened:
>> https://sourceware.org/bugzilla/show_bug.cgi?id=18635
>
> Stefan,
>
> Please fix this promptly as glibc 2.22 will be released
> shortly and the test results should be clean. If we can't
> fix it promptly, then we should revert the test changes.
>
> Cheers,
> Carlos.
>
Hi,

the testcase seems to be okay, but there is a bug in i686 backtrace 
handling if the context was set via makecontext.
If we revert the test changes, the test case will pass, but the bug is 
only hidden.

If you call backtrace() function in such a context, you'll get a 
segmentation fault, too. backtrace () also uses _Unwind_Backtrace.

The "exitcode"-block within __makecontext in 
sysdeps/unix/sysv/linux/i386/makecontext.S is surrounded by cfi_endproc 
and cfi_startproc.
The start addresses of these cfi's seems okay, but the end addresses are 
strange - see readelf/objdump output below.

readelf --debug-dump=frames libc.so:
000043dc 00000014 000043e0 FDE cie=00000000 pc=0003f610..0e44f810
Augmentation data: 41 0e 04 10 00 00 00 f8

000043f4 00000010 000043f8 FDE cie=00000000 pc=0003f67e..0003f67e
Augmentation data: 00 00 00 0c 44 00 00 d8 43 ec ff a6 00 00 00 0

objdump -d libc.so:
/* ENTRY(__makecontext) */
0003f610 <makecontext>:
3f610: 8b 44 24 04 mov 0x4(%esp),%eax
...
/* cfi_endproc  in makecontext.S.  */
/* L(exitcode): */
3f65b: 8d 24 9c lea (%esp,%ebx,4),%esp
3f65e: e8 00 00 00 00 call 3f663 <makecontext+0x53>
3f663: 5b pop %ebx
3f664: 81 c3 91 39 16 00 add $0x163991,%ebx
3f66a: 83 3c 24 00 cmpl $0x0,(%esp)
3f66e: 74 08 je 3f678 <makecontext+0x68>
3f670: e8 2b ff ff ff call 3f5a0 <setcontext>
3f675: 89 04 24 mov %eax,(%esp)
3f678: e8 13 01 ff ff call 2f790 <exit>
3f67d: f4 hlt
/* cfi_startproc in makecontext.S.  */
/* END(__makecontext)  */
3f67e: 90 nop
3f67f: 90 nop


For a quick test, I extracted the exitcode-block to a new function with 
ENTRY/END-macros and undefined cfi_start/end_proc, like it is done in 
s390-makecontext_ret - see attached patch. Afterwards _Unwind_backtrace 
does not segfault anymore.

Please test/comment.

Bye Stefan
  

Comments

Carlos O'Donell July 8, 2015, 2:43 p.m. UTC | #1
On 07/08/2015 08:00 AM, Stefan Liebler wrote:
> On 07/07/2015 09:02 PM, Carlos O'Donell wrote:
>> On 07/07/2015 01:47 PM, H.J. Lu wrote:
>>> I opened:
>>> https://sourceware.org/bugzilla/show_bug.cgi?id=18635
>>
>> Stefan,
>>
>> Please fix this promptly as glibc 2.22 will be released
>> shortly and the test results should be clean. If we can't
>> fix it promptly, then we should revert the test changes.
>>
>> Cheers,
>> Carlos.
>>
> Hi,
> 
> the testcase seems to be okay, but there is a bug in i686 backtrace handling if the context was set via makecontext.
> If we revert the test changes, the test case will pass, but the bug is only hidden.

If that's the case then please file a bug on sourceware for
this particular failure, mark the test as XFAIL for i686 and
use a comment to reference the bug when you mark it XFAIL.

Cheers,
Carlos.
  
H.J. Lu July 8, 2015, 2:44 p.m. UTC | #2
On Wed, Jul 8, 2015 at 5:00 AM, Stefan Liebler <stli@linux.vnet.ibm.com> wrote:
> On 07/07/2015 09:02 PM, Carlos O'Donell wrote:
>>
>> On 07/07/2015 01:47 PM, H.J. Lu wrote:
>>>
>>> I opened:
>>> https://sourceware.org/bugzilla/show_bug.cgi?id=18635
>>
>>
>> Stefan,
>>
>> Please fix this promptly as glibc 2.22 will be released
>> shortly and the test results should be clean. If we can't
>> fix it promptly, then we should revert the test changes.
>>
>> Cheers,
>> Carlos.
>>
> Hi,
>
> the testcase seems to be okay, but there is a bug in i686 backtrace handling
> if the context was set via makecontext.
> If we revert the test changes, the test case will pass, but the bug is only
> hidden.
>
> If you call backtrace() function in such a context, you'll get a
> segmentation fault, too. backtrace () also uses _Unwind_Backtrace.
>
> The "exitcode"-block within __makecontext in
> sysdeps/unix/sysv/linux/i386/makecontext.S is surrounded by cfi_endproc and
> cfi_startproc.
> The start addresses of these cfi's seems okay, but the end addresses are
> strange - see readelf/objdump output below.
>
> readelf --debug-dump=frames libc.so:
> 000043dc 00000014 000043e0 FDE cie=00000000 pc=0003f610..0e44f810
> Augmentation data: 41 0e 04 10 00 00 00 f8
>
> 000043f4 00000010 000043f8 FDE cie=00000000 pc=0003f67e..0003f67e
> Augmentation data: 00 00 00 0c 44 00 00 d8 43 ec ff a6 00 00 00 0
>
> objdump -d libc.so:
> /* ENTRY(__makecontext) */
> 0003f610 <makecontext>:
> 3f610: 8b 44 24 04 mov 0x4(%esp),%eax
> ...
> /* cfi_endproc  in makecontext.S.  */
> /* L(exitcode): */
> 3f65b: 8d 24 9c lea (%esp,%ebx,4),%esp
> 3f65e: e8 00 00 00 00 call 3f663 <makecontext+0x53>
> 3f663: 5b pop %ebx
> 3f664: 81 c3 91 39 16 00 add $0x163991,%ebx
> 3f66a: 83 3c 24 00 cmpl $0x0,(%esp)
> 3f66e: 74 08 je 3f678 <makecontext+0x68>
> 3f670: e8 2b ff ff ff call 3f5a0 <setcontext>
> 3f675: 89 04 24 mov %eax,(%esp)
> 3f678: e8 13 01 ff ff call 2f790 <exit>
> 3f67d: f4 hlt
> /* cfi_startproc in makecontext.S.  */
> /* END(__makecontext)  */
> 3f67e: 90 nop
> 3f67f: 90 nop
>
>
> For a quick test, I extracted the exitcode-block to a new function with
> ENTRY/END-macros and undefined cfi_start/end_proc, like it is done in
> s390-makecontext_ret - see attached patch. Afterwards _Unwind_backtrace does
> not segfault anymore.
>
> Please test/comment.

It works.

Thanks.
  
Carlos O'Donell July 8, 2015, 2:45 p.m. UTC | #3
On 07/08/2015 10:43 AM, Carlos O'Donell wrote:
> On 07/08/2015 08:00 AM, Stefan Liebler wrote:
>> On 07/07/2015 09:02 PM, Carlos O'Donell wrote:
>>> On 07/07/2015 01:47 PM, H.J. Lu wrote:
>>>> I opened:
>>>> https://sourceware.org/bugzilla/show_bug.cgi?id=18635
>>>
>>> Stefan,
>>>
>>> Please fix this promptly as glibc 2.22 will be released
>>> shortly and the test results should be clean. If we can't
>>> fix it promptly, then we should revert the test changes.
>>>
>>> Cheers,
>>> Carlos.
>>>
>> Hi,
>>
>> the testcase seems to be okay, but there is a bug in i686 backtrace handling if the context was set via makecontext.
>> If we revert the test changes, the test case will pass, but the bug is only hidden.
> 
> If that's the case then please file a bug on sourceware for
> this particular failure, mark the test as XFAIL for i686 and
> use a comment to reference the bug when you mark it XFAIL.

Bug 18635 was already filed by H.J, so use that.

c.
  
Carlos O'Donell July 8, 2015, 2:47 p.m. UTC | #4
On 07/08/2015 10:44 AM, H.J. Lu wrote:
>> For a quick test, I extracted the exitcode-block to a new function with
>> ENTRY/END-macros and undefined cfi_start/end_proc, like it is done in
>> s390-makecontext_ret - see attached patch. Afterwards _Unwind_backtrace does
>> not segfault anymore.
>>
>> Please test/comment.
> 
> It works.

But we don't really know why...

c.
  
H.J. Lu July 8, 2015, 2:51 p.m. UTC | #5
On Wed, Jul 8, 2015 at 7:47 AM, Carlos O'Donell <carlos@redhat.com> wrote:
> On 07/08/2015 10:44 AM, H.J. Lu wrote:
>>> For a quick test, I extracted the exitcode-block to a new function with
>>> ENTRY/END-macros and undefined cfi_start/end_proc, like it is done in
>>> s390-makecontext_ret - see attached patch. Afterwards _Unwind_backtrace does
>>> not segfault anymore.
>>>
>>> Please test/comment.
>>
>> It works.
>
> But we don't really know why...
>

The hand-written frame info in i386/makecontext.S is wrong as
shown in

https://sourceware.org/bugzilla/show_bug.cgi?id=18635


Program received signal SIGSEGV, Segmentation fault.
uw_frame_state_for (context=context@entry=0x8050120 <st1+15968>,
    fs=fs@entry=0x80501a0 <st1+16096>)
    at /export/gnu/import/git/sources/gcc/libgcc/unwind-dw2.c:1249
1249      return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
(gdb) bt
#0  uw_frame_state_for (context=context@entry=0x8050120 <st1+15968>,
    fs=fs@entry=0x80501a0 <st1+16096>)
    at /export/gnu/import/git/sources/gcc/libgcc/unwind-dw2.c:1249
#1  0xf7e102a8 in _Unwind_Backtrace (trace=0x8049420 <backtrace_helper>,
    trace_argument=0x8050298 <st1+16344>)
    at /export/gnu/import/git/sources/gcc/libgcc/unwind.inc:290
#2  0x080494a6 in cf (i=-78) at tst-makecontext.c:72
#3  0xf7e55d1b in makecontext ()
    at ../sysdeps/unix/sysv/linux/i386/makecontext.S:87
#4  0xffffffb2 in ?? () <<<<<<<< Bogus return address
#5  0x00000000 in ?? ()
(gdb)
  

Patch

diff --git a/sysdeps/unix/sysv/linux/i386/makecontext.S b/sysdeps/unix/sysv/linux/i386/makecontext.S
index 8364fb9..f88abf9 100644
--- a/sysdeps/unix/sysv/linux/i386/makecontext.S
+++ b/sysdeps/unix/sysv/linux/i386/makecontext.S
@@ -85,6 +85,7 @@  ENTRY(__makecontext)
 #endif
 	/* 'makecontext' returns no value.  */
 	ret
+END(__makecontext)
 
 	/* This is the helper code which gets called if a function which
 	   is registered with 'makecontext' returns.  In this case we
@@ -92,7 +93,11 @@  ENTRY(__makecontext)
 	   the context 'makecontext' manipulated at the time of the
 	   'makecontext' call.  If the pointer is NULL the process must
 	   terminate.  */
-	cfi_endproc
+#undef cfi_startproc
+#define cfi_startproc
+#undef cfi_endproc
+#define cfi_endproc
+ENTRY(__makecontext_ret)
 L(exitcode):
 	/* This removes the parameters passed to the function given to
 	   'makecontext' from the stack.  EBX contains the number of
@@ -116,7 +121,6 @@  L(exitcode):
 	/* The 'exit' call should never return.  In case it does cause
 	   the process to terminate.  */
 	hlt
-	cfi_startproc
-END(__makecontext)
+END(__makecontext_ret)
 
 weak_alias (__makecontext, makecontext)