--- /dev/null
+From stable-bounces@linux.kernel.org Thu Nov 2 19:46:17 2006
+Date: Fri, 3 Nov 2006 14:42:43 +1100
+From: Stephen Rothwell <sfr@canb.auug.org.au>
+To: Christoph Lameter <clameter@sgi.com>
+Message-Id: <20061103144243.4601ba76.sfr@canb.auug.org.au>
+Cc: Andrew Morton <akpm@osdl.org>, linux-mm@kvack.org, LKML <linux-kernel@vger.kernel.org>, stable@kernel.org
+Subject: Fix sys_move_pages when a NULL node list is passed.
+
+sys_move_pages() uses vmalloc() to allocate an array of structures
+that is fills with information passed from user mode and then passes to
+do_stat_pages() (in the case the node list is NULL). do_stat_pages()
+depends on a marker in the node field of the structure to decide how large
+the array is and this marker is correctly inserted into the last element
+of the array. However, vmalloc() doesn't zero the memory it allocates
+and if the user passes NULL for the node list, then the node fields are
+not filled in (except for the end marker). If the memory the vmalloc()
+returned happend to have a word with the marker value in it in just the
+right place, do_pages_stat will fail to fill the status field of part
+of the array and we will return (random) kernel data to user mode.
+
+Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
+Acked-by: Christoph Lameter <clameter@sgi.com>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+ mm/migrate.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- linux-2.6.18.2.orig/mm/migrate.c
++++ linux-2.6.18.2/mm/migrate.c
+@@ -950,7 +950,8 @@ asmlinkage long sys_move_pages(pid_t pid
+ goto out;
+
+ pm[i].node = node;
+- }
++ } else
++ pm[i].node = 0; /* anything to not match MAX_NUMNODES */
+ }
+ /* End marker */
+ pm[nr_pages].node = MAX_NUMNODES;
--- /dev/null
+From 4393c4f6788cee65095dd838cfeca6edefbfeb52 Mon Sep 17 00:00:00 2001
+From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Message-Id: <1162416427.25682.429.camel@localhost.localdomain>
+Date: Wed, 1 Nov 2006 15:11:39 +1100
+Subject: POWERPC: Make alignment exception always check exception table
+
+The alignment exception used to only check the exception table for
+-EFAULT, not for other errors. That opens an oops window if we can
+coerce the kernel into getting an alignment exception for other reasons
+in what would normally be a user-protected accessor, which can be done
+via some of the futex ops. This fixes it by always checking the
+exception tables.
+
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Paul Mackerras <paulus@samba.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+ arch/powerpc/kernel/traps.c | 18 ++++++++++--------
+ arch/ppc/kernel/traps.c | 18 ++++++++++--------
+ 2 files changed, 20 insertions(+), 16 deletions(-)
+
+--- linux-2.6.18.2.orig/arch/powerpc/kernel/traps.c
++++ linux-2.6.18.2/arch/powerpc/kernel/traps.c
+@@ -818,7 +818,7 @@ void __kprobes program_check_exception(s
+
+ void alignment_exception(struct pt_regs *regs)
+ {
+- int fixed = 0;
++ int sig, code, fixed = 0;
+
+ /* we don't implement logging of alignment exceptions */
+ if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
+@@ -832,14 +832,16 @@ void alignment_exception(struct pt_regs
+
+ /* Operand address was bad */
+ if (fixed == -EFAULT) {
+- if (user_mode(regs))
+- _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar);
+- else
+- /* Search exception table */
+- bad_page_fault(regs, regs->dar, SIGSEGV);
+- return;
++ sig = SIGSEGV;
++ code = SEGV_ACCERR;
++ } else {
++ sig = SIGBUS;
++ code = BUS_ADRALN;
+ }
+- _exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
++ if (user_mode(regs))
++ _exception(sig, regs, code, regs->dar);
++ else
++ bad_page_fault(regs, regs->dar, sig);
+ }
+
+ void StackOverflow(struct pt_regs *regs)
+--- linux-2.6.18.2.orig/arch/ppc/kernel/traps.c
++++ linux-2.6.18.2/arch/ppc/kernel/traps.c
+@@ -708,7 +708,7 @@ void single_step_exception(struct pt_reg
+
+ void alignment_exception(struct pt_regs *regs)
+ {
+- int fixed;
++ int sig, code, fixed = 0;
+
+ fixed = fix_alignment(regs);
+ if (fixed == 1) {
+@@ -717,14 +717,16 @@ void alignment_exception(struct pt_regs
+ return;
+ }
+ if (fixed == -EFAULT) {
+- /* fixed == -EFAULT means the operand address was bad */
+- if (user_mode(regs))
+- _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar);
+- else
+- bad_page_fault(regs, regs->dar, SIGSEGV);
+- return;
++ sig = SIGSEGV;
++ code = SEGV_ACCERR;
++ } else {
++ sig = SIGBUS;
++ code = BUS_ADRALN;
+ }
+- _exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
++ if (user_mode(regs))
++ _exception(sig, regs, code, regs->dar);
++ else
++ bad_page_fault(regs, regs->dar, sig);
+ }
+
+ void StackOverflow(struct pt_regs *regs)
--- /dev/null
+From schwidefsky@de.ibm.com Fri Nov 3 06:46:40 2006
+Date: Fri, 03 Nov 2006 15:43:36 +0100
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-Id: <1162565016.7416.7.camel@localhost>
+To: chrisw@sous-sol.org
+Cc: greg@kroah.com, stable@kernel.org
+Subject: S390: user readable uninitialised kernel memory, take 2.
+
+The previous patch to correct the copy_from_user padding is quite
+broken. The execute instruction needs to be done via the register %r4,
+not via %r2 and 31 bit doesn't know the instructions lgr and ahji.
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+ arch/s390/lib/uaccess.S | 10 +++++-----
+ arch/s390/lib/uaccess64.S | 2 +-
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+--- linux-2.6.18.2.orig/arch/s390/lib/uaccess64.S
++++ linux-2.6.18.2/arch/s390/lib/uaccess64.S
+@@ -49,7 +49,7 @@ __copy_from_user_asm:
+ la %r2,256(%r2)
+ 8: aghi %r5,-256
+ jnm 7b
+- ex %r5,0(%r2)
++ ex %r5,0(%r4)
+ 9: lgr %r2,%r3
+ br %r14
+ .section __ex_table,"a"
+--- linux-2.6.18.2.orig/arch/s390/lib/uaccess.S
++++ linux-2.6.18.2/arch/s390/lib/uaccess.S
+@@ -41,15 +41,15 @@ __copy_from_user_asm:
+ 5: mvcp 0(%r5,%r2),0(%r4),%r0
+ slr %r3,%r5
+ alr %r2,%r5
+-6: lgr %r5,%r3 # copy remaining size
++6: lr %r5,%r3 # copy remaining size
+ ahi %r5,-1 # subtract 1 for xc loop
+ bras %r4,8f
+- xc 0(1,%2),0(%2)
+-7: xc 0(256,%2),0(%2)
++ xc 0(1,%r2),0(%r2)
++7: xc 0(256,%r2),0(%r2)
+ la %r2,256(%r2)
+-8: ahji %r5,-256
++8: ahi %r5,-256
+ jnm 7b
+- ex %r5,0(%r2)
++ ex %r5,0(%r4)
+ 9: lr %r2,%r3
+ br %r14
+ .section __ex_table,"a"
--- /dev/null
+s390-user-readable-uninitialised-kernel-memory-take-2.patch
+make-alignment-exception-always-check-exception-table.patch
+sparc64-fix-futex_atomic_cmpxchg_inatomic-implementation.patch
+fix-sys_move_pages-when-a-null-node-list-is-passed.patch
+splice-fix-problem-introduced-with-inode-diet.patch
--- /dev/null
+From stable-bounces@linux.kernel.org Wed Nov 1 21:58:18 2006
+Date: Wed, 01 Nov 2006 21:55:00 -0800 (PST)
+Message-Id: <20061101.215500.63127619.davem@davemloft.net>
+To: stable@kernel.org
+From: David Miller <davem@davemloft.net>
+Subject: SPARC64: Fix futex_atomic_cmpxchg_inatomic implementation.
+
+I copied the logic from ll/sc arch implementations, but that
+was wrong and makes no sense at all. Just do a straight
+compare-exchange instruction, just like x86.
+
+Based upon bug reports from Dennis Gilmore and Fabio Massimo.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+---
+ include/asm-sparc64/futex.h | 18 ++++++++----------
+ 1 file changed, 8 insertions(+), 10 deletions(-)
+
+--- linux-2.6.18.2.orig/include/asm-sparc64/futex.h
++++ linux-2.6.18.2/include/asm-sparc64/futex.h
+@@ -87,24 +87,22 @@ static inline int
+ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+ {
+ __asm__ __volatile__(
+- "\n1: lduwa [%2] %%asi, %0\n"
+- "2: casa [%2] %%asi, %0, %1\n"
+- "3:\n"
++ "\n1: casa [%3] %%asi, %2, %0\n"
++ "2:\n"
+ " .section .fixup,#alloc,#execinstr\n"
+ " .align 4\n"
+- "4: ba 3b\n"
+- " mov %3, %0\n"
++ "3: ba 2b\n"
++ " mov %4, %0\n"
+ " .previous\n"
+ " .section __ex_table,\"a\"\n"
+ " .align 4\n"
+- " .word 1b, 4b\n"
+- " .word 2b, 4b\n"
++ " .word 1b, 3b\n"
+ " .previous\n"
+- : "=&r" (oldval)
+- : "r" (newval), "r" (uaddr), "i" (-EFAULT)
++ : "=r" (newval)
++ : "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
+ : "memory");
+
+- return oldval;
++ return newval;
+ }
+
+ #endif /* !(_SPARC64_FUTEX_H) */
--- /dev/null
+From stable-bounces@linux.kernel.org Sun Nov 5 03:41:17 2006
+Date: Sun, 5 Nov 2006 12:39:51 +0100
+From: Jens Axboe <jens.axboe@oracle.com>
+To: stable@kernel.org
+Subject: splice: fix problem introduced with inode diet
+
+After the inode slimming patch that unionised i_pipe/i_bdev/i_cdev, it's
+no longer enough to check for existance of ->i_pipe to verify that this
+is a pipe.
+
+Original patch from Eric Dumazet <dada1@cosmosbay.com>
+Final solution suggested by Linus.
+
+Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
+Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ fs/splice.c | 26 ++++++++++++++++++++------
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+--- linux-2.6.18.2.orig/fs/splice.c
++++ linux-2.6.18.2/fs/splice.c
+@@ -1042,6 +1042,19 @@ out_release:
+ EXPORT_SYMBOL(do_splice_direct);
+
+ /*
++ * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
++ * location, so checking ->i_pipe is not enough to verify that this is a
++ * pipe.
++ */
++static inline struct pipe_inode_info *pipe_info(struct inode *inode)
++{
++ if (S_ISFIFO(inode->i_mode))
++ return inode->i_pipe;
++
++ return NULL;
++}
++
++/*
+ * Determine where to splice to/from.
+ */
+ static long do_splice(struct file *in, loff_t __user *off_in,
+@@ -1052,7 +1065,7 @@ static long do_splice(struct file *in, l
+ loff_t offset, *off;
+ long ret;
+
+- pipe = in->f_dentry->d_inode->i_pipe;
++ pipe = pipe_info(in->f_dentry->d_inode);
+ if (pipe) {
+ if (off_in)
+ return -ESPIPE;
+@@ -1073,7 +1086,7 @@ static long do_splice(struct file *in, l
+ return ret;
+ }
+
+- pipe = out->f_dentry->d_inode->i_pipe;
++ pipe = pipe_info(out->f_dentry->d_inode);
+ if (pipe) {
+ if (off_out)
+ return -ESPIPE;
+@@ -1231,7 +1244,7 @@ static int get_iovec_page_array(const st
+ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
+ unsigned long nr_segs, unsigned int flags)
+ {
+- struct pipe_inode_info *pipe = file->f_dentry->d_inode->i_pipe;
++ struct pipe_inode_info *pipe;
+ struct page *pages[PIPE_BUFFERS];
+ struct partial_page partial[PIPE_BUFFERS];
+ struct splice_pipe_desc spd = {
+@@ -1241,7 +1254,8 @@ static long do_vmsplice(struct file *fil
+ .ops = &user_page_pipe_buf_ops,
+ };
+
+- if (unlikely(!pipe))
++ pipe = pipe_info(file->f_dentry->d_inode);
++ if (!pipe)
+ return -EBADF;
+ if (unlikely(nr_segs > UIO_MAXIOV))
+ return -EINVAL;
+@@ -1475,8 +1489,8 @@ static int link_pipe(struct pipe_inode_i
+ static long do_tee(struct file *in, struct file *out, size_t len,
+ unsigned int flags)
+ {
+- struct pipe_inode_info *ipipe = in->f_dentry->d_inode->i_pipe;
+- struct pipe_inode_info *opipe = out->f_dentry->d_inode->i_pipe;
++ struct pipe_inode_info *ipipe = pipe_info(in->f_dentry->d_inode);
++ struct pipe_inode_info *opipe = pipe_info(out->f_dentry->d_inode);
+ int ret = -EINVAL;
+
+ /*