From 2ff6502f3b3efa79a427cab154609fbb624e2aa6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pali=20Roh=C3=A1r?= Date: Thu, 13 Sep 2012 10:25:30 +0200 Subject: [PATCH] Added patch tif_restore_sigmask-syscalls-arm.patch which fix pselect bug --- kernel-power-2.6.28/debian/patches/series | 1 + .../patches/tif_restore_sigmask-syscalls-arm.patch | 268 ++++++++++++++++++++ 2 files changed, 269 insertions(+) create mode 100644 kernel-power-2.6.28/debian/patches/tif_restore_sigmask-syscalls-arm.patch diff --git a/kernel-power-2.6.28/debian/patches/series b/kernel-power-2.6.28/debian/patches/series index ca9184c..5aed59d 100644 --- a/kernel-power-2.6.28/debian/patches/series +++ b/kernel-power-2.6.28/debian/patches/series @@ -83,3 +83,4 @@ rx51_add_secure_ppa_api.diff rx51_arm_errata_430973.diff clear_the_it_state_when_invoking_a_thumb_2_signal_handler.diff udf-use-hw-sector-size.diff +tif_restore_sigmask-syscalls-arm.patch diff --git a/kernel-power-2.6.28/debian/patches/tif_restore_sigmask-syscalls-arm.patch b/kernel-power-2.6.28/debian/patches/tif_restore_sigmask-syscalls-arm.patch new file mode 100644 index 0000000..554b760 --- /dev/null +++ b/kernel-power-2.6.28/debian/patches/tif_restore_sigmask-syscalls-arm.patch @@ -0,0 +1,268 @@ +--- kernel-2.6.28.orig/arch/arm/include/asm/thread_info.h ++++ kernel-2.6.28/arch/arm/include/asm/thread_info.h +@@ -138,6 +138,7 @@ + #define TIF_USING_IWMMXT 17 + #define TIF_MEMDIE 18 + #define TIF_FREEZE 19 ++#define TIF_RESTORE_SIGMASK 20 + + #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) + #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) +@@ -145,6 +146,7 @@ + #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) + #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) + #define _TIF_FREEZE (1 << TIF_FREEZE) ++#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) + + /* + * Change these and you break ASM code in entry-common.S +--- kernel-2.6.28.orig/arch/arm/include/asm/unistd.h ++++ kernel-2.6.28/arch/arm/include/asm/unistd.h +@@ -360,8 +360,8 @@ + #define __NR_readlinkat (__NR_SYSCALL_BASE+332) + #define __NR_fchmodat (__NR_SYSCALL_BASE+333) + #define __NR_faccessat (__NR_SYSCALL_BASE+334) +- /* 335 for pselect6 */ +- /* 336 for ppoll */ ++#define __NR_pselect6 (__NR_SYSCALL_BASE+335) ++#define __NR_ppoll (__NR_SYSCALL_BASE+336) + #define __NR_unshare (__NR_SYSCALL_BASE+337) + #define __NR_set_robust_list (__NR_SYSCALL_BASE+338) + #define __NR_get_robust_list (__NR_SYSCALL_BASE+339) +@@ -372,7 +372,7 @@ + #define __NR_vmsplice (__NR_SYSCALL_BASE+343) + #define __NR_move_pages (__NR_SYSCALL_BASE+344) + #define __NR_getcpu (__NR_SYSCALL_BASE+345) +- /* 346 for epoll_pwait */ ++#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346) + #define __NR_kexec_load (__NR_SYSCALL_BASE+347) + #define __NR_utimensat (__NR_SYSCALL_BASE+348) + #define __NR_signalfd (__NR_SYSCALL_BASE+349) +@@ -428,6 +428,7 @@ + #define __ARCH_WANT_SYS_SIGPENDING + #define __ARCH_WANT_SYS_SIGPROCMASK + #define __ARCH_WANT_SYS_RT_SIGACTION ++#define __ARCH_WANT_SYS_RT_SIGSUSPEND + + #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) + #define __ARCH_WANT_SYS_TIME +--- kernel-2.6.28.orig/arch/arm/kernel/calls.S ++++ kernel-2.6.28/arch/arm/kernel/calls.S +@@ -81,7 +81,7 @@ + CALL(sys_ni_syscall) /* was sys_ssetmask */ + /* 70 */ CALL(sys_setreuid16) + CALL(sys_setregid16) +- CALL(sys_sigsuspend_wrapper) ++ CALL(sys_sigsuspend) + CALL(sys_sigpending) + CALL(sys_sethostname) + /* 75 */ CALL(sys_setrlimit) +@@ -188,7 +188,7 @@ + CALL(sys_rt_sigpending) + CALL(sys_rt_sigtimedwait) + CALL(sys_rt_sigqueueinfo) +- CALL(sys_rt_sigsuspend_wrapper) ++ CALL(sys_rt_sigsuspend) + /* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64)) + CALL(ABI(sys_pwrite64, sys_oabi_pwrite64)) + CALL(sys_chown16) +@@ -344,8 +344,8 @@ + CALL(sys_readlinkat) + CALL(sys_fchmodat) + CALL(sys_faccessat) +-/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */ +- CALL(sys_ni_syscall) /* eventually ppoll */ ++/* 335 */ CALL(sys_pselect6) ++ CALL(sys_ppoll) + CALL(sys_unshare) + CALL(sys_set_robust_list) + CALL(sys_get_robust_list) +@@ -355,7 +355,7 @@ + CALL(sys_vmsplice) + CALL(sys_move_pages) + /* 345 */ CALL(sys_getcpu) +- CALL(sys_ni_syscall) /* eventually epoll_pwait */ ++ CALL(sys_epoll_pwait) + CALL(sys_kexec_load) + CALL(sys_utimensat) + CALL(sys_signalfd) +--- kernel-2.6.28.orig/arch/arm/kernel/entry-common.S ++++ kernel-2.6.28/arch/arm/kernel/entry-common.S +@@ -362,16 +362,6 @@ + b sys_clone + ENDPROC(sys_clone_wrapper) + +-sys_sigsuspend_wrapper: +- add r3, sp, #S_OFF +- b sys_sigsuspend +-ENDPROC(sys_sigsuspend_wrapper) +- +-sys_rt_sigsuspend_wrapper: +- add r2, sp, #S_OFF +- b sys_rt_sigsuspend +-ENDPROC(sys_rt_sigsuspend_wrapper) +- + sys_sigreturn_wrapper: + add r0, sp, #S_OFF + b sys_sigreturn +--- kernel-2.6.28.orig/arch/arm/kernel/signal.c ++++ kernel-2.6.28/arch/arm/kernel/signal.c +@@ -47,57 +47,22 @@ + MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, + }; + +-static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall); +- + /* + * atomically swap in the new signal mask, and wait for a signal. + */ +-asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs) ++asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask) + { +- sigset_t saveset; +- + mask &= _BLOCKABLE; + spin_lock_irq(¤t->sighand->siglock); +- saveset = current->blocked; ++ current->saved_sigmask = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); +- regs->ARM_r0 = -EINTR; +- +- while (1) { +- current->state = TASK_INTERRUPTIBLE; +- schedule(); +- if (do_signal(&saveset, regs, 0)) +- return regs->ARM_r0; +- } +-} +- +-asmlinkage int +-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs) +-{ +- sigset_t saveset, newset; +- +- /* XXX: Don't preclude handling different sized sigset_t's. */ +- if (sigsetsize != sizeof(sigset_t)) +- return -EINVAL; +- +- if (copy_from_user(&newset, unewset, sizeof(newset))) +- return -EFAULT; +- sigdelsetmask(&newset, ~_BLOCKABLE); +- +- spin_lock_irq(¤t->sighand->siglock); +- saveset = current->blocked; +- current->blocked = newset; +- recalc_sigpending(); +- spin_unlock_irq(¤t->sighand->siglock); +- regs->ARM_r0 = -EINTR; + +- while (1) { +- current->state = TASK_INTERRUPTIBLE; +- schedule(); +- if (do_signal(&saveset, regs, 0)) +- return regs->ARM_r0; +- } ++ current->state = TASK_INTERRUPTIBLE; ++ schedule(); ++ set_restore_sigmask(); ++ return -ERESTARTNOHAND; + } + + asmlinkage int +@@ -606,7 +571,7 @@ + /* + * OK, we're invoking a handler + */ +-static void ++static int + handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, + struct pt_regs * regs, int syscall) +@@ -657,7 +622,7 @@ + + if (ret != 0) { + force_sigsegv(sig, tsk); +- return; ++ return ret; + } + + /* +@@ -671,6 +636,7 @@ + recalc_sigpending(); + spin_unlock_irq(&tsk->sighand->siglock); + ++ return 0; + } + + /* +@@ -682,7 +648,7 @@ + * the kernel can handle, and then we build all the user-level signal handling + * stack-frames in one go after that. + */ +-static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) ++static void do_signal(struct pt_regs *regs, int syscall) + { + struct k_sigaction ka; + siginfo_t info; +@@ -695,7 +661,7 @@ + * if so. + */ + if (!user_mode(regs)) +- return 0; ++ return; + + if (try_to_freeze()) + goto no_signal; +@@ -704,9 +670,24 @@ + + signr = get_signal_to_deliver(&info, &ka, regs, NULL); + if (signr > 0) { +- handle_signal(signr, &ka, &info, oldset, regs, syscall); ++ sigset_t *oldset; ++ ++ if (test_thread_flag(TIF_RESTORE_SIGMASK)) ++ oldset = ¤t->saved_sigmask; ++ else ++ oldset = ¤t->blocked; ++ if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) { ++ /* ++ * A signal was successfully delivered; the saved ++ * sigmask will have been stored in the signal frame, ++ * and will be restored by sigreturn, so we can simply ++ * clear the TIF_RESTORE_SIGMASK flag. ++ */ ++ if (test_thread_flag(TIF_RESTORE_SIGMASK)) ++ clear_thread_flag(TIF_RESTORE_SIGMASK); ++ } + single_step_set(current); +- return 1; ++ return; + } + + no_signal: +@@ -758,14 +739,21 @@ + regs->ARM_r0 == -ERESTARTNOINTR) { + restart_syscall(regs); + } ++ ++ /* If there's no signal to deliver, we just put the saved sigmask ++ * back. ++ */ ++ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { ++ clear_thread_flag(TIF_RESTORE_SIGMASK); ++ sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); ++ } + } + single_step_set(current); +- return 0; + } + + asmlinkage void + do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall) + { + if (thread_flags & _TIF_SIGPENDING) +- do_signal(¤t->blocked, regs, syscall); ++ do_signal(regs, syscall); + } -- 1.7.9.5