WIP: ucored(8) for user-core handling

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Sat, 26 Jul 2025 22:59:29 UTC
Hi,

Just today, I've committed some changes[0][1] to allow for kmods to 
replace the standard 'dump to foo.core' user process coredump mechanism. 
  The first change enables one to dump to something other than a file, 
and the second change allows replacement of what would historically 
happen in coredump() after initial limits/policies are checked.


Before these changes, we could get a notice via devd that a coredump was 
generated, but with the following limitations that I wasn't fond of:

1.) devd notifications have < 1k worth of buffer to work with, so it's 
fairly limited what you can cram into; that's not even PATH_MAX once you 
take into account the other overhead that eats away at your buffer 
(subsystem details, key labels), and ideally we'd fit the command path, 
the path to the coredump, and other metadata inside

2.) the path to the corefile isn't always accurate by necessity; the 
core= path doesn't take into account jails and probably shouldn't due to 
aforementioned size constraints

3.) it's just not really flexible, and a core still has to hit the disk 
for a daemon to add any kind of flexibility

My companion project that motivated this is called ucored[2], and I'm 
hoping to add it to ports in the coming weeks.  ucored's purpose is to 
take user cores and apply some policy to them, based on pattern-matching 
whatever data we might have available.  Today, that means: command 
(path), domainname, hostname, jail, and path (to the core; not always 
available).  Supported policies being things like: discard the core, 
execute some command (and pass data about the core to it), move the core 
somewhere else, pipe the core to a command (via stdin), or pass it over 
to another lua script to deal with.  The default policy (at the moment) 
is to grab all cores and move them over to /var/ucrash for consolidation.

It works on all supported versions, but it will be more capable on 
FreeBSD 15.x than it is on FreeBSD 13.5 and 14.x.  ucored(8) on 13.x and 
14.x will use devd (by way of devd invoking ucore-shuttle, which does 
the devd-specific bits needed like resolving the jail then sending the 
core over to ucored(8)).

On 15.x, I have this WIP kmod that dumps to a shmfd instead of to the 
disk, and if you want it written out then ucored(8) has to do it.  This 
has some neat properties, such as: discarding a core means it doesn't 
hit the disk (modulo shmfd swapping) and you can snatch cores out of 
jails (even short-lived jails) pretty easily and catch jail properties 
before it's torn down.

It would be useful to know if this would be helpful to anyone else.  As 
a developer and sometimes system administrator, I've found myself 
needing some way to organize cores on a system in a way that 
kern.corefile can't really offer because I want them all moved out of 
jails into a central location, rather than having to hunt down whatever 
cwd of some process may have been at the time.  As a default behavior 
that's not really a good idea, but on a case-by-case basis it's not 
unreasonable.

Ideas for other metadata we could be collecting when a process crashes 
would be nice, too.  In addition to the bits we can pattern-match 
mentioned above, we also collect: ppid, pid, signal that caused it, 
whether the process was running setuid/setgid (so we can reset 
permissions on the coredump, if one was produced), and euid/egid of the 
process.

Thanks,

Kyle Evans

[0] 
https://cgit.freebsd.org/src/commit/?id=8eb37cd06b345e7187e4b65484a1194ed7e300f8
[1] 
https://cgit.freebsd.org/src/commit/?id=ce51f79913aa28a32217a424845a2649019535af
[2] https://git.kevans.dev/kevans/ucored