From owner-freebsd-bugs@FreeBSD.ORG Tue Mar 31 17:40:01 2009 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id AB5161065673 for ; Tue, 31 Mar 2009 17:40:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 843D08FC1C for ; Tue, 31 Mar 2009 17:40:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id n2VHe1Tm072220 for ; Tue, 31 Mar 2009 17:40:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id n2VHe1Jq072219; Tue, 31 Mar 2009 17:40:01 GMT (envelope-from gnats) Resent-Date: Tue, 31 Mar 2009 17:40:01 GMT Resent-Message-Id: <200903311740.n2VHe1Jq072219@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Michael Moller Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 97A46106566C for ; Tue, 31 Mar 2009 17:34:45 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 84CFD8FC20 for ; Tue, 31 Mar 2009 17:34:45 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n2VHYjxx017492 for ; Tue, 31 Mar 2009 17:34:45 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id n2VHYjv1017491; Tue, 31 Mar 2009 17:34:45 GMT (envelope-from nobody) Message-Id: <200903311734.n2VHYjv1017491@www.freebsd.org> Date: Tue, 31 Mar 2009 17:34:45 GMT From: Michael Moller To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/133246: dlclose gives segfault when called in the fini function of another module X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 31 Mar 2009 17:40:02 -0000 >Number: 133246 >Category: kern >Synopsis: dlclose gives segfault when called in the fini function of another module >Confidential: no >Severity: serious >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Mar 31 17:40:01 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Michael Moller >Release: 7.1-RELEASE >Organization: Sybase, Inc. >Environment: FreeBSD xxxx 7.1-RELEASE FreeBSD 7.1-RELEASE #0: Thu Jan 1 14:37:25 UTC 2009 root@logan.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386 >Description: Dlopened ELF module A dlopens ELF module B and keeps a handle to it in a static C++ object. When the process exits, rtld_exit is called and the fini function for A is called. This function calls the object static destructor and it tries to dlclose the handle to B. This gives a segfault, and stack corruption. >How-To-Repeat: See attachment for a repro. The attachment contains 5 files, separated by === cut here ===. Separate the files, and run "build.sh" to create the shared objects and executable "prog" which will repro the problem. >Fix: Patch attached with submission follows: There are 5 files included below: build.sh ctest.h ctest1.c ctest2.c prog.c To compile, enter: ./build.sh To run the repro, enter: ./prog Result: Segmentation fault: 11 (core dumped) ==================== cut here ==================== #!/bin/bash rm *.o rm *.so rm prog g++ -g -Wall -fPIC -c ctest2.c g++ -g -shared -Wl,-soname,libctest2.so -o libctest2.so ctest2.o g++ -g -Wall -fPIC -c ctest1.c g++ -g -shared -Wl,-soname,libctest1.so -o libctest1.so ctest1.o g++ -g -Wall -I. prog.c -o prog ==================== cut here ==================== // ***************************************************** // ctest.h // ***************************************************** #ifndef CTEST_H #define CTEST_H #include #ifdef __cplusplus extern "C" { #endif void LibInit_1(void); void LibFini_1(void); void LibInit_2(void); void LibFini_2(void); void ctest1(int *); void ctest2(int *); #ifdef __cplusplus } #endif class an_init_fini_execute_me_1 { public: an_init_fini_execute_me_1 () { LibInit_1(); } ~an_init_fini_execute_me_1 () { LibFini_1(); } }; class an_init_fini_execute_me_2 { public: an_init_fini_execute_me_2 () { LibInit_2(); } ~an_init_fini_execute_me_2 () { LibFini_2(); } }; #endif ==================== cut here ==================== // ***************************************************** // ctest1.c // ***************************************************** #include #include #include "ctest.h" static int init_fini_call_count_1 = 0 ; static class an_init_fini_execute_me_1 execute_me_1; static void *lib_handle = NULL; void LibInit_1( void ) { init_fini_call_count_1++ ; if( init_fini_call_count_1 == 1 ) { fprintf( stderr, "LibInit/Fini - %s of %s\n", "Beg Init", "1" ); lib_handle = dlopen("libctest2.so", RTLD_LAZY); fprintf( stderr, "LibInit/Fini - %s of %s\n", "End Init", "1" ); } } void LibFini_1( void ) { init_fini_call_count_1-- ; if( init_fini_call_count_1 == 0 ) { fprintf( stderr, "LibInit/Fini - %s of %s\n", "Beg Fini", "1" ); if( lib_handle != NULL ) { dlclose(lib_handle); lib_handle = NULL; } fprintf( stderr, "LibInit/Fini - %s of %s\n", "End Fini", "1" ); } } void ctest1(int *i) { *i = 1; } ==================== cut here ==================== // ***************************************************** // ctest2.c // ***************************************************** #include "ctest.h" static int init_fini_call_count_2 = 0 ; static class an_init_fini_execute_me_2 execute_me_2; void LibInit_2( void ) { init_fini_call_count_2++ ; if( init_fini_call_count_2 == 1 ) { fprintf( stderr, "LibInit/Fini - %s of %s\n", "Beg Init", "2" ); fprintf( stderr, "LibInit/Fini - %s of %s\n", "End Init", "2" ); } } void LibFini_2( void ) { init_fini_call_count_2-- ; if( init_fini_call_count_2 == 0 ) { fprintf( stderr, "LibInit/Fini - %s of %s\n", "Beg Fini", "2" ); fprintf( stderr, "LibInit/Fini - %s of %s\n", "End Fini", "2" ); } } void ctest2(int *i) { *i = 2; } ==================== cut here ==================== // ***************************************************** // prog.c // ***************************************************** #include #include #include #include "ctest.h" int main(int argc, char **argv) { void *lib_handle; lib_handle = dlopen("libctest1.so", RTLD_LAZY); if (!lib_handle) { fprintf(stderr, "%s\n", dlerror()); exit(1); } dlclose(lib_handle); return 0; } >Release-Note: >Audit-Trail: >Unformatted: