syscall.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * Access to user system call parameters and results
  3. *
  4. * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved.
  5. *
  6. * This copyrighted material is made available to anyone wishing to use,
  7. * modify, copy, or redistribute it subject to the terms and conditions
  8. * of the GNU General Public License v.2.
  9. *
  10. * See asm-generic/syscall.h for descriptions of what we must do here.
  11. */
  12. #ifndef _ASM_X86_SYSCALL_H
  13. #define _ASM_X86_SYSCALL_H
  14. #include <uapi/linux/audit.h>
  15. #include <linux/sched.h>
  16. #include <linux/err.h>
  17. #include <asm/asm-offsets.h> /* For NR_syscalls */
  18. #include <asm/thread_info.h> /* for TS_COMPAT */
  19. #include <asm/unistd.h>
  20. typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long,
  21. unsigned long, unsigned long,
  22. unsigned long, unsigned long);
  23. extern const sys_call_ptr_t sys_call_table[];
  24. #if defined(CONFIG_X86_32)
  25. #define ia32_sys_call_table sys_call_table
  26. #define __NR_syscall_compat_max __NR_syscall_max
  27. #define IA32_NR_syscalls NR_syscalls
  28. #endif
  29. #if defined(CONFIG_IA32_EMULATION)
  30. extern const sys_call_ptr_t ia32_sys_call_table[];
  31. #endif
  32. /*
  33. * Only the low 32 bits of orig_ax are meaningful, so we return int.
  34. * This importantly ignores the high bits on 64-bit, so comparisons
  35. * sign-extend the low 32 bits.
  36. */
  37. static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
  38. {
  39. return regs->orig_ax;
  40. }
  41. static inline void syscall_rollback(struct task_struct *task,
  42. struct pt_regs *regs)
  43. {
  44. regs->ax = regs->orig_ax;
  45. }
  46. static inline long syscall_get_error(struct task_struct *task,
  47. struct pt_regs *regs)
  48. {
  49. unsigned long error = regs->ax;
  50. #ifdef CONFIG_IA32_EMULATION
  51. /*
  52. * TS_COMPAT is set for 32-bit syscall entries and then
  53. * remains set until we return to user mode.
  54. */
  55. if (task->thread.status & (TS_COMPAT|TS_I386_REGS_POKED))
  56. /*
  57. * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
  58. * and will match correctly in comparisons.
  59. */
  60. error = (long) (int) error;
  61. #endif
  62. return IS_ERR_VALUE(error) ? error : 0;
  63. }
  64. static inline long syscall_get_return_value(struct task_struct *task,
  65. struct pt_regs *regs)
  66. {
  67. return regs->ax;
  68. }
  69. static inline void syscall_set_return_value(struct task_struct *task,
  70. struct pt_regs *regs,
  71. int error, long val)
  72. {
  73. regs->ax = (long) error ?: val;
  74. }
  75. #ifdef CONFIG_X86_32
  76. static inline void syscall_get_arguments(struct task_struct *task,
  77. struct pt_regs *regs,
  78. unsigned int i, unsigned int n,
  79. unsigned long *args)
  80. {
  81. BUG_ON(i + n > 6);
  82. memcpy(args, &regs->bx + i, n * sizeof(args[0]));
  83. }
  84. static inline void syscall_set_arguments(struct task_struct *task,
  85. struct pt_regs *regs,
  86. unsigned int i, unsigned int n,
  87. const unsigned long *args)
  88. {
  89. BUG_ON(i + n > 6);
  90. memcpy(&regs->bx + i, args, n * sizeof(args[0]));
  91. }
  92. static inline int syscall_get_arch(void)
  93. {
  94. return AUDIT_ARCH_I386;
  95. }
  96. #else /* CONFIG_X86_64 */
  97. static inline void syscall_get_arguments(struct task_struct *task,
  98. struct pt_regs *regs,
  99. unsigned int i, unsigned int n,
  100. unsigned long *args)
  101. {
  102. # ifdef CONFIG_IA32_EMULATION
  103. if (task->thread.status & TS_COMPAT)
  104. switch (i) {
  105. case 0:
  106. if (!n--) break;
  107. *args++ = regs->bx;
  108. case 1:
  109. if (!n--) break;
  110. *args++ = regs->cx;
  111. case 2:
  112. if (!n--) break;
  113. *args++ = regs->dx;
  114. case 3:
  115. if (!n--) break;
  116. *args++ = regs->si;
  117. case 4:
  118. if (!n--) break;
  119. *args++ = regs->di;
  120. case 5:
  121. if (!n--) break;
  122. *args++ = regs->bp;
  123. case 6:
  124. if (!n--) break;
  125. default:
  126. BUG();
  127. break;
  128. }
  129. else
  130. # endif
  131. switch (i) {
  132. case 0:
  133. if (!n--) break;
  134. *args++ = regs->di;
  135. case 1:
  136. if (!n--) break;
  137. *args++ = regs->si;
  138. case 2:
  139. if (!n--) break;
  140. *args++ = regs->dx;
  141. case 3:
  142. if (!n--) break;
  143. *args++ = regs->r10;
  144. case 4:
  145. if (!n--) break;
  146. *args++ = regs->r8;
  147. case 5:
  148. if (!n--) break;
  149. *args++ = regs->r9;
  150. case 6:
  151. if (!n--) break;
  152. default:
  153. BUG();
  154. break;
  155. }
  156. }
  157. static inline void syscall_set_arguments(struct task_struct *task,
  158. struct pt_regs *regs,
  159. unsigned int i, unsigned int n,
  160. const unsigned long *args)
  161. {
  162. # ifdef CONFIG_IA32_EMULATION
  163. if (task->thread.status & TS_COMPAT)
  164. switch (i) {
  165. case 0:
  166. if (!n--) break;
  167. regs->bx = *args++;
  168. case 1:
  169. if (!n--) break;
  170. regs->cx = *args++;
  171. case 2:
  172. if (!n--) break;
  173. regs->dx = *args++;
  174. case 3:
  175. if (!n--) break;
  176. regs->si = *args++;
  177. case 4:
  178. if (!n--) break;
  179. regs->di = *args++;
  180. case 5:
  181. if (!n--) break;
  182. regs->bp = *args++;
  183. case 6:
  184. if (!n--) break;
  185. default:
  186. BUG();
  187. break;
  188. }
  189. else
  190. # endif
  191. switch (i) {
  192. case 0:
  193. if (!n--) break;
  194. regs->di = *args++;
  195. case 1:
  196. if (!n--) break;
  197. regs->si = *args++;
  198. case 2:
  199. if (!n--) break;
  200. regs->dx = *args++;
  201. case 3:
  202. if (!n--) break;
  203. regs->r10 = *args++;
  204. case 4:
  205. if (!n--) break;
  206. regs->r8 = *args++;
  207. case 5:
  208. if (!n--) break;
  209. regs->r9 = *args++;
  210. case 6:
  211. if (!n--) break;
  212. default:
  213. BUG();
  214. break;
  215. }
  216. }
  217. static inline int syscall_get_arch(void)
  218. {
  219. /* x32 tasks should be considered AUDIT_ARCH_X86_64. */
  220. return in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
  221. }
  222. #endif /* CONFIG_X86_32 */
  223. #endif /* _ASM_X86_SYSCALL_H */