When smbd dies, it would be nice if it could dump a core file.  For
several reasons, the current code is not able to do it.  The main
reasons that it could not do it were:

        1. Most UNIX variants disable core dumps in programs that have
           changed their uid or euid during operation.  This includes
           Solaris and Linux.
        2. It is quite possible that when smbd would crash it would not
           be running as root.  It may, therefore, be unable to dump the
           core file into its current directory.  
        3. There are logic errors in the code that make it so that the
           routines that would dump_core() are never called.

This set of patches addresses those issues and one other issue:  the
administrator should be able to choose whether core dumps are done or
not.  The changes introduced are:

        1. If the smb.conf parameter "core dump directory" is not
           defined, no attempt is made to dump core.  exit() is used
           rather than abort() (I think... I should verify that yet.)
        2. If the core dump directory is not safe, no attempt to dump
           core is made.  Safe is defined as mode 700, root, and not a
           symbolic link to somewhere else.
        3. If the system is Linux, prctl() is called to enable core
           dumps that were disabled by the kernel during set*uid() or
           set*gid() calls.  After enabling the core dump, it calls
           abort(), which should dump core in its CWD (core dump
           directory).  See fs/exec.c, include/linux/prctl.h, and
           kernel/sys.c in the Linux 2.4 kernel code.  My read was based
           off of the kernel-source rpm that accompanies redhat 7.3
        4. At least on Solaris, gcore(1) is an effective way to get core
           dumps to happen.  I suspect that this will be the case on a
           good number of OS's with BSD heritage.

Now the patches, in bite size pieces (against SAMBA_2_2):

    coredump-0-build.patch
        
        Does the configure.in, makefile.in, etc. changes necessary for
        finding prctl and gcore.
    
    coredump-1-parameter.patch
    
        Add a new parameter "core dump directory" parameter.  This
        parameter gets used in the new dump_core() implementation.
    
    coredump-2-delete_coredump.patch
    
        nmbd/nmbd.c, nsswitch/winbindd.c and smbd/server.c all had the
        exact same function defined in them.  Since this was the real
        guts of what I was changing, it made sense to consolidate it in
        one place so that the duplicate code does not diverge over time.
    
    coredump-3-new_coredump.patch
    
        I started out by modifying the dump_core() implementation
        removed from one of the three copies removed in the previous
        patch.  By the time I got done, I think I changed everything
        except the ulimit mangling stuff.  This is where it actually
        handles doing the core dump either through an abort or call to
        the system's gcore command.


And for a not-so-bitesize piece:

    coredump.patch
    
        The combination of coredump-[0-3]-*.patch.  You can apply this
        instead of the other four to get the same effect.
    
After applying these patches, you will need to run autoconf and make
proto.

There is some additional cleanup that could be done in code that
surrounds this code.  I will hold off on that until after I get
feedback, and will probably only submit cleanup patches for HEAD.

Comments are encouraged.
Mike
Index: Makefile.in
===================================================================
RCS file: /cvsroot/samba/source/Makefile.in,v
retrieving revision 1.227.2.146
diff -u -r1.227.2.146 Makefile.in
--- Makefile.in	26 Jul 2002 14:10:25 -0000	1.227.2.146
+++ Makefile.in	21 Aug 2002 15:28:07 -0000
@@ -17,6 +17,7 @@
 LDFLAGS=@LDFLAGS@
 AWK=@AWK@
 DYNEXP=@DYNEXP@
+GCORE=@GCORE@
 
 TERMLDFLAGS=@TERMLDFLAGS@
 TERMLIBS=@TERMLIBS@
@@ -85,7 +86,7 @@
 FLAGS2 = -DCONFIGFILE=\"$(CONFIGFILE)\" -DLMHOSTSFILE=\"$(LMHOSTSFILE)\"  
 FLAGS3 = -DSWATDIR=\"$(SWATDIR)\" -DSBINDIR=\"$(SBINDIR)\" -DLOCKDIR=\"$(LOCKDIR)\" -DCODEPAGEDIR=\"$(CODEPAGEDIR)\"
 FLAGS4 = -DDRIVERFILE=\"$(DRIVERFILE)\" -DBINDIR=\"$(BINDIR)\" -DPIDDIR=\"$(PIDDIR)\" -DLIBDIR=\"$(LIBDIR)\"
-FLAGS5 = $(FLAGS1) $(FLAGS2) $(FLAGS3) $(FLAGS4) -DHAVE_INCLUDES_H
+FLAGS5 = $(FLAGS1) $(FLAGS2) $(FLAGS3) $(FLAGS4) -DHAVE_INCLUDES_H -DGCORECOMMAND=\"$(GCORE)\"
 FLAGS  = $(ISA) $(FLAGS5) $(PASSWD_FLAGS)
 FLAGS32  = $(ISA32) $(FLAGS5) $(PASSWD_FLAGS)
 
Index: configure.in
===================================================================
RCS file: /cvsroot/samba/source/configure.in,v
retrieving revision 1.130.4.165
diff -u -r1.130.4.165 configure.in
--- configure.in	15 Aug 2002 00:58:30 -0000	1.130.4.165
+++ configure.in	21 Aug 2002 15:28:10 -0000
@@ -461,6 +461,16 @@
 # For quotas on Linux XFS filesystems
 AC_CHECK_HEADERS(linux/xqm.h)
 
+# For allowing core dumps on linux after seteuid() has been called
+AC_CHECK_HEADERS(sys/prctl.h)
+
+# For core dumps on platforms that have gcore(1)
+AC_CHECK_PROG(GCORE,gcore,gcore)
+if test x$GCORE != x ; then
+	AC_DEFINE(HAVE_GCORE)
+	AC_SUBST(GCORE)
+fi
+
 AC_CHECK_SIZEOF(int,cross)
 AC_CHECK_SIZEOF(long,cross)
 AC_CHECK_SIZEOF(short,cross)
Index: include/config.h.in
===================================================================
RCS file: /cvsroot/samba/source/include/config.h.in,v
retrieving revision 1.83.4.67
diff -u -r1.83.4.67 config.h.in
--- include/config.h.in	17 Jun 2002 15:51:33 -0000	1.83.4.67
+++ include/config.h.in	21 Aug 2002 15:28:11 -0000
@@ -1131,3 +1131,9 @@
 
 /* Define if you have the socket library (-lsocket).  */
 #undef HAVE_LIBSOCKET
+
+/* Define if you have the <sys/prctl.h> header file */
+#undef HAVE_SYS_PRCTL_H
+
+/* Define if you have the gcore command */
+#undef HAVE_GCORE
Index: include/includes.h
===================================================================
RCS file: /cvsroot/samba/source/include/includes.h,v
retrieving revision 1.190.2.41
diff -u -r1.190.2.41 includes.h
--- include/includes.h	9 Aug 2002 12:55:18 -0000	1.190.2.41
+++ include/includes.h	21 Aug 2002 15:28:11 -0000
@@ -1104,5 +1104,10 @@
 #define VA_COPY(dest, src) (dest) = (src)
 #endif
 
+/* For allowing core dumps on Linux */
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
 #endif /* _INCLUDES_H */
 
Index: param/loadparm.c
===================================================================
RCS file: /cvsroot/samba/source/param/loadparm.c,v
retrieving revision 1.251.2.113
diff -u -r1.251.2.113 loadparm.c
--- param/loadparm.c	10 Jul 2002 14:33:37 -0000	1.251.2.113
+++ param/loadparm.c	21 Aug 2002 15:28:14 -0000
@@ -120,6 +120,7 @@
 	char *szPasswdChat;
 	char *szLogFile;
 	char *szConfigFile;
+	char *szCoreDumpDirectory;
 #ifdef WITH_TDB_SAM
 	char *szTDBPasswdFile;
 #else
@@ -840,6 +841,7 @@
 	
 	{"status", P_BOOL, P_LOCAL, &sDefault.status, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE | FLAG_PRINT | FLAG_DEPRECATED},
 
