X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fia64%2Fkernel%2Fptrace.c;h=9140c2c29cbd902eda8fd600a8c3f723c0328fc7;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hp=ad92fee8eb0e15facc5e0659bbb3840f7a31f9f2;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index ad92fee8e..9140c2c29 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -634,11 +635,17 @@ ia64_flush_fph (struct task_struct *task) { 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(); } /* @@ -691,16 +698,30 @@ convert_to_non_syscall (struct task_struct *child, struct pt_regs *pt, 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; } @@ -924,6 +945,13 @@ access_uarea (struct task_struct *child, unsigned long addr, *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 *) @@ -975,9 +1003,6 @@ access_uarea (struct task_struct *child, unsigned long addr, 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; @@ -1074,15 +1099,12 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) 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); @@ -1105,8 +1127,6 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) || access_uarea(child, PT_NAT_BITS, &nat_bits, 0)) return -EIO; - retval = 0; - /* control regs */ retval |= __put_user(pt->cr_iip, &ppr->cr_iip); @@ -1218,21 +1238,18 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) 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); @@ -1246,8 +1263,6 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) return -EIO; } - retval = 0; - /* control regs */ retval |= __get_user(pt->cr_iip, &ppr->cr_iip); @@ -1256,7 +1271,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) /* 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]); @@ -1354,6 +1369,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) 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); @@ -1494,7 +1510,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) 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); @@ -1533,7 +1549,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) /* 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); @@ -1608,20 +1624,25 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3, 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... */ @@ -1632,7 +1653,7 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3, 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))