--- /dev/null
+From 7f3dc0088b98533f17128058fac73cd8b2752ef1 Mon Sep 17 00:00:00 2001
+From: Todd Kjos <tkjos@android.com>
+Date: Mon, 27 Nov 2017 09:32:33 -0800
+Subject: binder: fix proc->files use-after-free
+
+From: Todd Kjos <tkjos@android.com>
+
+commit 7f3dc0088b98533f17128058fac73cd8b2752ef1 upstream.
+
+proc->files cleanup is initiated by binder_vma_close. Therefore
+a reference on the binder_proc is not enough to prevent the
+files_struct from being released while the binder_proc still has
+a reference. This can lead to an attempt to dereference the
+stale pointer obtained from proc->files prior to proc->files
+cleanup. This has been seen once in task_get_unused_fd_flags()
+when __alloc_fd() is called with a stale "files".
+
+The fix is to protect proc->files with a mutex to prevent cleanup
+while in use.
+
+Signed-off-by: Todd Kjos <tkjos@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/android/binder.c | 41 +++++++++++++++++++++++++++++------------
+ 1 file changed, 29 insertions(+), 12 deletions(-)
+
+--- a/drivers/android/binder.c
++++ b/drivers/android/binder.c
+@@ -302,6 +302,7 @@ struct binder_proc {
+ struct mm_struct *vma_vm_mm;
+ struct task_struct *tsk;
+ struct files_struct *files;
++ struct mutex files_lock;
+ struct hlist_node deferred_work_node;
+ int deferred_work;
+ void *buffer;
+@@ -375,20 +376,26 @@ binder_defer_work(struct binder_proc *pr
+
+ static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
+ {
+- struct files_struct *files = proc->files;
+ unsigned long rlim_cur;
+ unsigned long irqs;
++ int ret;
+
+- if (files == NULL)
+- return -ESRCH;
+-
+- if (!lock_task_sighand(proc->tsk, &irqs))
+- return -EMFILE;
+-
++ mutex_lock(&proc->files_lock);
++ if (proc->files == NULL) {
++ ret = -ESRCH;
++ goto err;
++ }
++ if (!lock_task_sighand(proc->tsk, &irqs)) {
++ ret = -EMFILE;
++ goto err;
++ }
+ rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
+ unlock_task_sighand(proc->tsk, &irqs);
+
+- return __alloc_fd(files, 0, rlim_cur, flags);
++ ret = __alloc_fd(proc->files, 0, rlim_cur, flags);
++err:
++ mutex_unlock(&proc->files_lock);
++ return ret;
+ }
+
+ /*
+@@ -397,8 +404,10 @@ static int task_get_unused_fd_flags(stru
+ static void task_fd_install(
+ struct binder_proc *proc, unsigned int fd, struct file *file)
+ {
++ mutex_lock(&proc->files_lock);
+ if (proc->files)
+ __fd_install(proc->files, fd, file);
++ mutex_unlock(&proc->files_lock);
+ }
+
+ /*
+@@ -408,9 +417,11 @@ static long task_close_fd(struct binder_
+ {
+ int retval;
+
+- if (proc->files == NULL)
+- return -ESRCH;
+-
++ mutex_lock(&proc->files_lock);
++ if (proc->files == NULL) {
++ retval = -ESRCH;
++ goto err;
++ }
+ retval = __close_fd(proc->files, fd);
+ /* can't restart close syscall because file table entry was cleared */
+ if (unlikely(retval == -ERESTARTSYS ||
+@@ -418,7 +429,8 @@ static long task_close_fd(struct binder_
+ retval == -ERESTARTNOHAND ||
+ retval == -ERESTART_RESTARTBLOCK))
+ retval = -EINTR;
+-
++err:
++ mutex_unlock(&proc->files_lock);
+ return retval;
+ }
+
+@@ -2946,7 +2958,9 @@ static int binder_mmap(struct file *filp
+ binder_insert_free_buffer(proc, buffer);
+ proc->free_async_space = proc->buffer_size / 2;
+ barrier();
++ mutex_lock(&proc->files_lock);
+ proc->files = get_files_struct(current);
++ mutex_unlock(&proc->files_lock);
+ proc->vma = vma;
+ proc->vma_vm_mm = vma->vm_mm;
+
+@@ -2982,6 +2996,7 @@ static int binder_open(struct inode *nod
+ return -ENOMEM;
+ get_task_struct(current->group_leader);
+ proc->tsk = current->group_leader;
++ mutex_init(&proc->files_lock);
+ INIT_LIST_HEAD(&proc->todo);
+ init_waitqueue_head(&proc->wait);
+ proc->default_priority = task_nice(current);
+@@ -3220,9 +3235,11 @@ static void binder_deferred_func(struct
+
+ files = NULL;
+ if (defer & BINDER_DEFERRED_PUT_FILES) {
++ mutex_lock(&proc->files_lock);
+ files = proc->files;
+ if (files)
+ proc->files = NULL;
++ mutex_unlock(&proc->files_lock);
+ }
+
+ if (defer & BINDER_DEFERRED_FLUSH)