+	{"core dump directory", P_STRING, P_GLOBAL, &Globals.szCoreDumpDirectory, NULL, NULL, 0},
 	{"Protocol Options", P_SEP, P_SEPARATOR},
 	
 	{"protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, 0},
@@ -1523,6 +1525,7 @@
 #define FN_LOCAL_INTEGER(fn_name,val) \
  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
 
+FN_GLOBAL_STRING(lp_coredumpdirectory, &Globals.szCoreDumpDirectory)
 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
 #ifdef WITH_TDB_SAM
Index: nmbd/nmbd.c
===================================================================
RCS file: /cvsroot/samba/source/nmbd/nmbd.c,v
retrieving revision 1.105.2.19
diff -u -r1.105.2.19 nmbd.c
--- nmbd/nmbd.c	11 Jun 2002 03:25:49 -0000	1.105.2.19
+++ nmbd/nmbd.c	21 Aug 2002 15:28:13 -0000
@@ -97,46 +97,6 @@
 	sys_select_signal();
 }
 
-#if DUMP_CORE
-/**************************************************************************** **
- Prepare to dump a core file - carefully!
- **************************************************************************** */
-
-static BOOL dump_core(void)
-{
-  char *p;
-  pstring dname;
-  pstrcpy( dname, lp_logfile() );
-  if ((p=strrchr(dname,'/')))
-    *p=0;
-  pstrcat( dname, "/corefiles" );
-  mkdir( dname, 0700 );
-  sys_chown( dname, getuid(), getgid() );
-  chmod( dname, 0700 );
-  if ( chdir(dname) )
-    return( False );
-  umask( ~(0700) );
-
-#ifdef HAVE_GETRLIMIT
-#ifdef RLIMIT_CORE
-  {
-    struct rlimit rlp;
-    getrlimit( RLIMIT_CORE, &rlp );
-    rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
-    setrlimit( RLIMIT_CORE, &rlp );
-    getrlimit( RLIMIT_CORE, &rlp );
-    DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) );
-  }
-#endif
-#endif
-
-
-  DEBUG(0,("Dumping core in %s\n",dname));
-  abort();
-  return( True );
-} /* dump_core */
-#endif
-
 /**************************************************************************** **
  Possibly continue after a fault.
  **************************************************************************** */
Index: nsswitch/winbindd.c
===================================================================
RCS file: /cvsroot/samba/source/nsswitch/winbindd.c,v
retrieving revision 1.3.2.31
diff -u -r1.3.2.31 winbindd.c
--- nsswitch/winbindd.c	17 Jun 2002 15:51:33 -0000	1.3.2.31
+++ nsswitch/winbindd.c	21 Aug 2002 15:28:13 -0000
@@ -70,46 +70,6 @@
 	return(ret);
 }
 
-#if DUMP_CORE
-
-/**************************************************************************** **
- Prepare to dump a core file - carefully!
- **************************************************************************** */
-
-static BOOL dump_core(void)
-{
-	char *p;
-	pstring dname;
-	pstrcpy( dname, lp_logfile() );
-	if ((p=strrchr(dname,'/')))
-		*p=0;
-	pstrcat( dname, "/corefiles" );
-	mkdir( dname, 0700 );
-	sys_chown( dname, getuid(), getgid() );
-	chmod( dname, 0700 );
-	if ( chdir(dname) )
-		return( False );
-	umask( ~(0700) );
- 
-#ifdef HAVE_GETRLIMIT
-#ifdef RLIMIT_CORE
-	{
-		struct rlimit rlp;
-		getrlimit( RLIMIT_CORE, &rlp );
-		rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
-		setrlimit( RLIMIT_CORE, &rlp );
-		getrlimit( RLIMIT_CORE, &rlp );
-		DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) );
-	}
-#endif
-#endif
- 
-	DEBUG(0,("Dumping core in %s\n",dname));
-	abort();
-	return( True );
-} /* dump_core */
-#endif
-
 /**************************************************************************** **
  Handle a fault..
  **************************************************************************** */
Index: smbd/server.c
===================================================================
RCS file: /cvsroot/samba/source/smbd/server.c,v
retrieving revision 1.305.2.44
diff -u -r1.305.2.44 server.c
--- smbd/server.c	11 Jun 2002 03:25:50 -0000	1.305.2.44
+++ smbd/server.c	21 Aug 2002 15:28:14 -0000
@@ -391,45 +391,6 @@
 	return(ret);
 }
 
