Add dedicated functions for handling the movement of fds, binder objects,
and references across processes.

Signed-off-by: Riley Andrews <riandr...@android.com>
---
 drivers/android/binder.c | 311 +++++++++++++++++++++++++----------------------
 1 file changed, 167 insertions(+), 144 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index e47c2d4..a9a160a 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1314,6 +1314,156 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
        }
 }
 
+static int binder_translate_object(struct flat_binder_object *fp,
+                                  struct binder_transaction *t,
+                                  struct binder_thread *thread)
+{
+       struct binder_ref *ref;
+       struct binder_proc *proc = thread->proc;
+       struct binder_node *node;
+       struct binder_proc *target_proc = t->to_proc;
+
+       node = binder_get_node(proc, fp->binder);
+       if (!node) {
+               node = binder_new_node(proc, fp->binder, fp->cookie);
+               if (!node)
+                       return BR_FAILED_REPLY;
+
+               node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
+               node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
+       }
+       if (fp->cookie != node->cookie) {
+               binder_user_error("%d:%d sending u%016llx node %d, cookie 
mismatch %016llx != %016llx\n",
+                                 proc->pid, thread->pid,
+                                 (u64)fp->binder, node->debug_id,
+                                 (u64)fp->cookie, (u64)node->cookie);
+               return BR_FAILED_REPLY;
+       }
+
+       if (security_binder_transfer_binder(proc->tsk, target_proc->tsk))
+               return BR_FAILED_REPLY;
+
+       ref = binder_get_ref_for_node(target_proc, node);
+       if (!ref)
+               return BR_FAILED_REPLY;
+
+       if (fp->type == BINDER_TYPE_BINDER)
+               fp->type = BINDER_TYPE_HANDLE;
+       else
+               fp->type = BINDER_TYPE_WEAK_HANDLE;
+       fp->handle = ref->desc;
+       binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE, &thread->todo);
+
+       trace_binder_transaction_node_to_ref(t, node, ref);
+       binder_debug(BINDER_DEBUG_TRANSACTION,
+                    "        node %d u%016llx -> ref %d desc %d\n",
+                    node->debug_id, (u64)node->ptr,
+                    ref->debug_id, ref->desc);
+       return BR_OK;
+}
+
+static int binder_translate_handle(struct flat_binder_object *fp,
+                                  struct binder_transaction *t,
+                                  struct binder_thread *thread)
+{
+       struct binder_proc *proc = thread->proc;
+       struct binder_proc *target_proc = t->to_proc;
+       struct binder_ref *ref;
+
+       ref = binder_get_ref(proc, fp->handle);
+       if (!ref) {
+               binder_user_error("%d:%d got transaction with invalid handle, 
%d\n",
+                                 proc->pid, thread->pid, fp->handle);
+               return BR_FAILED_REPLY;
+       }
+       if (security_binder_transfer_binder(proc->tsk, target_proc->tsk))
+               return BR_FAILED_REPLY;
+       if (ref->node->proc == target_proc) {
+               if (fp->type == BINDER_TYPE_HANDLE)
+                       fp->type = BINDER_TYPE_BINDER;
+               else
+                       fp->type = BINDER_TYPE_WEAK_BINDER;
+               fp->binder = ref->node->ptr;
+               fp->cookie = ref->node->cookie;
+               binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0,
+                               NULL);
+               trace_binder_transaction_ref_to_node(t, ref);
+               binder_debug(BINDER_DEBUG_TRANSACTION,
+                            "        ref %d desc %d -> node %d u%016llx\n",
+                            ref->debug_id, ref->desc, ref->node->debug_id,
+                            (u64)ref->node->ptr);
+       } else {
+               struct binder_ref *new_ref;
+
+               new_ref = binder_get_ref_for_node(target_proc, ref->node);
+               if (!new_ref)
+                       return BR_FAILED_REPLY;
+               fp->handle = new_ref->desc;
+               binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
+               trace_binder_transaction_ref_to_ref(t, ref, new_ref);
+               binder_debug(BINDER_DEBUG_TRANSACTION,
+                            "        ref %d desc %d -> ref %d desc %d (node 
%d)\n",
+                            ref->debug_id, ref->desc, new_ref->debug_id,
+                            new_ref->desc, ref->node->debug_id);
+       }
+       return BR_OK;
+}
+
+static int binder_translate_fd(struct flat_binder_object *fp,
+                              struct binder_transaction *t,
+                              struct binder_thread *thread,
+                              struct binder_transaction *in_reply_to)
+
+{
+       struct binder_proc *proc = thread->proc;
+       struct binder_proc *target_proc = t->to_proc;
+       int target_fd;
+       struct file *file;
+       int ret;
+       bool target_allows_fd;
+
+       if (in_reply_to)
+               target_allows_fd = !!(in_reply_to->flags & TF_ACCEPT_FDS);
+       else
+               target_allows_fd = t->buffer->target_node->accept_fds;
+       if (!target_allows_fd) {
+               binder_user_error("%d:%d got %s with fd, %d, but target does 
not allow fds\n",
+                                 proc->pid, thread->pid,
+                                 (in_reply_to ? "reply" : "transaction"),
+                                 fp->handle);
+               goto err_fd_not_accepted;
+       }
+
+       file = fget(fp->handle);
+       if (!file) {
+               binder_user_error("%d:%d got transaction with invalid fd, %d\n",
+                                 proc->pid, thread->pid, fp->handle);
+               goto err_fget;
+       }
+       ret = security_binder_transfer_file(proc->tsk, target_proc->tsk, file);
+       if (ret < 0)
+               goto err_security;
+
+       target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
+       if (target_fd < 0)
+               goto err_get_unused_fd;
+
+       task_fd_install(target_proc, target_fd, file);
+       trace_binder_transaction_fd(t, fp->handle, target_fd);
+       binder_debug(BINDER_DEBUG_TRANSACTION, "        fd %d -> %d\n",
+                    fp->handle, target_fd);
+       /* TODO: fput? */
+       fp->handle = target_fd;
+       return BR_OK;
+
+err_get_unused_fd:
+err_security:
+       fput(file);
+err_fget:
+err_fd_not_accepted:
+       return BR_FAILED_REPLY;
+}
+
 static void binder_transaction(struct binder_thread *thread,
                               struct binder_transaction_data *tr, int reply)
 {
@@ -1536,145 +1686,23 @@ static void binder_transaction(struct binder_thread 
*thread,
                fp = (struct flat_binder_object *)(t->buffer->data + *offp);
                switch (fp->type) {
                case BINDER_TYPE_BINDER:
-               case BINDER_TYPE_WEAK_BINDER: {
-                       struct binder_ref *ref;
-                       struct binder_node *node = binder_get_node(proc, 
fp->binder);
-
-                       if (node == NULL) {
-                               node = binder_new_node(proc, fp->binder, 
fp->cookie);
-                               if (node == NULL) {
-                                       return_error = BR_FAILED_REPLY;
-                                       goto err_binder_new_node_failed;
-                               }
-                               node->min_priority = fp->flags & 
FLAT_BINDER_FLAG_PRIORITY_MASK;
-                               node->accept_fds = !!(fp->flags & 
FLAT_BINDER_FLAG_ACCEPTS_FDS);
-                       }
-                       if (fp->cookie != node->cookie) {
-                               binder_user_error("%d:%d sending u%016llx node 
%d, cookie mismatch %016llx != %016llx\n",
-                                       proc->pid, thread->pid,
-                                       (u64)fp->binder, node->debug_id,
-                                       (u64)fp->cookie, (u64)node->cookie);
-                               return_error = BR_FAILED_REPLY;
-                               goto err_binder_get_ref_for_node_failed;
-                       }
-                       if (security_binder_transfer_binder(proc->tsk,
-                                                           target_proc->tsk)) {
-                               return_error = BR_FAILED_REPLY;
-                               goto err_binder_get_ref_for_node_failed;
-                       }
-                       ref = binder_get_ref_for_node(target_proc, node);
-                       if (ref == NULL) {
-                               return_error = BR_FAILED_REPLY;
-                               goto err_binder_get_ref_for_node_failed;
-                       }
-                       if (fp->type == BINDER_TYPE_BINDER)
-                               fp->type = BINDER_TYPE_HANDLE;
-                       else
-                               fp->type = BINDER_TYPE_WEAK_HANDLE;
-                       fp->handle = ref->desc;
-                       binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
-                                      &thread->todo);
-
-                       trace_binder_transaction_node_to_ref(t, node, ref);
-                       binder_debug(BINDER_DEBUG_TRANSACTION,
-                                    "        node %d u%016llx -> ref %d desc 
%d\n",
-                                    node->debug_id, (u64)node->ptr,
-                                    ref->debug_id, ref->desc);
-               } break;
+               case BINDER_TYPE_WEAK_BINDER:
+                       return_error = binder_translate_object(fp, t, thread);
+                       if (return_error != BR_OK)
+                               goto err_translate_failed;
+                       break;
                case BINDER_TYPE_HANDLE:
-               case BINDER_TYPE_WEAK_HANDLE: {
-                       struct binder_ref *ref = binder_get_ref(proc, 
fp->handle);
-
-                       if (ref == NULL) {
-                               binder_user_error("%d:%d got transaction with 
invalid handle, %d\n",
-                                               proc->pid,
-                                               thread->pid, fp->handle);
-                               return_error = BR_FAILED_REPLY;
-                               goto err_binder_get_ref_failed;
-                       }
-                       if (security_binder_transfer_binder(proc->tsk,
-                                                           target_proc->tsk)) {
-                               return_error = BR_FAILED_REPLY;
-                               goto err_binder_get_ref_failed;
-                       }
-                       if (ref->node->proc == target_proc) {
-                               if (fp->type == BINDER_TYPE_HANDLE)
-                                       fp->type = BINDER_TYPE_BINDER;
-                               else
-                                       fp->type = BINDER_TYPE_WEAK_BINDER;
-                               fp->binder = ref->node->ptr;
-                               fp->cookie = ref->node->cookie;
-                               binder_inc_node(ref->node, fp->type == 
BINDER_TYPE_BINDER, 0, NULL);
-                               trace_binder_transaction_ref_to_node(t, ref);
-                               binder_debug(BINDER_DEBUG_TRANSACTION,
-                                            "        ref %d desc %d -> node %d 
u%016llx\n",
-                                            ref->debug_id, ref->desc, 
ref->node->debug_id,
-                                            (u64)ref->node->ptr);
-                       } else {
-                               struct binder_ref *new_ref;
-
-                               new_ref = binder_get_ref_for_node(target_proc, 
ref->node);
-                               if (new_ref == NULL) {
-                                       return_error = BR_FAILED_REPLY;
-                                       goto err_binder_get_ref_for_node_failed;
-                               }
-                               fp->handle = new_ref->desc;
-                               binder_inc_ref(new_ref, fp->type == 
BINDER_TYPE_HANDLE, NULL);
-                               trace_binder_transaction_ref_to_ref(t, ref,
-                                                                   new_ref);
-                               binder_debug(BINDER_DEBUG_TRANSACTION,
-                                            "        ref %d desc %d -> ref %d 
desc %d (node %d)\n",
-                                            ref->debug_id, ref->desc, 
new_ref->debug_id,
-                                            new_ref->desc, 
ref->node->debug_id);
-                       }
-               } break;
-
-               case BINDER_TYPE_FD: {
-                       int target_fd;
-                       struct file *file;
-
-                       if (reply) {
-                               if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
-                                       binder_user_error("%d:%d got reply with 
fd, %d, but target does not allow fds\n",
-                                               proc->pid, thread->pid, 
fp->handle);
-                                       return_error = BR_FAILED_REPLY;
-                                       goto err_fd_not_allowed;
-                               }
-                       } else if (!target_node->accept_fds) {
-                               binder_user_error("%d:%d got transaction with 
fd, %d, but target does not allow fds\n",
-                                       proc->pid, thread->pid, fp->handle);
-                               return_error = BR_FAILED_REPLY;
-                               goto err_fd_not_allowed;
-                       }
-
-                       file = fget(fp->handle);
-                       if (file == NULL) {
-                               binder_user_error("%d:%d got transaction with 
invalid fd, %d\n",
-                                       proc->pid, thread->pid, fp->handle);
-                               return_error = BR_FAILED_REPLY;
-                               goto err_fget_failed;
-                       }
-                       if (security_binder_transfer_file(proc->tsk,
-                                                         target_proc->tsk,
-                                                         file) < 0) {
-                               fput(file);
-                               return_error = BR_FAILED_REPLY;
-                               goto err_get_unused_fd_failed;
-                       }
-                       target_fd = task_get_unused_fd_flags(target_proc, 
O_CLOEXEC);
-                       if (target_fd < 0) {
-                               fput(file);
-                               return_error = BR_FAILED_REPLY;
-                               goto err_get_unused_fd_failed;
-                       }
-                       task_fd_install(target_proc, target_fd, file);
-                       trace_binder_transaction_fd(t, fp->handle, target_fd);
-                       binder_debug(BINDER_DEBUG_TRANSACTION,
-                                    "        fd %d -> %d\n", fp->handle, 
target_fd);
-                       /* TODO: fput? */
-                       fp->handle = target_fd;
-               } break;
-
+               case BINDER_TYPE_WEAK_HANDLE:
+                       return_error = binder_translate_handle(fp, t, thread);
+                       if (return_error != BR_OK)
+                               goto err_translate_failed;
+                       break;
+               case BINDER_TYPE_FD:
+                       return_error = binder_translate_fd(fp, t, thread,
+                                                          in_reply_to);
+                       if (return_error != BR_OK)
+                               goto err_translate_failed;
+                       break;
                default:
                        binder_user_error("%d:%d got transaction with invalid 
object type, %x\n",
                                proc->pid, thread->pid, fp->type);
@@ -1707,12 +1735,7 @@ static void binder_transaction(struct binder_thread 
*thread,
                wake_up_interruptible(target_wait);
        return;
 
-err_get_unused_fd_failed:
-err_fget_failed:
-err_fd_not_allowed:
-err_binder_get_ref_for_node_failed:
-err_binder_get_ref_failed:
-err_binder_new_node_failed:
+err_translate_failed:
 err_bad_object_type:
 err_bad_offset:
 err_copy_data_failed:
-- 
2.2.0.rc0.207.ga3a616c

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to