git: 8eb37cd06b34 - main - kern: factor out the 'writing' bits of user process coredumping
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 26 Jul 2025 21:31:50 UTC
The branch main has been updated by kevans:
URL: https://cgit.FreeBSD.org/src/commit/?id=8eb37cd06b345e7187e4b65484a1194ed7e300f8
commit 8eb37cd06b345e7187e4b65484a1194ed7e300f8
Author: Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-07-15 20:14:55 +0000
Commit: Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-07-26 21:31:41 +0000
kern: factor out the 'writing' bits of user process coredumping
Instead of assuming we have a vnode to dump to, pull out the bits that
describe how to write acoredump into a struct coredump_writer; the ctx
in that is expected to be opaque, but used by write/extend functions.
This should not be a functional change- we change two callers to use the
classic vnode write/extend interface.
This opens us up to other possible targets for coredumps, such as a
shmfd.
Reviewed by: markj (earlier version), kib
Differential Revision: https://reviews.freebsd.org/D51337
---
sys/kern/imgact_elf.c | 11 ++++++++---
sys/kern/kern_exec.c | 50 ++++++++++++++++++++++++++++++++++++++------------
sys/kern/kern_sig.c | 23 +++++++++++++++++++++--
sys/sys/exec.h | 32 ++++++++++++++++++++++++++++++--
sys/sys/imgact_elf.h | 3 ++-
sys/sys/sysent.h | 4 +++-
6 files changed, 102 insertions(+), 21 deletions(-)
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index b7ffbe68b483..a7d3e22e6279 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1595,7 +1595,7 @@ core_compressed_write(void *base, size_t len, off_t offset, void *arg)
}
int
-__elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
+__elfN(coredump)(struct thread *td, struct coredump_writer *cdw, off_t limit, int flags)
{
struct ucred *cred = td->td_ucred;
int compm, error = 0;
@@ -1625,9 +1625,8 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
/* Set up core dump parameters. */
params.offset = 0;
params.active_cred = cred;
- params.file_cred = NOCRED;
params.td = td;
- params.vp = vp;
+ params.cdw = cdw;
params.comp = NULL;
#ifdef RACCT
@@ -1662,6 +1661,12 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
tmpbuf = malloc(CORE_BUF_SIZE, M_TEMP, M_WAITOK | M_ZERO);
}
+ if (cdw->init_fn != NULL) {
+ error = (*cdw->init_fn)(cdw, ¶ms);
+ if (error != 0)
+ goto done;
+ }
+
/*
* Allocate memory for building the header, fill it up,
* and write it out following the notes.
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 03268365891e..a0a22ee8539b 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1998,14 +1998,48 @@ compress_chunk(struct coredump_params *cp, char *base, char *buf, size_t len)
return (error);
}
+int
+core_vn_write(const struct coredump_writer *cdw, const void *base, size_t len,
+ off_t offset, enum uio_seg seg, struct ucred *cred, size_t *resid,
+ struct thread *td)
+{
+ struct coredump_vnode_ctx *ctx = cdw->ctx;
+
+ return (vn_rdwr_inchunks(UIO_WRITE, ctx->vp, __DECONST(void *, base),
+ len, offset, seg, IO_UNIT | IO_DIRECT | IO_RANGELOCKED,
+ cred, ctx->fcred, resid, td));
+}
+
int
core_write(struct coredump_params *cp, const void *base, size_t len,
off_t offset, enum uio_seg seg, size_t *resid)
{
+ return ((*cp->cdw->write_fn)(cp->cdw, base, len, offset, seg,
+ cp->active_cred, resid, cp->td));
+}
- return (vn_rdwr_inchunks(UIO_WRITE, cp->vp, __DECONST(void *, base),
- len, offset, seg, IO_UNIT | IO_DIRECT | IO_RANGELOCKED,
- cp->active_cred, cp->file_cred, resid, cp->td));
+int
+core_vn_extend(const struct coredump_writer *cdw, off_t newsz,
+ struct ucred *cred)
+{
+ struct coredump_vnode_ctx *ctx = cdw->ctx;
+ struct mount *mp;
+ int error;
+
+ error = vn_start_write(ctx->vp, &mp, V_WAIT);
+ if (error != 0)
+ return (error);
+ vn_lock(ctx->vp, LK_EXCLUSIVE | LK_RETRY);
+ error = vn_truncate_locked(ctx->vp, newsz, false, cred);
+ VOP_UNLOCK(ctx->vp);
+ vn_finished_write(mp);
+ return (error);
+}
+
+static int
+core_extend(struct coredump_params *cp, off_t newsz)
+{
+ return ((*cp->cdw->extend_fn)(cp->cdw, newsz, cp->td->td_ucred));
}
int
@@ -2013,7 +2047,6 @@ core_output(char *base, size_t len, off_t offset, struct coredump_params *cp,
void *tmpbuf)
{
vm_map_t map;
- struct mount *mp;
size_t resid, runlen;
int error;
bool success;
@@ -2068,14 +2101,7 @@ core_output(char *base, size_t len, off_t offset, struct coredump_params *cp,
}
}
if (!success) {
- error = vn_start_write(cp->vp, &mp, V_WAIT);
- if (error != 0)
- break;
- vn_lock(cp->vp, LK_EXCLUSIVE | LK_RETRY);
- error = vn_truncate_locked(cp->vp, offset + runlen,
- false, cp->td->td_ucred);
- VOP_UNLOCK(cp->vp);
- vn_finished_write(mp);
+ error = core_extend(cp, offset + runlen);
if (error != 0)
break;
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 5d51aa675cb7..e96f72d56e18 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -49,6 +49,7 @@
#include <sys/condvar.h>
#include <sys/devctl.h>
#include <sys/event.h>
+#include <sys/exec.h>
#include <sys/fcntl.h>
#include <sys/imgact.h>
#include <sys/jail.h>
@@ -2665,6 +2666,8 @@ static void
ptrace_coredumpreq(struct thread *td, struct proc *p,
struct thr_coredump_req *tcq)
{
+ struct coredump_vnode_ctx wctx;
+ struct coredump_writer cdw;
void *rl_cookie;
if (p->p_sysent->sv_coredump == NULL) {
@@ -2672,8 +2675,15 @@ ptrace_coredumpreq(struct thread *td, struct proc *p,
return;
}
+ wctx.vp = tcq->tc_vp;
+ wctx.fcred = NOCRED;
+
+ cdw.ctx = &wctx;
+ cdw.write_fn = core_vn_write;
+ cdw.extend_fn = core_vn_extend;
+
rl_cookie = vn_rangelock_wlock(tcq->tc_vp, 0, OFF_MAX);
- tcq->tc_error = p->p_sysent->sv_coredump(td, tcq->tc_vp,
+ tcq->tc_error = p->p_sysent->sv_coredump(td, &cdw,
tcq->tc_limit, tcq->tc_flags);
vn_rangelock_unlock(tcq->tc_vp, rl_cookie);
}
@@ -4135,6 +4145,8 @@ coredump(struct thread *td)
struct proc *p = td->td_proc;
struct ucred *cred = td->td_ucred;
struct vnode *vp;
+ struct coredump_vnode_ctx wctx;
+ struct coredump_writer cdw;
struct flock lf;
struct vattr vattr;
size_t fullpathsize;
@@ -4212,8 +4224,15 @@ coredump(struct thread *td)
p->p_acflag |= ACORE;
PROC_UNLOCK(p);
+ wctx.vp = vp;
+ wctx.fcred = NOCRED;
+
+ cdw.ctx = &wctx;
+ cdw.write_fn = core_vn_write;
+ cdw.extend_fn = core_vn_extend;
+
if (p->p_sysent->sv_coredump != NULL) {
- error = p->p_sysent->sv_coredump(td, vp, limit, 0);
+ error = p->p_sysent->sv_coredump(td, &cdw, limit, 0);
} else {
error = ENOSYS;
}
diff --git a/sys/sys/exec.h b/sys/sys/exec.h
index 4bf114a7c698..fed93949dae5 100644
--- a/sys/sys/exec.h
+++ b/sys/sys/exec.h
@@ -37,6 +37,8 @@
#ifndef _SYS_EXEC_H_
#define _SYS_EXEC_H_
+#include <sys/_uio.h>
+
/*
* Before ps_args existed, the following structure, found at the top of
* the user stack of each user process, was used by ps(1) to locate
@@ -58,12 +60,38 @@ struct ps_strings {
};
/* Coredump output parameters. */
+struct coredump_params;
+struct coredump_writer;
+struct thread;
+struct ucred;
+
+typedef int coredump_init_fn(const struct coredump_writer *,
+ const struct coredump_params *);
+typedef int coredump_write_fn(const struct coredump_writer *, const void *, size_t,
+ off_t, enum uio_seg, struct ucred *, size_t *, struct thread *);
+typedef int coredump_extend_fn(const struct coredump_writer *, off_t,
+ struct ucred *);
+
+struct coredump_vnode_ctx {
+ struct vnode *vp;
+ struct ucred *fcred;
+};
+
+coredump_write_fn core_vn_write;
+coredump_extend_fn core_vn_extend;
+
+struct coredump_writer {
+ void *ctx;
+ coredump_init_fn *init_fn;
+ coredump_write_fn *write_fn;
+ coredump_extend_fn *extend_fn;
+};
+
struct coredump_params {
off_t offset;
struct ucred *active_cred;
- struct ucred *file_cred;
struct thread *td;
- struct vnode *vp;
+ const struct coredump_writer *cdw;
struct compressor *comp;
};
diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h
index c9444e5aec41..2845a9dbc1e2 100644
--- a/sys/sys/imgact_elf.h
+++ b/sys/sys/imgact_elf.h
@@ -45,6 +45,7 @@
{(pos)->a_type = (id); (pos)->a_un.a_ptr = (ptr); (pos)++;}
#endif
+struct coredump_writer;
struct image_params;
struct thread;
struct vnode;
@@ -114,7 +115,7 @@ bool __elfN(brand_inuse)(Elf_Brandinfo *entry);
int __elfN(insert_brand_entry)(Elf_Brandinfo *entry);
int __elfN(remove_brand_entry)(Elf_Brandinfo *entry);
int __elfN(freebsd_fixup)(uintptr_t *, struct image_params *);
-int __elfN(coredump)(struct thread *, struct vnode *, off_t, int);
+int __elfN(coredump)(struct thread *, struct coredump_writer *, off_t, int);
size_t __elfN(populate_note)(int, void *, void *, size_t, void **);
int __elfN(freebsd_copyout_auxargs)(struct image_params *, uintptr_t);
void __elfN(puthdr)(struct thread *, void *, size_t, int, size_t, int);
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
index 4ddfc8516053..1714fa5a7416 100644
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -90,6 +90,7 @@ struct sysent { /* system call table */
#define SY_THR_STATIC_KLD SY_THR_STATIC
#endif
+struct coredump_writer;
struct image_params;
struct proc;
struct __sigset;
@@ -108,7 +109,8 @@ struct sysentvec {
int *sv_szsigcode; /* size of sigtramp code */
int sv_sigcodeoff;
char *sv_name; /* name of binary type */
- int (*sv_coredump)(struct thread *, struct vnode *, off_t, int);
+ int (*sv_coredump)(struct thread *, struct coredump_writer *,
+ off_t, int);
/* function to dump core, or NULL */
int sv_elf_core_osabi;
const char *sv_elf_core_abi_vendor;