-#if DUMP_CORE
-/*******************************************************************
- Prepare to dump a core file - carefully !
-********************************************************************/
-
-static BOOL dump_core(void)
-{
-	char *p;
-	pstring dname;
-	pstrcpy(dname,lp_logfile());
-	if ((p=strrchr(dname,'/'))) *p=0;
-	pstrcat(dname,"/corefiles");
-	mkdir(dname,0700);
-	sys_chown(dname,getuid(),getgid());
-	chmod(dname,0700);
-	if (chdir(dname)) return(False);
-	umask(~(0700));
-
-#ifdef HAVE_GETRLIMIT
-#ifdef RLIMIT_CORE
-	{
-		struct rlimit rlp;
-		getrlimit(RLIMIT_CORE, &rlp);
-		rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
-		setrlimit(RLIMIT_CORE, &rlp);
-		getrlimit(RLIMIT_CORE, &rlp);
-		DEBUG(3,("Core limits now %d %d\n",
-			 (int)rlp.rlim_cur,(int)rlp.rlim_max));
-	}
-#endif
-#endif
-
-
-	DEBUG(0,("Dumping core in %s\n",dname));
-	abort();
-	return(True);
-}
-#endif
-
 /****************************************************************************
 update the current smbd process count
 ****************************************************************************/
Index: lib/util.c
===================================================================
RCS file: /cvsroot/samba/source/lib/util.c,v
retrieving revision 1.287.4.55
diff -u -r1.287.4.55 util.c
--- lib/util.c	18 Jul 2002 23:45:02 -0000	1.287.4.55
+++ lib/util.c	21 Aug 2002 15:28:13 -0000
@@ -1082,6 +1082,100 @@
 	return (gid_t)-1;
 }
 
+/**************************************************************************** **
+ Prepare to dump a core file - carefully!
+ TODO: Some uses of this function assume that it will not just do an abort()
+       and that the return value is meaningful.  It is currently ill equipped
+       to deal with such assumptions because it modifies the umask, performs
+       a chdir, and in may cases will exit as the result of an abort().
+       All of these issues existed before I rewrote it. --Mike Gerdts
+ **************************************************************************** */
+BOOL dump_core(void)
+{
+#if DUMP_CORE
+	char *p;
+	struct stat sbuf;
+	pstring dname;
+	pstrcpy(dname, lp_coredumpdirectory());
+	if ( !(*dname) ) {
+		DEBUG(2,("Core dump skipped because \"core dump directory\" not set\n"));
+		return False;
+	}
+
+	umask(~(0700));
+
+	gain_root_privilege();
+
+	if (sys_lstat(dname,&sbuf)) {
+		DEBUG(0,("Core dump skipped: lstat(%s): %s\n",
+					dname, strerror(errno)));
+		return False;
+	}
+
+	if ( !S_ISDIR(sbuf.st_mode) ) {
+		DEBUG(0,("Core dump skipped: %s is not a directory\n", dname));
+		return False;
+	}
+	
+	if ( sbuf.st_uid != 0) {
+		DEBUG(0,("Core dump skipped: %s not owned by root\n", dname));
+		return False;
+	}
+
+	if ( sbuf.st_mode & (S_IRWXG | S_IRWXO) ) {
+		DEBUG(0,("Core dump skipped: %s is readable or writable by someon other than root\n", dname));
+		return False;
+	}
+	/* TODO: check for ACL's */
+
+	if (chdir(dname)) {
+		DEBUG(0,("Core dump skipped: cannot chdir(%s): %s\n", 
+					dname, strerror(errno)));
+		return False;
+	}
+ 
+#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
+	{
+		struct rlimit rlp;
+		getrlimit( RLIMIT_CORE, &rlp );
+		rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
+		setrlimit( RLIMIT_CORE, &rlp );
+		getrlimit( RLIMIT_CORE, &rlp );
+		DEBUG( 3, ( "Core limits now %d %d\n", 
+				(int)rlp.rlim_cur, (int)rlp.rlim_max ) );
+	}
+#endif
+	
+	DEBUG(0,("Dumping core in %s\n",dname));
+#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE)
+	/* On Linux if euid or uid has changed during execution the process
+	 * will not coredump.  This tells the kernel to dump anyways. */
+	prctl(PR_SET_DUMPABLE,1,0,0,0);
+	abort();
+	return True;	/* Not reached */
+#endif /* HAVE_SYS_PRCTL_H && PR_SET_DUMPABLE */
+
+#ifdef HAVE_GCORE
+	{
+		pstring cmd;
+		snprintf(cmd, sizeof(pstring), "%s %d", GCORECOMMAND, 
+				(int)getpid());
+		cmd[sizeof(pstring) -1] = '\0';
+		return system(cmd);
+	}
+#endif /* HAVE_GCORE */
+
+	DEBUG(3,("No reliable core dump method found.\n"));
+	abort();
+	return  False; 
+
+#else /* DUMP_CORE */
+	DEBUG(0,("Core dumps disabled on this platform\n"));
+	return ( False );
+#endif /* DUMP_CORE */
+} /* dump_core */
+
+
 /*******************************************************************
 something really nasty happened - panic!
 ********************************************************************/
