Patch "binder: fix proc->files use-after-free" has been added to the 4.14-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
binder: fix proc->files use-after-free
to the 4.14-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
binder-fix-proc-files-use-after-free.patch
and it can be found in the queue-4.14 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
7f3dc0088b98533f17128058fac73cd8b2752ef1Mon Sep 17 00:00:00 2001
From: Todd Kjos <[email protected]>
Date: Mon, 27 Nov 2017 09:32:33 -0800
Subject: binder: fix proc->files use-after-free
From: Todd Kjos <[email protected]>
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.
--- drivers/android/binder.c | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-)
drivers/android/binder.c +31 -13
@@ -482,7 +482,8 @@ enum binder_deferred_state {* @tsk task_struct for group_leader of process * (invariant after initialized) * @files files_struct for process -* (invariant after initialized) +* (protected by @files_lock) +* @files_lock mutex to protect @files * @deferred_work_node: element for binder_deferred_list * (protected by binder_deferred_lock) * @deferred_work: bitmap of deferred work to perform
@@ -530,6 +531,7 @@ struct binder_proc {int pid;struct task_struct *tsk;struct files_struct *files; +struct mutex files_lock;struct hlist_node deferred_work_node;int deferred_work;bool is_dead;
@@ -877,20 +879,26 @@ static void binder_inc_node_tmpref_ilockstatic 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; }/*
@@ -899,8 +907,10 @@ static int task_get_unused_fd_flags(strustatic 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); }/*
@@ -910,9 +920,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 ||
@@ -920,7 +932,8 @@ static long task_close_fd(struct binder_ retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK)) retval = -EINTR ; - +err: +mutex_unlock (&proc->files_lock);return retval; }
@@ -4627,7 +4640,9 @@ static int binder_mmap(struct file *filp ret =binder_alloc_mmap_handler (&proc->alloc, vma);if (ret)return ret; +mutex_lock (&proc->files_lock); proc->files =get_files_struct (current); +mutex_unlock (&proc->files_lock);return 0 ; err_bad_arg:
@@ -4651,6 +4666,7 @@ static int binder_open(struct inode *nodspin_lock_init (&proc->outer_lock);get_task_struct (current->group_leader); proc->tsk = current->group_leader; +mutex_init (&proc->files_lock);INIT_LIST_HEAD (&proc->todo); proc->default_priority =task_nice (current); binder_dev = container_of(filp->private_data, struct binder_device,
@@ -4903,9 +4919,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 )
Patches currently in stable-queue which might be from [email protected] are
queue-4.14/binder-fix-proc-files-use-after-free.patch