The branch main has been updated by kevans:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=8eb37cd06b345e7187e4b65484a1194ed7e300f8

commit 8eb37cd06b345e7187e4b65484a1194ed7e300f8
Author:     Kyle Evans <kev...@freebsd.org>
AuthorDate: 2025-07-15 20:14:55 +0000
Commit:     Kyle Evans <kev...@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;

Reply via email to