@@ -1093,7 +1187,8 @@
 	}
 	DEBUG(0,("PANIC: %s\n", why));
 	dbgflush();
-	abort();
+	dump_core();
+	exit(1);
 }
 
 
Index: Makefile.in
===================================================================
RCS file: /cvsroot/samba/source/Makefile.in,v
retrieving revision 1.227.2.146
diff -u -r1.227.2.146 Makefile.in
--- Makefile.in	26 Jul 2002 14:10:25 -0000	1.227.2.146
+++ Makefile.in	21 Aug 2002 15:28:07 -0000
@@ -17,6 +17,7 @@
 LDFLAGS=@LDFLAGS@
 AWK=@AWK@
 DYNEXP=@DYNEXP@
+GCORE=@GCORE@
 
 TERMLDFLAGS=@TERMLDFLAGS@
 TERMLIBS=@TERMLIBS@
@@ -85,7 +86,7 @@
 FLAGS2 = -DCONFIGFILE=\"$(CONFIGFILE)\" -DLMHOSTSFILE=\"$(LMHOSTSFILE)\"  
 FLAGS3 = -DSWATDIR=\"$(SWATDIR)\" -DSBINDIR=\"$(SBINDIR)\" -DLOCKDIR=\"$(LOCKDIR)\" -DCODEPAGEDIR=\"$(CODEPAGEDIR)\"
 FLAGS4 = -DDRIVERFILE=\"$(DRIVERFILE)\" -DBINDIR=\"$(BINDIR)\" -DPIDDIR=\"$(PIDDIR)\" -DLIBDIR=\"$(LIBDIR)\"
-FLAGS5 = $(FLAGS1) $(FLAGS2) $(FLAGS3) $(FLAGS4) -DHAVE_INCLUDES_H
+FLAGS5 = $(FLAGS1) $(FLAGS2) $(FLAGS3) $(FLAGS4) -DHAVE_INCLUDES_H -DGCORECOMMAND=\"$(GCORE)\"
 FLAGS  = $(ISA) $(FLAGS5) $(PASSWD_FLAGS)
 FLAGS32  = $(ISA32) $(FLAGS5) $(PASSWD_FLAGS)
 
Index: configure.in
===================================================================
RCS file: /cvsroot/samba/source/configure.in,v
retrieving revision 1.130.4.165
diff -u -r1.130.4.165 configure.in
--- configure.in	15 Aug 2002 00:58:30 -0000	1.130.4.165
+++ configure.in	21 Aug 2002 15:28:10 -0000
@@ -461,6 +461,16 @@
 # For quotas on Linux XFS filesystems
 AC_CHECK_HEADERS(linux/xqm.h)
 
