2
0

965-arm_restore_sigmask_v2.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. From: Mikael Pettersson <[email protected]>
  2. Date: Sat, 15 Aug 2009 11:58:11 +0000 (+0100)
  3. Subject: ARM: 5677/1: ARM support for TIF_RESTORE_SIGMASK/pselect6/ppoll/epoll_pwait
  4. X-Git-Tag: next-20090817~86^2~1^6
  5. X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=369842658a36bcea28ecb643ba4bdb53919330dd
  6. ARM: 5677/1: ARM support for TIF_RESTORE_SIGMASK/pselect6/ppoll/epoll_pwait
  7. This patch adds support for TIF_RESTORE_SIGMASK to ARM's
  8. signal handling, which allows to hook up the pselect6, ppoll,
  9. and epoll_pwait syscalls on ARM.
  10. Tested here with eabi userspace and a test program with a
  11. deliberate race between a child's exit and the parent's
  12. sigprocmask/select sequence. Using sys_pselect6() instead
  13. of sigprocmask/select reliably prevents the race.
  14. The other arch's support for TIF_RESTORE_SIGMASK has evolved
  15. over time:
  16. In 2.6.16:
  17. - add TIF_RESTORE_SIGMASK which parallels TIF_SIGPENDING
  18. - test both when checking for pending signal [changed later]
  19. - reimplement sys_sigsuspend() to use current->saved_sigmask,
  20. TIF_RESTORE_SIGMASK [changed later], and -ERESTARTNOHAND;
  21. ditto for sys_rt_sigsuspend(), but drop private code and
  22. use common code via __ARCH_WANT_SYS_RT_SIGSUSPEND;
  23. - there are now no "extra" calls to do_signal() so its oldset
  24. parameter is always &current->blocked so need not be passed,
  25. also its return value is changed to void
  26. - change handle_signal() to return 0/-errno
  27. - change do_signal() to honor TIF_RESTORE_SIGMASK:
  28. + get oldset from current->saved_sigmask if TIF_RESTORE_SIGMASK
  29. is set
  30. + if handle_signal() was successful then clear TIF_RESTORE_SIGMASK
  31. + if no signal was delivered and TIF_RESTORE_SIGMASK is set then
  32. clear it and restore the sigmask
  33. - hook up sys_pselect6() and sys_ppoll()
  34. In 2.6.19:
  35. - hook up sys_epoll_pwait()
  36. In 2.6.26:
  37. - allow archs to override how TIF_RESTORE_SIGMASK is implemented;
  38. default set_restore_sigmask() sets both TIF_RESTORE_SIGMASK and
  39. TIF_SIGPENDING; archs need now just test TIF_SIGPENDING again
  40. when checking for pending signal work; some archs now implement
  41. TIF_RESTORE_SIGMASK as a secondary/non-atomic thread flag bit
  42. - call set_restore_sigmask() in sys_sigsuspend() instead of setting
  43. TIF_RESTORE_SIGMASK
  44. In 2.6.29-rc:
  45. - kill sys_pselect7() which no arch wanted
  46. So for 2.6.31-rc6/ARM this patch does the following:
  47. - Add TIF_RESTORE_SIGMASK. Use the generic set_restore_sigmask()
  48. which sets both TIF_SIGPENDING and TIF_RESTORE_SIGMASK, so
  49. TIF_RESTORE_SIGMASK need not claim one of the scarce low thread
  50. flags, and existing TIF_SIGPENDING and _TIF_WORK_MASK tests need
  51. not be extended for TIF_RESTORE_SIGMASK.
  52. - sys_sigsuspend() is reimplemented to use current->saved_sigmask
  53. and set_restore_sigmask(), making it identical to most other archs
  54. - The private code for sys_rt_sigsuspend() is removed, instead
  55. generic code supplies it via __ARCH_WANT_SYS_RT_SIGSUSPEND.
  56. - sys_sigsuspend() and sys_rt_sigsuspend() no longer need a pt_regs
  57. parameter, so their assembly code wrappers are removed.
  58. - handle_signal() is changed to return 0 on success or -errno.
  59. - The oldset parameter to do_signal() is now redundant and removed,
  60. and the return value is now also redundant and changed to void.
  61. - do_signal() is changed to honor TIF_RESTORE_SIGMASK:
  62. + get oldset from current->saved_sigmask if TIF_RESTORE_SIGMASK
  63. is set
  64. + if handle_signal() was successful then clear TIF_RESTORE_SIGMASK
  65. + if no signal was delivered and TIF_RESTORE_SIGMASK is set then
  66. clear it and restore the sigmask
  67. - Hook up sys_pselect6, sys_ppoll, and sys_epoll_pwait.
  68. Signed-off-by: Mikael Pettersson <[email protected]>
  69. Signed-off-by: Russell King <[email protected]>
  70. ---
  71. --- a/arch/arm/include/asm/thread_info.h 2009-04-18 18:55:23.000000000 +0200
  72. +++ b/arch/arm/include/asm/thread_info.h 2009-04-18 19:10:22.000000000 +0200
  73. @@ -140,6 +140,7 @@ extern void vfp_sync_state(struct thread
  74. #define TIF_USING_IWMMXT 17
  75. #define TIF_MEMDIE 18
  76. #define TIF_FREEZE 19
  77. +#define TIF_RESTORE_SIGMASK 20
  78. #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
  79. #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
  80. @@ -147,6 +148,7 @@ extern void vfp_sync_state(struct thread
  81. #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
  82. #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
  83. #define _TIF_FREEZE (1 << TIF_FREEZE)
  84. +#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
  85. /*
  86. * Change these and you break ASM code in entry-common.S
  87. --- a/arch/arm/include/asm/unistd.h 2008-10-11 10:43:49.000000000 +0200
  88. +++ b/arch/arm/include/asm/unistd.h 2009-04-18 19:10:22.000000000 +0200
  89. @@ -360,8 +360,8 @@
  90. #define __NR_readlinkat (__NR_SYSCALL_BASE+332)
  91. #define __NR_fchmodat (__NR_SYSCALL_BASE+333)
  92. #define __NR_faccessat (__NR_SYSCALL_BASE+334)
  93. - /* 335 for pselect6 */
  94. - /* 336 for ppoll */
  95. +#define __NR_pselect6 (__NR_SYSCALL_BASE+335)
  96. +#define __NR_ppoll (__NR_SYSCALL_BASE+336)
  97. #define __NR_unshare (__NR_SYSCALL_BASE+337)
  98. #define __NR_set_robust_list (__NR_SYSCALL_BASE+338)
  99. #define __NR_get_robust_list (__NR_SYSCALL_BASE+339)
  100. @@ -372,7 +372,7 @@
  101. #define __NR_vmsplice (__NR_SYSCALL_BASE+343)
  102. #define __NR_move_pages (__NR_SYSCALL_BASE+344)
  103. #define __NR_getcpu (__NR_SYSCALL_BASE+345)
  104. - /* 346 for epoll_pwait */
  105. +#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346)
  106. #define __NR_kexec_load (__NR_SYSCALL_BASE+347)
  107. #define __NR_utimensat (__NR_SYSCALL_BASE+348)
  108. #define __NR_signalfd (__NR_SYSCALL_BASE+349)
  109. @@ -428,6 +428,7 @@
  110. #define __ARCH_WANT_SYS_SIGPENDING
  111. #define __ARCH_WANT_SYS_SIGPROCMASK
  112. #define __ARCH_WANT_SYS_RT_SIGACTION
  113. +#define __ARCH_WANT_SYS_RT_SIGSUSPEND
  114. #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
  115. #define __ARCH_WANT_SYS_TIME
  116. --- a/arch/arm/kernel/calls.S 2009-03-24 18:00:31.000000000 +0100
  117. +++ b/arch/arm/kernel/calls.S 2009-04-18 19:10:22.000000000 +0200
  118. @@ -81,7 +81,7 @@
  119. CALL(sys_ni_syscall) /* was sys_ssetmask */
  120. /* 70 */ CALL(sys_setreuid16)
  121. CALL(sys_setregid16)
  122. - CALL(sys_sigsuspend_wrapper)
  123. + CALL(sys_sigsuspend)
  124. CALL(sys_sigpending)
  125. CALL(sys_sethostname)
  126. /* 75 */ CALL(sys_setrlimit)
  127. @@ -188,7 +188,7 @@
  128. CALL(sys_rt_sigpending)
  129. CALL(sys_rt_sigtimedwait)
  130. CALL(sys_rt_sigqueueinfo)
  131. - CALL(sys_rt_sigsuspend_wrapper)
  132. + CALL(sys_rt_sigsuspend)
  133. /* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64))
  134. CALL(ABI(sys_pwrite64, sys_oabi_pwrite64))
  135. CALL(sys_chown16)
  136. @@ -344,8 +344,8 @@
  137. CALL(sys_readlinkat)
  138. CALL(sys_fchmodat)
  139. CALL(sys_faccessat)
  140. -/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */
  141. - CALL(sys_ni_syscall) /* eventually ppoll */
  142. +/* 335 */ CALL(sys_pselect6)
  143. + CALL(sys_ppoll)
  144. CALL(sys_unshare)
  145. CALL(sys_set_robust_list)
  146. CALL(sys_get_robust_list)
  147. @@ -355,7 +355,7 @@
  148. CALL(sys_vmsplice)
  149. CALL(sys_move_pages)
  150. /* 345 */ CALL(sys_getcpu)
  151. - CALL(sys_ni_syscall) /* eventually epoll_pwait */
  152. + CALL(sys_epoll_pwait)
  153. CALL(sys_kexec_load)
  154. CALL(sys_utimensat)
  155. CALL(sys_signalfd)
  156. --- a/arch/arm/kernel/entry-common.S 2009-04-18 18:55:23.000000000 +0200
  157. +++ b/arch/arm/kernel/entry-common.S 2009-04-18 19:10:22.000000000 +0200
  158. @@ -370,16 +370,6 @@ sys_clone_wrapper:
  159. b sys_clone
  160. ENDPROC(sys_clone_wrapper)
  161. -sys_sigsuspend_wrapper:
  162. - add r3, sp, #S_OFF
  163. - b sys_sigsuspend
  164. -ENDPROC(sys_sigsuspend_wrapper)
  165. -
  166. -sys_rt_sigsuspend_wrapper:
  167. - add r2, sp, #S_OFF
  168. - b sys_rt_sigsuspend
  169. -ENDPROC(sys_rt_sigsuspend_wrapper)
  170. -
  171. sys_sigreturn_wrapper:
  172. add r0, sp, #S_OFF
  173. b sys_sigreturn
  174. --- a/arch/arm/kernel/signal.c 2008-12-25 15:54:13.000000000 +0100
  175. +++ b/arch/arm/kernel/signal.c 2009-04-18 19:10:22.000000000 +0200
  176. @@ -47,57 +47,22 @@ const unsigned long sigreturn_codes[7] =
  177. MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
  178. };
  179. -static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
  180. -
  181. /*
  182. * atomically swap in the new signal mask, and wait for a signal.
  183. */
  184. -asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs)
  185. +asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
  186. {
  187. - sigset_t saveset;
  188. -
  189. mask &= _BLOCKABLE;
  190. spin_lock_irq(&current->sighand->siglock);
  191. - saveset = current->blocked;
  192. + current->saved_sigmask = current->blocked;
  193. siginitset(&current->blocked, mask);
  194. recalc_sigpending();
  195. spin_unlock_irq(&current->sighand->siglock);
  196. - regs->ARM_r0 = -EINTR;
  197. -
  198. - while (1) {
  199. - current->state = TASK_INTERRUPTIBLE;
  200. - schedule();
  201. - if (do_signal(&saveset, regs, 0))
  202. - return regs->ARM_r0;
  203. - }
  204. -}
  205. -
  206. -asmlinkage int
  207. -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
  208. -{
  209. - sigset_t saveset, newset;
  210. -
  211. - /* XXX: Don't preclude handling different sized sigset_t's. */
  212. - if (sigsetsize != sizeof(sigset_t))
  213. - return -EINVAL;
  214. -
  215. - if (copy_from_user(&newset, unewset, sizeof(newset)))
  216. - return -EFAULT;
  217. - sigdelsetmask(&newset, ~_BLOCKABLE);
  218. -
  219. - spin_lock_irq(&current->sighand->siglock);
  220. - saveset = current->blocked;
  221. - current->blocked = newset;
  222. - recalc_sigpending();
  223. - spin_unlock_irq(&current->sighand->siglock);
  224. - regs->ARM_r0 = -EINTR;
  225. - while (1) {
  226. - current->state = TASK_INTERRUPTIBLE;
  227. - schedule();
  228. - if (do_signal(&saveset, regs, 0))
  229. - return regs->ARM_r0;
  230. - }
  231. + current->state = TASK_INTERRUPTIBLE;
  232. + schedule();
  233. + set_restore_sigmask();
  234. + return -ERESTARTNOHAND;
  235. }
  236. asmlinkage int
  237. @@ -541,7 +506,7 @@ static inline void restart_syscall(struc
  238. /*
  239. * OK, we're invoking a handler
  240. */
  241. -static void
  242. +static int
  243. handle_signal(unsigned long sig, struct k_sigaction *ka,
  244. siginfo_t *info, sigset_t *oldset,
  245. struct pt_regs * regs, int syscall)
  246. @@ -592,7 +557,7 @@ handle_signal(unsigned long sig, struct
  247. if (ret != 0) {
  248. force_sigsegv(sig, tsk);
  249. - return;
  250. + return ret;
  251. }
  252. /*
  253. @@ -606,6 +571,7 @@ handle_signal(unsigned long sig, struct
  254. recalc_sigpending();
  255. spin_unlock_irq(&tsk->sighand->siglock);
  256. + return 0;
  257. }
  258. /*
  259. @@ -617,11 +583,12 @@ handle_signal(unsigned long sig, struct
  260. * the kernel can handle, and then we build all the user-level signal handling
  261. * stack-frames in one go after that.
  262. */
  263. -static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
  264. +static void do_signal(struct pt_regs *regs, int syscall)
  265. {
  266. struct k_sigaction ka;
  267. siginfo_t info;
  268. int signr;
  269. + sigset_t *oldset;
  270. /*
  271. * We want the common case to go fast, which
  272. @@ -630,18 +597,32 @@ static int do_signal(sigset_t *oldset, s
  273. * if so.
  274. */
  275. if (!user_mode(regs))
  276. - return 0;
  277. + return;
  278. if (try_to_freeze())
  279. goto no_signal;
  280. single_step_clear(current);
  281. + if (test_thread_flag(TIF_RESTORE_SIGMASK))
  282. + oldset = &current->saved_sigmask;
  283. + else
  284. + oldset = &current->blocked;
  285. +
  286. signr = get_signal_to_deliver(&info, &ka, regs, NULL);
  287. if (signr > 0) {
  288. - handle_signal(signr, &ka, &info, oldset, regs, syscall);
  289. + if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) {
  290. + /*
  291. + * A signal was successfully delivered; the saved
  292. + * sigmask will have been stored in the signal frame,
  293. + * and will be restored by sigreturn, so we can simply
  294. + * clear the TIF_RESTORE_SIGMASK flag.
  295. + */
  296. + if (test_thread_flag(TIF_RESTORE_SIGMASK))
  297. + clear_thread_flag(TIF_RESTORE_SIGMASK);
  298. + }
  299. single_step_set(current);
  300. - return 1;
  301. + return;
  302. }
  303. no_signal:
  304. @@ -693,14 +674,21 @@ static int do_signal(sigset_t *oldset, s
  305. regs->ARM_r0 == -ERESTARTNOINTR) {
  306. restart_syscall(regs);
  307. }
  308. +
  309. + /* If there's no signal to deliver, we just put the saved sigmask
  310. + * back.
  311. + */
  312. + if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
  313. + clear_thread_flag(TIF_RESTORE_SIGMASK);
  314. + sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
  315. + }
  316. }
  317. single_step_set(current);
  318. - return 0;
  319. }
  320. asmlinkage void
  321. do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
  322. {
  323. if (thread_flags & _TIF_SIGPENDING)
  324. - do_signal(&current->blocked, regs, syscall);
  325. + do_signal(regs, syscall);
  326. }