Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Pull utrace into release branch

Tony Luck 9224652c 4d4230c2

+285 -133
+1
arch/ia64/Kconfig
··· 21 21 select HAVE_KRETPROBES 22 22 select HAVE_DMA_ATTRS 23 23 select HAVE_KVM 24 + select HAVE_ARCH_TRACEHOOK 24 25 default y 25 26 help 26 27 The Itanium Processor Family is Intel's 64-bit successor to
+6 -1
arch/ia64/ia32/ia32_entry.S
··· 108 108 ;; 109 109 st8 [r2]=r3 // initialize return code to -ENOSYS 110 110 br.call.sptk.few rp=syscall_trace_enter // give parent a chance to catch syscall args 111 + cmp.lt p6,p0=r8,r0 // check tracehook 112 + adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8 113 + ;; 114 + (p6) st8.spill [r2]=r8 // store return value in slot for r8 115 + (p6) br.spnt.few .ret4 111 116 .ret2: // Need to reload arguments (they may be changed by the tracing process) 112 117 adds r2=IA64_PT_REGS_R1_OFFSET+16,sp // r2 = &pt_regs.r1 113 118 adds r3=IA64_PT_REGS_R13_OFFSET+16,sp // r3 = &pt_regs.r13 ··· 204 199 data8 sys_setuid /* 16-bit version */ 205 200 data8 sys_getuid /* 16-bit version */ 206 201 data8 compat_sys_stime /* 25 */ 207 - data8 sys32_ptrace 202 + data8 compat_sys_ptrace 208 203 data8 sys32_alarm 209 204 data8 sys_ni_syscall 210 205 data8 sys_pause
+6 -77
arch/ia64/ia32/sys_ia32.c
··· 1194 1194 return compat_sys_wait4(pid, stat_addr, options, NULL); 1195 1195 } 1196 1196 1197 - static unsigned int 1198 - ia32_peek (struct task_struct *child, unsigned long addr, unsigned int *val) 1199 - { 1200 - size_t copied; 1201 - unsigned int ret; 1202 - 1203 - copied = access_process_vm(child, addr, val, sizeof(*val), 0); 1204 - return (copied != sizeof(ret)) ? -EIO : 0; 1205 - } 1206 - 1207 - static unsigned int 1208 - ia32_poke (struct task_struct *child, unsigned long addr, unsigned int val) 1209 - { 1210 - 1211 - if (access_process_vm(child, addr, &val, sizeof(val), 1) != sizeof(val)) 1212 - return -EIO; 1213 - return 0; 1214 - } 1215 - 1216 1197 /* 1217 1198 * The order in which registers are stored in the ptrace regs structure 1218 1199 */ ··· 1491 1510 return 0; 1492 1511 } 1493 1512 1494 - asmlinkage long 1495 - sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data) 1513 + long compat_arch_ptrace(struct task_struct *child, compat_long_t request, 1514 + compat_ulong_t caddr, compat_ulong_t cdata) 1496 1515 { 1497 - struct task_struct *child; 1498 - unsigned int value, tmp; 1516 + unsigned long addr = caddr; 1517 + unsigned long data = cdata; 1518 + unsigned int tmp; 1499 1519 long i, ret; 1500 1520 1501 - lock_kernel(); 1502 - if (request == PTRACE_TRACEME) { 1503 - ret = ptrace_traceme(); 1504 - goto out; 1505 - } 1506 - 1507 - child = ptrace_get_task_struct(pid); 1508 - if (IS_ERR(child)) { 1509 - ret = PTR_ERR(child); 1510 - goto out; 1511 - } 1512 - 1513 - if (request == PTRACE_ATTACH) { 1514 - ret = sys_ptrace(request, pid, addr, data); 1515 - goto out_tsk; 1516 - } 1517 - 1518 - ret = ptrace_check_attach(child, request == PTRACE_KILL); 1519 - if (ret < 0) 1520 - goto out_tsk; 1521 - 1522 1521 switch (request) { 1523 - case PTRACE_PEEKTEXT: 1524 - case PTRACE_PEEKDATA: /* read word at location addr */ 1525 - ret = ia32_peek(child, addr, &value); 1526 - if (ret == 0) 1527 - ret = put_user(value, (unsigned int __user *) compat_ptr(data)); 1528 - else 1529 - ret = -EIO; 1530 - goto out_tsk; 1531 - 1532 - case PTRACE_POKETEXT: 1533 - case PTRACE_POKEDATA: /* write the word at location addr */ 1534 - ret = ia32_poke(child, addr, data); 1535 - goto out_tsk; 1536 - 1537 1522 case PTRACE_PEEKUSR: /* read word at addr in USER area */ 1538 1523 ret = -EIO; 1539 1524 if ((addr & 3) || addr > 17*sizeof(int)) ··· 1564 1617 compat_ptr(data)); 1565 1618 break; 1566 1619 1567 - case PTRACE_GETEVENTMSG: 1568 - ret = put_user(child->ptrace_message, (unsigned int __user *) compat_ptr(data)); 1569 - break; 1570 - 1571 - case PTRACE_SYSCALL: /* continue, stop after next syscall */ 1572 - case PTRACE_CONT: /* restart after signal. */ 1573 - case PTRACE_KILL: 1574 - case PTRACE_SINGLESTEP: /* execute chile for one instruction */ 1575 - case PTRACE_DETACH: /* detach a process */ 1576 - ret = sys_ptrace(request, pid, addr, data); 1577 - break; 1578 - 1579 1620 default: 1580 - ret = ptrace_request(child, request, addr, data); 1581 - break; 1582 - 1621 + return compat_ptrace_request(child, request, caddr, cdata); 1583 1622 } 1584 - out_tsk: 1585 - put_task_struct(child); 1586 - out: 1587 - unlock_kernel(); 1588 1623 return ret; 1589 1624 } 1590 1625
+8
arch/ia64/include/asm/ptrace.h
··· 240 240 */ 241 241 # define instruction_pointer(regs) ((regs)->cr_iip + ia64_psr(regs)->ri) 242 242 243 + static inline unsigned long user_stack_pointer(struct pt_regs *regs) 244 + { 245 + /* FIXME: should this be bspstore + nr_dirty regs? */ 246 + return regs->ar_bspstore; 247 + } 248 + 243 249 #define regs_return_value(regs) ((regs)->r8) 244 250 245 251 /* Conserve space in histogram by encoding slot bits in address ··· 324 318 325 319 #define arch_has_block_step() (1) 326 320 extern void user_enable_block_step(struct task_struct *); 321 + 322 + #define __ARCH_WANT_COMPAT_SYS_PTRACE 327 323 328 324 #endif /* !__KERNEL__ */ 329 325
+163
arch/ia64/include/asm/syscall.h
··· 1 + /* 2 + * Access to user system call parameters and results 3 + * 4 + * Copyright (C) 2008 Intel Corp. Shaohua Li <shaohua.li@intel.com> 5 + * 6 + * This copyrighted material is made available to anyone wishing to use, 7 + * modify, copy, or redistribute it subject to the terms and conditions 8 + * of the GNU General Public License v.2. 9 + * 10 + * See asm-generic/syscall.h for descriptions of what we must do here. 11 + */ 12 + 13 + #ifndef _ASM_SYSCALL_H 14 + #define _ASM_SYSCALL_H 1 15 + 16 + #include <linux/sched.h> 17 + #include <linux/err.h> 18 + 19 + static inline long syscall_get_nr(struct task_struct *task, 20 + struct pt_regs *regs) 21 + { 22 + if ((long)regs->cr_ifs < 0) /* Not a syscall */ 23 + return -1; 24 + 25 + #ifdef CONFIG_IA32_SUPPORT 26 + if (IS_IA32_PROCESS(regs)) 27 + return regs->r1; 28 + #endif 29 + 30 + return regs->r15; 31 + } 32 + 33 + static inline void syscall_rollback(struct task_struct *task, 34 + struct pt_regs *regs) 35 + { 36 + #ifdef CONFIG_IA32_SUPPORT 37 + if (IS_IA32_PROCESS(regs)) 38 + regs->r8 = regs->r1; 39 + #endif 40 + 41 + /* do nothing */ 42 + } 43 + 44 + static inline long syscall_get_error(struct task_struct *task, 45 + struct pt_regs *regs) 46 + { 47 + #ifdef CONFIG_IA32_SUPPORT 48 + if (IS_IA32_PROCESS(regs)) 49 + return regs->r8; 50 + #endif 51 + 52 + return regs->r10 == -1 ? regs->r8:0; 53 + } 54 + 55 + static inline long syscall_get_return_value(struct task_struct *task, 56 + struct pt_regs *regs) 57 + { 58 + return regs->r8; 59 + } 60 + 61 + static inline void syscall_set_return_value(struct task_struct *task, 62 + struct pt_regs *regs, 63 + int error, long val) 64 + { 65 + #ifdef CONFIG_IA32_SUPPORT 66 + if (IS_IA32_PROCESS(regs)) { 67 + regs->r8 = (long) error ? error : val; 68 + return; 69 + } 70 + #endif 71 + 72 + if (error) { 73 + /* error < 0, but ia64 uses > 0 return value */ 74 + regs->r8 = -error; 75 + regs->r10 = -1; 76 + } else { 77 + regs->r8 = val; 78 + regs->r10 = 0; 79 + } 80 + } 81 + 82 + extern void ia64_syscall_get_set_arguments(struct task_struct *task, 83 + struct pt_regs *regs, unsigned int i, unsigned int n, 84 + unsigned long *args, int rw); 85 + static inline void syscall_get_arguments(struct task_struct *task, 86 + struct pt_regs *regs, 87 + unsigned int i, unsigned int n, 88 + unsigned long *args) 89 + { 90 + BUG_ON(i + n > 6); 91 + 92 + #ifdef CONFIG_IA32_SUPPORT 93 + if (IS_IA32_PROCESS(regs)) { 94 + switch (i + n) { 95 + case 6: 96 + if (!n--) break; 97 + *args++ = regs->r13; 98 + case 5: 99 + if (!n--) break; 100 + *args++ = regs->r15; 101 + case 4: 102 + if (!n--) break; 103 + *args++ = regs->r14; 104 + case 3: 105 + if (!n--) break; 106 + *args++ = regs->r10; 107 + case 2: 108 + if (!n--) break; 109 + *args++ = regs->r9; 110 + case 1: 111 + if (!n--) break; 112 + *args++ = regs->r11; 113 + case 0: 114 + if (!n--) break; 115 + default: 116 + BUG(); 117 + break; 118 + } 119 + 120 + return; 121 + } 122 + #endif 123 + ia64_syscall_get_set_arguments(task, regs, i, n, args, 0); 124 + } 125 + 126 + static inline void syscall_set_arguments(struct task_struct *task, 127 + struct pt_regs *regs, 128 + unsigned int i, unsigned int n, 129 + unsigned long *args) 130 + { 131 + BUG_ON(i + n > 6); 132 + 133 + #ifdef CONFIG_IA32_SUPPORT 134 + if (IS_IA32_PROCESS(regs)) { 135 + switch (i + n) { 136 + case 6: 137 + if (!n--) break; 138 + regs->r13 = *args++; 139 + case 5: 140 + if (!n--) break; 141 + regs->r15 = *args++; 142 + case 4: 143 + if (!n--) break; 144 + regs->r14 = *args++; 145 + case 3: 146 + if (!n--) break; 147 + regs->r10 = *args++; 148 + case 2: 149 + if (!n--) break; 150 + regs->r9 = *args++; 151 + case 1: 152 + if (!n--) break; 153 + regs->r11 = *args++; 154 + case 0: 155 + if (!n--) break; 156 + } 157 + 158 + return; 159 + } 160 + #endif 161 + ia64_syscall_get_set_arguments(task, regs, i, n, args, 1); 162 + } 163 + #endif /* _ASM_SYSCALL_H */
-3
arch/ia64/include/asm/thread_info.h
··· 87 87 #define alloc_task_struct() ((struct task_struct *)__get_free_pages(GFP_KERNEL | __GFP_COMP, KERNEL_STACK_SIZE_ORDER)) 88 88 #define free_task_struct(tsk) free_pages((unsigned long) (tsk), KERNEL_STACK_SIZE_ORDER) 89 89 90 - #define tsk_set_notify_resume(tsk) \ 91 - set_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME) 92 - extern void tsk_clear_notify_resume(struct task_struct *tsk); 93 90 #endif /* !__ASSEMBLY */ 94 91 95 92 /*
+5
arch/ia64/kernel/entry.S
··· 534 534 stf.spill [r16]=f10 535 535 stf.spill [r17]=f11 536 536 br.call.sptk.many rp=syscall_trace_enter // give parent a chance to catch syscall args 537 + cmp.lt p6,p0=r8,r0 // check tracehook 538 + adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8 539 + adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10 540 + mov r10=0 541 + (p6) br.cond.sptk strace_error // syscall failed -> 537 542 adds r16=PT(F6)+16,sp 538 543 adds r17=PT(F7)+16,sp 539 544 ;;
+3 -4
arch/ia64/kernel/perfmon.c
··· 40 40 #include <linux/capability.h> 41 41 #include <linux/rcupdate.h> 42 42 #include <linux/completion.h> 43 + #include <linux/tracehook.h> 43 44 44 45 #include <asm/errno.h> 45 46 #include <asm/intrinsics.h> ··· 3685 3684 3686 3685 PFM_SET_WORK_PENDING(task, 1); 3687 3686 3688 - tsk_set_notify_resume(task); 3687 + set_notify_resume(task); 3689 3688 3690 3689 /* 3691 3690 * XXX: send reschedule if task runs on another CPU ··· 5045 5044 5046 5045 PFM_SET_WORK_PENDING(current, 0); 5047 5046 5048 - tsk_clear_notify_resume(current); 5049 - 5050 5047 regs = task_pt_regs(current); 5051 5048 5052 5049 /* ··· 5413 5414 * when coming from ctxsw, current still points to the 5414 5415 * previous task, therefore we must work with task and not current. 5415 5416 */ 5416 - tsk_set_notify_resume(task); 5417 + set_notify_resume(task); 5417 5418 } 5418 5419 /* 5419 5420 * defer until state is changed (shorten spin window). the context is locked
+6 -15
arch/ia64/kernel/process.c
··· 28 28 #include <linux/delay.h> 29 29 #include <linux/kdebug.h> 30 30 #include <linux/utsname.h> 31 + #include <linux/tracehook.h> 31 32 32 33 #include <asm/cpu.h> 33 34 #include <asm/delay.h> ··· 161 160 show_stack(NULL, NULL); 162 161 } 163 162 164 - void tsk_clear_notify_resume(struct task_struct *tsk) 165 - { 166 - #ifdef CONFIG_PERFMON 167 - if (tsk->thread.pfm_needs_checking) 168 - return; 169 - #endif 170 - if (test_ti_thread_flag(task_thread_info(tsk), TIF_RESTORE_RSE)) 171 - return; 172 - clear_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME); 173 - } 174 - 175 - /* 176 - * do_notify_resume_user(): 177 - * Called from notify_resume_user at entry.S, with interrupts disabled. 178 - */ 179 163 void 180 164 do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall) 181 165 { ··· 187 201 if (test_thread_flag(TIF_SIGPENDING)) { 188 202 local_irq_enable(); /* force interrupt enable */ 189 203 ia64_do_signal(scr, in_syscall); 204 + } 205 + 206 + if (test_thread_flag(TIF_NOTIFY_RESUME)) { 207 + clear_thread_flag(TIF_NOTIFY_RESUME); 208 + tracehook_notify_resume(&scr->pt); 190 209 } 191 210 192 211 /* copy user rbs to kernel rbs */
+79 -33
arch/ia64/kernel/ptrace.c
··· 22 22 #include <linux/signal.h> 23 23 #include <linux/regset.h> 24 24 #include <linux/elf.h> 25 + #include <linux/tracehook.h> 25 26 26 27 #include <asm/pgtable.h> 27 28 #include <asm/processor.h> ··· 604 603 { 605 604 if (test_and_set_tsk_thread_flag(current, TIF_RESTORE_RSE)) 606 605 return; 607 - tsk_set_notify_resume(current); 606 + set_notify_resume(current); 608 607 unw_init_running(do_sync_rbs, ia64_sync_user_rbs); 609 608 } 610 609 ··· 614 613 void ia64_sync_krbs(void) 615 614 { 616 615 clear_tsk_thread_flag(current, TIF_RESTORE_RSE); 617 - tsk_clear_notify_resume(current); 618 616 619 617 unw_init_running(do_sync_rbs, ia64_sync_kernel_rbs); 620 618 } ··· 644 644 spin_lock_irq(&child->sighand->siglock); 645 645 if (child->state == TASK_STOPPED && 646 646 !test_and_set_tsk_thread_flag(child, TIF_RESTORE_RSE)) { 647 - tsk_set_notify_resume(child); 647 + set_notify_resume(child); 648 648 649 649 child->state = TASK_TRACED; 650 650 stopped = 1; ··· 1232 1232 } 1233 1233 1234 1234 1235 - static void 1236 - syscall_trace (void) 1237 - { 1238 - /* 1239 - * The 0x80 provides a way for the tracing parent to 1240 - * distinguish between a syscall stop and SIGTRAP delivery. 1241 - */ 1242 - ptrace_notify(SIGTRAP 1243 - | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); 1244 - 1245 - /* 1246 - * This isn't the same as continuing with a signal, but it 1247 - * will do for normal use. strace only continues with a 1248 - * signal if the stopping signal is not SIGTRAP. -brl 1249 - */ 1250 - if (current->exit_code) { 1251 - send_sig(current->exit_code, current, 1); 1252 - current->exit_code = 0; 1253 - } 1254 - } 1255 - 1256 1235 /* "asmlinkage" so the input arguments are preserved... */ 1257 1236 1258 - asmlinkage void 1237 + asmlinkage long 1259 1238 syscall_trace_enter (long arg0, long arg1, long arg2, long arg3, 1260 1239 long arg4, long arg5, long arg6, long arg7, 1261 1240 struct pt_regs regs) 1262 1241 { 1263 - if (test_thread_flag(TIF_SYSCALL_TRACE) 1264 - && (current->ptrace & PT_PTRACED)) 1265 - syscall_trace(); 1242 + if (test_thread_flag(TIF_SYSCALL_TRACE)) 1243 + if (tracehook_report_syscall_entry(&regs)) 1244 + return -ENOSYS; 1266 1245 1267 1246 /* copy user rbs to kernel rbs */ 1268 1247 if (test_thread_flag(TIF_RESTORE_RSE)) ··· 1262 1283 audit_syscall_entry(arch, syscall, arg0, arg1, arg2, arg3); 1263 1284 } 1264 1285 1286 + return 0; 1265 1287 } 1266 1288 1267 1289 /* "asmlinkage" so the input arguments are preserved... */ ··· 1272 1292 long arg4, long arg5, long arg6, long arg7, 1273 1293 struct pt_regs regs) 1274 1294 { 1295 + int step; 1296 + 1275 1297 if (unlikely(current->audit_context)) { 1276 1298 int success = AUDITSC_RESULT(regs.r10); 1277 1299 long result = regs.r8; ··· 1283 1301 audit_syscall_exit(success, result); 1284 1302 } 1285 1303 1286 - if ((test_thread_flag(TIF_SYSCALL_TRACE) 1287 - || test_thread_flag(TIF_SINGLESTEP)) 1288 - && (current->ptrace & PT_PTRACED)) 1289 - syscall_trace(); 1304 + step = test_thread_flag(TIF_SINGLESTEP); 1305 + if (step || test_thread_flag(TIF_SYSCALL_TRACE)) 1306 + tracehook_report_syscall_exit(&regs, step); 1290 1307 1291 1308 /* copy user rbs to kernel rbs */ 1292 1309 if (test_thread_flag(TIF_RESTORE_RSE)) ··· 1921 1940 { 1922 1941 if (test_and_set_tsk_thread_flag(target, TIF_RESTORE_RSE)) 1923 1942 return 0; 1924 - tsk_set_notify_resume(target); 1943 + set_notify_resume(target); 1925 1944 return do_regset_call(do_gpregs_writeback, target, regset, 0, 0, 1926 1945 NULL, NULL); 1927 1946 } ··· 2179 2198 return &user_ia32_view; 2180 2199 #endif 2181 2200 return &user_ia64_view; 2201 + } 2202 + 2203 + struct syscall_get_set_args { 2204 + unsigned int i; 2205 + unsigned int n; 2206 + unsigned long *args; 2207 + struct pt_regs *regs; 2208 + int rw; 2209 + }; 2210 + 2211 + static void syscall_get_set_args_cb(struct unw_frame_info *info, void *data) 2212 + { 2213 + struct syscall_get_set_args *args = data; 2214 + struct pt_regs *pt = args->regs; 2215 + unsigned long *krbs, cfm, ndirty; 2216 + int i, count; 2217 + 2218 + if (unw_unwind_to_user(info) < 0) 2219 + return; 2220 + 2221 + cfm = pt->cr_ifs; 2222 + krbs = (unsigned long *)info->task + IA64_RBS_OFFSET/8; 2223 + ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19)); 2224 + 2225 + count = 0; 2226 + if (in_syscall(pt)) 2227 + count = min_t(int, args->n, cfm & 0x7f); 2228 + 2229 + for (i = 0; i < count; i++) { 2230 + if (args->rw) 2231 + *ia64_rse_skip_regs(krbs, ndirty + i + args->i) = 2232 + args->args[i]; 2233 + else 2234 + args->args[i] = *ia64_rse_skip_regs(krbs, 2235 + ndirty + i + args->i); 2236 + } 2237 + 2238 + if (!args->rw) { 2239 + while (i < args->n) { 2240 + args->args[i] = 0; 2241 + i++; 2242 + } 2243 + } 2244 + } 2245 + 2246 + void ia64_syscall_get_set_arguments(struct task_struct *task, 2247 + struct pt_regs *regs, unsigned int i, unsigned int n, 2248 + unsigned long *args, int rw) 2249 + { 2250 + struct syscall_get_set_args data = { 2251 + .i = i, 2252 + .n = n, 2253 + .args = args, 2254 + .regs = regs, 2255 + .rw = rw, 2256 + }; 2257 + 2258 + if (task == current) 2259 + unw_init_running(syscall_get_set_args_cb, &data); 2260 + else { 2261 + struct unw_frame_info ufi; 2262 + memset(&ufi, 0, sizeof(ufi)); 2263 + unw_init_from_blocked_task(&ufi, task); 2264 + syscall_get_set_args_cb(&ufi, &data); 2265 + } 2182 2266 }
+8
arch/ia64/kernel/signal.c
··· 11 11 #include <linux/kernel.h> 12 12 #include <linux/mm.h> 13 13 #include <linux/ptrace.h> 14 + #include <linux/tracehook.h> 14 15 #include <linux/sched.h> 15 16 #include <linux/signal.h> 16 17 #include <linux/smp.h> ··· 440 439 sigaddset(&current->blocked, sig); 441 440 recalc_sigpending(); 442 441 spin_unlock_irq(&current->sighand->siglock); 442 + 443 + /* 444 + * Let tracing know that we've done the handler setup. 445 + */ 446 + tracehook_signal_handler(sig, info, ka, &scr->pt, 447 + test_thread_flag(TIF_SINGLESTEP)); 448 + 443 449 return 1; 444 450 } 445 451