+# For allowing core dumps on linux after seteuid() has been called
+AC_CHECK_HEADERS(sys/prctl.h)
+
+# For core dumps on platforms that have gcore(1)
+AC_CHECK_PROG(GCORE,gcore,gcore)
+if test x$GCORE != x ; then
+	AC_DEFINE(HAVE_GCORE)
+	AC_SUBST(GCORE)
+fi
+
 AC_CHECK_SIZEOF(int,cross)
 AC_CHECK_SIZEOF(long,cross)
 AC_CHECK_SIZEOF(short,cross)
Index: include/config.h.in
===================================================================
RCS file: /cvsroot/samba/source/include/config.h.in,v
retrieving revision 1.83.4.67
diff -u -r1.83.4.67 config.h.in
--- include/config.h.in	17 Jun 2002 15:51:33 -0000	1.83.4.67
+++ include/config.h.in	21 Aug 2002 15:28:11 -0000
@@ -1131,3 +1131,9 @@
 
 /* Define if you have the socket library (-lsocket).  */
 #undef HAVE_LIBSOCKET
+
+/* Define if you have the <sys/prctl.h> header file */
+#undef HAVE_SYS_PRCTL_H
+
+/* Define if you have the gcore command */
+#undef HAVE_GCORE
Index: include/includes.h
===================================================================
RCS file: /cvsroot/samba/source/include/includes.h,v
retrieving revision 1.190.2.41
diff -u -r1.190.2.41 includes.h
--- include/includes.h	9 Aug 2002 12:55:18 -0000	1.190.2.41
+++ include/includes.h	21 Aug 2002 15:28:11 -0000
@@ -1104,5 +1104,10 @@
 #define VA_COPY(dest, src) (dest) = (src)
 #endif
 
+/* For allowing core dumps on Linux */
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
 #endif /* _INCLUDES_H */
 
Index: lib/util.c
===================================================================
RCS file: /cvsroot/samba/source/lib/util.c,v
retrieving revision 1.287.4.55
diff -u -r1.287.4.55 util.c
--- lib/util.c	18 Jul 2002 23:45:02 -0000	1.287.4.55
+++ lib/util.c	21 Aug 2002 15:28:13 -0000
@@ -1082,6 +1082,100 @@
 	return (gid_t)-1;
 }
 
+/**************************************************************************** **
+ Prepare to dump a core file - carefully!
+ TODO: Some uses of this function assume that it will not just do an abort()
+       and that the return value is meaningful.  It is currently ill equipped
+       to deal with such assumptions because it modifies the umask, performs
+       a chdir, and in may cases will exit as the result of an abort().
+       All of these issues existed before I rewrote it. --Mike Gerdts
+ **************************************************************************** */
+BOOL dump_core(void)
+{
+#if DUMP_CORE
+	char *p;
+	struct stat sbuf;
+	pstring dname;
+	pstrcpy(dname, lp_coredumpdirectory());
+	if ( !(*dname) ) {
+		DEBUG(2,("Core dump skipped because \"core dump directory\" not set\n"));
+		return False;
+	}
+
+	umask(~(0700));
+
+	gain_root_privilege();
+
+	if (sys_lstat(dname,&sbuf)) {
+		DEBUG(0,("Core dump skipped: lstat(%s): %s\n",
+					dname, strerror(errno)));
+		return False;
+	}
+
+	if ( !S_ISDIR(sbuf.st_mode) ) {
+		DEBUG(0,("Core dump skipped: %s is not a directory\n", dname));
+		return False;
+	}
+	
+	if ( sbuf.st_uid != 0) {
+		DEBUG(0,("Core dump skipped: %s not owned by root\n", dname));
+		return False;
+	}
+
+	if ( sbuf.st_mode & (S_IRWXG | S_IRWXO) ) {
+		DEBUG(0,("Core dump skipped: %s is readable or writable by someon other than root\n", dname));
+		return False;
+	}
+	/* TODO: check for ACL's */
+
+	if (chdir(dname)) {
+		DEBUG(0,("Core dump skipped: cannot chdir(%s): %s\n", 
+					dname, strerror(errno)));
+		return False;
+	}
+ 
+#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
+	{
+		struct rlimit rlp;
+		getrlimit( RLIMIT_CORE, &rlp );
+		rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
+		setrlimit( RLIMIT_CORE, &rlp );
+		getrlimit( RLIMIT_CORE, &rlp );
+		DEBUG( 3, ( "Core limits now %d %d\n", 
+				(int)rlp.rlim_cur, (int)rlp.rlim_max ) );
+	}
+#endif
+	
+	DEBUG(0,("Dumping core in %s\n",dname));
+#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE)
+	/* On Linux if euid or uid has changed during execution the process
+	 * will not coredump.  This tells the kernel to dump anyways. */
+	prctl(PR_SET_DUMPABLE,1,0,0,0);
+	abort();
+	return True;	/* Not reached */
+#endif /* HAVE_SYS_PRCTL_H && PR_SET_DUMPABLE */
+
+#ifdef HAVE_GCORE
+	{
+		pstring cmd;
+		snprintf(cmd, sizeof(pstring), "%s %d", GCORECOMMAND, 
+				(int)getpid());
+		cmd[sizeof(pstring) -1] = '\0';
+		return system(cmd);
+	}
+#endif /* HAVE_GCORE */
+
+	DEBUG(3,("No reliable core dump method found.\n"));
+	abort();
+	return  False; 
+
+#else /* DUMP_CORE */
+	DEBUG(0,("Core dumps disabled on this platform\n"));
+	return ( False );
+#endif /* DUMP_CORE */
+} /* dump_core */
+
+
 /*******************************************************************
 something really nasty happened - panic!
 ********************************************************************/
