Page MenuHomeFreeBSD

D24813.id72116.diff
No OneTemporary

D24813.id72116.diff

Index: libexec/Makefile
===================================================================
--- libexec/Makefile
+++ libexec/Makefile
@@ -7,6 +7,7 @@
${_atrun} \
${_blacklistd-helper} \
${_comsat} \
+ corestop \
${_dma} \
flua \
getty \
Index: libexec/corestop/Makefile
===================================================================
--- /dev/null
+++ libexec/corestop/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SCRIPTS= corestop.sh
+
+.include <bsd.prog.mk>
Index: libexec/corestop/corestop.sh
===================================================================
--- /dev/null
+++ libexec/corestop/corestop.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+die() {
+ echo "$*; exiting" 1>&2
+ exit 1
+}
+
+PID="$1"
+EUID="$2"
+
+if [ "$3" != "su-done" ]; then
+ # Reexecute ourselves as user $EUID.
+ LOGIN=$(getent passwd "${EUID}" | cut -f 1 -d ':')
+
+ if [ -z "${LOGIN}" ]; then
+ die "cannot retrieve login name for EUID ${EUID}"
+ exit 1
+ fi
+
+ exec su -l ${LOGIN} -c "${0} ${PID} ${EUID} su-done"
+
+ # This cannot happen, but hey, what if there's a bug in sh(1)?
+ exit 1
+fi
+
+# From this point on we're running as user $EUID.
+
+if [ "${EUID}" -ne $(id -u) ]; then
+ # Make extra sure it doesn't happen.
+ die "not running as EUID ${EUID}"
+fi
+
+# Get the process working directory.
+CWD=$(procstat -f "${PID}" | awk '$3 == "cwd" { print $10 }')
+[ -n "${CWD}" ] || die "unable to query working directory"
+
+# Get process name.
+COMM=$(procstat -b "${PID}" | awk 'NR == 2 { print $2 }')
+[ -n "${CWD}" ] || die "unable to query process name"
+
+CORETMP=$(mktemp -d -t corestop.XXXXXX)
+if [ $? -ne 0 -o -z "${CORETMP}" ]; then
+ die "mktemp failed"
+fi
+
+cd "${CORETMP}"
+
+show() {
+ echo "\$ $@"
+ $@
+ echo
+}
+
+{
+ echo bt | show /usr/bin/lldb -p "${PID}"
+ #echo bt | show /usr/local/bin/gdb -q -p "${PID}"
+
+ show procstat arguments "${PID}"
+ show procstat environment "${PID}"
+ show procstat vm "${PID}"
+ show procstat files "${PID}"
+ show procstat threads "${PID}"
+ show procstat basic "${PID}"
+ show procstat binary "${PID}"
+ show procstat credentials "${PID}"
+ show procstat auxv "${PID}"
+ show procstat signal "${PID}"
+ show procstat tsignal "${PID}"
+ show procstat kstack "${PID}"
+ show procstat rlimit "${PID}"
+ # XXX: The one below doesn't seem to work.
+ #show procstat ptlwpinfo "${PID}"
+ show procstat rusage "${PID}"
+ show procstat cpuset "${PID}"
+
+} > "${CORETMP}/core.txt" 2>&1
+
+# Get list of files mapped as executable into the process virtual memory,
+# ie the main executable and its shared libraries.
+FILES=$(procstat -v "${PID}" | awk '$4 ~ /x/ && $10 == "vn" {print $11 }' | sort -u | xargs)
+
+gcore -c "${COMM}.core" "${PID}"
+
+COREDIR="${COMM}.${PID}.coredir"
+CORETAR="${CWD}/${COREDIR}.tar.gz"
+tar -c -z -L -s ",^,${COREDIR}/," -f "${CORETAR}" * ${FILES}
+rc=$?
+rm -rf "${CORETMP}"
+
+if [ $rc -eq 0 ]; then
+ echo "${CORETAR} created for pid ${PID} (${COMM}), euid ${EUID}"
+fi
Index: sbin/devd/devd.conf
===================================================================
--- sbin/devd/devd.conf
+++ sbin/devd/devd.conf
@@ -263,6 +263,13 @@
action "/etc/rc.resume acpi $notify";
};
+notify 10 {
+ match "system" "kernel";
+ match "subsystem" "signal";
+ match "type" "corestop";
+ action "/usr/libexec/corestop $pid $euid 2>&1 | /usr/bin/logger -st corestop\(pid=$pid\); kill -KILL $pid";
+};
+
/* EXAMPLES TO END OF FILE
# An example of something that a vendor might install if you were to
Index: sbin/devd/devd.conf.5
===================================================================
--- sbin/devd/devd.conf.5
+++ sbin/devd/devd.conf.5
@@ -272,6 +272,8 @@
Name of attached/detached device.
.It Li endpoints
Endpoint count (USB).
+.It Li euid
+Effective UID (corestop).
.It Li function
Card functions.
.It Li interface
@@ -295,7 +297,8 @@
.It Li parent
Parent device.
.It Li pid
-PID of the process triggering the rule (RCTL).
+PID of the process triggering the rule (RCTL),
+or the process that crashed (corestop).
.It Li port
Hub port number (USB).
.It Li product
@@ -521,6 +524,9 @@
.It Sy Type
.It Li coredump
Notification that a process has crashed and dumped core.
+.It Li corestop
+Notification that a process would crash, but was stopped
+just before executing the offending instruction.
.El
.El
.Pp
Index: sys/kern/kern_sig.c
===================================================================
--- sys/kern/kern_sig.c
+++ sys/kern/kern_sig.c
@@ -189,6 +189,10 @@
SYSCTL_INT(_kern, OID_AUTO, coredump, CTLFLAG_RW,
&do_coredump, 0, "Enable/Disable coredumps");
+static int do_corestop = 0;
+SYSCTL_INT(_kern, OID_AUTO, corestop, CTLFLAG_RW,
+ &do_corestop, 0, "Stop the process instead of dumping core");
+
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");
@@ -2977,7 +2981,17 @@
#endif
break; /* == ignore */
}
+
/*
+ * If the process is being corestopped, signals
+ * that would otherwise coredump turn into stops.
+ */
+ if ((p->p_flag2 & P2_CORESTOPPED) &&
+ (prop & SIGPROP_CORE)) {
+ prop |= SIGPROP_STOP;
+ }
+
+ /*
* If there is a pending stop signal to process with
* default action, stop here, then clear the signal.
* Traced or exiting processes should ignore stops.
@@ -3064,6 +3078,43 @@
}
}
+static void
+corestop(int sig)
+{
+ char strbuf[32];
+ struct thread *td;
+ struct proc *p;
+ int rv;
+
+ td = curthread;
+ p = td->td_proc;
+
+ KASSERT((p->p_flag2 & P2_CORESTOPPED) == 0,
+ ("%s: P2_CORESTOPPED already set", __func__));
+
+ /*
+ * Borrow policy checking from coredump(9).
+ */
+ if ((!sugid_coredump && (p->p_flag & P_SUGID) != 0) ||
+ (p->p_flag2 & P2_NOTRACE) != 0) {
+ PROC_UNLOCK(p);
+ return;
+ }
+
+ p->p_flag2 |= P2_CORESTOPPED;
+ log(LOG_INFO,
+ "pid %d (%s), jid %d, uid %d: would exit on "
+ "signal %d (core stopped)\n", p->p_pid, p->p_comm,
+ p->p_ucred->cr_prison->pr_id,
+ td->td_ucred->cr_uid,
+ sig &~ WCOREFLAG);
+ rv = snprintf(strbuf, sizeof(strbuf),
+ "pid=%d euid=%d", p->p_pid, p->p_ucred->cr_uid);
+ KASSERT(rv > 0 && rv < sizeof(strbuf),
+ ("%s: snprintf failed\n", __func__));
+ devctl_notify("kernel", "signal", "corestop", strbuf);
+}
+
/*
* Take the action for the specified signal
* from the current set of pending signals.
@@ -3100,14 +3151,18 @@
#endif
if (action == SIG_DFL) {
- /*
- * Default action, where the default is to kill
- * the process. (Other cases were ignored above.)
- */
- mtx_unlock(&ps->ps_mtx);
- proc_td_siginfo_capture(td, &ksi.ksi_info);
- sigexit(td, sig);
- /* NOTREACHED */
+ if (do_corestop && (sigprop(sig) & SIGPROP_CORE)) {
+ corestop(sig);
+ } else {
+ /*
+ * Default action, where the default is to kill
+ * the process. (Other cases were ignored above.)
+ */
+ mtx_unlock(&ps->ps_mtx);
+ proc_td_siginfo_capture(td, &ksi.ksi_info);
+ sigexit(td, sig);
+ /* NOTREACHED */
+ }
} else {
/*
* If we get here, the signal must be caught.
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -782,6 +782,7 @@
#define P2_PROTMAX_DISABLE 0x00000400 /* Force disable implied PROT_MAX. */
#define P2_STKGAP_DISABLE 0x00000800 /* Disable stack gap for MAP_STACK */
#define P2_STKGAP_DISABLE_EXEC 0x00001000 /* Stack gap disabled after exec */
+#define P2_CORESTOPPED 0x00002000 /* Stopped instead of dumping core */
/* Flags protected by proctree_lock, kept in p_treeflags. */
#define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 29, 8:59 AM (17 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32261518
Default Alt Text
D24813.id72116.diff (7 KB)

Event Timeline