svn commit: r322848 - in stable/10: etc sys/kern

Will Andrews will at FreeBSD.org
Thu Aug 24 17:25:18 UTC 2017


Author: will
Date: Thu Aug 24 17:25:16 2017
New Revision: 322848
URL: https://svnweb.freebsd.org/changeset/base/322848

Log:
  MFC r278479,278494,278525,278545,278592,279237,280410:
  
  This change merges devctl notification for userland coredumps.
  
  r278479 (rpaulo):
  
    Notify devd(8) when a process crashed.
  
    This change implements a notification (via devctl) to userland when
    the kernel produces coredumps after a process has crashed.
    devd can then run a specific command to produce a human readable crash
    report.  The command is most usually a helper that runs gdb/lldb
    commands on the file/coredump pair.  It's possible to use this
    functionality for implementing automatic generation of crash reports.
  
    devd(8) will be notified of the full path of the binary that crashed and
    the full path of the coredump file.
  
  r278494 (rpaulo):
  
    Sanitise the coredump file names sent to devd.
  
    While there, add a sysctl to turn this feature off as requested by kib at .
  
  r278525 (rpaulo):
  
    Remove a printf and an strlen() from the coredump code.
  
  r278545 (rpaulo):
  
    Restore the data array in coredump(), but use a different style to
    calculate the length.
  
  r278592 (rpaulo):
  
    Remove check against NULL after M_WAITOK.
  
  r279237 (kib):
  
    Keep a reference on the coredump vnode for vn_fullpath() call.  Do it
    by moving vn_close() after the point where notification is sent.
  
  r280410 (rpaulo):
  
    Disable coredump_devctl because it could lead to leaking paths to jails.
  
  Approved by:	re

Modified:
  stable/10/etc/devd.conf
  stable/10/sys/kern/kern_sig.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/etc/devd.conf
==============================================================================
--- stable/10/etc/devd.conf	Thu Aug 24 16:49:34 2017	(r322847)
+++ stable/10/etc/devd.conf	Thu Aug 24 17:25:16 2017	(r322848)
@@ -324,4 +324,16 @@ notify 100 {
 	action "/usr/sbin/automount -c";
 };
 
+# Handle userland coredumps.
+# This commented out handler makes it possible to run an
+# automated debugging session after the core dump is generated.
+# Replace action with a proper coredump handler, but be aware that
+# it will run with elevated privileges.
+notify 10 {
+	match "system"          "kernel";
+	match "subsystem"       "signal";
+	match "type"            "coredump";
+	action "logger $comm $core";
+};
+
 */

Modified: stable/10/sys/kern/kern_sig.c
==============================================================================
--- stable/10/sys/kern/kern_sig.c	Thu Aug 24 16:49:34 2017	(r322847)
+++ stable/10/sys/kern/kern_sig.c	Thu Aug 24 17:25:16 2017	(r322848)
@@ -44,10 +44,12 @@ __FBSDID("$FreeBSD$");
 #include "opt_procdesc.h"
 
 #include <sys/param.h>
+#include <sys/ctype.h>
 #include <sys/systm.h>
 #include <sys/signalvar.h>
 #include <sys/vnode.h>
 #include <sys/acct.h>
+#include <sys/bus.h>
 #include <sys/capsicum.h>
 #include <sys/condvar.h>
 #include <sys/event.h>
@@ -183,6 +185,10 @@ static int	set_core_nodump_flag = 0;
 SYSCTL_INT(_kern, OID_AUTO, nodump_coredump, CTLFLAG_RW, &set_core_nodump_flag,
 	0, "Enable setting the NODUMP flag on coredump files");
 
+static int	coredump_devctl = 0;
+SYSCTL_INT(_kern, OID_AUTO, coredump_devctl, CTLFLAG_RW, &coredump_devctl,
+	0, "Generate a devctl notification when processes coredump");
+
 /*
  * Signal properties and actions.
  * The array below categorizes the signals and their default actions
@@ -3317,6 +3323,24 @@ out:
 	return (0);
 }
 
+static int
+coredump_sanitise_path(const char *path)
+{
+	size_t i;
+
+	/*
+	 * Only send a subset of ASCII to devd(8) because it
+	 * might pass these strings to sh -c.
+	 */
+	for (i = 0; path[i]; i++)
+		if (!(isalpha(path[i]) || isdigit(path[i])) &&
+		    path[i] != '/' && path[i] != '.' &&
+		    path[i] != '-')
+			return (0);
+
+	return (1);
+}
+
 /*
  * Dump a process' core.  The main routine does some
  * policy checking, and creates the name of the coredump;
@@ -3338,6 +3362,11 @@ coredump(struct thread *td)
 	char *name;			/* name of corefile */
 	off_t limit;
 	int compress;
+	char *data = NULL;
+	char *fullpath, *freepath = NULL;
+	size_t len;
+	static const char comm_name[] = "comm=";
+	static const char core_name[] = "core=";
 
 #ifdef COMPRESS_USER_CORES
 	compress = compress_user_cores;
@@ -3380,7 +3409,7 @@ restart:
 	    vattr.va_nlink != 1) {
 		VOP_UNLOCK(vp, 0);
 		error = EFAULT;
-		goto close;
+		goto out;
 	}
 
 	VOP_UNLOCK(vp, 0);
@@ -3425,14 +3454,39 @@ restart:
 		lf.l_type = F_UNLCK;
 		VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK);
 	}
-close:
+
+	/*
+	 * Notify the userland helper that a process triggered a core dump.
+	 * This allows the helper to run an automated debugging session.
+	 */
+	if (error != 0 || coredump_devctl == 0)
+		goto out;
+	len = MAXPATHLEN * 2 + sizeof(comm_name) - 1 +
+	    sizeof(' ') + sizeof(core_name) - 1;
+	data = malloc(len, M_TEMP, M_WAITOK);
+	if (vn_fullpath_global(td, p->p_textvp, &fullpath, &freepath) != 0)
+		goto out;
+	if (!coredump_sanitise_path(fullpath))
+		goto out;
+	snprintf(data, len, "%s%s ", comm_name, fullpath);
+	free(freepath, M_TEMP);
+	freepath = NULL;
+	if (vn_fullpath_global(td, vp, &fullpath, &freepath) != 0)
+		goto out;
+	if (!coredump_sanitise_path(fullpath))
+		goto out;
+	strlcat(data, core_name, len);
+	strlcat(data, fullpath, len);
+	devctl_notify("kernel", "signal", "coredump", data);
+out:
 	error1 = vn_close(vp, FWRITE, cred, td);
 	if (error == 0)
 		error = error1;
-out:
 #ifdef AUDIT
 	audit_proc_coredump(td, name, error);
 #endif
+	free(freepath, M_TEMP);
+	free(data, M_TEMP);
 	free(name, M_TEMP);
 	return (error);
 }


More information about the svn-src-all mailing list