Page MenuHomeFreeBSD

D29691.id87973.diff
No OneTemporary

D29691.id87973.diff

Index: lib/libc/sys/ptrace.2
===================================================================
--- lib/libc/sys/ptrace.2
+++ lib/libc/sys/ptrace.2
@@ -2,7 +2,7 @@
.\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $
.\"
.\" This file is in the public domain.
-.Dd July 15, 2019
+.Dd April 10, 2021
.Dt PTRACE 2
.Os
.Sh NAME
@@ -807,6 +807,22 @@
The
.Fa data
argument is ignored.
+.It Dv PT_COREDUMP
+This request creates a coredump for the stopped program.
+.Fa addr
+argument specifies a pointer to a
+.Vt "struct ptrace_coredump" ,
+which is defined as follows:
+.Bd -literal
+struct ptrace_coredump {
+ TODO;
+};
+.Ed
+.Pp
+The size of
+.Vt "struct ptrace_coredump"
+must be passed in
+.Fa data .
.El
.Sh ARM MACHINE-SPECIFIC REQUESTS
.Bl -tag -width "Dv PT_SETVFPREGS"
Index: sys/kern/subr_trap.c
===================================================================
--- sys/kern/subr_trap.c
+++ sys/kern/subr_trap.c
@@ -193,6 +193,40 @@
#endif
}
+static void
+ptrace_coredump(struct thread *td)
+{
+ struct proc *p = td->td_proc;
+ struct vnode *vp;
+
+ if ((td->td_flags & TDF_COREDUMP) == 0)
+ return;
+ KASSERT(td->td_coredump, ("td_coredump is NULL"));
+ if (p->p_sysent->sv_coredump == NULL) {
+ td->td_coredump->tc_error = ENOSYS;
+ return;
+ }
+
+ if ((p->p_flag & P_HADTHREADS) != 0) {
+ if (thread_single(p, SINGLE_BOUNDARY) != 0) {
+ td->td_coredump->tc_error = EBUSY;
+ return;
+ }
+ }
+
+ vp = td->td_coredump->tc_vn;
+ PROC_UNLOCK(p);
+ td->td_coredump->tc_error =
+ p->p_sysent->sv_coredump(td, vp, td->td_coredump->tc_limit, 0);
+ PROC_LOCK(p);
+
+ if ((p->p_flag & P_HADTHREADS) != 0)
+ thread_single_end(p, SINGLE_BOUNDARY);
+
+ td->td_flags &= ~TDF_COREDUMP;
+ wakeup(p);
+}
+
/*
* Process an asynchronous software trap.
* This is relatively easy.
@@ -355,6 +389,12 @@
kern_sigprocmask(td, SIG_SETMASK, &td->td_oldsigmask, NULL, 0);
}
+ if (td->td_flags & TDF_COREDUMP) {
+ PROC_LOCK(p);
+ ptrace_coredump(td);
+ PROC_UNLOCK(p);
+ }
+
#ifdef RACCT
if (__predict_false(racct_enable && p->p_throttled != 0))
racct_proc_throttled(p);
Index: sys/kern/sys_process.c
===================================================================
--- sys/kern/sys_process.c
+++ sys/kern/sys_process.c
@@ -51,6 +51,8 @@
#include <sys/sx.h>
#include <sys/malloc.h>
#include <sys/signalvar.h>
+#include <sys/caprights.h>
+#include <sys/filedesc.h>
#include <machine/reg.h>
@@ -469,6 +471,7 @@
struct ptrace_io_desc piod;
struct ptrace_lwpinfo pl;
struct ptrace_vm_entry pve;
+ struct ptrace_coredump pc;
struct dbreg dbreg;
struct fpreg fpreg;
struct reg reg;
@@ -519,6 +522,14 @@
case PT_VM_ENTRY:
error = copyin(uap->addr, &r.pve, sizeof(r.pve));
break;
+ case PT_COREDUMP:
+ if (uap->data != sizeof(r.pc))
+ error = EINVAL;
+ else
+ error = copyin(uap->addr, &r.pc, uap->data);
+ if (r.pc.pc_flags != 0)
+ error = EINVAL;
+ break;
default:
addr = uap->addr;
break;
@@ -611,6 +622,7 @@
struct ptrace_io_desc *piod = NULL;
struct ptrace_lwpinfo *pl;
struct ptrace_sc_ret *psr;
+ struct file *fp;
int error, num, tmp;
int proctree_locked = 0;
lwpid_t tid = 0, *buf;
@@ -635,6 +647,7 @@
case PT_SET_EVENT_MASK:
case PT_DETACH:
case PT_GET_SC_ARGS:
+ case PT_COREDUMP:
sx_xlock(&proctree_lock);
proctree_locked = 1;
break;
@@ -950,6 +963,11 @@
case PT_TO_SCX:
case PT_SYSCALL:
case PT_DETACH:
+ case PT_COREDUMP:
+ /* PT_COREDUMP does not pass signal in data. */
+ if (req == PT_COREDUMP)
+ data = 0;
+
/* Zero means do not send any signal */
if (data < 0 || data > _SIG_MAXSIG) {
error = EINVAL;
@@ -1003,6 +1021,48 @@
break;
}
break;
+ case PT_COREDUMP:
+ {
+ struct ptrace_coredump *pc = addr;
+ struct thread_coredump *coredump_data;
+ CTR2(KTR_PTRACE,
+ "PT_COREDUMP: pid %d, fd = %d",
+ p->p_pid, pc->pc_fd);
+
+ if (td2->td_flags & TDF_COREDUMP) {
+ error = EBUSY;
+ break;
+ }
+
+ error = getvnode(td, pc->pc_fd, &cap_write_rights, &fp);
+ if (error != 0)
+ break;
+
+ /* Do not try writing to non-regular files. */
+ if (fp->f_vnode->v_type != VREG) {
+ error = EFAULT;
+ fdrop(fp, td);
+ break;
+ }
+
+ PROC_UNLOCK(p);
+ coredump_data = malloc(sizeof(*td2->td_coredump),
+ M_SUBPROC, M_WAITOK | M_ZERO);
+ PROC_LOCK(p);
+ if (!coredump_data) {
+ error = ENOMEM;
+ fdrop(fp, td);
+ break;
+ }
+
+ coredump_data->tc_vn = fp->f_vnode;
+ coredump_data->tc_limit = (pc->pc_limit <= 0)
+ ? OFF_MAX : pc->pc_limit;
+ td2->td_coredump = coredump_data,
+ td2->td_flags |= (TDF_COREDUMP | TDF_ASTPENDING);
+
+ break;
+ }
case PT_DETACH:
/*
* Clear P_TRACED before reparenting
@@ -1052,6 +1112,9 @@
break;
}
+ if (error != 0)
+ break;
+
sx_xunlock(&proctree_lock);
proctree_locked = 0;
@@ -1313,6 +1376,20 @@
}
out:
+ if (req == PT_COREDUMP && error != 0) {
+ void *coredump_data;
+ while ((td2->td_flags & TDF_COREDUMP) != 0)
+ msleep(p, &p->p_mtx, PPAUSE, "crdmp", 0);
+ KASSERT(td2->td_coredump, ("td_coredump is NULL"));
+ error = td2->td_coredump->tc_error;
+ fdrop(fp, td);
+ coredump_data = td2->td_coredump;
+ td2->td_coredump = NULL;
+ PROC_UNLOCK(p);
+ free(coredump_data, M_SUBPROC);
+ PROC_LOCK(p);
+ }
+
/* Drop our hold on this process now that the request has completed. */
_PRELE(p);
fail:
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -222,6 +222,12 @@
uint64_t rux_tu; /* (c) Previous total time in usec. */
};
+struct thread_coredump {
+ struct vnode *tc_vn; /* vnode to write coredump to. */
+ off_t tc_limit; /* (c) max coredump file size. */
+ int tc_error; /* (c) coredump return value. */
+};
+
/*
* Kernel runnable context (thread).
* This is what is put to sleep and reactivated.
@@ -377,6 +383,7 @@
int td_oncpu; /* (t) Which cpu we are on. */
void *td_lkpi_task; /* LinuxKPI task struct pointer */
int td_pmcpend;
+ struct thread_coredump *td_coredump; /* (c) coredump request. */
#ifdef EPOCH_TRACE
SLIST_HEAD(, epoch_tracker) td_epochs;
#endif
@@ -443,7 +450,7 @@
#define TDF_TIMEOUT 0x00000010 /* Timing out during sleep. */
#define TDF_IDLETD 0x00000020 /* This is a per-CPU idle thread. */
#define TDF_CANSWAP 0x00000040 /* Thread can be swapped. */
-#define TDF_UNUSED80 0x00000080 /* unused. */
+#define TDF_COREDUMP 0x00000080 /* Coredump request. */
#define TDF_KTH_SUSP 0x00000100 /* kthread is suspended */
#define TDF_ALLPROCSUSP 0x00000200 /* suspended by SINGLE_ALLPROC */
#define TDF_BOUNDARY 0x00000400 /* Thread suspended at user boundary */
Index: sys/sys/ptrace.h
===================================================================
--- sys/sys/ptrace.h
+++ sys/sys/ptrace.h
@@ -74,6 +74,8 @@
#define PT_GET_SC_ARGS 27 /* fetch syscall args */
#define PT_GET_SC_RET 28 /* fetch syscall results */
+#define PT_COREDUMP 29 /* create a coredump */
+
#define PT_GETREGS 33 /* get general-purpose registers */
#define PT_SETREGS 34 /* set general-purpose registers */
#define PT_GETFPREGS 35 /* get floating-point registers */
@@ -176,6 +178,14 @@
char *pve_path; /* Path name of object. */
};
+/* Argument structure for PT_COREDUMP. */
+struct ptrace_coredump {
+ int pc_fd; /* File descriptor to write dump to. */
+ off_t pc_limit; /* Maximum size of the coredump,
+ 0 for no limit. */
+ uint32_t pc_flags; /* Flags (currently reserved). */
+};
+
#ifdef _KERNEL
int ptrace_set_pc(struct thread *_td, unsigned long _addr);

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 12, 10:56 PM (5 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29599244
Default Alt Text
D29691.id87973.diff (7 KB)

Event Timeline