ptrace.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. /* ptrace.c: Sparc process tracing support.
  2. *
  3. * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
  4. * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  5. *
  6. * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
  7. * and David Mosberger.
  8. *
  9. * Added Linux support -miguel (weird, eh?, the original code was meant
  10. * to emulate SunOS).
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/sched.h>
  14. #include <linux/mm.h>
  15. #include <linux/errno.h>
  16. #include <linux/ptrace.h>
  17. #include <linux/user.h>
  18. #include <linux/smp.h>
  19. #include <linux/smp_lock.h>
  20. #include <linux/security.h>
  21. #include <linux/signal.h>
  22. #include <asm/asi.h>
  23. #include <asm/pgtable.h>
  24. #include <asm/system.h>
  25. #include <asm/uaccess.h>
  26. #include <asm/psrcompat.h>
  27. #include <asm/visasm.h>
  28. #include <asm/spitfire.h>
  29. /* Returning from ptrace is a bit tricky because the syscall return
  30. * low level code assumes any value returned which is negative and
  31. * is a valid errno will mean setting the condition codes to indicate
  32. * an error return. This doesn't work, so we have this hook.
  33. */
  34. static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
  35. {
  36. regs->u_regs[UREG_I0] = error;
  37. regs->tstate |= (TSTATE_ICARRY | TSTATE_XCARRY);
  38. regs->tpc = regs->tnpc;
  39. regs->tnpc += 4;
  40. }
  41. static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
  42. {
  43. regs->u_regs[UREG_I0] = value;
  44. regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
  45. regs->tpc = regs->tnpc;
  46. regs->tnpc += 4;
  47. }
  48. static inline void
  49. pt_succ_return_linux(struct pt_regs *regs, unsigned long value, void __user *addr)
  50. {
  51. if (test_thread_flag(TIF_32BIT)) {
  52. if (put_user(value, (unsigned int __user *) addr)) {
  53. pt_error_return(regs, EFAULT);
  54. return;
  55. }
  56. } else {
  57. if (put_user(value, (long __user *) addr)) {
  58. pt_error_return(regs, EFAULT);
  59. return;
  60. }
  61. }
  62. regs->u_regs[UREG_I0] = 0;
  63. regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
  64. regs->tpc = regs->tnpc;
  65. regs->tnpc += 4;
  66. }
  67. static void
  68. pt_os_succ_return (struct pt_regs *regs, unsigned long val, void __user *addr)
  69. {
  70. if (current->personality == PER_SUNOS)
  71. pt_succ_return (regs, val);
  72. else
  73. pt_succ_return_linux (regs, val, addr);
  74. }
  75. /* #define ALLOW_INIT_TRACING */
  76. /* #define DEBUG_PTRACE */
  77. #ifdef DEBUG_PTRACE
  78. char *pt_rq [] = {
  79. /* 0 */ "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSR",
  80. /* 4 */ "POKETEXT", "POKEDATA", "POKEUSR", "CONT",
  81. /* 8 */ "KILL", "SINGLESTEP", "SUNATTACH", "SUNDETACH",
  82. /* 12 */ "GETREGS", "SETREGS", "GETFPREGS", "SETFPREGS",
  83. /* 16 */ "READDATA", "WRITEDATA", "READTEXT", "WRITETEXT",
  84. /* 20 */ "GETFPAREGS", "SETFPAREGS", "unknown", "unknown",
  85. /* 24 */ "SYSCALL", ""
  86. };
  87. #endif
  88. /*
  89. * Called by kernel/ptrace.c when detaching..
  90. *
  91. * Make sure single step bits etc are not set.
  92. */
  93. void ptrace_disable(struct task_struct *child)
  94. {
  95. /* nothing to do */
  96. }
  97. /* To get the necessary page struct, access_process_vm() first calls
  98. * get_user_pages(). This has done a flush_dcache_page() on the
  99. * accessed page. Then our caller (copy_{to,from}_user_page()) did
  100. * to memcpy to read/write the data from that page.
  101. *
  102. * Now, the only thing we have to do is:
  103. * 1) flush the D-cache if it's possible than an illegal alias
  104. * has been created
  105. * 2) flush the I-cache if this is pre-cheetah and we did a write
  106. */
  107. void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
  108. unsigned long uaddr, void *kaddr,
  109. unsigned long len, int write)
  110. {
  111. BUG_ON(len > PAGE_SIZE);
  112. #ifdef DCACHE_ALIASING_POSSIBLE
  113. /* If bit 13 of the kernel address we used to access the
  114. * user page is the same as the virtual address that page
  115. * is mapped to in the user's address space, we can skip the
  116. * D-cache flush.
  117. */
  118. if ((uaddr ^ kaddr) & (1UL << 13)) {
  119. unsigned long start = __pa(kaddr);
  120. unsigned long end = start + len;
  121. if (tlb_type == spitfire) {
  122. for (; start < end; start += 32)
  123. spitfire_put_dcache_tag(va & 0x3fe0, 0x0);
  124. } else {
  125. for (; start < end; start += 32)
  126. __asm__ __volatile__(
  127. "stxa %%g0, [%0] %1\n\t"
  128. "membar #Sync"
  129. : /* no outputs */
  130. : "r" (va),
  131. "i" (ASI_DCACHE_INVALIDATE));
  132. }
  133. }
  134. #endif
  135. if (write && tlb_type == spitfire) {
  136. unsigned long start = (unsigned long) kaddr;
  137. unsigned long end = start + len;
  138. for (; start < end; start += 32)
  139. flushi(start);
  140. }
  141. }
  142. asmlinkage void do_ptrace(struct pt_regs *regs)
  143. {
  144. int request = regs->u_regs[UREG_I0];
  145. pid_t pid = regs->u_regs[UREG_I1];
  146. unsigned long addr = regs->u_regs[UREG_I2];
  147. unsigned long data = regs->u_regs[UREG_I3];
  148. unsigned long addr2 = regs->u_regs[UREG_I4];
  149. struct task_struct *child;
  150. int ret;
  151. if (test_thread_flag(TIF_32BIT)) {
  152. addr &= 0xffffffffUL;
  153. data &= 0xffffffffUL;
  154. addr2 &= 0xffffffffUL;
  155. }
  156. lock_kernel();
  157. #ifdef DEBUG_PTRACE
  158. {
  159. char *s;
  160. if ((request >= 0) && (request <= 24))
  161. s = pt_rq [request];
  162. else
  163. s = "unknown";
  164. if (request == PTRACE_POKEDATA && data == 0x91d02001){
  165. printk ("do_ptrace: breakpoint pid=%d, addr=%016lx addr2=%016lx\n",
  166. pid, addr, addr2);
  167. } else
  168. printk("do_ptrace: rq=%s(%d) pid=%d addr=%016lx data=%016lx addr2=%016lx\n",
  169. s, request, pid, addr, data, addr2);
  170. }
  171. #endif
  172. if (request == PTRACE_TRACEME) {
  173. int ret;
  174. /* are we already being traced? */
  175. if (current->ptrace & PT_PTRACED) {
  176. pt_error_return(regs, EPERM);
  177. goto out;
  178. }
  179. ret = security_ptrace(current->parent, current);
  180. if (ret) {
  181. pt_error_return(regs, -ret);
  182. goto out;
  183. }
  184. /* set the ptrace bit in the process flags. */
  185. current->ptrace |= PT_PTRACED;
  186. pt_succ_return(regs, 0);
  187. goto out;
  188. }
  189. #ifndef ALLOW_INIT_TRACING
  190. if (pid == 1) {
  191. /* Can't dork with init. */
  192. pt_error_return(regs, EPERM);
  193. goto out;
  194. }
  195. #endif
  196. read_lock(&tasklist_lock);
  197. child = find_task_by_pid(pid);
  198. if (child)
  199. get_task_struct(child);
  200. read_unlock(&tasklist_lock);
  201. if (!child) {
  202. pt_error_return(regs, ESRCH);
  203. goto out;
  204. }
  205. if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
  206. || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
  207. if (ptrace_attach(child)) {
  208. pt_error_return(regs, EPERM);
  209. goto out_tsk;
  210. }
  211. pt_succ_return(regs, 0);
  212. goto out_tsk;
  213. }
  214. ret = ptrace_check_attach(child, request == PTRACE_KILL);
  215. if (ret < 0) {
  216. pt_error_return(regs, -ret);
  217. goto out_tsk;
  218. }
  219. if (!(test_thread_flag(TIF_32BIT)) &&
  220. ((request == PTRACE_READDATA64) ||
  221. (request == PTRACE_WRITEDATA64) ||
  222. (request == PTRACE_READTEXT64) ||
  223. (request == PTRACE_WRITETEXT64) ||
  224. (request == PTRACE_PEEKTEXT64) ||
  225. (request == PTRACE_POKETEXT64) ||
  226. (request == PTRACE_PEEKDATA64) ||
  227. (request == PTRACE_POKEDATA64))) {
  228. addr = regs->u_regs[UREG_G2];
  229. addr2 = regs->u_regs[UREG_G3];
  230. request -= 30; /* wheee... */
  231. }
  232. switch(request) {
  233. case PTRACE_PEEKTEXT: /* read word at location addr. */
  234. case PTRACE_PEEKDATA: {
  235. unsigned long tmp64;
  236. unsigned int tmp32;
  237. int res, copied;
  238. res = -EIO;
  239. if (test_thread_flag(TIF_32BIT)) {
  240. copied = access_process_vm(child, addr,
  241. &tmp32, sizeof(tmp32), 0);
  242. tmp64 = (unsigned long) tmp32;
  243. if (copied == sizeof(tmp32))
  244. res = 0;
  245. } else {
  246. copied = access_process_vm(child, addr,
  247. &tmp64, sizeof(tmp64), 0);
  248. if (copied == sizeof(tmp64))
  249. res = 0;
  250. }
  251. if (res < 0)
  252. pt_error_return(regs, -res);
  253. else
  254. pt_os_succ_return(regs, tmp64, (void __user *) data);
  255. goto out_tsk;
  256. }
  257. case PTRACE_POKETEXT: /* write the word at location addr. */
  258. case PTRACE_POKEDATA: {
  259. unsigned long tmp64;
  260. unsigned int tmp32;
  261. int copied, res = -EIO;
  262. if (test_thread_flag(TIF_32BIT)) {
  263. tmp32 = data;
  264. copied = access_process_vm(child, addr,
  265. &tmp32, sizeof(tmp32), 1);
  266. if (copied == sizeof(tmp32))
  267. res = 0;
  268. } else {
  269. tmp64 = data;
  270. copied = access_process_vm(child, addr,
  271. &tmp64, sizeof(tmp64), 1);
  272. if (copied == sizeof(tmp64))
  273. res = 0;
  274. }
  275. if (res < 0)
  276. pt_error_return(regs, -res);
  277. else
  278. pt_succ_return(regs, res);
  279. goto out_tsk;
  280. }
  281. case PTRACE_GETREGS: {
  282. struct pt_regs32 __user *pregs =
  283. (struct pt_regs32 __user *) addr;
  284. struct pt_regs *cregs = child->thread_info->kregs;
  285. int rval;
  286. if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
  287. __put_user(cregs->tpc, (&pregs->pc)) ||
  288. __put_user(cregs->tnpc, (&pregs->npc)) ||
  289. __put_user(cregs->y, (&pregs->y))) {
  290. pt_error_return(regs, EFAULT);
  291. goto out_tsk;
  292. }
  293. for (rval = 1; rval < 16; rval++)
  294. if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
  295. pt_error_return(regs, EFAULT);
  296. goto out_tsk;
  297. }
  298. pt_succ_return(regs, 0);
  299. #ifdef DEBUG_PTRACE
  300. printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
  301. #endif
  302. goto out_tsk;
  303. }
  304. case PTRACE_GETREGS64: {
  305. struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
  306. struct pt_regs *cregs = child->thread_info->kregs;
  307. unsigned long tpc = cregs->tpc;
  308. int rval;
  309. if ((child->thread_info->flags & _TIF_32BIT) != 0)
  310. tpc &= 0xffffffff;
  311. if (__put_user(cregs->tstate, (&pregs->tstate)) ||
  312. __put_user(tpc, (&pregs->tpc)) ||
  313. __put_user(cregs->tnpc, (&pregs->tnpc)) ||
  314. __put_user(cregs->y, (&pregs->y))) {
  315. pt_error_return(regs, EFAULT);
  316. goto out_tsk;
  317. }
  318. for (rval = 1; rval < 16; rval++)
  319. if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
  320. pt_error_return(regs, EFAULT);
  321. goto out_tsk;
  322. }
  323. pt_succ_return(regs, 0);
  324. #ifdef DEBUG_PTRACE
  325. printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
  326. #endif
  327. goto out_tsk;
  328. }
  329. case PTRACE_SETREGS: {
  330. struct pt_regs32 __user *pregs =
  331. (struct pt_regs32 __user *) addr;
  332. struct pt_regs *cregs = child->thread_info->kregs;
  333. unsigned int psr, pc, npc, y;
  334. int i;
  335. /* Must be careful, tracing process can only set certain
  336. * bits in the psr.
  337. */
  338. if (__get_user(psr, (&pregs->psr)) ||
  339. __get_user(pc, (&pregs->pc)) ||
  340. __get_user(npc, (&pregs->npc)) ||
  341. __get_user(y, (&pregs->y))) {
  342. pt_error_return(regs, EFAULT);
  343. goto out_tsk;
  344. }
  345. cregs->tstate &= ~(TSTATE_ICC);
  346. cregs->tstate |= psr_to_tstate_icc(psr);
  347. if (!((pc | npc) & 3)) {
  348. cregs->tpc = pc;
  349. cregs->tnpc = npc;
  350. }
  351. cregs->y = y;
  352. for (i = 1; i < 16; i++) {
  353. if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
  354. pt_error_return(regs, EFAULT);
  355. goto out_tsk;
  356. }
  357. }
  358. pt_succ_return(regs, 0);
  359. goto out_tsk;
  360. }
  361. case PTRACE_SETREGS64: {
  362. struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
  363. struct pt_regs *cregs = child->thread_info->kregs;
  364. unsigned long tstate, tpc, tnpc, y;
  365. int i;
  366. /* Must be careful, tracing process can only set certain
  367. * bits in the psr.
  368. */
  369. if (__get_user(tstate, (&pregs->tstate)) ||
  370. __get_user(tpc, (&pregs->tpc)) ||
  371. __get_user(tnpc, (&pregs->tnpc)) ||
  372. __get_user(y, (&pregs->y))) {
  373. pt_error_return(regs, EFAULT);
  374. goto out_tsk;
  375. }
  376. if ((child->thread_info->flags & _TIF_32BIT) != 0) {
  377. tpc &= 0xffffffff;
  378. tnpc &= 0xffffffff;
  379. }
  380. tstate &= (TSTATE_ICC | TSTATE_XCC);
  381. cregs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
  382. cregs->tstate |= tstate;
  383. if (!((tpc | tnpc) & 3)) {
  384. cregs->tpc = tpc;
  385. cregs->tnpc = tnpc;
  386. }
  387. cregs->y = y;
  388. for (i = 1; i < 16; i++) {
  389. if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
  390. pt_error_return(regs, EFAULT);
  391. goto out_tsk;
  392. }
  393. }
  394. pt_succ_return(regs, 0);
  395. goto out_tsk;
  396. }
  397. case PTRACE_GETFPREGS: {
  398. struct fps {
  399. unsigned int regs[32];
  400. unsigned int fsr;
  401. unsigned int flags;
  402. unsigned int extra;
  403. unsigned int fpqd;
  404. struct fq {
  405. unsigned int insnaddr;
  406. unsigned int insn;
  407. } fpq[16];
  408. };
  409. struct fps __user *fps = (struct fps __user *) addr;
  410. unsigned long *fpregs = child->thread_info->fpregs;
  411. if (copy_to_user(&fps->regs[0], fpregs,
  412. (32 * sizeof(unsigned int))) ||
  413. __put_user(child->thread_info->xfsr[0], (&fps->fsr)) ||
  414. __put_user(0, (&fps->fpqd)) ||
  415. __put_user(0, (&fps->flags)) ||
  416. __put_user(0, (&fps->extra)) ||
  417. clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) {
  418. pt_error_return(regs, EFAULT);
  419. goto out_tsk;
  420. }
  421. pt_succ_return(regs, 0);
  422. goto out_tsk;
  423. }
  424. case PTRACE_GETFPREGS64: {
  425. struct fps {
  426. unsigned int regs[64];
  427. unsigned long fsr;
  428. };
  429. struct fps __user *fps = (struct fps __user *) addr;
  430. unsigned long *fpregs = child->thread_info->fpregs;
  431. if (copy_to_user(&fps->regs[0], fpregs,
  432. (64 * sizeof(unsigned int))) ||
  433. __put_user(child->thread_info->xfsr[0], (&fps->fsr))) {
  434. pt_error_return(regs, EFAULT);
  435. goto out_tsk;
  436. }
  437. pt_succ_return(regs, 0);
  438. goto out_tsk;
  439. }
  440. case PTRACE_SETFPREGS: {
  441. struct fps {
  442. unsigned int regs[32];
  443. unsigned int fsr;
  444. unsigned int flags;
  445. unsigned int extra;
  446. unsigned int fpqd;
  447. struct fq {
  448. unsigned int insnaddr;
  449. unsigned int insn;
  450. } fpq[16];
  451. };
  452. struct fps __user *fps = (struct fps __user *) addr;
  453. unsigned long *fpregs = child->thread_info->fpregs;
  454. unsigned fsr;
  455. if (copy_from_user(fpregs, &fps->regs[0],
  456. (32 * sizeof(unsigned int))) ||
  457. __get_user(fsr, (&fps->fsr))) {
  458. pt_error_return(regs, EFAULT);
  459. goto out_tsk;
  460. }
  461. child->thread_info->xfsr[0] &= 0xffffffff00000000UL;
  462. child->thread_info->xfsr[0] |= fsr;
  463. if (!(child->thread_info->fpsaved[0] & FPRS_FEF))
  464. child->thread_info->gsr[0] = 0;
  465. child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL);
  466. pt_succ_return(regs, 0);
  467. goto out_tsk;
  468. }
  469. case PTRACE_SETFPREGS64: {
  470. struct fps {
  471. unsigned int regs[64];
  472. unsigned long fsr;
  473. };
  474. struct fps __user *fps = (struct fps __user *) addr;
  475. unsigned long *fpregs = child->thread_info->fpregs;
  476. if (copy_from_user(fpregs, &fps->regs[0],
  477. (64 * sizeof(unsigned int))) ||
  478. __get_user(child->thread_info->xfsr[0], (&fps->fsr))) {
  479. pt_error_return(regs, EFAULT);
  480. goto out_tsk;
  481. }
  482. if (!(child->thread_info->fpsaved[0] & FPRS_FEF))
  483. child->thread_info->gsr[0] = 0;
  484. child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU);
  485. pt_succ_return(regs, 0);
  486. goto out_tsk;
  487. }
  488. case PTRACE_READTEXT:
  489. case PTRACE_READDATA: {
  490. int res = ptrace_readdata(child, addr,
  491. (char __user *)addr2, data);
  492. if (res == data) {
  493. pt_succ_return(regs, 0);
  494. goto out_tsk;
  495. }
  496. if (res >= 0)
  497. res = -EIO;
  498. pt_error_return(regs, -res);
  499. goto out_tsk;
  500. }
  501. case PTRACE_WRITETEXT:
  502. case PTRACE_WRITEDATA: {
  503. int res = ptrace_writedata(child, (char __user *) addr2,
  504. addr, data);
  505. if (res == data) {
  506. pt_succ_return(regs, 0);
  507. goto out_tsk;
  508. }
  509. if (res >= 0)
  510. res = -EIO;
  511. pt_error_return(regs, -res);
  512. goto out_tsk;
  513. }
  514. case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
  515. addr = 1;
  516. case PTRACE_CONT: { /* restart after signal. */
  517. if (!valid_signal(data)) {
  518. pt_error_return(regs, EIO);
  519. goto out_tsk;
  520. }
  521. if (request == PTRACE_SYSCALL) {
  522. set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
  523. } else {
  524. clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
  525. }
  526. child->exit_code = data;
  527. #ifdef DEBUG_PTRACE
  528. printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", child->comm,
  529. child->pid, child->exit_code,
  530. child->thread_info->kregs->tpc,
  531. child->thread_info->kregs->tnpc);
  532. #endif
  533. wake_up_process(child);
  534. pt_succ_return(regs, 0);
  535. goto out_tsk;
  536. }
  537. /*
  538. * make the child exit. Best I can do is send it a sigkill.
  539. * perhaps it should be put in the status that it wants to
  540. * exit.
  541. */
  542. case PTRACE_KILL: {
  543. if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
  544. pt_succ_return(regs, 0);
  545. goto out_tsk;
  546. }
  547. child->exit_code = SIGKILL;
  548. wake_up_process(child);
  549. pt_succ_return(regs, 0);
  550. goto out_tsk;
  551. }
  552. case PTRACE_SUNDETACH: { /* detach a process that was attached. */
  553. int error = ptrace_detach(child, data);
  554. if (error) {
  555. pt_error_return(regs, EIO);
  556. goto out_tsk;
  557. }
  558. pt_succ_return(regs, 0);
  559. goto out_tsk;
  560. }
  561. /* PTRACE_DUMPCORE unsupported... */
  562. default: {
  563. int err = ptrace_request(child, request, addr, data);
  564. if (err)
  565. pt_error_return(regs, -err);
  566. else
  567. pt_succ_return(regs, 0);
  568. goto out_tsk;
  569. }
  570. }
  571. out_tsk:
  572. if (child)
  573. put_task_struct(child);
  574. out:
  575. unlock_kernel();
  576. }
  577. asmlinkage void syscall_trace(void)
  578. {
  579. #ifdef DEBUG_PTRACE
  580. printk("%s [%d]: syscall_trace\n", current->comm, current->pid);
  581. #endif
  582. if (!test_thread_flag(TIF_SYSCALL_TRACE))
  583. return;
  584. if (!(current->ptrace & PT_PTRACED))
  585. return;
  586. ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
  587. ? 0x80 : 0));
  588. /*
  589. * this isn't the same as continuing with a signal, but it will do
  590. * for normal use. strace only continues with a signal if the
  591. * stopping signal is not SIGTRAP. -brl
  592. */
  593. #ifdef DEBUG_PTRACE
  594. printk("%s [%d]: syscall_trace exit= %x\n", current->comm,
  595. current->pid, current->exit_code);
  596. #endif
  597. if (current->exit_code) {
  598. send_sig (current->exit_code, current, 1);
  599. current->exit_code = 0;
  600. }
  601. }