Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144427335
D51338.id158587.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D51338.id158587.diff
View Options
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -68,6 +68,7 @@
#include <sys/posix4.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
+#include <sys/rmlock.h>
#include <sys/sdt.h>
#include <sys/sbuf.h>
#include <sys/sleepqueue.h>
@@ -102,6 +103,14 @@
SDT_PROBE_DEFINE3(proc, , , signal__discard,
"struct thread *", "struct proc *", "int");
+static SLIST_HEAD(, coredumper) coredumpers = \
+ SLIST_HEAD_INITIALIZER(coredumpers);
+static struct rmlock coredump_rmlock;
+RM_SYSINIT(coredump_lock, &coredump_rmlock, "coredump_lock");
+
+static coredumper_handle_fn coredump_vnode;
+COREDUMP_HANDLER(coredump_vnode, NULL, coredump_vnode);
+
static int coredump(struct thread *);
static int killpg1(struct thread *td, int sig, int pgid, int all,
ksiginfo_t *ksi);
@@ -4131,16 +4140,15 @@
return (0);
}
-/*
- * Dump a process' core. The main routine does some
- * policy checking, and creates the name of the coredump;
- * then it passes on a vnode and a size limit to the process-specific
- * coredump routine if there is one; if there _is not_ one, it returns
- * ENOSYS; otherwise it returns the error from the process-specific routine.
+ /*
+ * The vnode dumper is the traditional coredump handler. Our policy and limits
+ * are generally checked already, so it creates the coredump name and passes on
+ * a vnode and a size limit to the process-specific coredump routine if there is
+ * one. If there _is not_ one, it returns ENOSYS; otherwise it returns the
+ * error from the process-specific routine.
*/
-
static int
-coredump(struct thread *td)
+coredump_vnode(struct thread *td, off_t limit)
{
struct proc *p = td->td_proc;
struct ucred *cred = td->td_ucred;
@@ -4153,33 +4161,9 @@
int error, error1, jid, locked, ppid, sig;
char *name; /* name of corefile */
void *rl_cookie;
- off_t limit;
char *fullpath, *freepath = NULL;
struct sbuf *sb;
- PROC_LOCK_ASSERT(p, MA_OWNED);
- MPASS((p->p_flag & P_HADTHREADS) == 0 || p->p_singlethread == td);
-
- if (!do_coredump || (!sugid_coredump && (p->p_flag & P_SUGID) != 0) ||
- (p->p_flag2 & P2_NOTRACE) != 0) {
- PROC_UNLOCK(p);
- return (EFAULT);
- }
-
- /*
- * Note that the bulk of limit checking is done after
- * the corefile is created. The exception is if the limit
- * for corefiles is 0, in which case we don't bother
- * creating the corefile at all. This layout means that
- * a corefile is truncated instead of not being created,
- * if it is larger than the limit.
- */
- limit = (off_t)lim_cur(td, RLIMIT_CORE);
- if (limit == 0 || racct_get_available(p, RACCT_CORE) == 0) {
- PROC_UNLOCK(p);
- return (EFBIG);
- }
-
ppid = p->p_oppid;
sig = p->p_sig;
jid = p->p_ucred->cr_prison->pr_id;
@@ -4293,6 +4277,107 @@
return (error);
}
+void
+coredumper_register(struct coredumper *cd)
+{
+
+ rm_wlock(&coredump_rmlock);
+ SLIST_INSERT_HEAD(&coredumpers, cd, cd_entry);
+ rm_wunlock(&coredump_rmlock);
+}
+
+void
+coredumper_unregister(struct coredumper *cd)
+{
+
+ rm_wlock(&coredump_rmlock);
+ SLIST_REMOVE(&coredumpers, cd, coredumper, cd_entry);
+ rm_wunlock(&coredump_rmlock);
+}
+
+/*
+ * Dump a process' core. The main routine does some policy checking, then does
+ * a search for an appropriate coredumper to use. It is expected that the
+ * dumper implementations will call into the process images' dumper routines
+ * if there is one, and return ENOSYS if there is not. We don't handle the
+ * latter bit here in case one wants to add a pluggable coredumper that can
+ * encode a dump of those processes in some other way that's helpful to them.
+ *
+ * By default, we will use coredump_vnode() above if a custom coredump module
+ * has not been loaded.
+ */
+static int
+coredump(struct thread *td)
+{
+ struct coredumper *iter, *chosen;
+ struct proc *p = td->td_proc;
+ struct rm_priotracker tracker;
+ off_t limit;
+ int error, priority;
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ MPASS((p->p_flag & P_HADTHREADS) == 0 || p->p_singlethread == td);
+
+ if (!do_coredump || (!sugid_coredump && (p->p_flag & P_SUGID) != 0) ||
+ (p->p_flag2 & P2_NOTRACE) != 0) {
+ PROC_UNLOCK(p);
+ return (EFAULT);
+ }
+
+ /*
+ * Note that the bulk of limit checking is done after
+ * the corefile is created. The exception is if the limit
+ * for corefiles is 0, in which case we don't bother
+ * creating the corefile at all. This layout means that
+ * a corefile is truncated instead of not being created,
+ * if it is larger than the limit.
+ */
+ limit = (off_t)lim_cur(td, RLIMIT_CORE);
+ if (limit == 0 || racct_get_available(p, RACCT_CORE) == 0) {
+ PROC_UNLOCK(p);
+ return (EFBIG);
+ }
+
+ rm_rlock(&coredump_rmlock, &tracker);
+ priority = -1;
+ chosen = NULL;
+ SLIST_FOREACH(iter, &coredumpers, cd_entry) {
+ if (iter->cd_probe == NULL) {
+ /*
+ * If we haven't found anything of a higher priority
+ * yet, we'll call this a GENERIC. Ideally, we want
+ * coredumper modules to include a probe function.
+ */
+ if (priority < 0) {
+ priority = COREDUMPER_GENERIC;
+ chosen = iter;
+ }
+
+ continue;
+ }
+
+ error = (*iter->cd_probe)(td);
+ if (error < 0)
+ continue;
+
+ /*
+ * Higher priority than previous options.
+ */
+ if (error > priority) {
+ priority = error;
+ chosen = iter;
+ }
+ }
+ rm_runlock(&coredump_rmlock, &tracker);
+
+ /* Currently, we always have the vnode dumper built in. */
+ MPASS(chosen != NULL);
+ error = ((*chosen->cd_handle)(td, limit));
+ PROC_LOCK_ASSERT(p, MA_NOTOWNED);
+
+ return (error);
+}
+
/*
* Nonexistent system call-- signal process (may want to handle it). Flag
* error in case process won't see signal immediately (blocked or ignored).
diff --git a/sys/sys/exec.h b/sys/sys/exec.h
--- a/sys/sys/exec.h
+++ b/sys/sys/exec.h
@@ -38,6 +38,7 @@
#define _SYS_EXEC_H_
#include <sys/_uio.h>
+#include <sys/queue.h>
/*
* Before ps_args existed, the following structure, found at the top of
@@ -90,6 +91,45 @@
struct compressor *comp;
};
+typedef int coredumper_probe_fn(struct thread *);
+/*
+ * Some arbitrary values for coredumper probes to return. The highest priority
+ * we can find wins. It's somewhat expected that a coredumper may want to bid
+ * differently based on the process in question. Note that probe functions will
+ * be called with the proc lock held, so they must not sleep.
+ */
+#define COREDUMPER_NOMATCH (-1) /* Decline to touch it */
+#define COREDUMPER_GENERIC (0) /* I handle coredumps */
+#define COREDUMPER_SPECIAL (50) /* Special handler */
+#define COREDUMPER_HIGH_PRIORITY (100) /* High-priority handler */
+
+/*
+ * The handle functions will be called with the proc lock held, and should
+ * return with the proc lock dropped.
+ */
+typedef int coredumper_handle_fn(struct thread *, off_t);
+
+struct coredumper {
+ SLIST_ENTRY(coredumper) cd_entry;
+ const char *cd_name;
+ coredumper_probe_fn *cd_probe;
+ coredumper_handle_fn *cd_handle;
+};
+
+void coredumper_register(struct coredumper *);
+void coredumper_unregister(struct coredumper *);
+
+#define COREDUMP_HANDLER(name, probe, handle) \
+ static struct coredumper name##_coredumper = { \
+ .cd_name = #name, \
+ .cd_probe = probe, \
+ .cd_handle = handle, \
+ }; \
+ SYSINIT(name##_register, SI_SUB_EXEC, SI_ORDER_ANY, \
+ coredumper_register, &name##_coredumper); \
+ SYSUNINIT(name##_unregister, SI_SUB_EXEC, SI_ORDER_ANY, \
+ coredumper_unregister, &name##_coredumper); \
+
struct image_params;
struct execsw {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 9, 9:33 AM (8 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28563885
Default Alt Text
D51338.id158587.diff (7 KB)
Attached To
Mode
D51338: kern: abstract away the vnode coredumper to allow pluggable dumpers
Attached
Detach File
Event Timeline
Log In to Comment