Bug 598160 - genkey segfaults
Summary: genkey segfaults
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Fedora
Classification: Fedora
Component: perl-Newt
Version: 13
Hardware: All
OS: Linux
low
medium
Target Milestone: ---
Assignee: Joe Orton
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
: 604635 625005 (view as bug list)
Depends On:
Blocks: 600670
TreeView+ depends on / blocked
 
Reported: 2010-05-31 15:43 UTC by Nathanael Noblet
Modified: 2010-10-28 05:56 UTC (History)
9 users (show)

Fixed In Version: perl-Newt-1.08-25.fc13.1
Doc Type: Bug Fix
Doc Text:
Clone Of:
: 600670 (view as bug list)
Environment:
Last Closed: 2010-10-28 05:44:25 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)
HelloWorld-like script that segfaults (5.05 KB, application/x-perl)
2010-06-16 14:11 UTC, Elio Maldonado Batiz
no flags Details
minimal repro case (231 bytes, text/plain)
2010-06-16 14:43 UTC, Joe Orton
no flags Details

Description Nathanael Noblet 2010-05-31 15:43:04 UTC
Description of problem:
I received an email with the following:


  Certificate for hostname 'iridium', in file (or by nickname):
     /etc/pki/tls/certs/localhost.crt

  The certificate needs to be renewed; this can be done
  using the 'genkey' program.

When attempting to run genkey --days 365 localhost (this is a workstation using a self signed key) I get an error about a /etc/pki/tls/private/localhost.key existing, to remove it first and then re-run genkey. Once removed if I re-run genkey I get an immediate segfault. I just ran this on a CentOS 5.4 box moments before without a problem.

Version-Release number of selected component (if applicable):


How reproducible:
Always

Steps to Reproduce:
1. genkey --days 365 servername
2.
3.
  
Actual results:
segfault

Expected results:
New cert

Additional info:

Comment 1 Nathanael Noblet 2010-06-01 15:19:52 UTC
Also, genkey --gdb servername is of no help as it just segfaults anyway before getting into gdb

Comment 2 Joe Orton 2010-06-05 14:42:55 UTC
Thanks for the report.

Comment 3 Elio Maldonado Batiz 2010-06-06 19:56:17 UTC
The segfault occurs on F-13 but not on F-12. The code is the same in both Fedoras.
It happens inside RunForm in the line 
($reason, $data) = $panel->Run();
genkey has been using NSS under the covers since F-10. F-9 has the old code, the one that works fine in RHEL-4. I recompiled the F-9 tools and ran the version for F-9 I ran ./genkey --days 365 myservername and other commands and had the segfault. Could the problem be with perl-Newt?

Comment 4 Elio Maldonado Batiz 2010-06-06 20:01:06 UTC
On the other hand, perl-Newt is at the same version on F-12 and F-13.

Comment 5 Elio Maldonado Batiz 2010-06-16 14:11:20 UTC
Created attachment 424474 [details]
HelloWorld-like script that segfaults

This is the aame script as the one in Bug 600670 that this one blocks. Will reassign to perlNewt.

Comment 6 Joe Orton 2010-06-16 14:43:07 UTC
Created attachment 424486 [details]
minimal repro case

Comment 7 Joe Orton 2010-06-16 14:43:52 UTC
This one will segfault on exit.

Comment 8 Elio Maldonado Batiz 2010-06-16 14:57:11 UTC
I looked and perl-Newt F-13 (with segfault) and F-12 (no segfault) have the same code but I did find this difference.

$ diff F-12/perl-Newt.spec F-13/perl-Newt.spec 
4c4
< Release: 24%{?dist}
---
> Release: 25%{?dist}
62a63,65
> * Mon Dec  7 2009 Stepan Kasal <skasal> - 1.08-25
> - rebuild against perl 5.10.1
>

Comment 9 Petr Pisar 2010-06-16 15:15:11 UTC
This is more minimal test case:

#!/usr/bin/perl -w

use Newt;
Newt::Init();

#my $ok = Newt::Button("OK", 0);
my $panel = Newt::Panel(1, 1, "Panel example");

Newt::Finished();


If you create Newt::Panel, it will segfault. If you create Newt::Button
instead, it will not.

Comment 10 Petr Pisar 2010-06-16 16:22:32 UTC
This is trace from Perl debugger:

Package ./newt-reproducer.
in  .=Newt::Init() from ./newt-reproducer:4
out .=Newt::Init() from ./newt-reproducer:4
in  $=Newt::Panel(1, 1, 'Panel example') from ./newt-reproducer:7
 in  $=Newt::Form() from /usr/lib64/perl5/Newt.pm:342
  in  $=Newt::newtForm() from /usr/lib64/perl5/Newt.pm:250
  out $=Newt::newtForm() from /usr/lib64/perl5/Newt.pm:250
  scalar context return from Newt::newtForm: -> 20259296
 out $=Newt::Form() from /usr/lib64/perl5/Newt.pm:342
 scalar context return from Newt::Form: 'co' => newtComponent=SCALAR(0x13508e8)
   -> 20259296
 in  $=Newt::newtCreateGrid(1, 1) from /usr/lib64/perl5/Newt.pm:343
 out $=Newt::newtCreateGrid(1, 1) from /usr/lib64/perl5/Newt.pm:343
 scalar context return from Newt::newtCreateGrid: -> 17667664
