1996-05-04 11:50:46 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-04 11:50:46 +04:00
Critical Fault handling
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
1996-05-04 11:50:46 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 11:50:46 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-05-04 11:50:46 +04:00
*/
# include "includes.h"
2006-04-04 04:27:50 +04:00
# ifdef HAVE_SYS_PRCTL_H
# include <sys/prctl.h>
# endif
1998-04-13 23:24:06 +04:00
static void ( * cont_fn ) ( void * ) ;
2007-11-16 01:19:52 +03:00
static char * corepath ;
1996-05-04 11:50:46 +04:00
/*******************************************************************
report a fault
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void fault_report ( int sig )
{
1998-08-11 17:55:16 +04:00
static int counter ;
if ( counter ) _exit ( 1 ) ;
counter + + ;
2006-04-04 04:27:50 +04:00
DEBUGSEP ( 0 ) ;
2003-08-20 21:13:38 +04:00
DEBUG ( 0 , ( " INTERNAL ERROR: Signal %d in pid %d (%s) " , sig , ( int ) sys_getpid ( ) , SAMBA_VERSION_STRING ) ) ;
2005-08-17 10:01:38 +04:00
DEBUG ( 0 , ( " \n Please read the Trouble-Shooting section of the Samba3-HOWTO \n " ) ) ;
DEBUG ( 0 , ( " \n From: http://www.samba.org/samba/docs/Samba3-HOWTO.pdf \n " ) ) ;
2006-04-04 04:27:50 +04:00
DEBUGSEP ( 0 ) ;
1996-05-04 11:50:46 +04:00
1998-08-21 15:37:40 +04:00
smb_panic ( " internal error " ) ;
1996-05-04 11:50:46 +04:00
1998-08-11 17:55:16 +04:00
if ( cont_fn ) {
cont_fn ( NULL ) ;
1996-05-04 11:50:46 +04:00
# ifdef SIGSEGV
1998-08-11 17:55:16 +04:00
CatchSignal ( SIGSEGV , SIGNAL_CAST SIG_DFL ) ;
1996-05-04 11:50:46 +04:00
# endif
# ifdef SIGBUS
1998-08-11 17:55:16 +04:00
CatchSignal ( SIGBUS , SIGNAL_CAST SIG_DFL ) ;
2004-01-22 04:50:58 +03:00
# endif
# ifdef SIGABRT
CatchSignal ( SIGABRT , SIGNAL_CAST SIG_DFL ) ;
1996-05-04 11:50:46 +04:00
# endif
1998-08-11 17:55:16 +04:00
return ; /* this should cause a core dump */
}
exit ( 1 ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
catch serious errors
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void sig_fault ( int sig )
{
1998-08-11 17:55:16 +04:00
fault_report ( sig ) ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
setup our fault handlers
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-04-13 23:24:06 +04:00
void fault_setup ( void ( * fn ) ( void * ) )
1996-05-04 11:50:46 +04:00
{
1998-08-11 17:55:16 +04:00
cont_fn = fn ;
1996-05-04 11:50:46 +04:00
# ifdef SIGSEGV
1998-08-11 17:55:16 +04:00
CatchSignal ( SIGSEGV , SIGNAL_CAST sig_fault ) ;
1996-05-04 11:50:46 +04:00
# endif
# ifdef SIGBUS
1998-08-11 17:55:16 +04:00
CatchSignal ( SIGBUS , SIGNAL_CAST sig_fault ) ;
1996-05-04 11:50:46 +04:00
# endif
2004-01-22 04:50:58 +03:00
# ifdef SIGABRT
CatchSignal ( SIGABRT , SIGNAL_CAST sig_fault ) ;
# endif
1996-05-04 11:50:46 +04:00
}
2006-04-04 04:27:50 +04:00
/*******************************************************************
make all the preparations to safely dump a core file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void dump_core_setup ( const char * progname )
{
2007-11-16 01:19:52 +03:00
char * logbase = NULL ;
char * end = NULL ;
2006-04-04 04:27:50 +04:00
if ( lp_logfile ( ) & & * lp_logfile ( ) ) {
2007-11-16 01:19:52 +03:00
if ( asprintf ( & logbase , " %s " , lp_logfile ( ) ) < 0 ) {
return ;
}
2006-04-04 04:27:50 +04:00
if ( ( end = strrchr_m ( logbase , ' / ' ) ) ) {
* end = ' \0 ' ;
}
} else {
/* We will end up here is the log file is given on the command
* line by the - l option but the " log file " option is not set
* in smb . conf .
*/
2007-12-10 22:30:37 +03:00
if ( asprintf ( & logbase , " %s " , get_dyn_LOGFILEBASE ( ) ) < 0 ) {
2007-11-16 01:19:52 +03:00
return ;
}
2006-04-04 04:27:50 +04:00
}
SMB_ASSERT ( progname ! = NULL ) ;
2007-11-16 01:19:52 +03:00
if ( asprintf ( & corepath , " %s/cores " , logbase ) < 0 ) {
SAFE_FREE ( logbase ) ;
return ;
}
2006-04-04 04:27:50 +04:00
mkdir ( corepath , 0700 ) ;
2007-11-16 01:19:52 +03:00
SAFE_FREE ( corepath ) ;
if ( asprintf ( & corepath , " %s/cores/%s " ,
logbase , progname ) < 0 ) {
SAFE_FREE ( logbase ) ;
return ;
}
2006-04-04 04:27:50 +04:00
mkdir ( corepath , 0700 ) ;
sys_chown ( corepath , getuid ( ) , getgid ( ) ) ;
chmod ( corepath , 0700 ) ;
2007-11-30 03:30:18 +03:00
SAFE_FREE ( logbase ) ;
2007-11-16 01:19:52 +03:00
2006-04-04 04:27:50 +04:00
# ifdef HAVE_GETRLIMIT
# ifdef RLIMIT_CORE
{
struct rlimit rlp ;
getrlimit ( RLIMIT_CORE , & rlp ) ;
rlp . rlim_cur = MAX ( 16 * 1024 * 1024 , rlp . rlim_cur ) ;
setrlimit ( RLIMIT_CORE , & rlp ) ;
getrlimit ( RLIMIT_CORE , & rlp ) ;
DEBUG ( 3 , ( " Maximum core file size limits now %d(soft) %d(hard) \n " ,
( int ) rlp . rlim_cur , ( int ) rlp . rlim_max ) ) ;
}
# endif
# endif
# if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
/* On Linux we lose the ability to dump core when we change our user
* ID . We know how to dump core safely , so let ' s make sure we have our
* dumpable flag set .
*/
prctl ( PR_SET_DUMPABLE , 1 ) ;
# endif
/* FIXME: if we have a core-plus-pid facility, configurably set
* this up here .
*/
}
void dump_core ( void )
{
2007-09-14 15:07:02 +04:00
static bool called ;
if ( called ) {
DEBUG ( 0 , ( " dump_core() called recursive \n " ) ) ;
exit ( 1 ) ;
}
called = true ;
2006-05-16 06:50:49 +04:00
/* Note that even if core dumping has been disabled, we still set up
* the core path . This is to handle the case where core dumping is
* turned on in smb . conf and the relevant daemon is not restarted .
*/
if ( ! lp_enable_core_files ( ) ) {
2007-04-06 23:17:15 +04:00
DEBUG ( 0 , ( " Exiting on internal error (core file administratively disabled) \n " ) ) ;
2006-05-16 06:50:49 +04:00
exit ( 1 ) ;
}
2006-11-07 20:18:00 +03:00
# if DUMP_CORE
2007-04-17 21:17:19 +04:00
/* If we're running as non root we might not be able to dump the core
* file to the corepath . There must not be an unbecome_root ( ) before
* we call abort ( ) . */
2007-04-17 22:35:10 +04:00
if ( geteuid ( ) ! = 0 ) {
2007-04-17 21:17:19 +04:00
become_root ( ) ;
}
2008-06-13 13:56:40 +04:00
if ( corepath = = NULL ) {
DEBUG ( 0 , ( " Can not dump core: corepath not set up \n " ) ) ;
exit ( 1 ) ;
}
2006-04-04 04:27:50 +04:00
if ( * corepath ! = ' \0 ' ) {
/* The chdir might fail if we dump core before we finish
* processing the config file .
*/
if ( chdir ( corepath ) ! = 0 ) {
2006-11-07 20:18:00 +03:00
DEBUG ( 0 , ( " unable to change to %s \n " , corepath ) ) ;
2006-04-04 04:27:50 +04:00
DEBUGADD ( 0 , ( " refusing to dump core \n " ) ) ;
exit ( 1 ) ;
}
DEBUG ( 0 , ( " dumping core in %s \n " , corepath ) ) ;
}
umask ( ~ ( 0700 ) ) ;
dbgflush ( ) ;
/* Ensure we don't have a signal handler for abort. */
# ifdef SIGABRT
CatchSignal ( SIGABRT , SIGNAL_CAST SIG_DFL ) ;
# endif
abort ( ) ;
2006-11-07 20:18:00 +03:00
# else /* DUMP_CORE */
exit ( 1 ) ;
# endif /* DUMP_CORE */
2006-04-04 04:27:50 +04:00
}