aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArve Hjønnevåg <arve@android.com>2009-04-06 18:12:57 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-04-17 14:06:26 -0400
commit282ca175d4c440ec4d74bc622ee497e5b3530ce5 (patch)
tree4e336942fcfca0715a988332da6d0e7890fbad8e
parentea5c4cc68e2b5f4ec41d666376d3606d4d5c3426 (diff)
Staging: binder: Keep a reference to the files_struct while the driver is mmapped
This prevents breaking fget_light if a single threaded application allows incoming file descriptors (in replies or on nodes). Should also prevent inserting a file in the wrong files_struct if the receving process execs in the middle of a transaction (between task_get_unused_fd_flags and task_fd_install). Signed-off-by: Arve Hjønnevåg <arve@android.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/staging/android/binder.c79
1 files changed, 63 insertions, 16 deletions
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 64f95ee8a704..09962e87c600 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -41,6 +41,8 @@ static int binder_last_id;
41static struct proc_dir_entry *binder_proc_dir_entry_root; 41static struct proc_dir_entry *binder_proc_dir_entry_root;
42static struct proc_dir_entry *binder_proc_dir_entry_proc; 42static struct proc_dir_entry *binder_proc_dir_entry_proc;
43static struct hlist_head binder_dead_nodes; 43static struct hlist_head binder_dead_nodes;
44static HLIST_HEAD(binder_release_files_list);
45static DEFINE_MUTEX(binder_release_files_lock);
44 46
45static int binder_read_proc_proc( 47static int binder_read_proc_proc(
46 char *page, char **start, off_t off, int count, int *eof, void *data); 48 char *page, char **start, off_t off, int count, int *eof, void *data);
@@ -241,6 +243,8 @@ struct binder_proc {
241 int pid; 243 int pid;
242 struct vm_area_struct *vma; 244 struct vm_area_struct *vma;
243 struct task_struct *tsk; 245 struct task_struct *tsk;
246 struct files_struct *files;
247 struct hlist_node release_files_node;
244 void *buffer; 248 void *buffer;
245 size_t user_buffer_offset; 249 size_t user_buffer_offset;
246 250
@@ -309,9 +313,9 @@ struct binder_transaction {
309/* 313/*
310 * copied from get_unused_fd_flags 314 * copied from get_unused_fd_flags
311 */ 315 */
312int task_get_unused_fd_flags(struct task_struct *tsk, int flags) 316int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
313{ 317{
314 struct files_struct *files = get_files_struct(tsk); 318 struct files_struct *files = proc->files;
315 int fd, error; 319 int fd, error;
316 struct fdtable *fdt; 320 struct fdtable *fdt;
317 unsigned long rlim_cur; 321 unsigned long rlim_cur;
@@ -333,9 +337,9 @@ repeat:
333 * will limit the total number of files that can be opened. 337 * will limit the total number of files that can be opened.
334 */ 338 */
335 rlim_cur = 0; 339 rlim_cur = 0;
336 if (lock_task_sighand(tsk, &irqs)) { 340 if (lock_task_sighand(proc->tsk, &irqs)) {
337 rlim_cur = tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur; 341 rlim_cur = proc->tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur;
338 unlock_task_sighand(tsk, &irqs); 342 unlock_task_sighand(proc->tsk, &irqs);
339 } 343 }
340 if (fd >= rlim_cur) 344 if (fd >= rlim_cur)
341 goto out; 345 goto out;
@@ -371,7 +375,6 @@ repeat:
371 375
372out: 376out:
373 spin_unlock(&files->file_lock); 377 spin_unlock(&files->file_lock);
374 put_files_struct(files);
375 return error; 378 return error;
376} 379}
377 380
@@ -379,9 +382,9 @@ out:
379 * copied from fd_install 382 * copied from fd_install
380 */ 383 */
381static void task_fd_install( 384static void task_fd_install(
382 struct task_struct *tsk, unsigned int fd, struct file *file) 385 struct binder_proc *proc, unsigned int fd, struct file *file)
383{ 386{
384 struct files_struct *files = get_files_struct(tsk); 387 struct files_struct *files = proc->files;
385 struct fdtable *fdt; 388 struct fdtable *fdt;
386 389
387 if (files == NULL) 390 if (files == NULL)
@@ -392,7 +395,6 @@ static void task_fd_install(
392 BUG_ON(fdt->fd[fd] != NULL); 395 BUG_ON(fdt->fd[fd] != NULL);
393 rcu_assign_pointer(fdt->fd[fd], file); 396 rcu_assign_pointer(fdt->fd[fd], file);
394 spin_unlock(&files->file_lock); 397 spin_unlock(&files->file_lock);
395 put_files_struct(files);
396} 398}
397 399
398/* 400/*
@@ -409,10 +411,10 @@ static void __put_unused_fd(struct files_struct *files, unsigned int fd)
409/* 411/*
410 * copied from sys_close 412 * copied from sys_close
411 */ 413 */
412static long task_close_fd(struct task_struct *tsk, unsigned int fd) 414static long task_close_fd(struct binder_proc *proc, unsigned int fd)
413{ 415{
414 struct file *filp; 416 struct file *filp;
415 struct files_struct *files = get_files_struct(tsk); 417 struct files_struct *files = proc->files;
416 struct fdtable *fdt; 418 struct fdtable *fdt;
417 int retval; 419 int retval;
418 420
@@ -439,12 +441,10 @@ static long task_close_fd(struct task_struct *tsk, unsigned int fd)
439 retval == -ERESTART_RESTARTBLOCK)) 441 retval == -ERESTART_RESTARTBLOCK))
440 retval = -EINTR; 442 retval = -EINTR;
441 443
442 put_files_struct(files);
443 return retval; 444 return retval;
444 445
445out_unlock: 446out_unlock:
446 spin_unlock(&files->file_lock); 447 spin_unlock(&files->file_lock);
447 put_files_struct(files);
448 return -EBADF; 448 return -EBADF;
449} 449}
450 450
@@ -1549,13 +1549,13 @@ binder_transaction(struct binder_proc *proc, struct binder_thread *thread,
1549 return_error = BR_FAILED_REPLY; 1549 return_error = BR_FAILED_REPLY;
1550 goto err_fget_failed; 1550 goto err_fget_failed;
1551 } 1551 }
1552 target_fd = task_get_unused_fd_flags(target_proc->tsk, O_CLOEXEC); 1552 target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
1553 if (target_fd < 0) { 1553 if (target_fd < 0) {
1554 fput(file); 1554 fput(file);
1555 return_error = BR_FAILED_REPLY; 1555 return_error = BR_FAILED_REPLY;
1556 goto err_get_unused_fd_failed; 1556 goto err_get_unused_fd_failed;
1557 } 1557 }
1558 task_fd_install(target_proc->tsk, target_fd, file); 1558 task_fd_install(target_proc, target_fd, file);
1559 if (binder_debug_mask & BINDER_DEBUG_TRANSACTION) 1559 if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
1560 printk(KERN_INFO " fd %ld -> %d\n", fp->handle, target_fd); 1560 printk(KERN_INFO " fd %ld -> %d\n", fp->handle, target_fd);
1561 /* TODO: fput? */ 1561 /* TODO: fput? */
@@ -1698,7 +1698,7 @@ binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer
1698 if (binder_debug_mask & BINDER_DEBUG_TRANSACTION) 1698 if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
1699 printk(KERN_INFO " fd %ld\n", fp->handle); 1699 printk(KERN_INFO " fd %ld\n", fp->handle);
1700 if (failed_at) 1700 if (failed_at)
1701 task_close_fd(proc->tsk, fp->handle); 1701 task_close_fd(proc, fp->handle);
1702 break; 1702 break;
1703 1703
1704 default: 1704 default:
@@ -2663,6 +2663,34 @@ static void binder_vma_open(struct vm_area_struct *vma)
2663 (unsigned long)pgprot_val(vma->vm_page_prot)); 2663 (unsigned long)pgprot_val(vma->vm_page_prot));
2664 dump_stack(); 2664 dump_stack();
2665} 2665}
2666
2667static void binder_release_files(struct work_struct *work)
2668{
2669 struct binder_proc *proc;
2670 struct files_struct *files;
2671 do {
2672 mutex_lock(&binder_lock);
2673 mutex_lock(&binder_release_files_lock);
2674 if (!hlist_empty(&binder_release_files_list)) {
2675 proc = hlist_entry(binder_release_files_list.first,
2676 struct binder_proc, release_files_node);
2677 hlist_del_init(&proc->release_files_node);
2678 files = proc->files;
2679 if (files)
2680 proc->files = NULL;
2681 } else {
2682 proc = NULL;
2683 files = NULL;
2684 }
2685 mutex_unlock(&binder_release_files_lock);
2686 mutex_unlock(&binder_lock);
2687 if (files)
2688 put_files_struct(files);
2689 } while (proc);
2690}
2691
2692static DECLARE_WORK(binder_release_files_work, binder_release_files);
2693
2666static void binder_vma_close(struct vm_area_struct *vma) 2694static void binder_vma_close(struct vm_area_struct *vma)
2667{ 2695{
2668 struct binder_proc *proc = vma->vm_private_data; 2696 struct binder_proc *proc = vma->vm_private_data;
@@ -2673,6 +2701,13 @@ static void binder_vma_close(struct vm_area_struct *vma)
2673 (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, 2701 (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
2674 (unsigned long)pgprot_val(vma->vm_page_prot)); 2702 (unsigned long)pgprot_val(vma->vm_page_prot));
2675 proc->vma = NULL; 2703 proc->vma = NULL;
2704 mutex_lock(&binder_release_files_lock);
2705 if (proc->files) {
2706 hlist_add_head(&proc->release_files_node,
2707 &binder_release_files_list);
2708 schedule_work(&binder_release_files_work);
2709 }
2710 mutex_unlock(&binder_release_files_lock);
2676} 2711}
2677 2712
2678static struct vm_operations_struct binder_vm_ops = { 2713static struct vm_operations_struct binder_vm_ops = {
@@ -2751,6 +2786,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
2751 binder_insert_free_buffer(proc, buffer); 2786 binder_insert_free_buffer(proc, buffer);
2752 proc->free_async_space = proc->buffer_size / 2; 2787 proc->free_async_space = proc->buffer_size / 2;
2753 barrier(); 2788 barrier();
2789 proc->files = get_files_struct(current);
2754 proc->vma = vma; 2790 proc->vma = vma;
2755 2791
2756 /*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/ 2792 /*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
@@ -2831,6 +2867,7 @@ static int binder_release(struct inode *nodp, struct file *filp)
2831 struct hlist_node *pos; 2867 struct hlist_node *pos;
2832 struct binder_transaction *t; 2868 struct binder_transaction *t;
2833 struct rb_node *n; 2869 struct rb_node *n;
2870 struct files_struct *files;
2834 struct binder_proc *proc = filp->private_data; 2871 struct binder_proc *proc = filp->private_data;
2835 int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count; 2872 int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count;
2836 2873
@@ -2840,6 +2877,14 @@ static int binder_release(struct inode *nodp, struct file *filp)
2840 remove_proc_entry(strbuf, binder_proc_dir_entry_proc); 2877 remove_proc_entry(strbuf, binder_proc_dir_entry_proc);
2841 } 2878 }
2842 mutex_lock(&binder_lock); 2879 mutex_lock(&binder_lock);
2880 mutex_lock(&binder_release_files_lock);
2881 if (!hlist_unhashed(&proc->release_files_node))
2882 hlist_del(&proc->release_files_node);
2883 files = proc->files;
2884 if (files)
2885 proc->files = NULL;
2886 mutex_unlock(&binder_release_files_lock);
2887
2843 hlist_del(&proc->proc_node); 2888 hlist_del(&proc->proc_node);
2844 if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) { 2889 if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
2845 if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER) 2890 if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)
@@ -2937,6 +2982,8 @@ static int binder_release(struct inode *nodp, struct file *filp)
2937 proc->pid, threads, nodes, incoming_refs, outgoing_refs, active_transactions, buffers, page_count); 2982 proc->pid, threads, nodes, incoming_refs, outgoing_refs, active_transactions, buffers, page_count);
2938 2983
2939 kfree(proc); 2984 kfree(proc);
2985 if (files)
2986 put_files_struct(files);
2940 return 0; 2987 return 0;
2941} 2988}
2942 2989