out $=Newt::Panel(1, 1, 'Panel example') from ./newt-reproducer:7
scalar context return from Newt::Panel: 'co' => newtComponent=SCALAR(0x13508e8)
   -> 20259296
'g' => newtGrid=SCALAR(0x13254a0)
   -> 17667664
'refs' => HASH(0x131e138)
     empty hash
'title' => 'Panel example'
in  .=Newt::Finished() from ./newt-reproducer:9
out .=Newt::Finished() from ./newt-reproducer:9


It segfaults after Newt::Finished(). Thus it's definitively memory corruption shooting Perl deinitializer. Lets use gdb to figure out what happens.

Comment 11 Petr Pisar 2010-06-17 07:41:24 UTC
Yet shorter reproducer:

#!/usr/bin/perl -w

use Newt;
Newt::Init();

my $form = Newt::Form();
$form->DESTROY();

sleep 2;

Newt::Finished();


If you run this under debugger, you will get segfault in free(3) called from newt dynamic library:

(gdb) bt full
#0  0x000000385ac7a83c in __libc_free (mem=0x69e1e0) at malloc.c:3724
        ar_ptr = <value optimized out>
        p = 0x69e1d0
        hook = <value optimized out>
#1  0x00007ffff1d1e6e6 in newtFormDestroy (co=0x6bd290) at form.c:828
        form = 0x636db0
        i = <value optimized out>
#2  0x00007ffff1f37c90 in XS_Newt_newtFormDestroy (my_perl=<value optimized out>, cv=<value optimized out>) at Newt.c:3136
        Perl_form_nocontext = <value optimized out>
        sp = <value optimized out>
        ax = <value optimized out>
        mark = <value optimized out>
#3  0x0000003fb7ca6375 in Perl_pp_entersub (my_perl=0x603010) at pp_hot.c:2888
        markix = 0
        sp = <value optimized out>
        sv = 0x70b750
        gv = 0x6c5220
        cv = 0x70b768
        cx = <value optimized out>
        gimme = 128
        hasargs = 0 '\000'
#4  0x0000003fb7ca4666 in Perl_runops_standard (my_perl=0x603010) at run.c:40
No locals.
[...]


If you remove the explicit $form->DESTROY(), it segfaults too but in perl itself:

(gdb) run newt-reproducer arg
Starting program: /usr/bin/perl newt-reproducer arg
[Thread debugging using libthread_db enabled]

Program received signal SIGSEGV, Segmentation fault.
0x0000003fb7cb89ec in Perl_sv_clear (my_perl=0x603010, sv=0x606d48) at sv.c:5422
5422                            || CvSTART(destructor)->op_next->op_type != OP_LEAVESUB))


And if you run the code with explicit DESTROY() with non-empty command line argument AND in UTF-8 locale, you get beautiful invalid-pointer free() abort initiated by glibc:

