Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 26 Jul 2025 21:31:50 GMT
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 8eb37cd06b34 - main - kern: factor out the 'writing' bits of user process coredumping
Message-ID:  <202507262131.56QLVoCN065753@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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, &params);
+		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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202507262131.56QLVoCN065753>