diff options
Diffstat (limited to 'drivers/android')
| -rw-r--r-- | drivers/android/binder.c | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index bccec9de0533..a7ecfde66b7b 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c | |||
| @@ -482,7 +482,8 @@ enum binder_deferred_state { | |||
| 482 | * @tsk task_struct for group_leader of process | 482 | * @tsk task_struct for group_leader of process |
| 483 | * (invariant after initialized) | 483 | * (invariant after initialized) |
| 484 | * @files files_struct for process | 484 | * @files files_struct for process |
| 485 | * (invariant after initialized) | 485 | * (protected by @files_lock) |
| 486 | * @files_lock mutex to protect @files | ||
| 486 | * @deferred_work_node: element for binder_deferred_list | 487 | * @deferred_work_node: element for binder_deferred_list |
| 487 | * (protected by binder_deferred_lock) | 488 | * (protected by binder_deferred_lock) |
| 488 | * @deferred_work: bitmap of deferred work to perform | 489 | * @deferred_work: bitmap of deferred work to perform |
| @@ -530,6 +531,7 @@ struct binder_proc { | |||
| 530 | int pid; | 531 | int pid; |
| 531 | struct task_struct *tsk; | 532 | struct task_struct *tsk; |
| 532 | struct files_struct *files; | 533 | struct files_struct *files; |
| 534 | struct mutex files_lock; | ||
| 533 | struct hlist_node deferred_work_node; | 535 | struct hlist_node deferred_work_node; |
| 534 | int deferred_work; | 536 | int deferred_work; |
| 535 | bool is_dead; | 537 | bool is_dead; |
| @@ -877,20 +879,26 @@ static void binder_inc_node_tmpref_ilocked(struct binder_node *node); | |||
| 877 | 879 | ||
| 878 | static int task_get_unused_fd_flags(struct binder_proc *proc, int flags) | 880 | static int task_get_unused_fd_flags(struct binder_proc *proc, int flags) |
| 879 | { | 881 | { |
| 880 | struct files_struct *files = proc->files; | ||
| 881 | unsigned long rlim_cur; | 882 | unsigned long rlim_cur; |
| 882 | unsigned long irqs; | 883 | unsigned long irqs; |
| 884 | int ret; | ||
| 883 | 885 | ||
| 884 | if (files == NULL) | 886 | mutex_lock(&proc->files_lock); |
| 885 | return -ESRCH; | 887 | if (proc->files == NULL) { |
| 886 | 888 | ret = -ESRCH; | |
| 887 | if (!lock_task_sighand(proc->tsk, &irqs)) | 889 | goto err; |
| 888 | return -EMFILE; | 890 | } |
| 889 | 891 | if (!lock_task_sighand(proc->tsk, &irqs)) { | |
| 892 | ret = -EMFILE; | ||
| 893 | goto err; | ||
| 894 | } | ||
| 890 | rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE); | 895 | rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE); |
| 891 | unlock_task_sighand(proc->tsk, &irqs); | 896 | unlock_task_sighand(proc->tsk, &irqs); |
| 892 | 897 | ||
| 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; | ||
| 894 | } | 902 | } |
| 895 | 903 | ||
| 896 | /* | 904 | /* |
| @@ -899,8 +907,10 @@ static int task_get_unused_fd_flags(struct binder_proc *proc, int flags) | |||
| 899 | static void task_fd_install( | 907 | static void task_fd_install( |
| 900 | struct binder_proc *proc, unsigned int fd, struct file *file) | 908 | struct binder_proc *proc, unsigned int fd, struct file *file) |
| 901 | { | 909 | { |
| 910 | mutex_lock(&proc->files_lock); | ||
| 902 | if (proc->files) | 911 | if (proc->files) |
| 903 | __fd_install(proc->files, fd, file); | 912 | __fd_install(proc->files, fd, file); |
| 913 | mutex_unlock(&proc->files_lock); | ||
| 904 | } | 914 | } |
| 905 | 915 | ||
| 906 | /* | 916 | /* |
| @@ -910,9 +920,11 @@ static long task_close_fd(struct binder_proc *proc, unsigned int fd) | |||
| 910 | { | 920 | { |
| 911 | int retval; | 921 | int retval; |
| 912 | 922 | ||
| 913 | if (proc->files == NULL) | 923 | mutex_lock(&proc->files_lock); |
| 914 | return -ESRCH; | 924 | if (proc->files == NULL) { |
| 915 | 925 | retval = -ESRCH; | |
| 926 | goto err; | ||
| 927 | } | ||
| 916 | retval = __close_fd(proc->files, fd); | 928 | retval = __close_fd(proc->files, fd); |
| 917 | /* can't restart close syscall because file table entry was cleared */ | 929 | /* can't restart close syscall because file table entry was cleared */ |
| 918 | if (unlikely(retval == -ERESTARTSYS || | 930 | if (unlikely(retval == -ERESTARTSYS || |
| @@ -920,7 +932,8 @@ static long task_close_fd(struct binder_proc *proc, unsigned int fd) | |||
| 920 | retval == -ERESTARTNOHAND || | 932 | retval == -ERESTARTNOHAND || |
| 921 | retval == -ERESTART_RESTARTBLOCK)) | 933 | retval == -ERESTART_RESTARTBLOCK)) |
| 922 | retval = -EINTR; | 934 | retval = -EINTR; |
| 923 | 935 | err: | |
| 936 | mutex_unlock(&proc->files_lock); | ||
| 924 | return retval; | 937 | return retval; |
| 925 | } | 938 | } |
| 926 | 939 | ||
| @@ -4627,7 +4640,9 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) | |||
| 4627 | ret = binder_alloc_mmap_handler(&proc->alloc, vma); | 4640 | ret = binder_alloc_mmap_handler(&proc->alloc, vma); |
| 4628 | if (ret) | 4641 | if (ret) |
| 4629 | return ret; | 4642 | return ret; |
| 4643 | mutex_lock(&proc->files_lock); | ||
| 4630 | proc->files = get_files_struct(current); | 4644 | proc->files = get_files_struct(current); |
| 4645 | mutex_unlock(&proc->files_lock); | ||
| 4631 | return 0; | 4646 | return 0; |
| 4632 | 4647 | ||
| 4633 | err_bad_arg: | 4648 | err_bad_arg: |
| @@ -4651,6 +4666,7 @@ static int binder_open(struct inode *nodp, struct file *filp) | |||
| 4651 | spin_lock_init(&proc->outer_lock); | 4666 | spin_lock_init(&proc->outer_lock); |
| 4652 | get_task_struct(current->group_leader); | 4667 | get_task_struct(current->group_leader); |
| 4653 | proc->tsk = current->group_leader; | 4668 | proc->tsk = current->group_leader; |
| 4669 | mutex_init(&proc->files_lock); | ||
| 4654 | INIT_LIST_HEAD(&proc->todo); | 4670 | INIT_LIST_HEAD(&proc->todo); |
| 4655 | proc->default_priority = task_nice(current); | 4671 | proc->default_priority = task_nice(current); |
| 4656 | binder_dev = container_of(filp->private_data, struct binder_device, | 4672 | binder_dev = container_of(filp->private_data, struct binder_device, |
| @@ -4903,9 +4919,11 @@ static void binder_deferred_func(struct work_struct *work) | |||
| 4903 | 4919 | ||
| 4904 | files = NULL; | 4920 | files = NULL; |
| 4905 | if (defer & BINDER_DEFERRED_PUT_FILES) { | 4921 | if (defer & BINDER_DEFERRED_PUT_FILES) { |
| 4922 | mutex_lock(&proc->files_lock); | ||
| 4906 | files = proc->files; | 4923 | files = proc->files; |
| 4907 | if (files) | 4924 | if (files) |
| 4908 | proc->files = NULL; | 4925 | proc->files = NULL; |
| 4926 | mutex_unlock(&proc->files_lock); | ||
| 4909 | } | 4927 | } |
| 4910 | 4928 | ||
| 4911 | if (defer & BINDER_DEFERRED_FLUSH) | 4929 | if (defer & BINDER_DEFERRED_FLUSH) |
