ptrace.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:11k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* ptrace.c */
  2. /* By Ross Biro 1/23/92 */
  3. /*
  4.  * Pentium III FXSR, SSE support
  5.  * Gareth Hughes <gareth@valinux.com>, May 2000
  6.  */
  7. #include <linux/kernel.h>
  8. #include <linux/sched.h>
  9. #include <linux/mm.h>
  10. #include <linux/smp.h>
  11. #include <linux/smp_lock.h>
  12. #include <linux/errno.h>
  13. #include <linux/ptrace.h>
  14. #include <linux/user.h>
  15. #include <asm/uaccess.h>
  16. #include <asm/pgtable.h>
  17. #include <asm/system.h>
  18. #include <asm/processor.h>
  19. #include <asm/i387.h>
  20. #include <asm/debugreg.h>
  21. /*
  22.  * does not yet catch signals sent when the child dies.
  23.  * in exit.c or in signal.c.
  24.  */
  25. /* determines which flags the user has access to. */
  26. /* 1 = access 0 = no access */
  27. #define FLAG_MASK 0x00044dd5
  28. /* set's the trap flag. */
  29. #define TRAP_FLAG 0x100
  30. /*
  31.  * Offset of eflags on child stack..
  32.  */
  33. #define EFL_OFFSET ((EFL-2)*4-sizeof(struct pt_regs))
  34. /*
  35.  * this routine will get a word off of the processes privileged stack. 
  36.  * the offset is how far from the base addr as stored in the TSS.  
  37.  * this routine assumes that all the privileged stacks are in our
  38.  * data space.
  39.  */   
  40. static inline int get_stack_long(struct task_struct *task, int offset)
  41. {
  42. unsigned char *stack;
  43. stack = (unsigned char *)task->thread.esp0;
  44. stack += offset;
  45. return (*((int *)stack));
  46. }
  47. /*
  48.  * this routine will put a word on the processes privileged stack. 
  49.  * the offset is how far from the base addr as stored in the TSS.  
  50.  * this routine assumes that all the privileged stacks are in our
  51.  * data space.
  52.  */
  53. static inline int put_stack_long(struct task_struct *task, int offset,
  54. unsigned long data)
  55. {
  56. unsigned char * stack;
  57. stack = (unsigned char *) task->thread.esp0;
  58. stack += offset;
  59. *(unsigned long *) stack = data;
  60. return 0;
  61. }
  62. static int putreg(struct task_struct *child,
  63. unsigned long regno, unsigned long value)
  64. {
  65. switch (regno >> 2) {
  66. case FS:
  67. if (value && (value & 3) != 3)
  68. return -EIO;
  69. child->thread.fs = value;
  70. return 0;
  71. case GS:
  72. if (value && (value & 3) != 3)
  73. return -EIO;
  74. child->thread.gs = value;
  75. return 0;
  76. case DS:
  77. case ES:
  78. if (value && (value & 3) != 3)
  79. return -EIO;
  80. value &= 0xffff;
  81. break;
  82. case SS:
  83. case CS:
  84. if ((value & 3) != 3)
  85. return -EIO;
  86. value &= 0xffff;
  87. break;
  88. case EFL:
  89. value &= FLAG_MASK;
  90. value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;
  91. break;
  92. }
  93. if (regno > GS*4)
  94. regno -= 2*4;
  95. put_stack_long(child, regno - sizeof(struct pt_regs), value);
  96. return 0;
  97. }
  98. static unsigned long getreg(struct task_struct *child,
  99. unsigned long regno)
  100. {
  101. unsigned long retval = ~0UL;
  102. switch (regno >> 2) {
  103. case FS:
  104. retval = child->thread.fs;
  105. break;
  106. case GS:
  107. retval = child->thread.gs;
  108. break;
  109. case DS:
  110. case ES:
  111. case SS:
  112. case CS:
  113. retval = 0xffff;
  114. /* fall through */
  115. default:
  116. if (regno > GS*4)
  117. regno -= 2*4;
  118. regno = regno - sizeof(struct pt_regs);
  119. retval &= get_stack_long(child, regno);
  120. }
  121. return retval;
  122. }
  123. /*
  124.  * Called by kernel/ptrace.c when detaching..
  125.  *
  126.  * Make sure the single step bit is not set.
  127.  */
  128. void ptrace_disable(struct task_struct *child)
  129. long tmp;
  130. tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
  131. put_stack_long(child, EFL_OFFSET, tmp);
  132. }
  133. asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
  134. {
  135. struct task_struct *child;
  136. struct user * dummy = NULL;
  137. int i, ret;
  138. lock_kernel();
  139. ret = -EPERM;
  140. if (request == PTRACE_TRACEME) {
  141. /* are we already being traced? */
  142. if (current->ptrace & PT_PTRACED)
  143. goto out;
  144. /* set the ptrace bit in the process flags. */
  145. current->ptrace |= PT_PTRACED;
  146. ret = 0;
  147. goto out;
  148. }
  149. ret = -ESRCH;
  150. read_lock(&tasklist_lock);
  151. child = find_task_by_pid(pid);
  152. if (child)
  153. get_task_struct(child);
  154. read_unlock(&tasklist_lock);
  155. if (!child)
  156. goto out;
  157. ret = -EPERM;
  158. if (pid == 1) /* you may not mess with init */
  159. goto out_tsk;
  160. if (request == PTRACE_ATTACH) {
  161. ret = ptrace_attach(child);
  162. goto out_tsk;
  163. }
  164. ret = ptrace_check_attach(child, request == PTRACE_KILL);
  165. if (ret < 0)
  166. goto out_tsk;
  167. switch (request) {
  168. /* when I and D space are separate, these will need to be fixed. */
  169. case PTRACE_PEEKTEXT: /* read word at location addr. */ 
  170. case PTRACE_PEEKDATA: {
  171. unsigned long tmp;
  172. int copied;
  173. copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
  174. ret = -EIO;
  175. if (copied != sizeof(tmp))
  176. break;
  177. ret = put_user(tmp,(unsigned long *) data);
  178. break;
  179. }
  180. /* read the word at location addr in the USER area. */
  181. case PTRACE_PEEKUSR: {
  182. unsigned long tmp;
  183. ret = -EIO;
  184. if ((addr & 3) || addr < 0 || 
  185.     addr > sizeof(struct user) - 3)
  186. break;
  187. tmp = 0;  /* Default return condition */
  188. if(addr < FRAME_SIZE*sizeof(long))
  189. tmp = getreg(child, addr);
  190. if(addr >= (long) &dummy->u_debugreg[0] &&
  191.    addr <= (long) &dummy->u_debugreg[7]){
  192. addr -= (long) &dummy->u_debugreg[0];
  193. addr = addr >> 2;
  194. tmp = child->thread.debugreg[addr];
  195. }
  196. ret = put_user(tmp,(unsigned long *) data);
  197. break;
  198. }
  199. /* when I and D space are separate, this will have to be fixed. */
  200. case PTRACE_POKETEXT: /* write the word at location addr. */
  201. case PTRACE_POKEDATA:
  202. ret = 0;
  203. if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
  204. break;
  205. ret = -EIO;
  206. break;
  207. case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
  208. ret = -EIO;
  209. if ((addr & 3) || addr < 0 || 
  210.     addr > sizeof(struct user) - 3)
  211. break;
  212. if (addr < FRAME_SIZE*sizeof(long)) {
  213. ret = putreg(child, addr, data);
  214. break;
  215. }
  216. /* We need to be very careful here.  We implicitly
  217.    want to modify a portion of the task_struct, and we
  218.    have to be selective about what portions we allow someone
  219.    to modify. */
  220.   ret = -EIO;
  221.   if(addr >= (long) &dummy->u_debugreg[0] &&
  222.      addr <= (long) &dummy->u_debugreg[7]){
  223.   if(addr == (long) &dummy->u_debugreg[4]) break;
  224.   if(addr == (long) &dummy->u_debugreg[5]) break;
  225.   if(addr < (long) &dummy->u_debugreg[4] &&
  226.      ((unsigned long) data) >= TASK_SIZE-3) break;
  227.   
  228.   if(addr == (long) &dummy->u_debugreg[7]) {
  229.   data &= ~DR_CONTROL_RESERVED;
  230.   for(i=0; i<4; i++)
  231.   if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
  232.   goto out_tsk;
  233.   }
  234.   addr -= (long) &dummy->u_debugreg;
  235.   addr = addr >> 2;
  236.   child->thread.debugreg[addr] = data;
  237.   ret = 0;
  238.   }
  239.   break;
  240. case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
  241. case PTRACE_CONT: { /* restart after signal. */
  242. long tmp;
  243. ret = -EIO;
  244. if ((unsigned long) data > _NSIG)
  245. break;
  246. if (request == PTRACE_SYSCALL)
  247. child->ptrace |= PT_TRACESYS;
  248. else
  249. child->ptrace &= ~PT_TRACESYS;
  250. child->exit_code = data;
  251. /* make sure the single step bit is not set. */
  252. tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
  253. put_stack_long(child, EFL_OFFSET,tmp);
  254. wake_up_process(child);
  255. ret = 0;
  256. break;
  257. }
  258. /*
  259.  * make the child exit.  Best I can do is send it a sigkill. 
  260.  * perhaps it should be put in the status that it wants to 
  261.  * exit.
  262.  */
  263. case PTRACE_KILL: {
  264. long tmp;
  265. ret = 0;
  266. if (child->state == TASK_ZOMBIE) /* already dead */
  267. break;
  268. child->exit_code = SIGKILL;
  269. /* make sure the single step bit is not set. */
  270. tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
  271. put_stack_long(child, EFL_OFFSET, tmp);
  272. wake_up_process(child);
  273. break;
  274. }
  275. case PTRACE_SINGLESTEP: {  /* set the trap flag. */
  276. long tmp;
  277. ret = -EIO;
  278. if ((unsigned long) data > _NSIG)
  279. break;
  280. child->ptrace &= ~PT_TRACESYS;
  281. if ((child->ptrace & PT_DTRACE) == 0) {
  282. /* Spurious delayed TF traps may occur */
  283. child->ptrace |= PT_DTRACE;
  284. }
  285. tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
  286. put_stack_long(child, EFL_OFFSET, tmp);
  287. child->exit_code = data;
  288. /* give it a chance to run. */
  289. wake_up_process(child);
  290. ret = 0;
  291. break;
  292. }
  293. case PTRACE_DETACH:
  294. /* detach a process that was attached. */
  295. ret = ptrace_detach(child, data);
  296. break;
  297. case PTRACE_GETREGS: { /* Get all gp regs from the child. */
  298.    if (!access_ok(VERIFY_WRITE, (unsigned *)data, FRAME_SIZE*sizeof(long))) {
  299. ret = -EIO;
  300. break;
  301. }
  302. for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) {
  303. __put_user(getreg(child, i),(unsigned long *) data);
  304. data += sizeof(long);
  305. }
  306. ret = 0;
  307. break;
  308. }
  309. case PTRACE_SETREGS: { /* Set all gp regs in the child. */
  310. unsigned long tmp;
  311.    if (!access_ok(VERIFY_READ, (unsigned *)data, FRAME_SIZE*sizeof(long))) {
  312. ret = -EIO;
  313. break;
  314. }
  315. for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) {
  316. __get_user(tmp, (unsigned long *) data);
  317. putreg(child, i, tmp);
  318. data += sizeof(long);
  319. }
  320. ret = 0;
  321. break;
  322. }
  323. case PTRACE_GETFPREGS: { /* Get the child FPU state. */
  324. if (!access_ok(VERIFY_WRITE, (unsigned *)data,
  325.        sizeof(struct user_i387_struct))) {
  326. ret = -EIO;
  327. break;
  328. }
  329. ret = 0;
  330. if ( !child->used_math )
  331. load_empty_fpu(child);
  332. get_fpregs((struct user_i387_struct *)data, child);
  333. break;
  334. }
  335. case PTRACE_SETFPREGS: { /* Set the child FPU state. */
  336. if (!access_ok(VERIFY_READ, (unsigned *)data,
  337.        sizeof(struct user_i387_struct))) {
  338. ret = -EIO;
  339. break;
  340. }
  341. child->used_math = 1;
  342. set_fpregs(child, (struct user_i387_struct *)data);
  343. ret = 0;
  344. break;
  345. }
  346. case PTRACE_GETFPXREGS: { /* Get the child extended FPU state. */
  347. if (!access_ok(VERIFY_WRITE, (unsigned *)data,
  348.        sizeof(struct user_fxsr_struct))) {
  349. ret = -EIO;
  350. break;
  351. }
  352. if ( !child->used_math )
  353. load_empty_fpu(child);
  354. ret = get_fpxregs((struct user_fxsr_struct *)data, child);
  355. break;
  356. }
  357. case PTRACE_SETFPXREGS: { /* Set the child extended FPU state. */
  358. if (!access_ok(VERIFY_READ, (unsigned *)data,
  359.        sizeof(struct user_fxsr_struct))) {
  360. ret = -EIO;
  361. break;
  362. }
  363. child->used_math = 1;
  364. ret = set_fpxregs(child, (struct user_fxsr_struct *)data);
  365. break;
  366. }
  367. case PTRACE_SETOPTIONS: {
  368. if (data & PTRACE_O_TRACESYSGOOD)
  369. child->ptrace |= PT_TRACESYSGOOD;
  370. else
  371. child->ptrace &= ~PT_TRACESYSGOOD;
  372. ret = 0;
  373. break;
  374. }
  375. default:
  376. ret = -EIO;
  377. break;
  378. }
  379. out_tsk:
  380. free_task_struct(child);
  381. out:
  382. unlock_kernel();
  383. return ret;
  384. }
  385. asmlinkage void syscall_trace(void)
  386. {
  387. if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) !=
  388. (PT_PTRACED|PT_TRACESYS))
  389. return;
  390. /* the 0x80 provides a way for the tracing parent to distinguish
  391.    between a syscall stop and SIGTRAP delivery */
  392. current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
  393. ? 0x80 : 0);
  394. current->state = TASK_STOPPED;
  395. notify_parent(current, SIGCHLD);
  396. schedule();
  397. /*
  398.  * this isn't the same as continuing with a signal, but it will do
  399.  * for normal use.  strace only continues with a signal if the
  400.  * stopping signal is not SIGTRAP.  -brl
  401.  */
  402. if (current->exit_code) {
  403. send_sig(current->exit_code, current, 1);
  404. current->exit_code = 0;
  405. }
  406. }