For PT_TO_SCE stop that stops the ptraced process upon syscall entry,

syscall arguments are collected before ptracestop() is called. As a
consequence, debugger cannot modify syscall or its arguments.

For i386, amd64 and ia32 on amd64 MD syscall(), reread syscall number
and arguments after ptracestop(), if debugger modified anything in the
process environment. Since procfs stopeven requires number of syscall
arguments in p_xstat, this cannot be solved by moving stop/trace point
before argument fetching.

Move the code to read arguments into separate function
fetch_syscall_args() to avoid code duplication. Note that ktrace point
for modified syscall is intentionally recorded twice, once with original
arguments, and second time with the arguments set by debugger.

PT_TO_SCX stop is executed after cpu_syscall_set_retval() already.

Reported by:	Ali Polatel <alip exherbo org>
Briefly discussed with:	jhb
MFC after:	3 weeks
This commit is contained in:
kib 2010-01-23 11:45:35 +00:00
parent a22fc66b6e
commit ddbe48bd56
5 changed files with 317 additions and 201 deletions

View File

@ -885,6 +885,73 @@ dblfault_handler(struct trapframe *frame)
panic("double fault");
}
struct syscall_args {
u_int code;
struct sysent *callp;
register_t args[8];
register_t *argp;
int narg;
};
static int
fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
struct proc *p;
struct trapframe *frame;
caddr_t params;
int reg, regcnt, error;
p = td->td_proc;
frame = td->td_frame;
reg = 0;
regcnt = 6;
params = (caddr_t)frame->tf_rsp + sizeof(register_t);
sa->code = frame->tf_rax;
if (p->p_sysent->sv_prepsyscall) {
(*p->p_sysent->sv_prepsyscall)(frame, (int *)sa->args,
&sa->code, &params);
} else {
if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
sa->code = frame->tf_rdi;
reg++;
regcnt--;
}
}
if (p->p_sysent->sv_mask)
sa->code &= p->p_sysent->sv_mask;
if (sa->code >= p->p_sysent->sv_size)
sa->callp = &p->p_sysent->sv_table[0];
else
sa->callp = &p->p_sysent->sv_table[sa->code];
sa->narg = sa->callp->sy_narg;
KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]),
("Too many syscall arguments!"));
error = 0;
sa->argp = &frame->tf_rdi;
sa->argp += reg;
bcopy(sa->argp, sa->args, sizeof(sa->args[0]) * regcnt);
if (sa->narg > regcnt) {
KASSERT(params != NULL, ("copyin args with no params!"));
error = copyin(params, &sa->args[regcnt],
(sa->narg - regcnt) * sizeof(sa->args[0]));
}
sa->argp = &sa->args[0];
/*
* This may result in two records if debugger modified
* registers or memory during sleep at stop/ptrace point.
*/
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSCALL))
ktrsyscall(sa->code, sa->narg, sa->argp);
#endif
return (error);
}
/*
* syscall - system call request C handler
*
@ -893,20 +960,17 @@ dblfault_handler(struct trapframe *frame)
void
syscall(struct trapframe *frame)
{
caddr_t params;
struct sysent *callp;
struct thread *td = curthread;
struct proc *p = td->td_proc;
struct thread *td;
struct proc *p;
struct syscall_args sa;
register_t orig_tf_rflags;
int error;
int narg;
register_t args[8];
register_t *argp;
u_int code;
int reg, regcnt;
ksiginfo_t ksi;
PCPU_INC(cnt.v_syscall);
td = curthread;
p = td->td_proc;
td->td_syscalls++;
#ifdef DIAGNOSTIC
if (ISPL(frame->tf_cs) != SEL_UPL) {
@ -915,65 +979,37 @@ syscall(struct trapframe *frame)
}
#endif
reg = 0;
regcnt = 6;
td->td_pticks = 0;
td->td_frame = frame;
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
params = (caddr_t)frame->tf_rsp + sizeof(register_t);
code = frame->tf_rax;
orig_tf_rflags = frame->tf_rflags;
if (p->p_sysent->sv_prepsyscall) {
(*p->p_sysent->sv_prepsyscall)(frame, (int *)args, &code, &params);
} else {
if (code == SYS_syscall || code == SYS___syscall) {
code = frame->tf_rdi;
reg++;
regcnt--;
}
if (p->p_flag & P_TRACED) {
PROC_LOCK(p);
td->td_dbgflags &= ~TDB_USERWR;
PROC_UNLOCK(p);
}
if (p->p_sysent->sv_mask)
code &= p->p_sysent->sv_mask;
if (code >= p->p_sysent->sv_size)
callp = &p->p_sysent->sv_table[0];
else
callp = &p->p_sysent->sv_table[code];
narg = callp->sy_narg;
KASSERT(narg <= sizeof(args) / sizeof(args[0]),
("Too many syscall arguments!"));
error = 0;
argp = &frame->tf_rdi;
argp += reg;
bcopy(argp, args, sizeof(args[0]) * regcnt);
if (narg > regcnt) {
KASSERT(params != NULL, ("copyin args with no params!"));
error = copyin(params, &args[regcnt],
(narg - regcnt) * sizeof(args[0]));
}
argp = &args[0];
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSCALL))
ktrsyscall(code, narg, argp);
#endif
error = fetch_syscall_args(td, &sa);
CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
td->td_proc->p_pid, td->td_name, code);
td->td_syscalls++;
td->td_proc->p_pid, td->td_name, sa.code);
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = frame->tf_rdx;
STOPEVENT(p, S_SCE, narg);
STOPEVENT(p, S_SCE, sa.narg);
PTRACESTOP_SC(p, td, S_PT_SCE);
if (td->td_dbgflags & TDB_USERWR) {
/*
* Reread syscall number and arguments if
* debugger modified registers or memory.
*/
error = fetch_syscall_args(td, &sa);
if (error != 0)
goto retval;
td->td_retval[1] = frame->tf_rdx;
}
#ifdef KDTRACE_HOOKS
/*
@ -981,13 +1017,13 @@ syscall(struct trapframe *frame)
* callback and if there is a probe active for the
* syscall 'entry', process the probe.
*/
if (systrace_probe_func != NULL && callp->sy_entry != 0)
(*systrace_probe_func)(callp->sy_entry, code, callp,
args);
if (systrace_probe_func != NULL && sa.callp->sy_entry != 0)
(*systrace_probe_func)(sa.callp->sy_entry, sa.code,
sa.callp, sa.args);
#endif
AUDIT_SYSCALL_ENTER(code, td);
error = (*callp->sy_call)(td, argp);
AUDIT_SYSCALL_ENTER(sa.code, td);
error = (*sa.callp->sy_call)(td, sa.argp);
AUDIT_SYSCALL_EXIT(error, td);
/* Save the latest error return value. */
@ -999,12 +1035,12 @@ syscall(struct trapframe *frame)
* callback and if there is a probe active for the
* syscall 'return', process the probe.
*/
if (systrace_probe_func != NULL && callp->sy_return != 0)
(*systrace_probe_func)(callp->sy_return, code, callp,
args);
if (systrace_probe_func != NULL && sa.callp->sy_return != 0)
(*systrace_probe_func)(sa.callp->sy_return, sa.code,
sa.callp, sa.args);
#endif
}
retval:
cpu_set_syscall_retval(td, error);
/*
@ -1023,14 +1059,16 @@ syscall(struct trapframe *frame)
* Check for misbehavior.
*/
WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
(code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
(sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
syscallnames[sa.code] : "???");
KASSERT(td->td_critnest == 0,
("System call %s returning in a critical section",
(code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
(sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
syscallnames[sa.code] : "???"));
KASSERT(td->td_locks == 0,
("System call %s returning with %d locks held",
(code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
td->td_locks));
(sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
syscallnames[sa.code] : "???", td->td_locks));
/*
* Handle reschedule and other end-of-syscall issues
@ -1038,11 +1076,11 @@ syscall(struct trapframe *frame)
userret(td, frame);
CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
td->td_proc->p_pid, td->td_name, code);
td->td_proc->p_pid, td->td_name, sa.code);
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSRET))
ktrsysret(code, error, td->td_retval[0]);
ktrsysret(sa.code, error, td->td_retval[0]);
#endif
/*
@ -1050,7 +1088,7 @@ syscall(struct trapframe *frame)
* register set. If we ever support an emulation where this
* is not the case, this code will need to be revisited.
*/
STOPEVENT(p, S_SCX, code);
STOPEVENT(p, S_SCX, sa.code);
PTRACESTOP_SC(p, td, S_PT_SCX);
}

View File

@ -88,101 +88,136 @@ extern const char *freebsd32_syscallnames[];
void ia32_syscall(struct trapframe *frame); /* Called from asm code */
void
ia32_syscall(struct trapframe *frame)
{
caddr_t params;
int i;
struct sysent *callp;
struct thread *td = curthread;
struct proc *p = td->td_proc;
register_t orig_tf_rflags;
int error;
int narg;
u_int32_t args[8];
u_int64_t args64[8];
struct ia32_syscall_args {
u_int code;
ksiginfo_t ksi;
caddr_t params;
struct sysent *callp;
u_int64_t args64[8];
int narg;
};
PCPU_INC(cnt.v_syscall);
td->td_pticks = 0;
td->td_frame = frame;
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t);
code = frame->tf_rax;
orig_tf_rflags = frame->tf_rflags;
static int
fetch_ia32_syscall_args(struct thread *td, struct ia32_syscall_args *sa)
{
struct proc *p;
struct trapframe *frame;
u_int32_t args[8];
int error, i;
p = td->td_proc;
frame = td->td_frame;
sa->params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t);
sa->code = frame->tf_rax;
if (p->p_sysent->sv_prepsyscall) {
/*
* The prep code is MP aware.
*/
(*p->p_sysent->sv_prepsyscall)(frame, args, &code, &params);
(*p->p_sysent->sv_prepsyscall)(frame, args, &sa->code,
&sa->params);
} else {
/*
* Need to check if this is a 32 bit or 64 bit syscall.
* fuword is MP aware.
*/
if (code == SYS_syscall) {
if (sa->code == SYS_syscall) {
/*
* Code is first argument, followed by actual args.
*/
code = fuword32(params);
params += sizeof(int);
} else if (code == SYS___syscall) {
sa->code = fuword32(sa->params);
sa->params += sizeof(int);
} else if (sa->code == SYS___syscall) {
/*
* Like syscall, but code is a quad, so as to maintain
* quad alignment for the rest of the arguments.
* We use a 32-bit fetch in case params is not
* aligned.
*/
code = fuword32(params);
params += sizeof(quad_t);
sa->code = fuword32(sa->params);
sa->params += sizeof(quad_t);
}
}
if (p->p_sysent->sv_mask)
code &= p->p_sysent->sv_mask;
if (code >= p->p_sysent->sv_size)
callp = &p->p_sysent->sv_table[0];
sa->code &= p->p_sysent->sv_mask;
if (sa->code >= p->p_sysent->sv_size)
sa->callp = &p->p_sysent->sv_table[0];
else
callp = &p->p_sysent->sv_table[code];
sa->callp = &p->p_sysent->sv_table[sa->code];
sa->narg = sa->callp->sy_narg;
narg = callp->sy_narg;
/*
* copyin and the ktrsyscall()/ktrsysret() code is MP-aware
*/
if (params != NULL && narg != 0)
error = copyin(params, (caddr_t)args,
(u_int)(narg * sizeof(int)));
if (sa->params != NULL && sa->narg != 0)
error = copyin(sa->params, (caddr_t)args,
(u_int)(sa->narg * sizeof(int)));
else
error = 0;
for (i = 0; i < narg; i++)
args64[i] = args[i];
for (i = 0; i < sa->narg; i++)
sa->args64[i] = args[i];
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSCALL))
ktrsyscall(code, narg, args64);
ktrsyscall(sa->code, sa->narg, sa->args64);
#endif
return (error);
}
void
ia32_syscall(struct trapframe *frame)
{
struct thread *td;
struct proc *p;
struct ia32_syscall_args sa;
register_t orig_tf_rflags;
int error;
ksiginfo_t ksi;
PCPU_INC(cnt.v_syscall);
td = curthread;
p = td->td_proc;
td->td_syscalls++;
td->td_pticks = 0;
td->td_frame = frame;
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
orig_tf_rflags = frame->tf_rflags;
if (p->p_flag & P_TRACED) {
PROC_LOCK(p);
td->td_dbgflags &= ~TDB_USERWR;
PROC_UNLOCK(p);
}
error = fetch_ia32_syscall_args(td, &sa);
CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
td->td_proc->p_pid, td->td_proc->p_comm, code);
td->td_proc->p_pid, td->td_name, sa.code);
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = frame->tf_rdx;
STOPEVENT(p, S_SCE, narg);
STOPEVENT(p, S_SCE, sa.narg);
PTRACESTOP_SC(p, td, S_PT_SCE);
if (td->td_dbgflags & TDB_USERWR) {
/*
* Reread syscall number and arguments if
* debugger modified registers or memory.
*/
error = fetch_ia32_syscall_args(td, &sa);
if (error != 0)
goto retval;
td->td_retval[1] = frame->tf_rdx;
}
AUDIT_SYSCALL_ENTER(code, td);
error = (*callp->sy_call)(td, args64);
AUDIT_SYSCALL_ENTER(sa.code, td);
error = (*sa.callp->sy_call)(td, sa.args64);
AUDIT_SYSCALL_EXIT(error, td);
}
/* Save the latest error return value. */
td->td_errno = error;
}
retval:
cpu_set_syscall_retval(td, error);
/*
@ -201,14 +236,16 @@ ia32_syscall(struct trapframe *frame)
* Check for misbehavior.
*/
WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
(code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???");
(sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
freebsd32_syscallnames[sa.code] : "???");
KASSERT(td->td_critnest == 0,
("System call %s returning in a critical section",
(code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???"));
(sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
freebsd32_syscallnames[sa.code] : "???"));
KASSERT(td->td_locks == 0,
("System call %s returning with %d locks held",
(code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???",
td->td_locks));
(sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
freebsd32_syscallnames[sa.code] : "???", td->td_locks));
/*
* Handle reschedule and other end-of-syscall issues
@ -216,10 +253,10 @@ ia32_syscall(struct trapframe *frame)
userret(td, frame);
CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
td->td_proc->p_pid, td->td_proc->p_comm, code);
td->td_proc->p_pid, td->td_proc->p_comm, sa.code);
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSRET))
ktrsysret(code, error, td->td_retval[0]);
ktrsysret(sa.code, error, td->td_retval[0]);
#endif
/*
@ -227,7 +264,7 @@ ia32_syscall(struct trapframe *frame)
* register set. If we ever support an emulation where this
* is not the case, this code will need to be revisited.
*/
STOPEVENT(p, S_SCX, code);
STOPEVENT(p, S_SCX, sa.code);
PTRACESTOP_SC(p, td, S_PT_SCX);
}

View File

@ -969,6 +969,72 @@ dblfault_handler()
panic("double fault");
}
struct syscall_args {
u_int code;
struct sysent *callp;
int args[8];
register_t *argp;
int narg;
};
static int
fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
struct proc *p;
struct trapframe *frame;
caddr_t params;
int error;
p = td->td_proc;
frame = td->td_frame;
params = (caddr_t)frame->tf_esp + sizeof(int);
sa->code = frame->tf_eax;
if (p->p_sysent->sv_prepsyscall) {
(*p->p_sysent->sv_prepsyscall)(frame, sa->args, &sa->code,
&params);
} else {
/*
* Need to check if this is a 32 bit or 64 bit syscall.
*/
if (sa->code == SYS_syscall) {
/*
* Code is first argument, followed by actual args.
*/
sa->code = fuword(params);
params += sizeof(int);
} else if (sa->code == SYS___syscall) {
/*
* Like syscall, but code is a quad, so as to maintain
* quad alignment for the rest of the arguments.
*/
sa->code = fuword(params);
params += sizeof(quad_t);
}
}
if (p->p_sysent->sv_mask)
sa->code &= p->p_sysent->sv_mask;
if (sa->code >= p->p_sysent->sv_size)
sa->callp = &p->p_sysent->sv_table[0];
else
sa->callp = &p->p_sysent->sv_table[sa->code];
sa->narg = sa->callp->sy_narg;
if (params != NULL && sa->narg != 0)
error = copyin(params, (caddr_t)sa->args,
(u_int)(sa->narg * sizeof(int)));
else
error = 0;
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSCALL))
ktrsyscall(sa->code, sa->narg, sa->args);
#endif
return (error);
}
/*
* syscall - system call request C handler
*
@ -977,18 +1043,17 @@ dblfault_handler()
void
syscall(struct trapframe *frame)
{
caddr_t params;
struct sysent *callp;
struct thread *td = curthread;
struct proc *p = td->td_proc;
struct thread *td;
struct proc *p;
struct syscall_args sa;
register_t orig_tf_eflags;
int error;
int narg;
int args[8];
u_int code;
ksiginfo_t ksi;
PCPU_INC(cnt.v_syscall);
td = curthread;
p = td->td_proc;
td->td_syscalls++;
#ifdef DIAGNOSTIC
if (ISPL(frame->tf_cs) != SEL_UPL) {
@ -1001,65 +1066,33 @@ syscall(struct trapframe *frame)
td->td_frame = frame;
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
params = (caddr_t)frame->tf_esp + sizeof(int);
code = frame->tf_eax;
orig_tf_eflags = frame->tf_eflags;
if (p->p_sysent->sv_prepsyscall) {
(*p->p_sysent->sv_prepsyscall)(frame, args, &code, &params);
} else {
/*
* Need to check if this is a 32 bit or 64 bit syscall.
*/
if (code == SYS_syscall) {
/*
* Code is first argument, followed by actual args.
*/
code = fuword(params);
params += sizeof(int);
} else if (code == SYS___syscall) {
/*
* Like syscall, but code is a quad, so as to maintain
* quad alignment for the rest of the arguments.
*/
code = fuword(params);
params += sizeof(quad_t);
}
if (p->p_flag & P_TRACED) {
PROC_LOCK(p);
td->td_dbgflags &= ~TDB_USERWR;
PROC_UNLOCK(p);
}
if (p->p_sysent->sv_mask)
code &= p->p_sysent->sv_mask;
if (code >= p->p_sysent->sv_size)
callp = &p->p_sysent->sv_table[0];
else
callp = &p->p_sysent->sv_table[code];
narg = callp->sy_narg;
if (params != NULL && narg != 0)
error = copyin(params, (caddr_t)args,
(u_int)(narg * sizeof(int)));
else
error = 0;
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSCALL))
ktrsyscall(code, narg, args);
#endif
error = fetch_syscall_args(td, &sa);
CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
td->td_proc->p_pid, td->td_name, code);
td->td_syscalls++;
td->td_proc->p_pid, td->td_name, sa.code);
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = frame->tf_edx;
STOPEVENT(p, S_SCE, narg);
STOPEVENT(p, S_SCE, sa.narg);
PTRACESTOP_SC(p, td, S_PT_SCE);
if (td->td_dbgflags & TDB_USERWR) {
/*
* Reread syscall number and arguments if
* debugger modified registers or memory.
*/
error = fetch_syscall_args(td, &sa);
if (error != 0)
goto retval;
td->td_retval[1] = frame->tf_edx;
}
#ifdef KDTRACE_HOOKS
/*
@ -1067,13 +1100,13 @@ syscall(struct trapframe *frame)
* callback and if there is a probe active for the
* syscall 'entry', process the probe.
*/
if (systrace_probe_func != NULL && callp->sy_entry != 0)
(*systrace_probe_func)(callp->sy_entry, code, callp,
args);
if (systrace_probe_func != NULL && sa.callp->sy_entry != 0)
(*systrace_probe_func)(sa.callp->sy_entry, sa.code,
sa.callp, sa.args);
#endif
AUDIT_SYSCALL_ENTER(code, td);
error = (*callp->sy_call)(td, args);
AUDIT_SYSCALL_ENTER(sa.code, td);
error = (*sa.callp->sy_call)(td, sa.args);
AUDIT_SYSCALL_EXIT(error, td);
/* Save the latest error return value. */
@ -1085,12 +1118,12 @@ syscall(struct trapframe *frame)
* callback and if there is a probe active for the
* syscall 'return', process the probe.
*/
if (systrace_probe_func != NULL && callp->sy_return != 0)
(*systrace_probe_func)(callp->sy_return, code, callp,
args);
if (systrace_probe_func != NULL && sa.callp->sy_return != 0)
(*systrace_probe_func)(sa.callp->sy_return, sa.code,
sa.callp, sa.args);
#endif
}
retval:
cpu_set_syscall_retval(td, error);
/*
@ -1109,14 +1142,16 @@ syscall(struct trapframe *frame)
* Check for misbehavior.
*/
WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
(code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
(sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
syscallnames[sa.code] : "???");
KASSERT(td->td_critnest == 0,
("System call %s returning in a critical section",
(code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
(sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
syscallnames[sa.code] : "???"));
KASSERT(td->td_locks == 0,
("System call %s returning with %d locks held",
(code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
td->td_locks));
(sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
syscallnames[sa.code] : "???", td->td_locks));
/*
* Handle reschedule and other end-of-syscall issues
@ -1124,11 +1159,11 @@ syscall(struct trapframe *frame)
userret(td, frame);
CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
td->td_proc->p_pid, td->td_name, code);
td->td_proc->p_pid, td->td_name, sa.code);
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSRET))
ktrsysret(code, error, td->td_retval[0]);
ktrsysret(sa.code, error, td->td_retval[0]);
#endif
/*
@ -1136,7 +1171,7 @@ syscall(struct trapframe *frame)
* register set. If we ever support an emulation where this
* is not the case, this code will need to be revisited.
*/
STOPEVENT(p, S_SCX, code);
STOPEVENT(p, S_SCX, sa.code);
PTRACESTOP_SC(p, td, S_PT_SCX);
}

View File

@ -816,6 +816,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
case PT_WRITE_I:
case PT_WRITE_D:
td2->td_dbgflags |= TDB_USERWR;
write = 1;
/* FALLTHROUGH */
case PT_READ_I:
@ -884,6 +885,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
break;
case PIOD_WRITE_D:
case PIOD_WRITE_I:
td2->td_dbgflags |= TDB_USERWR;
uio.uio_rw = UIO_WRITE;
break;
default:
@ -906,6 +908,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
goto sendsig; /* in PT_CONTINUE above */
case PT_SETREGS:
td2->td_dbgflags |= TDB_USERWR;
error = PROC_WRITE(regs, td2, addr);
break;
@ -914,6 +917,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
break;
case PT_SETFPREGS:
td2->td_dbgflags |= TDB_USERWR;
error = PROC_WRITE(fpregs, td2, addr);
break;
@ -922,6 +926,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
break;
case PT_SETDBREGS:
td2->td_dbgflags |= TDB_USERWR;
error = PROC_WRITE(dbregs, td2, addr);
break;

View File

@ -341,6 +341,7 @@ do { \
/* Userland debug flags */
#define TDB_SUSPEND 0x00000001 /* Thread is suspended by debugger */
#define TDB_XSIG 0x00000002 /* Thread is exchanging signal under trace */
#define TDB_USERWR 0x00000004 /* Debugger modified memory or registers */
/*
* "Private" flags kept in td_pflags: