ptrace.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. /* ptrace.c: Sparc process tracing support.
  2. *
  3. * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
  4. *
  5. * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
  6. * and David Mosberger.
  7. *
  8. * Added Linux support -miguel (weird, eh?, the orignal code was meant
  9. * to emulate SunOS).
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/sched.h>
  13. #include <linux/mm.h>
  14. #include <linux/errno.h>
  15. #include <linux/ptrace.h>
  16. #include <linux/user.h>
  17. #include <linux/smp.h>
  18. #include <linux/smp_lock.h>
  19. #include <linux/security.h>
  20. #include <asm/pgtable.h>
  21. #include <asm/system.h>
  22. #include <asm/uaccess.h>
  23. #define MAGIC_CONSTANT 0x80000000
  24. /* Returning from ptrace is a bit tricky because the syscall return
  25. * low level code assumes any value returned which is negative and
  26. * is a valid errno will mean setting the condition codes to indicate
  27. * an error return. This doesn't work, so we have this hook.
  28. */
  29. static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
  30. {
  31. regs->u_regs[UREG_I0] = error;
  32. regs->psr |= PSR_C;
  33. regs->pc = regs->npc;
  34. regs->npc += 4;
  35. }
  36. static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
  37. {
  38. regs->u_regs[UREG_I0] = value;
  39. regs->psr &= ~PSR_C;
  40. regs->pc = regs->npc;
  41. regs->npc += 4;
  42. }
  43. static void
  44. pt_succ_return_linux(struct pt_regs *regs, unsigned long value, long __user *addr)
  45. {
  46. if (put_user(value, addr)) {
  47. pt_error_return(regs, EFAULT);
  48. return;
  49. }
  50. regs->u_regs[UREG_I0] = 0;
  51. regs->psr &= ~PSR_C;
  52. regs->pc = regs->npc;
  53. regs->npc += 4;
  54. }
  55. static void
  56. pt_os_succ_return (struct pt_regs *regs, unsigned long val, long __user *addr)
  57. {
  58. if (current->personality == PER_SUNOS)
  59. pt_succ_return (regs, val);
  60. else
  61. pt_succ_return_linux (regs, val, addr);
  62. }
  63. /* Fuck me gently with a chainsaw... */
  64. static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset,
  65. struct task_struct *tsk, long __user *addr)
  66. {
  67. struct pt_regs *cregs = tsk->thread.kregs;
  68. struct thread_info *t = tsk->thread_info;
  69. int v;
  70. if(offset >= 1024)
  71. offset -= 1024; /* whee... */
  72. if(offset & ((sizeof(unsigned long) - 1))) {
  73. pt_error_return(regs, EIO);
  74. return;
  75. }
  76. if(offset >= 16 && offset < 784) {
  77. offset -= 16; offset >>= 2;
  78. pt_os_succ_return(regs, *(((unsigned long *)(&t->reg_window[0]))+offset), addr);
  79. return;
  80. }
  81. if(offset >= 784 && offset < 832) {
  82. offset -= 784; offset >>= 2;
  83. pt_os_succ_return(regs, *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset), addr);
  84. return;
  85. }
  86. switch(offset) {
  87. case 0:
  88. v = t->ksp;
  89. break;
  90. case 4:
  91. v = t->kpc;
  92. break;
  93. case 8:
  94. v = t->kpsr;
  95. break;
  96. case 12:
  97. v = t->uwinmask;
  98. break;
  99. case 832:
  100. v = t->w_saved;
  101. break;
  102. case 896:
  103. v = cregs->u_regs[UREG_I0];
  104. break;
  105. case 900:
  106. v = cregs->u_regs[UREG_I1];
  107. break;
  108. case 904:
  109. v = cregs->u_regs[UREG_I2];
  110. break;
  111. case 908:
  112. v = cregs->u_regs[UREG_I3];
  113. break;
  114. case 912:
  115. v = cregs->u_regs[UREG_I4];
  116. break;
  117. case 916:
  118. v = cregs->u_regs[UREG_I5];
  119. break;
  120. case 920:
  121. v = cregs->u_regs[UREG_I6];
  122. break;
  123. case 924:
  124. if(tsk->thread.flags & MAGIC_CONSTANT)
  125. v = cregs->u_regs[UREG_G1];
  126. else
  127. v = 0;
  128. break;
  129. case 940:
  130. v = cregs->u_regs[UREG_I0];
  131. break;
  132. case 944:
  133. v = cregs->u_regs[UREG_I1];
  134. break;
  135. case 948:
  136. /* Isn't binary compatibility _fun_??? */
  137. if(cregs->psr & PSR_C)
  138. v = cregs->u_regs[UREG_I0] << 24;
  139. else
  140. v = 0;
  141. break;
  142. /* Rest of them are completely unsupported. */
  143. default:
  144. printk("%s [%d]: Wants to read user offset %ld\n",
  145. current->comm, current->pid, offset);
  146. pt_error_return(regs, EIO);
  147. return;
  148. }
  149. if (current->personality == PER_SUNOS)
  150. pt_succ_return (regs, v);
  151. else
  152. pt_succ_return_linux (regs, v, addr);
  153. return;
  154. }
  155. static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset,
  156. struct task_struct *tsk)
  157. {
  158. struct pt_regs *cregs = tsk->thread.kregs;
  159. struct thread_info *t = tsk->thread_info;
  160. unsigned long value = regs->u_regs[UREG_I3];
  161. if(offset >= 1024)
  162. offset -= 1024; /* whee... */
  163. if(offset & ((sizeof(unsigned long) - 1)))
  164. goto failure;
  165. if(offset >= 16 && offset < 784) {
  166. offset -= 16; offset >>= 2;
  167. *(((unsigned long *)(&t->reg_window[0]))+offset) = value;
  168. goto success;
  169. }
  170. if(offset >= 784 && offset < 832) {
  171. offset -= 784; offset >>= 2;
  172. *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset) = value;
  173. goto success;
  174. }
  175. switch(offset) {
  176. case 896:
  177. cregs->u_regs[UREG_I0] = value;
  178. break;
  179. case 900:
  180. cregs->u_regs[UREG_I1] = value;
  181. break;
  182. case 904:
  183. cregs->u_regs[UREG_I2] = value;
  184. break;
  185. case 908:
  186. cregs->u_regs[UREG_I3] = value;
  187. break;
  188. case 912:
  189. cregs->u_regs[UREG_I4] = value;
  190. break;
  191. case 916:
  192. cregs->u_regs[UREG_I5] = value;
  193. break;
  194. case 920:
  195. cregs->u_regs[UREG_I6] = value;
  196. break;
  197. case 924:
  198. cregs->u_regs[UREG_I7] = value;
  199. break;
  200. case 940:
  201. cregs->u_regs[UREG_I0] = value;
  202. break;
  203. case 944:
  204. cregs->u_regs[UREG_I1] = value;
  205. break;
  206. /* Rest of them are completely unsupported or "no-touch". */
  207. default:
  208. printk("%s [%d]: Wants to write user offset %ld\n",
  209. current->comm, current->pid, offset);
  210. goto failure;
  211. }
  212. success:
  213. pt_succ_return(regs, 0);
  214. return;
  215. failure:
  216. pt_error_return(regs, EIO);
  217. return;
  218. }
  219. /* #define ALLOW_INIT_TRACING */
  220. /* #define DEBUG_PTRACE */
  221. #ifdef DEBUG_PTRACE
  222. char *pt_rq [] = {
  223. /* 0 */ "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSR",
  224. /* 4 */ "POKETEXT", "POKEDATA", "POKEUSR", "CONT",
  225. /* 8 */ "KILL", "SINGLESTEP", "SUNATTACH", "SUNDETACH",
  226. /* 12 */ "GETREGS", "SETREGS", "GETFPREGS", "SETFPREGS",
  227. /* 16 */ "READDATA", "WRITEDATA", "READTEXT", "WRITETEXT",
  228. /* 20 */ "GETFPAREGS", "SETFPAREGS", "unknown", "unknown",
  229. /* 24 */ "SYSCALL", ""
  230. };
  231. #endif
  232. /*
  233. * Called by kernel/ptrace.c when detaching..
  234. *
  235. * Make sure single step bits etc are not set.
  236. */
  237. void ptrace_disable(struct task_struct *child)
  238. {
  239. /* nothing to do */
  240. }
  241. asmlinkage void do_ptrace(struct pt_regs *regs)
  242. {
  243. unsigned long request = regs->u_regs[UREG_I0];
  244. unsigned long pid = regs->u_regs[UREG_I1];
  245. unsigned long addr = regs->u_regs[UREG_I2];
  246. unsigned long data = regs->u_regs[UREG_I3];
  247. unsigned long addr2 = regs->u_regs[UREG_I4];
  248. struct task_struct *child;
  249. int ret;
  250. lock_kernel();
  251. #ifdef DEBUG_PTRACE
  252. {
  253. char *s;
  254. if ((request >= 0) && (request <= 24))
  255. s = pt_rq [request];
  256. else
  257. s = "unknown";
  258. if (request == PTRACE_POKEDATA && data == 0x91d02001){
  259. printk ("do_ptrace: breakpoint pid=%d, addr=%08lx addr2=%08lx\n",
  260. pid, addr, addr2);
  261. } else
  262. printk("do_ptrace: rq=%s(%d) pid=%d addr=%08lx data=%08lx addr2=%08lx\n",
  263. s, (int) request, (int) pid, addr, data, addr2);
  264. }
  265. #endif
  266. if (request == PTRACE_TRACEME) {
  267. int my_ret;
  268. /* are we already being traced? */
  269. if (current->ptrace & PT_PTRACED) {
  270. pt_error_return(regs, EPERM);
  271. goto out;
  272. }
  273. my_ret = security_ptrace(current->parent, current);
  274. if (my_ret) {
  275. pt_error_return(regs, -my_ret);
  276. goto out;
  277. }
  278. /* set the ptrace bit in the process flags. */
  279. current->ptrace |= PT_PTRACED;
  280. pt_succ_return(regs, 0);
  281. goto out;
  282. }
  283. #ifndef ALLOW_INIT_TRACING
  284. if (pid == 1) {
  285. /* Can't dork with init. */
  286. pt_error_return(regs, EPERM);
  287. goto out;
  288. }
  289. #endif
  290. read_lock(&tasklist_lock);
  291. child = find_task_by_pid(pid);
  292. if (child)
  293. get_task_struct(child);
  294. read_unlock(&tasklist_lock);
  295. if (!child) {
  296. pt_error_return(regs, ESRCH);
  297. goto out;
  298. }
  299. if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
  300. || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
  301. if (ptrace_attach(child)) {
  302. pt_error_return(regs, EPERM);
  303. goto out_tsk;
  304. }
  305. pt_succ_return(regs, 0);
  306. goto out_tsk;
  307. }
  308. ret = ptrace_check_attach(child, request == PTRACE_KILL);
  309. if (ret < 0) {
  310. pt_error_return(regs, -ret);
  311. goto out_tsk;
  312. }
  313. switch(request) {
  314. case PTRACE_PEEKTEXT: /* read word at location addr. */
  315. case PTRACE_PEEKDATA: {
  316. unsigned long tmp;
  317. if (access_process_vm(child, addr,
  318. &tmp, sizeof(tmp), 0) == sizeof(tmp))
  319. pt_os_succ_return(regs, tmp, (long __user *)data);
  320. else
  321. pt_error_return(regs, EIO);
  322. goto out_tsk;
  323. }
  324. case PTRACE_PEEKUSR:
  325. read_sunos_user(regs, addr, child, (long __user *) data);
  326. goto out_tsk;
  327. case PTRACE_POKEUSR:
  328. write_sunos_user(regs, addr, child);
  329. goto out_tsk;
  330. case PTRACE_POKETEXT: /* write the word at location addr. */
  331. case PTRACE_POKEDATA: {
  332. if (access_process_vm(child, addr,
  333. &data, sizeof(data), 1) == sizeof(data))
  334. pt_succ_return(regs, 0);
  335. else
  336. pt_error_return(regs, EIO);
  337. goto out_tsk;
  338. }
  339. case PTRACE_GETREGS: {
  340. struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
  341. struct pt_regs *cregs = child->thread.kregs;
  342. int rval;
  343. if (!access_ok(VERIFY_WRITE, pregs, sizeof(struct pt_regs))) {
  344. rval = -EFAULT;
  345. pt_error_return(regs, -rval);
  346. goto out_tsk;
  347. }
  348. __put_user(cregs->psr, (&pregs->psr));
  349. __put_user(cregs->pc, (&pregs->pc));
  350. __put_user(cregs->npc, (&pregs->npc));
  351. __put_user(cregs->y, (&pregs->y));
  352. for(rval = 1; rval < 16; rval++)
  353. __put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]));
  354. pt_succ_return(regs, 0);
  355. #ifdef DEBUG_PTRACE
  356. printk ("PC=%x nPC=%x o7=%x\n", cregs->pc, cregs->npc, cregs->u_regs [15]);
  357. #endif
  358. goto out_tsk;
  359. }
  360. case PTRACE_SETREGS: {
  361. struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
  362. struct pt_regs *cregs = child->thread.kregs;
  363. unsigned long psr, pc, npc, y;
  364. int i;
  365. /* Must be careful, tracing process can only set certain
  366. * bits in the psr.
  367. */
  368. if (!access_ok(VERIFY_READ, pregs, sizeof(struct pt_regs))) {
  369. pt_error_return(regs, EFAULT);
  370. goto out_tsk;
  371. }
  372. __get_user(psr, (&pregs->psr));
  373. __get_user(pc, (&pregs->pc));
  374. __get_user(npc, (&pregs->npc));
  375. __get_user(y, (&pregs->y));
  376. psr &= PSR_ICC;
  377. cregs->psr &= ~PSR_ICC;
  378. cregs->psr |= psr;
  379. if (!((pc | npc) & 3)) {
  380. cregs->pc = pc;
  381. cregs->npc =npc;
  382. }
  383. cregs->y = y;
  384. for(i = 1; i < 16; i++)
  385. __get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]));
  386. pt_succ_return(regs, 0);
  387. goto out_tsk;
  388. }
  389. case PTRACE_GETFPREGS: {
  390. struct fps {
  391. unsigned long regs[32];
  392. unsigned long fsr;
  393. unsigned long flags;
  394. unsigned long extra;
  395. unsigned long fpqd;
  396. struct fq {
  397. unsigned long *insnaddr;
  398. unsigned long insn;
  399. } fpq[16];
  400. };
  401. struct fps __user *fps = (struct fps __user *) addr;
  402. int i;
  403. if (!access_ok(VERIFY_WRITE, fps, sizeof(struct fps))) {
  404. i = -EFAULT;
  405. pt_error_return(regs, -i);
  406. goto out_tsk;
  407. }
  408. for(i = 0; i < 32; i++)
  409. __put_user(child->thread.float_regs[i], (&fps->regs[i]));
  410. __put_user(child->thread.fsr, (&fps->fsr));
  411. __put_user(child->thread.fpqdepth, (&fps->fpqd));
  412. __put_user(0, (&fps->flags));
  413. __put_user(0, (&fps->extra));
  414. for(i = 0; i < 16; i++) {
  415. __put_user(child->thread.fpqueue[i].insn_addr,
  416. (&fps->fpq[i].insnaddr));
  417. __put_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn));
  418. }
  419. pt_succ_return(regs, 0);
  420. goto out_tsk;
  421. }
  422. case PTRACE_SETFPREGS: {
  423. struct fps {
  424. unsigned long regs[32];
  425. unsigned long fsr;
  426. unsigned long flags;
  427. unsigned long extra;
  428. unsigned long fpqd;
  429. struct fq {
  430. unsigned long *insnaddr;
  431. unsigned long insn;
  432. } fpq[16];
  433. };
  434. struct fps __user *fps = (struct fps __user *) addr;
  435. int i;
  436. if (!access_ok(VERIFY_READ, fps, sizeof(struct fps))) {
  437. i = -EFAULT;
  438. pt_error_return(regs, -i);
  439. goto out_tsk;
  440. }
  441. copy_from_user(&child->thread.float_regs[0], &fps->regs[0], (32 * sizeof(unsigned long)));
  442. __get_user(child->thread.fsr, (&fps->fsr));
  443. __get_user(child->thread.fpqdepth, (&fps->fpqd));
  444. for(i = 0; i < 16; i++) {
  445. __get_user(child->thread.fpqueue[i].insn_addr,
  446. (&fps->fpq[i].insnaddr));
  447. __get_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn));
  448. }
  449. pt_succ_return(regs, 0);
  450. goto out_tsk;
  451. }
  452. case PTRACE_READTEXT:
  453. case PTRACE_READDATA: {
  454. int res = ptrace_readdata(child, addr,
  455. (void __user *) addr2, data);
  456. if (res == data) {
  457. pt_succ_return(regs, 0);
  458. goto out_tsk;
  459. }
  460. /* Partial read is an IO failure */
  461. if (res >= 0)
  462. res = -EIO;
  463. pt_error_return(regs, -res);
  464. goto out_tsk;
  465. }
  466. case PTRACE_WRITETEXT:
  467. case PTRACE_WRITEDATA: {
  468. int res = ptrace_writedata(child, (void __user *) addr2,
  469. addr, data);
  470. if (res == data) {
  471. pt_succ_return(regs, 0);
  472. goto out_tsk;
  473. }
  474. /* Partial write is an IO failure */
  475. if (res >= 0)
  476. res = -EIO;
  477. pt_error_return(regs, -res);
  478. goto out_tsk;
  479. }
  480. case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
  481. addr = 1;
  482. case PTRACE_CONT: { /* restart after signal. */
  483. if (data > _NSIG) {
  484. pt_error_return(regs, EIO);
  485. goto out_tsk;
  486. }
  487. if (request == PTRACE_SYSCALL)
  488. set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
  489. else
  490. clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
  491. child->exit_code = data;
  492. #ifdef DEBUG_PTRACE
  493. printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n",
  494. child->comm, child->pid, child->exit_code,
  495. child->thread.kregs->pc,
  496. child->thread.kregs->npc);
  497. #endif
  498. wake_up_process(child);
  499. pt_succ_return(regs, 0);
  500. goto out_tsk;
  501. }
  502. /*
  503. * make the child exit. Best I can do is send it a sigkill.
  504. * perhaps it should be put in the status that it wants to
  505. * exit.
  506. */
  507. case PTRACE_KILL: {
  508. if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
  509. pt_succ_return(regs, 0);
  510. goto out_tsk;
  511. }
  512. wake_up_process(child);
  513. child->exit_code = SIGKILL;
  514. pt_succ_return(regs, 0);
  515. goto out_tsk;
  516. }
  517. case PTRACE_SUNDETACH: { /* detach a process that was attached. */
  518. int err = ptrace_detach(child, data);
  519. if (err) {
  520. pt_error_return(regs, EIO);
  521. goto out_tsk;
  522. }
  523. pt_succ_return(regs, 0);
  524. goto out_tsk;
  525. }
  526. /* PTRACE_DUMPCORE unsupported... */
  527. default: {
  528. int err = ptrace_request(child, request, addr, data);
  529. if (err)
  530. pt_error_return(regs, -err);
  531. else
  532. pt_succ_return(regs, 0);
  533. goto out_tsk;
  534. }
  535. }
  536. out_tsk:
  537. if (child)
  538. put_task_struct(child);
  539. out:
  540. unlock_kernel();
  541. }
  542. asmlinkage void syscall_trace(void)
  543. {
  544. #ifdef DEBUG_PTRACE
  545. printk("%s [%d]: syscall_trace\n", current->comm, current->pid);
  546. #endif
  547. if (!test_thread_flag(TIF_SYSCALL_TRACE))
  548. return;
  549. if (!(current->ptrace & PT_PTRACED))
  550. return;
  551. current->thread.flags ^= MAGIC_CONSTANT;
  552. ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
  553. ? 0x80 : 0));
  554. /*
  555. * this isn't the same as continuing with a signal, but it will do
  556. * for normal use. strace only continues with a signal if the
  557. * stopping signal is not SIGTRAP. -brl
  558. */
  559. #ifdef DEBUG_PTRACE
  560. printk("%s [%d]: syscall_trace exit= %x\n", current->comm,
  561. current->pid, current->exit_code);
  562. #endif
  563. if (current->exit_code) {
  564. send_sig (current->exit_code, current, 1);
  565. current->exit_code = 0;
  566. }
  567. }