The branch main has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=3ce3b342db7e5c987e5eee039f7b290a3919ca37
commit 3ce3b342db7e5c987e5eee039f7b290a3919ca37 Author: Kyle Evans <kev...@freebsd.org> AuthorDate: 2025-07-22 16:49:52 +0000 Commit: Kyle Evans <kev...@freebsd.org> CommitDate: 2025-07-26 21:31:42 +0000 kern: add some better error messages for coredump() failures After debugging with a user on discord why their process is not generating coredumps, it became clear that we can use better error messages -- particularly to distinguish between the different EFAULT cases. For those that are denied by system policies, include some more specific pointers to the relevant knob. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D51465 --- sys/kern/kern_ucoredump.c | 57 ++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/sys/kern/kern_ucoredump.c b/sys/kern/kern_ucoredump.c index a2412bf06441..d425596b5f24 100644 --- a/sys/kern/kern_ucoredump.c +++ b/sys/kern/kern_ucoredump.c @@ -51,7 +51,7 @@ #include <sys/ucoredump.h> #include <sys/wait.h> -static int coredump(struct thread *td); +static int coredump(struct thread *td, const char **); int compress_user_cores = 0; @@ -135,7 +135,6 @@ void sigexit(struct thread *td, int sig) { struct proc *p = td->td_proc; - const char *coreinfo; int rv; bool logexit; @@ -158,6 +157,8 @@ sigexit(struct thread *td, int sig) * (e.g. via fork()), we won't get a dump at all. */ if (sig_do_core(sig) && thread_single(p, SINGLE_NO_EXIT) == 0) { + const char *err = NULL; + p->p_sig = sig; /* * Log signals which would cause core dumps @@ -166,32 +167,34 @@ sigexit(struct thread *td, int sig) * XXX : Todo, as well as euid, write out ruid too * Note that coredump() drops proc lock. */ - rv = coredump(td); - switch (rv) { - case 0: + rv = coredump(td, &err); + if (rv == 0) { + MPASS(err == NULL); sig |= WCOREFLAG; - coreinfo = " (core dumped)"; - break; - case EFAULT: - coreinfo = " (no core dump - bad address)"; - break; - case EINVAL: - coreinfo = " (no core dump - invalid argument)"; - break; - case EFBIG: - coreinfo = " (no core dump - too large)"; - break; - default: - coreinfo = " (no core dump - other error)"; - break; + } else if (err == NULL) { + switch (rv) { + case EFAULT: + err = "bad address"; + break; + case EINVAL: + err = "invalild argument"; + break; + case EFBIG: + err = "too large"; + break; + default: + err = "other error"; + break; + } } if (logexit) log(LOG_INFO, "pid %d (%s), jid %d, uid %d: exited on " - "signal %d%s\n", p->p_pid, p->p_comm, + "signal %d (%s%s)\n", p->p_pid, p->p_comm, p->p_ucred->cr_prison->pr_id, - td->td_ucred->cr_uid, - sig &~ WCOREFLAG, coreinfo); + td->td_ucred->cr_uid, sig &~ WCOREFLAG, + err != NULL ? "no core dump - " : "core dumped", + err != NULL ? err : ""); } else PROC_UNLOCK(p); exit1(td, 0, sig); @@ -207,7 +210,7 @@ sigexit(struct thread *td, int sig) * ENOSYS; otherwise it returns the error from the process-specific routine. */ static int -coredump(struct thread *td) +coredump(struct thread *td, const char **errmsg) { struct coredumper *iter, *chosen; struct proc *p = td->td_proc; @@ -221,6 +224,13 @@ coredump(struct thread *td) if (!do_coredump || (!sugid_coredump && (p->p_flag & P_SUGID) != 0) || (p->p_flag2 & P2_NOTRACE) != 0) { PROC_UNLOCK(p); + + if (!do_coredump) + *errmsg = "denied by kern.coredump"; + else if ((p->p_flag2 & P2_NOTRACE) != 0) + *errmsg = "process has trace disabled"; + else + *errmsg = "sugid process denied by kern.sugid_coredump"; return (EFAULT); } @@ -235,6 +245,7 @@ coredump(struct thread *td) limit = (off_t)lim_cur(td, RLIMIT_CORE); if (limit == 0 || racct_get_available(p, RACCT_CORE) == 0) { PROC_UNLOCK(p); + *errmsg = "coredumpsize limit is 0"; return (EFBIG); }