Skip to content

Commit 7f3dc00

Browse files
Todd Kjosgregkh
authored andcommitted
binder: fix proc->files use-after-free
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> Cc: stable <stable@vger.kernel.org> # 4.14 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 869b556 commit 7f3dc00

File tree

1 file changed

+31
-13
lines changed

1 file changed

+31
-13
lines changed

drivers/android/binder.c

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,8 @@ enum binder_deferred_state {
482482
* @tsk task_struct for group_leader of process
483483
* (invariant after initialized)
484484
* @files files_struct for process
485-
* (invariant after initialized)
485+
* (protected by @files_lock)
486+
* @files_lock mutex to protect @files
486487
* @deferred_work_node: element for binder_deferred_list
487488
* (protected by binder_deferred_lock)
488489
* @deferred_work: bitmap of deferred work to perform
@@ -530,6 +531,7 @@ struct binder_proc {
530531
int pid;
531532
struct task_struct *tsk;
532533
struct files_struct *files;
534+
struct mutex files_lock;
533535
struct hlist_node deferred_work_node;
534536
int deferred_work;
535537
bool is_dead;
@@ -877,20 +879,26 @@ static void binder_inc_node_tmpref_ilocked(struct binder_node *node);
877879

878880
static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
879881
{
880-
struct files_struct *files = proc->files;
881882
unsigned long rlim_cur;
882883
unsigned long irqs;
884+
int ret;
883885

884-
if (files == NULL)
885-
return -ESRCH;
886-
887-
if (!lock_task_sighand(proc->tsk, &irqs))
888-
return -EMFILE;
889-
886+
mutex_lock(&proc->files_lock);
887+
if (proc->files == NULL) {
888+
ret = -ESRCH;
889+
goto err;
890+
}
891+
if (!lock_task_sighand(proc->tsk, &irqs)) {
892+
ret = -EMFILE;
893+
goto err;
894+
}
890895
rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
891896
unlock_task_sighand(proc->tsk, &irqs);
892897

893-
return __alloc_fd(files, 0, rlim_cur, flags);
898+
ret = __alloc_fd(proc->files, 0, rlim_cur, flags);
899+
err:
900+
mutex_unlock(&proc->files_lock);
901+
return ret;
894902
}
895903

896904
/*
@@ -899,8 +907,10 @@ static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
899907
static void task_fd_install(
900908
struct binder_proc *proc, unsigned int fd, struct file *file)
901909
{
910+
mutex_lock(&proc->files_lock);
902911
if (proc->files)
903912
__fd_install(proc->files, fd, file);
913+
mutex_unlock(&proc->files_lock);
904914
}
905915

906916
/*
@@ -910,17 +920,20 @@ static long task_close_fd(struct binder_proc *proc, unsigned int fd)
910920
{
911921
int retval;
912922

913-
if (proc->files == NULL)
914-
return -ESRCH;
915-
923+
mutex_lock(&proc->files_lock);
924+
if (proc->files == NULL) {
925+
retval = -ESRCH;
926+
goto err;
927+
}
916928
retval = __close_fd(proc->files, fd);
917929
/* can't restart close syscall because file table entry was cleared */
918930
if (unlikely(retval == -ERESTARTSYS ||
919931
retval == -ERESTARTNOINTR ||
920932
retval == -ERESTARTNOHAND ||
921933
retval == -ERESTART_RESTARTBLOCK))
922934
retval = -EINTR;
923-
935+
err:
936+
mutex_unlock(&proc->files_lock);
924937
return retval;
925938
}
926939

@@ -4627,7 +4640,9 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
46274640
ret = binder_alloc_mmap_handler(&proc->alloc, vma);
46284641
if (ret)
46294642
return ret;
4643+
mutex_lock(&proc->files_lock);
46304644
proc->files = get_files_struct(current);
4645+
mutex_unlock(&proc->files_lock);
46314646
return 0;
46324647

46334648
err_bad_arg:
@@ -4651,6 +4666,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
46514666
spin_lock_init(&proc->outer_lock);
46524667
get_task_struct(current->group_leader);
46534668
proc->tsk = current->group_leader;
4669+
mutex_init(&proc->files_lock);
46544670
INIT_LIST_HEAD(&proc->todo);
46554671
proc->default_priority = task_nice(current);
46564672
binder_dev = container_of(filp->private_data, struct binder_device,
@@ -4903,9 +4919,11 @@ static void binder_deferred_func(struct work_struct *work)
49034919

49044920
files = NULL;
49054921
if (defer & BINDER_DEFERRED_PUT_FILES) {
4922+
mutex_lock(&proc->files_lock);
49064923
files = proc->files;
49074924
if (files)
49084925
proc->files = NULL;
4926+
mutex_unlock(&proc->files_lock);
49094927
}
49104928

49114929
if (defer & BINDER_DEFERRED_FLUSH)

0 commit comments

Comments
 (0)