Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144308738
D29691.id88028.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D29691.id88028.diff
View Options
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,41 @@
#endif
}
+static void
+ptrace_coredump(struct thread *td)
+{
+ struct proc *p = td->td_proc;
+ struct vnode *vp;
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ if ((td->td_dbgflags & TDB_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_dbgflags &= ~TDB_COREDUMP;
+ wakeup(p);
+}
+
/*
* Process an asynchronous software trap.
* This is relatively easy.
@@ -355,6 +390,11 @@
kern_sigprocmask(td, SIG_SETMASK, &td->td_oldsigmask, NULL, 0);
}
+ PROC_LOCK(p);
+ if (td->td_dbgflags & TDB_COREDUMP)
+ 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,46 @@
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_dbgflags & TDB_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);
+
+ 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_dbgflags |= TDB_COREDUMP;
+ thread_lock(td);
+ td2->td_flags |= TDF_ASTPENDING;
+ thread_unlock(td);
+
+ break;
+ }
case PT_DETACH:
/*
* Clear P_TRACED before reparenting
@@ -1052,6 +1110,9 @@
break;
}
+ if (error != 0)
+ break;
+
sx_xunlock(&proctree_lock);
proctree_locked = 0;
@@ -1313,6 +1374,19 @@
}
out:
+ if (req == PT_COREDUMP && error != 0) {
+ void *coredump_data;
+
+ while ((td2->td_dbgflags & TDB_COREDUMP) != 0)
+ msleep(p, &p->p_mtx, PPAUSE, "crdmp", 0);
+ MPASS(td2->td_coredump != NULL);
+ error = td2->td_coredump->tc_error;
+ fdrop(fp, td);
+ coredump_data = td2->td_coredump;
+ td2->td_coredump = NULL;
+ free(coredump_data, M_SUBPROC);
+ }
+
/* 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
@@ -485,6 +492,7 @@
#define TDB_VFORK 0x00000800 /* vfork indicator for ptrace() */
#define TDB_FSTP 0x00001000 /* The thread is PT_ATTACH leader */
#define TDB_STEP 0x00002000 /* (x86) PSL_T set for PT_STEP */
+#define TDB_COREDUMP 0x00004000 /* Coredump request */
/*
* "Private" flags kept in td_pflags:
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
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 8, 6:42 PM (5 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28485438
Default Alt Text
D29691.id88028.diff (7 KB)
Attached To
Mode
D29691: ptrace: Add PT_COREDUMP request (WIP)
Attached
Detach File
Event Timeline
Log In to Comment