ptrace.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/kernel/ptrace.c
  3.  *
  4.  * (C) Copyright 1999 Linus Torvalds
  5.  *
  6.  * Common interfaces for "ptrace()" which we do not want
  7.  * to continually duplicate across every architecture.
  8.  */
  9. #include <linux/sched.h>
  10. #include <linux/errno.h>
  11. #include <linux/mm.h>
  12. #include <linux/highmem.h>
  13. #include <linux/smp_lock.h>
  14. #include <asm/pgtable.h>
  15. #include <asm/uaccess.h>
  16. /*
  17.  * Check that we have indeed attached to the thing..
  18.  */
  19. int ptrace_check_attach(struct task_struct *child, int kill)
  20. {
  21. if (!(child->ptrace & PT_PTRACED))
  22. return -ESRCH;
  23. if (child->p_pptr != current)
  24. return -ESRCH;
  25. if (!kill) {
  26. if (child->state != TASK_STOPPED)
  27. return -ESRCH;
  28. #ifdef CONFIG_SMP
  29. /* Make sure the child gets off its CPU.. */
  30. for (;;) {
  31. task_lock(child);
  32. if (!task_has_cpu(child))
  33. break;
  34. task_unlock(child);
  35. do {
  36. if (child->state != TASK_STOPPED)
  37. return -ESRCH;
  38. barrier();
  39. cpu_relax();
  40. } while (task_has_cpu(child));
  41. }
  42. task_unlock(child);
  43. #endif
  44. }
  45. /* All systems go.. */
  46. return 0;
  47. }
  48. int ptrace_attach(struct task_struct *task)
  49. {
  50. task_lock(task);
  51. if (task->pid <= 1)
  52. goto bad;
  53. if (task == current)
  54. goto bad;
  55. if (!task->mm)
  56. goto bad;
  57. if(((current->uid != task->euid) ||
  58.     (current->uid != task->suid) ||
  59.     (current->uid != task->uid) ||
  60.       (current->gid != task->egid) ||
  61.       (current->gid != task->sgid) ||
  62.       (!cap_issubset(task->cap_permitted, current->cap_permitted)) ||
  63.       (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
  64. goto bad;
  65. rmb();
  66. if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
  67. goto bad;
  68. /* the same process cannot be attached many times */
  69. if (task->ptrace & PT_PTRACED)
  70. goto bad;
  71. /* Go */
  72. task->ptrace |= PT_PTRACED;
  73. if (capable(CAP_SYS_PTRACE))
  74. task->ptrace |= PT_PTRACE_CAP;
  75. task_unlock(task);
  76. write_lock_irq(&tasklist_lock);
  77. if (task->p_pptr != current) {
  78. REMOVE_LINKS(task);
  79. task->p_pptr = current;
  80. SET_LINKS(task);
  81. }
  82. write_unlock_irq(&tasklist_lock);
  83. send_sig(SIGSTOP, task, 1);
  84. return 0;
  85. bad:
  86. task_unlock(task);
  87. return -EPERM;
  88. }
  89. int ptrace_detach(struct task_struct *child, unsigned int data)
  90. {
  91. if ((unsigned long) data > _NSIG)
  92. return -EIO;
  93. /* Architecture-specific hardware disable .. */
  94. ptrace_disable(child);
  95. /* .. re-parent .. */
  96. child->ptrace = 0;
  97. child->exit_code = data;
  98. write_lock_irq(&tasklist_lock);
  99. REMOVE_LINKS(child);
  100. child->p_pptr = child->p_opptr;
  101. SET_LINKS(child);
  102. write_unlock_irq(&tasklist_lock);
  103. /* .. and wake it up. */
  104. wake_up_process(child);
  105. return 0;
  106. }
  107. /*
  108.  * Access another process' address space.
  109.  * Source/target buffer must be kernel space, 
  110.  * Do not walk the page table directly, use get_user_pages
  111.  */
  112. int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
  113. {
  114. struct mm_struct *mm;
  115. struct vm_area_struct *vma;
  116. struct page *page;
  117. void *old_buf = buf;
  118. /* Worry about races with exit() */
  119. task_lock(tsk);
  120. mm = tsk->mm;
  121. if (mm)
  122. atomic_inc(&mm->mm_users);
  123. task_unlock(tsk);
  124. if (!mm)
  125. return 0;
  126. down_read(&mm->mmap_sem);
  127. /* ignore errors, just check how much was sucessfully transfered */
  128. while (len) {
  129. int bytes, ret, offset;
  130. void *maddr;
  131. ret = get_user_pages(current, mm, addr, 1,
  132. write, 1, &page, &vma);
  133. if (ret <= 0)
  134. break;
  135. bytes = len;
  136. offset = addr & (PAGE_SIZE-1);
  137. if (bytes > PAGE_SIZE-offset)
  138. bytes = PAGE_SIZE-offset;
  139. flush_cache_page(vma, addr);
  140. maddr = kmap(page);
  141. if (write) {
  142. memcpy(maddr + offset, buf, bytes);
  143. flush_page_to_ram(page);
  144. flush_icache_page(vma, page);
  145. } else {
  146. memcpy(buf, maddr + offset, bytes);
  147. flush_page_to_ram(page);
  148. }
  149. kunmap(page);
  150. put_page(page);
  151. len -= bytes;
  152. buf += bytes;
  153. addr += bytes;
  154. }
  155. up_read(&mm->mmap_sem);
  156. mmput(mm);
  157. return buf - old_buf;
  158. }
  159. int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len)
  160. {
  161. int copied = 0;
  162. while (len > 0) {
  163. char buf[128];
  164. int this_len, retval;
  165. this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
  166. retval = access_process_vm(tsk, src, buf, this_len, 0);
  167. if (!retval) {
  168. if (copied)
  169. break;
  170. return -EIO;
  171. }
  172. if (copy_to_user(dst, buf, retval))
  173. return -EFAULT;
  174. copied += retval;
  175. src += retval;
  176. dst += retval;
  177. len -= retval;
  178. }
  179. return copied;
  180. }
  181. int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int len)
  182. {
  183. int copied = 0;
  184. while (len > 0) {
  185. char buf[128];
  186. int this_len, retval;
  187. this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
  188. if (copy_from_user(buf, src, this_len))
  189. return -EFAULT;
  190. retval = access_process_vm(tsk, dst, buf, this_len, 1);
  191. if (!retval) {
  192. if (copied)
  193. break;
  194. return -EIO;
  195. }
  196. copied += retval;
  197. src += retval;
  198. dst += retval;
  199. len -= retval;
  200. }
  201. return copied;
  202. }