{
long tmp;
+ clear_tsk_thread_flag(child, TIF_SINGLESTEP);
tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp);
}
value &= 0xffff;
return 0;
case offsetof(struct user_regs_struct,fs_base):
- if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
- return -EIO;
+ if (value >= TASK_SIZE)
+ return -EIO;
child->thread.fs = value;
return 0;
case offsetof(struct user_regs_struct,gs_base):
- if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
- return -EIO;
+ if (value >= TASK_SIZE)
+ return -EIO;
child->thread.gs = value;
return 0;
case offsetof(struct user_regs_struct, eflags):
return -EIO;
value &= 0xffff;
break;
+ case offsetof(struct user_regs_struct, rip):
+ /* Check if the new RIP address is canonical */
+ if (value >= TASK_SIZE)
+ return -EIO;
+ break;
}
put_stack_long(child, regno - sizeof(struct pt_regs), value);
return 0;
ret = 0;
break;
case offsetof(struct user, u_debugreg[7]):
+ /* See arch/i386/kernel/ptrace.c for an explanation of
+ * this awkward check.*/
data &= ~DR_CONTROL_RESERVED;
for(i=0; i<4; i++)
if ((0x5454 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
set_tsk_thread_flag(child,TIF_SYSCALL_TRACE);
else
clear_tsk_thread_flag(child,TIF_SYSCALL_TRACE);
+ clear_tsk_thread_flag(child, TIF_SINGLESTEP);
child->exit_code = data;
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, EFL_OFFSET);
long tmp;
ret = 0;
- if (child->state == TASK_ZOMBIE) /* already dead */
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
+ clear_tsk_thread_flag(child, TIF_SINGLESTEP);
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
}
tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp);
+ set_tsk_thread_flag(child, TIF_SINGLESTEP);
child->exit_code = data;
/* give it a chance to run. */
wake_up_process(child);
break;
case PTRACE_GETREGS: { /* Get all gp regs from the child. */
- if (!access_ok(VERIFY_WRITE, (unsigned __user *)data, FRAME_SIZE)) {
+ if (!access_ok(VERIFY_WRITE, (unsigned __user *)data,
+ sizeof(struct user_regs_struct))) {
ret = -EIO;
break;
}
+ ret = 0;
for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) {
- __put_user(getreg(child, ui),(unsigned long __user *) data);
+ ret |= __put_user(getreg(child, ui),(unsigned long __user *) data);
data += sizeof(long);
}
- ret = 0;
break;
}
case PTRACE_SETREGS: { /* Set all gp regs in the child. */
unsigned long tmp;
- if (!access_ok(VERIFY_READ, (unsigned __user *)data, FRAME_SIZE)) {
+ if (!access_ok(VERIFY_READ, (unsigned __user *)data,
+ sizeof(struct user_regs_struct))) {
ret = -EIO;
break;
}
+ ret = 0;
for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) {
- __get_user(tmp, (unsigned long __user *) data);
+ ret |= __get_user(tmp, (unsigned long __user *) data);
putreg(child, ui, tmp);
data += sizeof(long);
}
- ret = 0;
break;
}
ret = -EIO;
break;
}
- child->used_math = 1;
+ set_stopped_child_used_math(child);
ret = set_fpregs(child, (struct user_i387_struct __user *)data);
break;
}
if (unlikely(current->audit_context))
audit_syscall_exit(current, regs->rax);
- if (test_thread_flag(TIF_SYSCALL_TRACE)
+ if ((test_thread_flag(TIF_SYSCALL_TRACE)
+ || test_thread_flag(TIF_SINGLESTEP))
&& (current->ptrace & PT_PTRACED))
syscall_trace(regs);
}