Gitweb:
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=431dc8040354db65e4f8d4d4e21ae4fab41f5bc3
Commit: 431dc8040354db65e4f8d4d4e21ae4fab41f5bc3
Parent: 366d6aef281a670b32a51d289fc07bf0e5e72d9a
Author: Ralf Baechle <[EMAIL PROTECTED]>
AuthorDate: Tue Feb 13 00:05:11 2007 +
Committer: Ralf Baechle <[EMAIL PROTECTED]>
CommitDate: Tue Feb 13 22:40:51 2007 +0000
[MIPS] Fix sigset_t endianess swapping issues in 32-bit compat code.
Signed-off-by: Ralf Baechle <[EMAIL PROTECTED]>
---
arch/mips/kernel/linux32.c | 47
arch/mips/kernel/scall64-64.S|2 +-
arch/mips/kernel/scall64-n32.S |2 +-
arch/mips/kernel/signal32.c | 11 +---
arch/mips/kernel/signal_n32.c|7 +++--
include/asm-mips/compat-signal.h | 55 ++
6 files changed, 115 insertions(+), 9 deletions(-)
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index ca7ad78..fc4dd6c 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -39,6 +39,7 @@
#include
#include
+#include
#include
#include
#include
@@ -736,3 +737,49 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs)
return do_fork(clone_flags, newsp, ®s, 0,
parent_tidptr, child_tidptr);
}
+
+/*
+ * Implement the event wait interface for the eventpoll file. It is the kernel
+ * part of the user space epoll_pwait(2).
+ */
+asmlinkage long compat_sys_epoll_pwait(int epfd,
+ struct epoll_event __user *events, int maxevents, int timeout,
+ const compat_sigset_t __user *sigmask, size_t sigsetsize)
+{
+ int error;
+ sigset_t ksigmask, sigsaved;
+
+ /*
+* If the caller wants a certain signal mask to be set during the wait,
+* we apply it here.
+*/
+ if (sigmask) {
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+ if (!access_ok(VERIFY_READ, sigmask, sizeof(ksigmask)))
+ return -EFAULT;
+ if (__copy_conv_sigset_from_user(&ksigmask, sigmask))
+ return -EFAULT;
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+ error = sys_epoll_wait(epfd, events, maxevents, timeout);
+
+ /*
+* If we changed the signal mask, we need to restore the original one.
+* In case we've got a signal while waiting, we do not restore the
+* signal mask yet, and we allow do_signal() to deliver the signal on
+* the way back to userspace, before the signal mask is restored.
+*/
+ if (sigmask) {
+ if (error == -EINTR) {
+ memcpy(¤t->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ } else
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+ }
+
+ return error;
+}
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index e569b84..10e9a18 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -470,4 +470,4 @@ sys_call_table:
PTR sys_get_robust_list
PTR sys_kexec_load /* 5270 */
PTR sys_getcpu
- PTR sys_epoll_pwait
+ PTR compat_sys_epoll_pwait
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index ee8802b..2ceda46 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -396,4 +396,4 @@ EXPORT(sysn32_call_table)
PTR compat_sys_get_robust_list
PTR compat_sys_kexec_load
PTR sys_getcpu
- PTR sys_epoll_pwait
+ PTR compat_sys_epoll_pwait
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index db00c33..c28cb21 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -8,6 +8,7 @@
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include
+#include
#include
#include
#include
@@ -24,6 +25,7 @@
#include
#include
+#include
#include
#include
#include
@@ -517,7 +519,7 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct
pt_regs regs)
frame = (struct sigframe32 __user *) regs.regs[29];
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
- if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
+ if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
goto badframe;
sigdelsetmask(&blocked, ~_BLOCKABLE);
@@ -554,7 +556,7 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct
pt_regs regs)
frame = (struct rt_s