@@ -1093,7 +1187,8 @@
 	}
 	DEBUG(0,("PANIC: %s\n", why));
 	dbgflush();
-	abort();
+	dump_core();
+	exit(1);
 }
 
 
Index: nmbd/nmbd.c
===================================================================
RCS file: /cvsroot/samba/source/nmbd/nmbd.c,v
retrieving revision 1.105.2.19
diff -u -r1.105.2.19 nmbd.c
--- nmbd/nmbd.c	11 Jun 2002 03:25:49 -0000	1.105.2.19
+++ nmbd/nmbd.c	21 Aug 2002 15:28:13 -0000
@@ -97,46 +97,6 @@
 	sys_select_signal();
 }
 
-#if DUMP_CORE
-/**************************************************************************** **
- Prepare to dump a core file - carefully!
- **************************************************************************** */
-
-static BOOL dump_core(void)
-{
-  char *p;
-  pstring dname;
-  pstrcpy( dname, lp_logfile() );
-  if ((p=strrchr(dname,'/')))
-    *p=0;
-  pstrcat( dname, "/corefiles" );
-  mkdir( dname, 0700 );
-  sys_chown( dname, getuid(), getgid() );
-  chmod( dname, 0700 );
-  if ( chdir(dname) )
-    return( False );
-  umask( ~(0700) );
-
-#ifdef HAVE_GETRLIMIT
-#ifdef RLIMIT_CORE
-  {
-    struct rlimit rlp;
-    getrlimit( RLIMIT_CORE, &rlp );
-    rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
-    setrlimit( RLIMIT_CORE, &rlp );
-    getrlimit( RLIMIT_CORE, &rlp );
-    DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) );
-  }
-#endif
-#endif
-
-
-  DEBUG(0,("Dumping core in %s\n",dname));
-  abort();
-  return( True );
-} /* dump_core */
-#endif
-
 /**************************************************************************** **
  Possibly continue after a fault.
  **************************************************************************** */
Index: nsswitch/winbindd.c
===================================================================
RCS file: /cvsroot/samba/source/nsswitch/winbindd.c,v
retrieving revision 1.3.2.31
diff -u -r1.3.2.31 winbindd.c
--- nsswitch/winbindd.c	17 Jun 2002 15:51:33 -0000	1.3.2.31
+++ nsswitch/winbindd.c	21 Aug 2002 15:28:13 -0000
@@ -70,46 +70,6 @@
 	return(ret);
 }
 
