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@.
  
  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);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to