--- /dev/null
+From dannf@debian.org Mon May 4 15:16:52 2009
+From: dann frazier <dannf@debian.org>
+Date: Wed, 29 Apr 2009 16:14:58 -0600
+Subject: MIPS: CVE-2009-0029: Enable syscall wrappers
+To: Greg KH <greg@kroah.com>
+Cc: stable@kernel.org, Ralf Baechle <ralf@linux-mips.org>
+Message-ID: <20090429221458.GM24756@ldl.fc.hp.com>
+
+From: dann frazier <dannf@debian.org>
+
+Backport of upstream commits by:
+ Ralf Baechle <ralf@linux-mips.org>
+ Xiaotian Feng <Xiaotian.Feng@windriver.com>
+
+upstream commits:
+ dbda6ac0897603f6c6dfadbbc37f9882177ec7ac
+ d6c178e9694e7e0c7ffe0289cf4389a498cac735
+ c189846ecf900cd6b3ad7d3cef5b45a746ce646b
+
+Signed-off-by: dann frazier <dannf@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/mips/Kconfig | 1
+ arch/mips/kernel/linux32.c | 69 +++++++++++++++++++++++------------------
+ arch/mips/kernel/scall32-o32.S | 4 +-
+ arch/mips/kernel/scall64-64.S | 2 -
+ arch/mips/kernel/scall64-n32.S | 28 ++++++++--------
+ arch/mips/kernel/scall64-o32.S | 40 +++++++++++------------
+ arch/mips/kernel/signal.c | 5 +-
+ arch/mips/kernel/signal32.c | 28 ++++++++--------
+ arch/mips/kernel/syscall.c | 26 +++++++--------
+ arch/mips/mm/cache.c | 5 +-
+ 10 files changed, 110 insertions(+), 98 deletions(-)
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -1293,6 +1293,7 @@ config 32BIT
+ config 64BIT
+ bool "64-bit kernel"
+ depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL
++ select HAVE_SYSCALL_WRAPPERS
+ help
+ Select this option if you want to build a 64-bit kernel.
+
+--- a/arch/mips/kernel/linux32.c
++++ b/arch/mips/kernel/linux32.c
+@@ -32,6 +32,7 @@
+ #include <linux/module.h>
+ #include <linux/binfmts.h>
+ #include <linux/security.h>
++#include <linux/syscalls.h>
+ #include <linux/compat.h>
+ #include <linux/vfs.h>
+ #include <linux/ipc.h>
+@@ -98,9 +99,9 @@ int cp_compat_stat(struct kstat *stat, s
+ return copy_to_user(statbuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
+ }
+
+-asmlinkage unsigned long
+-sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+- unsigned long flags, unsigned long fd, unsigned long pgoff)
++SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len,
++ unsigned long, prot, unsigned long, flags, unsigned long, fd,
++ unsigned long, pgoff)
+ {
+ struct file * file = NULL;
+ unsigned long error;
+@@ -156,14 +157,14 @@ struct rlimit32 {
+ int rlim_max;
+ };
+
+-asmlinkage long sys32_truncate64(const char __user * path,
+- unsigned long __dummy, int a2, int a3)
++SYSCALL_DEFINE4(32_truncate64, const char __user *, path,
++ unsigned long, __dummy, unsigned long, a2, unsigned long, a3)
+ {
+ return sys_truncate(path, merge_64(a2, a3));
+ }
+
+-asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
+- int a2, int a3)
++SYSCALL_DEFINE4(32_ftruncate64, unsigned long, fd, unsigned long, __dummy,
++ unsigned long, a2, unsigned long, a3)
+ {
+ return sys_ftruncate(fd, merge_64(a2, a3));
+ }
+@@ -234,9 +235,9 @@ sys32_settimeofday(struct compat_timeval
+ return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
+ }
+
+-asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
+- unsigned int offset_low, loff_t __user * result,
+- unsigned int origin)
++SYSCALL_DEFINE5(32_llseek, unsigned int, fd, unsigned int, offset_high,
++ unsigned int, offset_low, loff_t __user *, result,
++ unsigned int, origin)
+ {
+ return sys_llseek(fd, offset_high, offset_low, result, origin);
+ }
+@@ -245,20 +246,20 @@ asmlinkage int sys32_llseek(unsigned int
+ lseek back to original location. They fail just like lseek does on
+ non-seekable files. */
+
+-asmlinkage ssize_t sys32_pread(unsigned int fd, char __user * buf,
+- size_t count, u32 unused, u64 a4, u64 a5)
++SYSCALL_DEFINE6(32_pread, unsigned long, fd, char __user *, buf, size_t, count,
++ unsigned long, unused, unsigned long, a4, unsigned long, a5)
+ {
+ return sys_pread64(fd, buf, count, merge_64(a4, a5));
+ }
+
+-asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char __user * buf,
+- size_t count, u32 unused, u64 a4, u64 a5)
++SYSCALL_DEFINE6(32_pwrite, unsigned int, fd, const char __user *, buf,
++ size_t, count, u32, unused, u64, a4, u64, a5)
+ {
+ return sys_pwrite64(fd, buf, count, merge_64(a4, a5));
+ }
+
+-asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
+- struct compat_timespec __user *interval)
++SYSCALL_DEFINE2(32_sched_rr_get_interval, compat_pid_t, pid,
++ struct compat_timespec __user *, interval)
+ {
+ struct timespec t;
+ int ret;
+@@ -275,8 +276,8 @@ asmlinkage int sys32_sched_rr_get_interv
+
+ #ifdef CONFIG_SYSVIPC
+
+-asmlinkage long
+-sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
++SYSCALL_DEFINE6(32_ipc, u32, call, long, first, long, second, long, third,
++ unsigned long, ptr, unsigned long, fifth)
+ {
+ int version, err;
+
+@@ -334,8 +335,8 @@ sys32_ipc(u32 call, int first, int secon
+
+ #else
+
+-asmlinkage long
+-sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
++SYSCALL_DEFINE6(32_ipc, u32, call, int, first, int, second, int, third,
++ u32, ptr, u32, fifth)
+ {
+ return -ENOSYS;
+ }
+@@ -343,7 +344,7 @@ sys32_ipc(u32 call, int first, int secon
+ #endif /* CONFIG_SYSVIPC */
+
+ #ifdef CONFIG_MIPS32_N32
+-asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg)
++SYSCALL_DEFINE4(n32_semctl, int, semid, int, semnum, int, cmd, u32, arg)
+ {
+ /* compat_sys_semctl expects a pointer to union semun */
+ u32 __user *uptr = compat_alloc_user_space(sizeof(u32));
+@@ -352,13 +353,14 @@ asmlinkage long sysn32_semctl(int semid,
+ return compat_sys_semctl(semid, semnum, cmd, uptr);
+ }
+
+-asmlinkage long sysn32_msgsnd(int msqid, u32 msgp, unsigned msgsz, int msgflg)
++SYSCALL_DEFINE4(n32_msgsnd, int, msqid, u32, msgp, unsigned int, msgsz,
++ int, msgflg)
+ {
+ return compat_sys_msgsnd(msqid, msgsz, msgflg, compat_ptr(msgp));
+ }
+
+-asmlinkage long sysn32_msgrcv(int msqid, u32 msgp, size_t msgsz, int msgtyp,
+- int msgflg)
++SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,
++ int, msgtyp, int, msgflg)
+ {
+ return compat_sys_msgrcv(msqid, msgsz, msgtyp, msgflg, IPC_64,
+ compat_ptr(msgp));
+@@ -378,7 +380,7 @@ struct sysctl_args32
+
+ #ifdef CONFIG_SYSCTL_SYSCALL
+
+-asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args)
++SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args)
+ {
+ struct sysctl_args32 tmp;
+ int error;
+@@ -417,9 +419,16 @@ asmlinkage long sys32_sysctl(struct sysc
+ return error;
+ }
+
++#else
++
++SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args)
++{
++ return -ENOSYS;
++}
++
+ #endif /* CONFIG_SYSCTL_SYSCALL */
+
+-asmlinkage long sys32_newuname(struct new_utsname __user * name)
++SYSCALL_DEFINE1(32_newuname, struct new_utsname __user *, name)
+ {
+ int ret = 0;
+
+@@ -435,7 +444,7 @@ asmlinkage long sys32_newuname(struct ne
+ return ret;
+ }
+
+-asmlinkage int sys32_personality(unsigned long personality)
++SYSCALL_DEFINE1(32_personality, unsigned long, personality)
+ {
+ int ret;
+ personality &= 0xffffffff;
+@@ -458,7 +467,7 @@ struct ustat32 {
+
+ extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf);
+
+-asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32)
++SYSCALL_DEFINE2(32_ustat, dev_t, dev, struct ustat32 __user *, ubuf32)
+ {
+ int err;
+ struct ustat tmp;
+@@ -482,8 +491,8 @@ out:
+ return err;
+ }
+
+-asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
+- s32 count)
++SYSCALL_DEFINE4(32_sendfile, long, out_fd, long, in_fd,
++ compat_off_t __user *, offset, s32, count)
+ {
+ mm_segment_t old_fs = get_fs();
+ int ret;
+--- a/arch/mips/kernel/scall32-o32.S
++++ b/arch/mips/kernel/scall32-o32.S
+@@ -402,7 +402,7 @@ einval: li v0, -EINVAL
+ sys sys_swapon 2
+ sys sys_reboot 3
+ sys sys_old_readdir 3
+- sys old_mmap 6 /* 4090 */
++ sys sys_mips_mmap 6 /* 4090 */
+ sys sys_munmap 2
+ sys sys_truncate 2
+ sys sys_ftruncate 2
+@@ -522,7 +522,7 @@ einval: li v0, -EINVAL
+ sys sys_sendfile 4
+ sys sys_ni_syscall 0
+ sys sys_ni_syscall 0
+- sys sys_mmap2 6 /* 4210 */
++ sys sys_mips_mmap2 6 /* 4210 */
+ sys sys_truncate64 4
+ sys sys_ftruncate64 4
+ sys sys_stat64 2
+--- a/arch/mips/kernel/scall64-64.S
++++ b/arch/mips/kernel/scall64-64.S
+@@ -207,7 +207,7 @@ sys_call_table:
+ PTR sys_newlstat
+ PTR sys_poll
+ PTR sys_lseek
+- PTR old_mmap
++ PTR sys_mips_mmap
+ PTR sys_mprotect /* 5010 */
+ PTR sys_munmap
+ PTR sys_brk
+--- a/arch/mips/kernel/scall64-n32.S
++++ b/arch/mips/kernel/scall64-n32.S
+@@ -129,12 +129,12 @@ EXPORT(sysn32_call_table)
+ PTR sys_newlstat
+ PTR sys_poll
+ PTR sys_lseek
+- PTR old_mmap
++ PTR sys_mips_mmap
+ PTR sys_mprotect /* 6010 */
+ PTR sys_munmap
+ PTR sys_brk
+- PTR sys32_rt_sigaction
+- PTR sys32_rt_sigprocmask
++ PTR sys_32_rt_sigaction
++ PTR sys_32_rt_sigprocmask
+ PTR compat_sys_ioctl /* 6015 */
+ PTR sys_pread64
+ PTR sys_pwrite64
+@@ -159,7 +159,7 @@ EXPORT(sysn32_call_table)
+ PTR compat_sys_setitimer
+ PTR sys_alarm
+ PTR sys_getpid
+- PTR sys32_sendfile
++ PTR sys_32_sendfile
+ PTR sys_socket /* 6040 */
+ PTR sys_connect
+ PTR sys_accept
+@@ -181,14 +181,14 @@ EXPORT(sysn32_call_table)
+ PTR sys_exit
+ PTR compat_sys_wait4
+ PTR sys_kill /* 6060 */
+- PTR sys32_newuname
++ PTR sys_32_newuname
+ PTR sys_semget
+ PTR sys_semop
+- PTR sysn32_semctl
++ PTR sys_n32_semctl
+ PTR sys_shmdt /* 6065 */
+ PTR sys_msgget
+- PTR sysn32_msgsnd
+- PTR sysn32_msgrcv
++ PTR sys_n32_msgsnd
++ PTR sys_n32_msgrcv
+ PTR compat_sys_msgctl
+ PTR compat_sys_fcntl /* 6070 */
+ PTR sys_flock
+@@ -245,15 +245,15 @@ EXPORT(sysn32_call_table)
+ PTR sys_getsid
+ PTR sys_capget
+ PTR sys_capset
+- PTR sys32_rt_sigpending /* 6125 */
++ PTR sys_32_rt_sigpending /* 6125 */
+ PTR compat_sys_rt_sigtimedwait
+- PTR sys32_rt_sigqueueinfo
++ PTR sys_32_rt_sigqueueinfo
+ PTR sysn32_rt_sigsuspend
+ PTR sys32_sigaltstack
+ PTR compat_sys_utime /* 6130 */
+ PTR sys_mknod
+- PTR sys32_personality
+- PTR sys32_ustat
++ PTR sys_32_personality
++ PTR sys_32_ustat
+ PTR compat_sys_statfs
+ PTR compat_sys_fstatfs /* 6135 */
+ PTR sys_sysfs
+@@ -265,14 +265,14 @@ EXPORT(sysn32_call_table)
+ PTR sys_sched_getscheduler
+ PTR sys_sched_get_priority_max
+ PTR sys_sched_get_priority_min
+- PTR sys32_sched_rr_get_interval /* 6145 */
++ PTR sys_32_sched_rr_get_interval /* 6145 */
+ PTR sys_mlock
+ PTR sys_munlock
+ PTR sys_mlockall
+ PTR sys_munlockall
+ PTR sys_vhangup /* 6150 */
+ PTR sys_pivot_root
+- PTR sys32_sysctl
++ PTR sys_32_sysctl
+ PTR sys_prctl
+ PTR compat_sys_adjtimex
+ PTR compat_sys_setrlimit /* 6155 */
+--- a/arch/mips/kernel/scall64-o32.S
++++ b/arch/mips/kernel/scall64-o32.S
+@@ -267,12 +267,12 @@ sys_call_table:
+ PTR sys_olduname
+ PTR sys_umask /* 4060 */
+ PTR sys_chroot
+- PTR sys32_ustat
++ PTR sys_32_ustat
+ PTR sys_dup2
+ PTR sys_getppid
+ PTR sys_getpgrp /* 4065 */
+ PTR sys_setsid
+- PTR sys32_sigaction
++ PTR sys_32_sigaction
+ PTR sys_sgetmask
+ PTR sys_ssetmask
+ PTR sys_setreuid /* 4070 */
+@@ -295,7 +295,7 @@ sys_call_table:
+ PTR sys_swapon
+ PTR sys_reboot
+ PTR compat_sys_old_readdir
+- PTR old_mmap /* 4090 */
++ PTR sys_mips_mmap /* 4090 */
+ PTR sys_munmap
+ PTR sys_truncate
+ PTR sys_ftruncate
+@@ -322,12 +322,12 @@ sys_call_table:
+ PTR compat_sys_wait4
+ PTR sys_swapoff /* 4115 */
+ PTR compat_sys_sysinfo
+- PTR sys32_ipc
++ PTR sys_32_ipc
+ PTR sys_fsync
+ PTR sys32_sigreturn
+ PTR sys32_clone /* 4120 */
+ PTR sys_setdomainname
+- PTR sys32_newuname
++ PTR sys_32_newuname
+ PTR sys_ni_syscall /* sys_modify_ldt */
+ PTR compat_sys_adjtimex
+ PTR sys_mprotect /* 4125 */
+@@ -341,11 +341,11 @@ sys_call_table:
+ PTR sys_fchdir
+ PTR sys_bdflush
+ PTR sys_sysfs /* 4135 */
+- PTR sys32_personality
++ PTR sys_32_personality
+ PTR sys_ni_syscall /* for afs_syscall */
+ PTR sys_setfsuid
+ PTR sys_setfsgid
+- PTR sys32_llseek /* 4140 */
++ PTR sys_32_llseek /* 4140 */
+ PTR compat_sys_getdents
+ PTR compat_sys_select
+ PTR sys_flock
+@@ -358,7 +358,7 @@ sys_call_table:
+ PTR sys_ni_syscall /* 4150 */
+ PTR sys_getsid
+ PTR sys_fdatasync
+- PTR sys32_sysctl
++ PTR sys_32_sysctl
+ PTR sys_mlock
+ PTR sys_munlock /* 4155 */
+ PTR sys_mlockall
+@@ -370,7 +370,7 @@ sys_call_table:
+ PTR sys_sched_yield
+ PTR sys_sched_get_priority_max
+ PTR sys_sched_get_priority_min
+- PTR sys32_sched_rr_get_interval /* 4165 */
++ PTR sys_32_sched_rr_get_interval /* 4165 */
+ PTR compat_sys_nanosleep
+ PTR sys_mremap
+ PTR sys_accept
+@@ -399,25 +399,25 @@ sys_call_table:
+ PTR sys_getresgid
+ PTR sys_prctl
+ PTR sys32_rt_sigreturn
+- PTR sys32_rt_sigaction
+- PTR sys32_rt_sigprocmask /* 4195 */
+- PTR sys32_rt_sigpending
++ PTR sys_32_rt_sigaction
++ PTR sys_32_rt_sigprocmask /* 4195 */
++ PTR sys_32_rt_sigpending
+ PTR compat_sys_rt_sigtimedwait
+- PTR sys32_rt_sigqueueinfo
++ PTR sys_32_rt_sigqueueinfo
+ PTR sys32_rt_sigsuspend
+- PTR sys32_pread /* 4200 */
+- PTR sys32_pwrite
++ PTR sys_32_pread /* 4200 */
++ PTR sys_32_pwrite
+ PTR sys_chown
+ PTR sys_getcwd
+ PTR sys_capget
+ PTR sys_capset /* 4205 */
+ PTR sys32_sigaltstack
+- PTR sys32_sendfile
++ PTR sys_32_sendfile
+ PTR sys_ni_syscall
+ PTR sys_ni_syscall
+- PTR sys32_mmap2 /* 4210 */
+- PTR sys32_truncate64
+- PTR sys32_ftruncate64
++ PTR sys_mips_mmap2 /* 4210 */
++ PTR sys_32_truncate64
++ PTR sys_32_ftruncate64
+ PTR sys_newstat
+ PTR sys_newlstat
+ PTR sys_newfstat /* 4215 */
+@@ -483,7 +483,7 @@ sys_call_table:
+ PTR compat_sys_mq_notify /* 4275 */
+ PTR compat_sys_mq_getsetattr
+ PTR sys_ni_syscall /* sys_vserver */
+- PTR sys32_waitid
++ PTR sys_32_waitid
+ PTR sys_ni_syscall /* available, was setaltroot */
+ PTR sys_add_key /* 4280 */
+ PTR sys_request_key
+--- a/arch/mips/kernel/signal32.c
++++ b/arch/mips/kernel/signal32.c
+@@ -349,8 +349,8 @@ asmlinkage int sys32_rt_sigsuspend(nabi_
+ return -ERESTARTNOHAND;
+ }
+
+-asmlinkage int sys32_sigaction(int sig, const struct sigaction32 __user *act,
+- struct sigaction32 __user *oact)
++SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act,
++ struct sigaction32 __user *, oact)
+ {
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+@@ -692,9 +692,9 @@ struct mips_abi mips_abi_32 = {
+ .restart = __NR_O32_restart_syscall
+ };
+
+-asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
+- struct sigaction32 __user *oact,
+- unsigned int sigsetsize)
++SYSCALL_DEFINE4(32_rt_sigaction, int, sig,
++ const struct sigaction32 __user *, act,
++ struct sigaction32 __user *, oact, unsigned int, sigsetsize)
+ {
+ struct k_sigaction new_sa, old_sa;
+ int ret = -EINVAL;
+@@ -736,8 +736,8 @@ out:
+ return ret;
+ }
+
+-asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
+- compat_sigset_t __user *oset, unsigned int sigsetsize)
++SYSCALL_DEFINE4(32_rt_sigprocmask, int, how, compat_sigset_t __user *, set,
++ compat_sigset_t __user *, oset, unsigned int, sigsetsize)
+ {
+ sigset_t old_set, new_set;
+ int ret;
+@@ -758,8 +758,8 @@ asmlinkage int sys32_rt_sigprocmask(int
+ return ret;
+ }
+
+-asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset,
+- unsigned int sigsetsize)
++SYSCALL_DEFINE2(32_rt_sigpending, compat_sigset_t __user *, uset,
++ unsigned int, sigsetsize)
+ {
+ int ret;
+ sigset_t set;
+@@ -775,7 +775,8 @@ asmlinkage int sys32_rt_sigpending(compa
+ return ret;
+ }
+
+-asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
++SYSCALL_DEFINE3(32_rt_sigqueueinfo, int, pid, int, sig,
++ compat_siginfo_t __user *, uinfo)
+ {
+ siginfo_t info;
+ int ret;
+@@ -790,10 +791,9 @@ asmlinkage int sys32_rt_sigqueueinfo(int
+ return ret;
+ }
+
+-asmlinkage long
+-sys32_waitid(int which, compat_pid_t pid,
+- compat_siginfo_t __user *uinfo, int options,
+- struct compat_rusage __user *uru)
++SYSCALL_DEFINE5(32_waitid, int, which, compat_pid_t, pid,
++ compat_siginfo_t __user *, uinfo, int, options,
++ struct compat_rusage __user *, uru)
+ {
+ siginfo_t info;
+ struct rusage ru;
+--- a/arch/mips/kernel/signal.c
++++ b/arch/mips/kernel/signal.c
+@@ -19,6 +19,7 @@
+ #include <linux/ptrace.h>
+ #include <linux/unistd.h>
+ #include <linux/compiler.h>
++#include <linux/syscalls.h>
+ #include <linux/uaccess.h>
+
+ #include <asm/abi.h>
+@@ -338,8 +339,8 @@ asmlinkage int sys_rt_sigsuspend(nabi_no
+ }
+
+ #ifdef CONFIG_TRAD_SIGNALS
+-asmlinkage int sys_sigaction(int sig, const struct sigaction __user *act,
+- struct sigaction __user *oact)
++SYSCALL_DEFINE3(sigaction, int, sig, const struct sigaction __user *, act,
++ struct sigaction __user *, oact)
+ {
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+--- a/arch/mips/kernel/syscall.c
++++ b/arch/mips/kernel/syscall.c
+@@ -153,9 +153,9 @@ out:
+ return error;
+ }
+
+-asmlinkage unsigned long
+-old_mmap(unsigned long addr, unsigned long len, int prot,
+- int flags, int fd, off_t offset)
++SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
++ unsigned long, prot, unsigned long, flags, unsigned long,
++ fd, off_t, offset)
+ {
+ unsigned long result;
+
+@@ -169,9 +169,9 @@ out:
+ return result;
+ }
+
+-asmlinkage unsigned long
+-sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+- unsigned long flags, unsigned long fd, unsigned long pgoff)
++SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
++ unsigned long, prot, unsigned long, flags, unsigned long, fd,
++ unsigned long, pgoff)
+ {
+ if (pgoff & (~PAGE_MASK >> 12))
+ return -EINVAL;
+@@ -241,7 +241,7 @@ out:
+ /*
+ * Compacrapability ...
+ */
+-asmlinkage int sys_uname(struct old_utsname __user * name)
++SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
+ {
+ if (name && !copy_to_user(name, utsname(), sizeof (*name)))
+ return 0;
+@@ -251,7 +251,7 @@ asmlinkage int sys_uname(struct old_utsn
+ /*
+ * Compacrapability ...
+ */
+-asmlinkage int sys_olduname(struct oldold_utsname __user * name)
++SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
+ {
+ int error;
+
+@@ -280,7 +280,7 @@ asmlinkage int sys_olduname(struct oldol
+ return error;
+ }
+
+-asmlinkage int sys_set_thread_area(unsigned long addr)
++SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
+ {
+ struct thread_info *ti = task_thread_info(current);
+
+@@ -291,7 +291,7 @@ asmlinkage int sys_set_thread_area(unsig
+ return 0;
+ }
+
+-asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
++asmlinkage int _sys_sysmips(long cmd, long arg1, long arg2, long arg3)
+ {
+ switch (cmd) {
+ case MIPS_ATOMIC_SET:
+@@ -326,8 +326,8 @@ asmlinkage int _sys_sysmips(int cmd, lon
+ *
+ * This is really horribly ugly.
+ */
+-asmlinkage int sys_ipc(unsigned int call, int first, int second,
+- unsigned long third, void __user *ptr, long fifth)
++SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, second,
++ unsigned long, third, void __user *, ptr, long, fifth)
+ {
+ int version, ret;
+
+@@ -412,7 +412,7 @@ asmlinkage int sys_ipc(unsigned int call
+ /*
+ * No implemented yet ...
+ */
+-asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
++SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op)
+ {
+ return -ENOSYS;
+ }
+--- a/arch/mips/mm/cache.c
++++ b/arch/mips/mm/cache.c
+@@ -13,6 +13,7 @@
+ #include <linux/linkage.h>
+ #include <linux/module.h>
+ #include <linux/sched.h>
++#include <linux/syscalls.h>
+ #include <linux/mm.h>
+
+ #include <asm/cacheflush.h>
+@@ -58,8 +59,8 @@ EXPORT_SYMBOL(_dma_cache_wback_inv);
+ * We could optimize the case where the cache argument is not BCACHE but
+ * that seems very atypical use ...
+ */
+-asmlinkage int sys_cacheflush(unsigned long addr,
+- unsigned long bytes, unsigned int cache)
++SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes,
++ unsigned int, cache)
+ {
+ if (bytes == 0)
+ return 0;
--- /dev/null
+From stern@rowland.harvard.edu Mon May 4 15:17:32 2009
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Mon, 4 May 2009 11:29:48 -0400 (EDT)
+Subject: USB: serial: fix lifetime and locking problems
+To: stable@kernel.org
+Message-ID: <Pine.LNX.4.44L0.0905041128001.6437-100000@iolanthe.rowland.org>
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+This is commit 2d93148ab6988cad872e65d694c95e8944e1b626 back-ported to
+2.6.27.
+
+This patch (as1229-1) fixes a few lifetime and locking problems in the
+usb-serial driver. The main symptom is that an invalid kevent is
+created when the serial device is unplugged while a connection is
+active.
+
+ Ports should be unregistered when device is disconnected,
+ not when the parent usb_serial structure is deallocated.
+
+ Each open file should hold a reference to the corresponding
+ port structure, and the reference should be released when
+ the file is closed.
+
+ serial->disc_mutex should be acquired in serial_open(), to
+ resolve the classic race between open and disconnect.
+
+ serial_close() doesn't need to hold both serial->disc_mutex
+ and port->mutex at the same time.
+
+ Release the subdriver's module reference only after releasing
+ all the other references, in case one of the release routines
+ needs to invoke some code in the subdriver module.
+
+ Replace a call to flush_scheduled_work() (which is prone to
+ deadlocks) with cancel_work_sync(). Also, add a call to
+ cancel_work_sync() in the disconnect routine.
+
+ Reduce the scope of serial->disc_mutex in serial_disconnect().
+ The only place it really needs to protect is where the
+ "disconnected" flag is set.
+
+ Call the shutdown method from within serial_disconnect()
+ instead of destroy_serial(), because some subdrivers expect
+ the port data structures still to be in existence when
+ their shutdown method runs.
+
+This fixes the bug reported in
+
+ http://bugs.freedesktop.org/show_bug.cgi?id=20703
+
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/usb-serial.c | 97 +++++++++++++++++++++++++++-------------
+ 1 file changed, 67 insertions(+), 30 deletions(-)
+
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -136,22 +136,10 @@ static void destroy_serial(struct kref *
+
+ dbg("%s - %s", __func__, serial->type->description);
+
+- serial->type->shutdown(serial);
+-
+ /* return the minor range that this device had */
+ if (serial->minor != SERIAL_TTY_NO_MINOR)
+ return_serial(serial);
+
+- for (i = 0; i < serial->num_ports; ++i)
+- serial->port[i]->port.count = 0;
+-
+- /* the ports are cleaned up and released in port_release() */
+- for (i = 0; i < serial->num_ports; ++i)
+- if (serial->port[i]->dev.parent != NULL) {
+- device_unregister(&serial->port[i]->dev);
+- serial->port[i] = NULL;
+- }
+-
+ /* If this is a "fake" port, we have to clean it up here, as it will
+ * not get cleaned up in port_release() as it was never registered with
+ * the driver core */
+@@ -186,7 +174,7 @@ static int serial_open (struct tty_struc
+ struct usb_serial *serial;
+ struct usb_serial_port *port;
+ unsigned int portNumber;
+- int retval;
++ int retval = 0;
+
+ dbg("%s", __func__);
+
+@@ -197,16 +185,24 @@ static int serial_open (struct tty_struc
+ return -ENODEV;
+ }
+
++ mutex_lock(&serial->disc_mutex);
+ portNumber = tty->index - serial->minor;
+ port = serial->port[portNumber];
+- if (!port) {
++ if (!port || serial->disconnected)
+ retval = -ENODEV;
+- goto bailout_kref_put;
+- }
++ else
++ get_device(&port->dev);
++ /*
++ * Note: Our locking order requirement does not allow port->mutex
++ * to be acquired while serial->disc_mutex is held.
++ */
++ mutex_unlock(&serial->disc_mutex);
++ if (retval)
++ goto bailout_serial_put;
+
+ if (mutex_lock_interruptible(&port->mutex)) {
+ retval = -ERESTARTSYS;
+- goto bailout_kref_put;
++ goto bailout_port_put;
+ }
+
+ ++port->port.count;
+@@ -226,14 +222,20 @@ static int serial_open (struct tty_struc
+ goto bailout_mutex_unlock;
+ }
+
+- retval = usb_autopm_get_interface(serial->interface);
++ mutex_lock(&serial->disc_mutex);
++ if (serial->disconnected)
++ retval = -ENODEV;
++ else
++ retval = usb_autopm_get_interface(serial->interface);
+ if (retval)
+ goto bailout_module_put;
++
+ /* only call the device specific open if this
+ * is the first time the port is opened */
+ retval = serial->type->open(tty, port, filp);
+ if (retval)
+ goto bailout_interface_put;
++ mutex_unlock(&serial->disc_mutex);
+ }
+
+ mutex_unlock(&port->mutex);
+@@ -242,13 +244,16 @@ static int serial_open (struct tty_struc
+ bailout_interface_put:
+ usb_autopm_put_interface(serial->interface);
+ bailout_module_put:
++ mutex_unlock(&serial->disc_mutex);
+ module_put(serial->type->driver.owner);
+ bailout_mutex_unlock:
+ port->port.count = 0;
+ tty->driver_data = NULL;
+ port->port.tty = NULL;
+ mutex_unlock(&port->mutex);
+-bailout_kref_put:
++bailout_port_put:
++ put_device(&port->dev);
++bailout_serial_put:
+ usb_serial_put(serial);
+ return retval;
+ }
+@@ -256,6 +261,9 @@ bailout_kref_put:
+ static void serial_close(struct tty_struct *tty, struct file *filp)
+ {
+ struct usb_serial_port *port = tty->driver_data;
++ struct usb_serial *serial;
++ struct module *owner;
++ int count;
+
+ if (!port)
+ return;
+@@ -263,6 +271,8 @@ static void serial_close(struct tty_stru
+ dbg("%s - port %d", __func__, port->number);
+
+ mutex_lock(&port->mutex);
++ serial = port->serial;
++ owner = serial->type->driver.owner;
+
+ if (port->port.count == 0) {
+ mutex_unlock(&port->mutex);
+@@ -273,7 +283,7 @@ static void serial_close(struct tty_stru
+ if (port->port.count == 0)
+ /* only call the device specific close if this
+ * port is being closed by the last owner */
+- port->serial->type->close(tty, port, filp);
++ serial->type->close(tty, port, filp);
+
+ if (port->port.count == (port->console? 1 : 0)) {
+ if (port->port.tty) {
+@@ -283,16 +293,22 @@ static void serial_close(struct tty_stru
+ }
+ }
+
+- if (port->port.count == 0) {
+- mutex_lock(&port->serial->disc_mutex);
+- if (!port->serial->disconnected)
+- usb_autopm_put_interface(port->serial->interface);
+- mutex_unlock(&port->serial->disc_mutex);
+- module_put(port->serial->type->driver.owner);
++ count = port->port.count;
++ mutex_unlock(&port->mutex);
++ put_device(&port->dev);
++
++ /* Mustn't dereference port any more */
++ if (count == 0) {
++ mutex_lock(&serial->disc_mutex);
++ if (!serial->disconnected)
++ usb_autopm_put_interface(serial->interface);
++ mutex_unlock(&serial->disc_mutex);
+ }
++ usb_serial_put(serial);
+
+- mutex_unlock(&port->mutex);
+- usb_serial_put(port->serial);
++ /* Mustn't dereference serial any more */
++ if (count == 0)
++ module_put(owner);
+ }
+
+ static int serial_write(struct tty_struct *tty, const unsigned char *buf,
+@@ -544,7 +560,13 @@ static void kill_traffic(struct usb_seri
+
+ static void port_free(struct usb_serial_port *port)
+ {
++ /*
++ * Stop all the traffic before cancelling the work, so that
++ * nobody will restart it by calling usb_serial_port_softint.
++ */
+ kill_traffic(port);
++ cancel_work_sync(&port->work);
++
+ usb_free_urb(port->read_urb);
+ usb_free_urb(port->write_urb);
+ usb_free_urb(port->interrupt_in_urb);
+@@ -553,7 +575,6 @@ static void port_free(struct usb_serial_
+ kfree(port->bulk_out_buffer);
+ kfree(port->interrupt_in_buffer);
+ kfree(port->interrupt_out_buffer);
+- flush_scheduled_work(); /* port->work */
+ kfree(port);
+ }
+
+@@ -1037,17 +1058,33 @@ void usb_serial_disconnect(struct usb_in
+ usb_set_intfdata(interface, NULL);
+ /* must set a flag, to signal subdrivers */
+ serial->disconnected = 1;
++ mutex_unlock(&serial->disc_mutex);
++
++ /* Unfortunately, many of the sub-drivers expect the port structures
++ * to exist when their shutdown method is called, so we have to go
++ * through this awkward two-step unregistration procedure.
++ */
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ if (port) {
+ if (port->port.tty)
+ tty_hangup(port->port.tty);
+ kill_traffic(port);
++ cancel_work_sync(&port->work);
++ device_del(&port->dev);
+ }
+ }
++ serial->type->shutdown(serial);
++ for (i = 0; i < serial->num_ports; ++i) {
++ port = serial->port[i];
++ if (port) {
++ put_device(&port->dev);
++ serial->port[i] = NULL;
++ }
++ }
++
+ /* let the last holder of this object
+ * cause it to be cleaned up */
+- mutex_unlock(&serial->disc_mutex);
+ usb_serial_put(serial);
+ dev_info(dev, "device disconnected\n");
+ }