]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 6 Dec 2018 10:28:07 +0000 (11:28 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 6 Dec 2018 10:28:07 +0000 (11:28 +0100)
added patches:
binder-fix-proc-files-use-after-free.patch

queue-4.9/binder-fix-proc-files-use-after-free.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/binder-fix-proc-files-use-after-free.patch b/queue-4.9/binder-fix-proc-files-use-after-free.patch
new file mode 100644 (file)
index 0000000..8d3c75e
--- /dev/null
@@ -0,0 +1,138 @@
+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)
index fee9d9c5945bec881838520a6af5f57eeb6931a0..8bb8fb948a3640183e92c7ec80b46ddf8d0356cc 100644 (file)
@@ -21,3 +21,4 @@ scsi-scsi_devinfo-cleanly-zero-pad-devinfo-strings.patch
 alsa-trident-suppress-gcc-string-warning.patch
 scsi-csiostor-avoid-content-leaks-and-casts.patch
 kgdboc-fix-restrict-error.patch
+binder-fix-proc-files-use-after-free.patch