--- /dev/null
+From b582ef5c53040c5feef4c96a8f9585b6831e2441 Mon Sep 17 00:00:00 2001
+From: "Maciej W. Rozycki" <macro@imgtec.com>
+Date: Mon, 26 Oct 2015 15:48:19 +0000
+Subject: binfmt_elf: Don't clobber passed executable's file header
+
+From: Maciej W. Rozycki <macro@imgtec.com>
+
+commit b582ef5c53040c5feef4c96a8f9585b6831e2441 upstream.
+
+Do not clobber the buffer space passed from `search_binary_handler' and
+originally preloaded by `prepare_binprm' with the executable's file
+header by overwriting it with its interpreter's file header. Instead
+keep the buffer space intact and directly use the data structure locally
+allocated for the interpreter's file header, fixing a bug introduced in
+2.1.14 with loadable module support (linux-mips.org commit beb11695
+[Import of Linux/MIPS 2.1.14], predating kernel.org repo's history).
+Adjust the amount of data read from the interpreter's file accordingly.
+
+This was not an issue before loadable module support, because back then
+`load_elf_binary' was executed only once for a given ELF executable,
+whether the function succeeded or failed.
+
+With loadable module support supported and enabled, upon a failure of
+`load_elf_binary' -- which may for example be caused by architecture
+code rejecting an executable due to a missing hardware feature requested
+in the file header -- a module load is attempted and then the function
+reexecuted by `search_binary_handler'. With the executable's file
+header replaced with its interpreter's file header the executable can
+then be erroneously accepted in this subsequent attempt.
+
+Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/binfmt_elf.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/fs/binfmt_elf.c
++++ b/fs/binfmt_elf.c
+@@ -759,16 +759,16 @@ static int load_elf_binary(struct linux_
+ */
+ would_dump(bprm, interpreter);
+
+- retval = kernel_read(interpreter, 0, bprm->buf,
+- BINPRM_BUF_SIZE);
+- if (retval != BINPRM_BUF_SIZE) {
++ /* Get the exec headers */
++ retval = kernel_read(interpreter, 0,
++ (void *)&loc->interp_elf_ex,
++ sizeof(loc->interp_elf_ex));
++ if (retval != sizeof(loc->interp_elf_ex)) {
+ if (retval >= 0)
+ retval = -EIO;
+ goto out_free_dentry;
+ }
+
+- /* Get the exec headers */
+- loc->interp_elf_ex = *((struct elfhdr *)bprm->buf);
+ break;
+ }
+ elf_ppnt++;
--- /dev/null
+From 6ae08069939f17422835448acae76bda8d96b16a Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers3@gmail.com>
+Date: Sat, 17 Oct 2015 16:26:09 -0500
+Subject: fs/pipe.c: return error code rather than 0 in pipe_write()
+
+From: Eric Biggers <ebiggers3@gmail.com>
+
+commit 6ae08069939f17422835448acae76bda8d96b16a upstream.
+
+pipe_write() would return 0 if it failed to merge the beginning of the
+data to write with the last, partially filled pipe buffer. It should
+return an error code instead. Userspace programs could be confused by
+write() returning 0 when called with a nonzero 'count'.
+
+The EFAULT error case was a regression from f0d1bec9d5 ("new helper:
+copy_page_from_iter()"), while the ops->confirm() error case was a much
+older bug.
+
+Test program:
+
+ #include <assert.h>
+ #include <errno.h>
+ #include <unistd.h>
+
+ int main(void)
+ {
+ int fd[2];
+ char data[1] = {0};
+
+ assert(0 == pipe(fd));
+ assert(1 == write(fd[1], data, 1));
+
+ /* prior to this patch, write() returned 0 here */
+ assert(-1 == write(fd[1], NULL, 1));
+ assert(errno == EFAULT);
+ }
+
+Signed-off-by: Eric Biggers <ebiggers3@gmail.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/pipe.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+--- a/fs/pipe.c
++++ b/fs/pipe.c
+@@ -366,18 +366,17 @@ pipe_write(struct kiocb *iocb, struct io
+ int offset = buf->offset + buf->len;
+
+ if (ops->can_merge && offset + chars <= PAGE_SIZE) {
+- int error = ops->confirm(pipe, buf);
+- if (error)
++ ret = ops->confirm(pipe, buf);
++ if (ret)
+ goto out;
+
+ ret = copy_page_from_iter(buf->page, offset, chars, from);
+ if (unlikely(ret < chars)) {
+- error = -EFAULT;
++ ret = -EFAULT;
+ goto out;
+ }
+ do_wakeup = 1;
+- buf->len += chars;
+- ret = chars;
++ buf->len += ret;
+ if (!iov_iter_count(from))
+ goto out;
+ }