-#if DUMP_CORE
-
-/**************************************************************************** **
- Prepare to dump a core file - carefully!
- **************************************************************************** */
-
-static BOOL dump_core(void)
-{
-	char *p;
-	pstring dname;
-	pstrcpy( dname, lp_logfile() );
-	if ((p=strrchr(dname,'/')))
-		*p=0;
-	pstrcat( dname, "/corefiles" );
-	mkdir( dname, 0700 );
-	sys_chown( dname, getuid(), getgid() );
-	chmod( dname, 0700 );
-	if ( chdir(dname) )
-		return( False );
-	umask( ~(0700) );
- 
-#ifdef HAVE_GETRLIMIT
-#ifdef RLIMIT_CORE
-	{
-		struct rlimit rlp;
-		getrlimit( RLIMIT_CORE, &rlp );
-		rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
-		setrlimit( RLIMIT_CORE, &rlp );
-		getrlimit( RLIMIT_CORE, &rlp );
-		DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) );
-	}
-#endif
-#endif
- 
-	DEBUG(0,("Dumping core in %s\n",dname));
-	abort();
-	return( True );
-} /* dump_core */
-#endif
-
 /**************************************************************************** **
  Handle a fault..
  **************************************************************************** */
Index: param/loadparm.c
===================================================================
RCS file: /cvsroot/samba/source/param/loadparm.c,v
retrieving revision 1.251.2.113
diff -u -r1.251.2.113 loadparm.c
--- param/loadparm.c	10 Jul 2002 14:33:37 -0000	1.251.2.113
+++ param/loadparm.c	21 Aug 2002 15:28:14 -0000
@@ -120,6 +120,7 @@
 	char *szPasswdChat;
 	char *szLogFile;
 	char *szConfigFile;
+	char *szCoreDumpDirectory;
 #ifdef WITH_TDB_SAM
 	char *szTDBPasswdFile;
 #else
@@ -840,6 +841,7 @@
 	
 	{"status", P_BOOL, P_LOCAL, &sDefault.status, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE | FLAG_PRINT | FLAG_DEPRECATED},
 
+	{"core dump directory", P_STRING, P_GLOBAL, &Globals.szCoreDumpDirectory, NULL, NULL, 0},
 	{"Protocol Options", P_SEP, P_SEPARATOR},
 	
 	{"protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, 0},
@@ -1523,6 +1525,7 @@
 #define FN_LOCAL_INTEGER(fn_name,val) \
  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
 
+FN_GLOBAL_STRING(lp_coredumpdirectory, &Globals.szCoreDumpDirectory)
 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
 #ifdef WITH_TDB_SAM
Index: smbd/server.c
===================================================================
RCS file: /cvsroot/samba/source/smbd/server.c,v
retrieving revision 1.305.2.44
diff -u -r1.305.2.44 server.c
--- smbd/server.c	11 Jun 2002 03:25:50 -0000	1.305.2.44
+++ smbd/server.c	21 Aug 2002 15:28:14 -0000
@@ -391,45 +391,6 @@
 	return(ret);
 }
 
-#if DUMP_CORE
-/*******************************************************************
- Prepare to dump a core file - carefully !
-********************************************************************/
-
-static BOOL dump_core(void)
-{
-	char *p;
-	pstring dname;
-	pstrcpy(dname,lp_logfile());
-	if ((p=strrchr(dname,'/'))) *p=0;
-	pstrcat(dname,"/corefiles");
-	mkdir(dname,0700);
-	sys_chown(dname,getuid(),getgid());
-	chmod(dname,0700);
-	if (chdir(dname)) return(False);
-	umask(~(0700));
-
-#ifdef HAVE_GETRLIMIT
-#ifdef RLIMIT_CORE
-	{
-		struct rlimit rlp;
-		getrlimit(RLIMIT_CORE, &rlp);
-		rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
-		setrlimit(RLIMIT_CORE, &rlp);
-		getrlimit(RLIMIT_CORE, &rlp);
-		DEBUG(3,("Core limits now %d %d\n",
-			 (int)rlp.rlim_cur,(int)rlp.rlim_max));
-	}
-#endif
-#endif
-
-
-	DEBUG(0,("Dumping core in %s\n",dname));
-	abort();
-	return(True);
-}
-#endif
-
 /****************************************************************************
 update the current smbd process count
 ****************************************************************************/

Reply via email to