#include <linux/user.h>
#include <linux/security.h>
#include <linux/audit.h>
+#include <linux/signal.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
{
struct ia64_psr *psr = ia64_psr(ia64_task_regs(task));
+ /*
+ * Prevent migrating this task while
+ * we're fiddling with the FPU state
+ */
+ preempt_disable();
if (ia64_is_local_fpu_owner(task) && psr->mfh) {
psr->mfh = 0;
task->thread.flags |= IA64_THREAD_FPH_VALID;
ia64_save_fpu(&task->thread.fph[0]);
}
+ preempt_enable();
}
/*
unsigned long cfm)
{
struct unw_frame_info info, prev_info;
- unsigned long ip, pr;
+ unsigned long ip, sp, pr;
unw_init_from_blocked_task(&info, child);
while (1) {
prev_info = info;
if (unw_unwind(&info) < 0)
return;
- if (unw_get_rp(&info, &ip) < 0)
+
+ unw_get_sp(&info, &sp);
+ if ((long)((unsigned long)child + IA64_STK_OFFSET - sp)
+ < IA64_PT_REGS_SIZE) {
+ dprintk("ptrace.%s: ran off the top of the kernel "
+ "stack\n", __FUNCTION__);
return;
- if (ip < FIXADDR_USER_END)
+ }
+ if (unw_get_pr (&prev_info, &pr) < 0) {
+ unw_get_rp(&prev_info, &ip);
+ dprintk("ptrace.%s: failed to read "
+ "predicate register (ip=0x%lx)\n",
+ __FUNCTION__, ip);
+ return;
+ }
+ if (unw_is_intr_frame(&info)
+ && (pr & (1UL << PRED_USER_STACK)))
break;
}
*data = (pt->cr_ipsr & IPSR_MASK);
return 0;
+ case PT_AR_RSC:
+ if (write_access)
+ pt->ar_rsc = *data | (3 << 2); /* force PL3 */
+ else
+ *data = pt->ar_rsc;
+ return 0;
+
case PT_AR_RNAT:
urbs_end = ia64_get_user_rbs_end(child, pt, NULL);
rnat_addr = (long) ia64_rse_rnat_addr((long *)
case PT_AR_BSPSTORE:
ptr = pt_reg_addr(pt, ar_bspstore);
break;
- case PT_AR_RSC:
- ptr = pt_reg_addr(pt, ar_rsc);
- break;
case PT_AR_UNAT:
ptr = pt_reg_addr(pt, ar_unat);
break;
struct ia64_fpreg fpval;
struct switch_stack *sw;
struct pt_regs *pt;
- long ret, retval;
+ long ret, retval = 0;
char nat = 0;
int i;
- retval = verify_area(VERIFY_WRITE, ppr,
- sizeof(struct pt_all_user_regs));
- if (retval != 0) {
+ if (!access_ok(VERIFY_WRITE, ppr, sizeof(struct pt_all_user_regs)))
return -EIO;
- }
pt = ia64_task_regs(child);
sw = (struct switch_stack *) (child->thread.ksp + 16);
|| access_uarea(child, PT_NAT_BITS, &nat_bits, 0))
return -EIO;
- retval = 0;
-
/* control regs */
retval |= __put_user(pt->cr_iip, &ppr->cr_iip);
static long
ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
{
- unsigned long psr, ec, lc, rnat, bsp, cfm, nat_bits, val = 0;
+ unsigned long psr, rsc, ec, lc, rnat, bsp, cfm, nat_bits, val = 0;
struct unw_frame_info info;
struct switch_stack *sw;
struct ia64_fpreg fpval;
struct pt_regs *pt;
- long ret, retval;
+ long ret, retval = 0;
int i;
memset(&fpval, 0, sizeof(fpval));
- retval = verify_area(VERIFY_READ, ppr,
- sizeof(struct pt_all_user_regs));
- if (retval != 0) {
+ if (!access_ok(VERIFY_READ, ppr, sizeof(struct pt_all_user_regs)))
return -EIO;
- }
pt = ia64_task_regs(child);
sw = (struct switch_stack *) (child->thread.ksp + 16);
return -EIO;
}
- retval = 0;
-
/* control regs */
retval |= __get_user(pt->cr_iip, &ppr->cr_iip);
/* app regs */
retval |= __get_user(pt->ar_pfs, &ppr->ar[PT_AUR_PFS]);
- retval |= __get_user(pt->ar_rsc, &ppr->ar[PT_AUR_RSC]);
+ retval |= __get_user(rsc, &ppr->ar[PT_AUR_RSC]);
retval |= __get_user(pt->ar_bspstore, &ppr->ar[PT_AUR_BSPSTORE]);
retval |= __get_user(pt->ar_unat, &ppr->ar[PT_AUR_UNAT]);
retval |= __get_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]);
retval |= __get_user(nat_bits, &ppr->nat);
retval |= access_uarea(child, PT_CR_IPSR, &psr, 1);
+ retval |= access_uarea(child, PT_AR_RSC, &rsc, 1);
retval |= access_uarea(child, PT_AR_EC, &ec, 1);
retval |= access_uarea(child, PT_AR_LC, &lc, 1);
retval |= access_uarea(child, PT_AR_RNAT, &rnat, 1);
case PTRACE_CONT:
/* restart after signal. */
ret = -EIO;
- if (data > _NSIG)
+ if (!valid_signal(data))
goto out_tsk;
if (request == PTRACE_SYSCALL)
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
/* let child execute for one instruction */
case PTRACE_SINGLEBLOCK:
ret = -EIO;
- if (data > _NSIG)
+ if (!valid_signal(data))
goto out_tsk;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
long arg4, long arg5, long arg6, long arg7,
struct pt_regs regs)
{
- long syscall;
+ if (test_thread_flag(TIF_SYSCALL_TRACE)
+ && (current->ptrace & PT_PTRACED))
+ syscall_trace();
if (unlikely(current->audit_context)) {
- if (IS_IA32_PROCESS(®s))
+ long syscall;
+ int arch;
+
+ if (IS_IA32_PROCESS(®s)) {
syscall = regs.r1;
- else
+ arch = AUDIT_ARCH_I386;
+ } else {
syscall = regs.r15;
+ arch = AUDIT_ARCH_IA64;
+ }
- audit_syscall_entry(current, syscall, arg0, arg1, arg2, arg3);
+ audit_syscall_entry(current, arch, syscall, arg0, arg1, arg2, arg3);
}
- if (test_thread_flag(TIF_SYSCALL_TRACE)
- && (current->ptrace & PT_PTRACED))
- syscall_trace();
}
/* "asmlinkage" so the input arguments are preserved... */
struct pt_regs regs)
{
if (unlikely(current->audit_context))
- audit_syscall_exit(current, regs.r8);
+ audit_syscall_exit(current, AUDITSC_RESULT(regs.r10), regs.r8);
if (test_thread_flag(TIF_SYSCALL_TRACE)
&& (current->ptrace & PT_PTRACED))