syscall.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #include <linux/ptrace.h>
  2. #include <linux/sched.h>
  3. #include <linux/export.h>
  4. #include <asm/syscall.h>
  5. static int collect_syscall(struct task_struct *target, long *callno,
  6. unsigned long args[6], unsigned int maxargs,
  7. unsigned long *sp, unsigned long *pc)
  8. {
  9. struct pt_regs *regs;
  10. if (!try_get_task_stack(target)) {
  11. /* Task has no stack, so the task isn't in a syscall. */
  12. *sp = *pc = 0;
  13. *callno = -1;
  14. return 0;
  15. }
  16. regs = task_pt_regs(target);
  17. if (unlikely(!regs)) {
  18. put_task_stack(target);
  19. return -EAGAIN;
  20. }
  21. *sp = user_stack_pointer(regs);
  22. *pc = instruction_pointer(regs);
  23. *callno = syscall_get_nr(target, regs);
  24. if (*callno != -1L && maxargs > 0)
  25. syscall_get_arguments(target, regs, 0, maxargs, args);
  26. put_task_stack(target);
  27. return 0;
  28. }
  29. /**
  30. * task_current_syscall - Discover what a blocked task is doing.
  31. * @target: thread to examine
  32. * @callno: filled with system call number or -1
  33. * @args: filled with @maxargs system call arguments
  34. * @maxargs: number of elements in @args to fill
  35. * @sp: filled with user stack pointer
  36. * @pc: filled with user PC
  37. *
  38. * If @target is blocked in a system call, returns zero with *@callno
  39. * set to the the call's number and @args filled in with its arguments.
  40. * Registers not used for system call arguments may not be available and
  41. * it is not kosher to use &struct user_regset calls while the system
  42. * call is still in progress. Note we may get this result if @target
  43. * has finished its system call but not yet returned to user mode, such
  44. * as when it's stopped for signal handling or syscall exit tracing.
  45. *
  46. * If @target is blocked in the kernel during a fault or exception,
  47. * returns zero with *@callno set to -1 and does not fill in @args.
  48. * If so, it's now safe to examine @target using &struct user_regset
  49. * get() calls as long as we're sure @target won't return to user mode.
  50. *
  51. * Returns -%EAGAIN if @target does not remain blocked.
  52. *
  53. * Returns -%EINVAL if @maxargs is too large (maximum is six).
  54. */
  55. int task_current_syscall(struct task_struct *target, long *callno,
  56. unsigned long args[6], unsigned int maxargs,
  57. unsigned long *sp, unsigned long *pc)
  58. {
  59. long state;
  60. unsigned long ncsw;
  61. if (unlikely(maxargs > 6))
  62. return -EINVAL;
  63. if (target == current)
  64. return collect_syscall(target, callno, args, maxargs, sp, pc);
  65. state = target->state;
  66. if (unlikely(!state))
  67. return -EAGAIN;
  68. ncsw = wait_task_inactive(target, state);
  69. if (unlikely(!ncsw) ||
  70. unlikely(collect_syscall(target, callno, args, maxargs, sp, pc)) ||
  71. unlikely(wait_task_inactive(target, state) != ncsw))
  72. return -EAGAIN;
  73. return 0;
  74. }