$ LANG=en_US.UTF-8 ./newt-reproducer arg
*** glibc detected *** /usr/bin/perl: free(): invalid pointer: 0x000000385af7af68 ***
======= Backtrace: =========
/lib64/libc.so.6[0x385ac75726]
/usr/lib64/libnewt.so.0.52(newtFormDestroy+0x56)[0x7f48c98416e6]
/usr/lib64/perl5/auto/Newt/Newt.so(XS_Newt_newtFormDestroy+0x130)[0x7f48c9a5ac90]
/usr/lib64/perl5/CORE/libperl.so(Perl_pp_entersub+0x5a5)[0x3fb7ca6375]
/usr/lib64/perl5/CORE/libperl.so(Perl_runops_standard+0x16)[0x3fb7ca4666]
/usr/lib64/perl5/CORE/libperl.so(Perl_call_sv+0x4cf)[0x3fb7c4c6af]
/usr/lib64/perl5/CORE/libperl.so(Perl_sv_clear+0xb6)[0x3fb7cb8916]
/usr/lib64/perl5/CORE/libperl.so(Perl_sv_free2+0x52)[0x3fb7cb9112]
/usr/lib64/perl5/CORE/libperl.so(Perl_leave_scope+0xe45)[0x3fb7cd5bf5]
/usr/lib64/perl5/CORE/libperl.so(Perl_pp_leave+0x105)[0x3fb7ca5c85]
/usr/lib64/perl5/CORE/libperl.so(Perl_runops_standard+0x16)[0x3fb7ca4666]
/usr/lib64/perl5/CORE/libperl.so(perl_run+0x338)[0x3fb7c4d1a8]
/usr/bin/perl(main+0xdc)[0x400c5c]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x385ac1ec5d]
/usr/bin/perl[0x400ab9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 fd:02 10077                              /usr/bin/perl
00601000-00603000 rw-p 00001000 fd:02 10077                              /usr/bin/perl
01aac000-01bf5000 rw-p 00000000 00:00 0                                  [heap]
385a800000-385a81e000 r-xp 00000000 fd:02 4525                           /lib64/ld-2.12.so
385aa1e000-385aa1f000 r--p 0001e000 fd:02 4525                           /lib64/ld-2.12.so
385aa1f000-385aa20000 rw-p 0001f000 fd:02 4525                           /lib64/ld-2.12.so
385aa20000-385aa21000 rw-p 00000000 00:00 0  <==
385ac00000-385ad75000 r-xp 00000000 fd:02 6828                           /lib64/libc-2.12.so
385ad75000-385af75000 ---p 00175000 fd:02 6828                           /lib64/libc-2.12.so
385af75000-385af79000 r--p 00175000 fd:02 6828                           /lib64/libc-2.12.so
385af79000-385af7a000 rw-p 00179000 fd:02 6828                           /lib64/libc-2.12.so
385af7a000-385af7f000 rw-p 00000000 00:00 0 
385b000000-385b002000 r-xp 00000000 fd:02 21846                          /lib64/libdl-2.12.so
[...]

Comment 12 Petr Pisar 2010-06-17 08:31:17 UTC
If explicit form->DESTROY() is called, it is killed by glibc because Newt::Form::Destroy → Newt::newtFormDestroy($self->{co}) → XS_Newt_newtFormDestroy → newtFormDestroy(co) → free() is called twice on the same co. First time by explicit DESTROY, second time by Perl on object destruction (second time `co' structure members points to different memory and thus it's killed by glibc or kernel depending on target address).

I checked newt C library and there are no checks for NULL pointers, any free() is not followed by assigning NULL to freed pointer. Thus it's application (perl-Newt) responsibility not use destroyed newt components.

However I don't understand the Perl XS magic. Thus I can not say what's bad in perl-Newt XS wrapper now.

Comment 13 Petr Pisar 2010-06-17 08:49:04 UTC
If explicit form->DESTROY() is NOT called, it segfaults in perl before calling any {XS_Newt_,}newtFormDestroy(). It seems like Newt::Form constructor not registering destructor for Newt::Form properly and that explicit DESTROY() corrects destructor handler.

Comment 14 Petr Pisar 2010-06-17 09:21:04 UTC
Yep, if I remove Newt::newtFormDestroy() call from Newt.pm:

sub Newt::Form::DESTROY {
  my $self = shift;

  # Newt::newtFormDestroy($self->{co});
}

I get segfault without explicit DESTROY() call only.

Comment 15 Petr Pisar 2010-06-17 15:25:37 UTC
If I remove complete destructor sub Newt::Form::DESTROY {} definition, then Perl does not crash. And Perl destroys it on interpret termination automatically via 
XS_Newt_newtFormDestroy wrapper.

Of course if I call destructor explicitly, it will crash because it will try to free already freed memory.

So the problem has been introduced by this upstream Changelog entry probably:

Mon Oct 26 18:04:51 1998  Alejandro Escalante Medina  <amedina.mx>
    * Newt.pm: Added DESTROY to forms

Comment 16 Joe Orton 2010-06-17 15:53:48 UTC
Excellent, that works here too.  Thanks a lot Petr!

Comment 17 Joe Orton 2010-10-14 13:12:17 UTC
*** Bug 604635 has been marked as a duplicate of this bug. ***

Comment 18 Joe Orton 2010-10-14 13:12:36 UTC
*** Bug 625005 has been marked as a duplicate of this bug. ***

Comment 19 Fedora Update System 2010-10-14 13:37:58 UTC
perl-Newt-1.08-25.fc13.1 has been submitted as an update for Fedora 13.
https://admin.fedoraproject.org/updates/perl-Newt-1.08-25.fc13.1

Comment 20 Fedora Update System 2010-10-14 13:38:45 UTC
perl-Newt-1.08-27.fc14 has been submitted as an update for Fedora 14.
https://admin.fedoraproject.org/updates/perl-Newt-1.08-27.fc14

Comment 21 Fedora Update System 2010-10-14 23:05:31 UTC
perl-Newt-1.08-25.fc13.1 has been pushed to the Fedora 13 testing repository.  If problems still persist, please make note of it in this bug report.
 If you want to test the update, you can install it with 
 su -c 'yum --enablerepo=updates-testing update perl-Newt'.  You can provide feedback for this update here: https://admin.fedoraproject.org/updates/perl-Newt-1.08-25.fc13.1

Comment 22 Fedora Update System 2010-10-28 05:44:19 UTC
perl-Newt-1.08-25.fc13.1 has been pushed to the Fedora 13 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 23 Fedora Update System 2010-10-28 05:56:52 UTC
perl-Newt-1.08-27.fc14 has been pushed to the Fedora 14 stable repository.  If problems still persist, please make note of it in this bug report.


Note You need to log in before you can comment on or make changes to this bug.