Added patch tif_restore_sigmask-syscalls-arm.patch which fix pselect bug
[kernel-power] / kernel-power-2.6.28 / debian / patches / tif_restore_sigmask-syscalls-arm.patch
1 --- kernel-2.6.28.orig/arch/arm/include/asm/thread_info.h
2 +++ kernel-2.6.28/arch/arm/include/asm/thread_info.h
3 @@ -138,6 +138,7 @@
4  #define TIF_USING_IWMMXT       17
5  #define TIF_MEMDIE             18
6  #define TIF_FREEZE             19
7 +#define TIF_RESTORE_SIGMASK    20
8  
9  #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
10  #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
11 @@ -145,6 +146,7 @@
12  #define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
13  #define _TIF_USING_IWMMXT      (1 << TIF_USING_IWMMXT)
14  #define _TIF_FREEZE            (1 << TIF_FREEZE)
15 +#define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
16  
17  /*
18   * Change these and you break ASM code in entry-common.S
19 --- kernel-2.6.28.orig/arch/arm/include/asm/unistd.h
20 +++ kernel-2.6.28/arch/arm/include/asm/unistd.h
21 @@ -360,8 +360,8 @@
22  #define __NR_readlinkat                        (__NR_SYSCALL_BASE+332)
23  #define __NR_fchmodat                  (__NR_SYSCALL_BASE+333)
24  #define __NR_faccessat                 (__NR_SYSCALL_BASE+334)
25 -                                       /* 335 for pselect6 */
26 -                                       /* 336 for ppoll */
27 +#define __NR_pselect6                  (__NR_SYSCALL_BASE+335)
28 +#define __NR_ppoll                     (__NR_SYSCALL_BASE+336)
29  #define __NR_unshare                   (__NR_SYSCALL_BASE+337)
30  #define __NR_set_robust_list           (__NR_SYSCALL_BASE+338)
31  #define __NR_get_robust_list           (__NR_SYSCALL_BASE+339)
32 @@ -372,7 +372,7 @@
33  #define __NR_vmsplice                  (__NR_SYSCALL_BASE+343)
34  #define __NR_move_pages                        (__NR_SYSCALL_BASE+344)
35  #define __NR_getcpu                    (__NR_SYSCALL_BASE+345)
36 -                                       /* 346 for epoll_pwait */
37 +#define __NR_epoll_pwait               (__NR_SYSCALL_BASE+346)
38  #define __NR_kexec_load                        (__NR_SYSCALL_BASE+347)
39  #define __NR_utimensat                 (__NR_SYSCALL_BASE+348)
40  #define __NR_signalfd                  (__NR_SYSCALL_BASE+349)
41 @@ -428,6 +428,7 @@
42  #define __ARCH_WANT_SYS_SIGPENDING
43  #define __ARCH_WANT_SYS_SIGPROCMASK
44  #define __ARCH_WANT_SYS_RT_SIGACTION
45 +#define __ARCH_WANT_SYS_RT_SIGSUSPEND
46  
47  #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
48  #define __ARCH_WANT_SYS_TIME
49 --- kernel-2.6.28.orig/arch/arm/kernel/calls.S
50 +++ kernel-2.6.28/arch/arm/kernel/calls.S
51 @@ -81,7 +81,7 @@
52                 CALL(sys_ni_syscall)            /* was sys_ssetmask */
53  /* 70 */       CALL(sys_setreuid16)
54                 CALL(sys_setregid16)
55 -               CALL(sys_sigsuspend_wrapper)
56 +               CALL(sys_sigsuspend)
57                 CALL(sys_sigpending)
58                 CALL(sys_sethostname)
59  /* 75 */       CALL(sys_setrlimit)
60 @@ -188,7 +188,7 @@
61                 CALL(sys_rt_sigpending)
62                 CALL(sys_rt_sigtimedwait)
63                 CALL(sys_rt_sigqueueinfo)
64 -               CALL(sys_rt_sigsuspend_wrapper)
65 +               CALL(sys_rt_sigsuspend)
66  /* 180 */      CALL(ABI(sys_pread64, sys_oabi_pread64))
67                 CALL(ABI(sys_pwrite64, sys_oabi_pwrite64))
68                 CALL(sys_chown16)
69 @@ -344,8 +344,8 @@
70                 CALL(sys_readlinkat)
71                 CALL(sys_fchmodat)
72                 CALL(sys_faccessat)
73 -/* 335 */      CALL(sys_ni_syscall)            /* eventually pselect6 */
74 -               CALL(sys_ni_syscall)            /* eventually ppoll */
75 +/* 335 */      CALL(sys_pselect6)
76 +               CALL(sys_ppoll)
77                 CALL(sys_unshare)
78                 CALL(sys_set_robust_list)
79                 CALL(sys_get_robust_list)
80 @@ -355,7 +355,7 @@
81                 CALL(sys_vmsplice)
82                 CALL(sys_move_pages)
83  /* 345 */      CALL(sys_getcpu)
84 -               CALL(sys_ni_syscall)            /* eventually epoll_pwait */
85 +               CALL(sys_epoll_pwait)
86                 CALL(sys_kexec_load)
87                 CALL(sys_utimensat)
88                 CALL(sys_signalfd)
89 --- kernel-2.6.28.orig/arch/arm/kernel/entry-common.S
90 +++ kernel-2.6.28/arch/arm/kernel/entry-common.S
91 @@ -362,16 +362,6 @@
92                 b       sys_clone
93  ENDPROC(sys_clone_wrapper)
94  
95 -sys_sigsuspend_wrapper:
96 -               add     r3, sp, #S_OFF
97 -               b       sys_sigsuspend
98 -ENDPROC(sys_sigsuspend_wrapper)
99 -
100 -sys_rt_sigsuspend_wrapper:
101 -               add     r2, sp, #S_OFF
102 -               b       sys_rt_sigsuspend
103 -ENDPROC(sys_rt_sigsuspend_wrapper)
104 -
105  sys_sigreturn_wrapper:
106                 add     r0, sp, #S_OFF
107                 b       sys_sigreturn
108 --- kernel-2.6.28.orig/arch/arm/kernel/signal.c
109 +++ kernel-2.6.28/arch/arm/kernel/signal.c
110 @@ -47,57 +47,22 @@
111         MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
112  };
113  
114 -static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
115 -
116  /*
117   * atomically swap in the new signal mask, and wait for a signal.
118   */
119 -asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs)
120 +asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
121  {
122 -       sigset_t saveset;
123 -
124         mask &= _BLOCKABLE;
125         spin_lock_irq(&current->sighand->siglock);
126 -       saveset = current->blocked;
127 +       current->saved_sigmask = current->blocked;
128         siginitset(&current->blocked, mask);
129         recalc_sigpending();
130         spin_unlock_irq(&current->sighand->siglock);
131 -       regs->ARM_r0 = -EINTR;
132 -
133 -       while (1) {
134 -               current->state = TASK_INTERRUPTIBLE;
135 -               schedule();
136 -               if (do_signal(&saveset, regs, 0))
137 -                       return regs->ARM_r0;
138 -       }
139 -}
140 -
141 -asmlinkage int
142 -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
143 -{
144 -       sigset_t saveset, newset;
145 -
146 -       /* XXX: Don't preclude handling different sized sigset_t's. */
147 -       if (sigsetsize != sizeof(sigset_t))
148 -               return -EINVAL;
149 -
150 -       if (copy_from_user(&newset, unewset, sizeof(newset)))
151 -               return -EFAULT;
152 -       sigdelsetmask(&newset, ~_BLOCKABLE);
153 -
154 -       spin_lock_irq(&current->sighand->siglock);
155 -       saveset = current->blocked;
156 -       current->blocked = newset;
157 -       recalc_sigpending();
158 -       spin_unlock_irq(&current->sighand->siglock);
159 -       regs->ARM_r0 = -EINTR;
160  
161 -       while (1) {
162 -               current->state = TASK_INTERRUPTIBLE;
163 -               schedule();
164 -               if (do_signal(&saveset, regs, 0))
165 -                       return regs->ARM_r0;
166 -       }
167 +       current->state = TASK_INTERRUPTIBLE;
168 +       schedule();
169 +       set_restore_sigmask();
170 +       return -ERESTARTNOHAND;
171  }
172  
173  asmlinkage int 
174 @@ -606,7 +571,7 @@
175  /*
176   * OK, we're invoking a handler
177   */    
178 -static void
179 +static int
180  handle_signal(unsigned long sig, struct k_sigaction *ka,
181               siginfo_t *info, sigset_t *oldset,
182               struct pt_regs * regs, int syscall)
183 @@ -657,7 +622,7 @@
184  
185         if (ret != 0) {
186                 force_sigsegv(sig, tsk);
187 -               return;
188 +               return ret;
189         }
190  
191         /*
192 @@ -671,6 +636,7 @@
193         recalc_sigpending();
194         spin_unlock_irq(&tsk->sighand->siglock);
195  
196 +       return 0;
197  }
198  
199  /*
200 @@ -682,7 +648,7 @@
201   * the kernel can handle, and then we build all the user-level signal handling
202   * stack-frames in one go after that.
203   */
204 -static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
205 +static void do_signal(struct pt_regs *regs, int syscall)
206  {
207         struct k_sigaction ka;
208         siginfo_t info;
209 @@ -695,7 +661,7 @@
210          * if so.
211          */
212         if (!user_mode(regs))
213 -               return 0;
214 +               return;
215  
216         if (try_to_freeze())
217                 goto no_signal;
218 @@ -704,9 +670,24 @@
219  
220         signr = get_signal_to_deliver(&info, &ka, regs, NULL);
221         if (signr > 0) {
222 -               handle_signal(signr, &ka, &info, oldset, regs, syscall);
223 +               sigset_t *oldset;
224 +
225 +               if (test_thread_flag(TIF_RESTORE_SIGMASK))
226 +                       oldset = &current->saved_sigmask;
227 +               else
228 +                       oldset = &current->blocked;
229 +               if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) {
230 +                       /*
231 +                        * A signal was successfully delivered; the saved
232 +                        * sigmask will have been stored in the signal frame,
233 +                        * and will be restored by sigreturn, so we can simply
234 +                        * clear the TIF_RESTORE_SIGMASK flag.
235 +                        */
236 +                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
237 +                               clear_thread_flag(TIF_RESTORE_SIGMASK);
238 +               }
239                 single_step_set(current);
240 -               return 1;
241 +               return;
242         }
243  
244   no_signal:
245 @@ -758,14 +739,21 @@
246                     regs->ARM_r0 == -ERESTARTNOINTR) {
247                         restart_syscall(regs);
248                 }
249 +
250 +               /* If there's no signal to deliver, we just put the saved sigmask
251 +                * back.
252 +                */
253 +               if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
254 +                       clear_thread_flag(TIF_RESTORE_SIGMASK);
255 +                       sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
256 +               }
257         }
258         single_step_set(current);
259 -       return 0;
260  }
261  
262  asmlinkage void
263  do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
264  {
265         if (thread_flags & _TIF_SIGPENDING)
266 -               do_signal(&current->blocked, regs, syscall);
267 +               do_signal(regs, syscall);
268  }