lkml.org 
[lkml]   [2021]   [Nov]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH 1/3] binder: avoid potential data leakage when copying txn
Hi Todd,

I love your patch! Perhaps something to improve:

[auto build test WARNING on staging/staging-testing]
[also build test WARNING on v5.16-rc2 next-20211124]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/Todd-Kjos/binder-Prevent-untranslated-sender-data-from-being-copied-to-target/20211124-031908
base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git 1189d2fb15a4b09b2e8dd01d60a0817d985d933d
config: nds32-buildonly-randconfig-r004-20211123 (https://download.01.org/0day-ci/archive/20211125/202111251005.ZQfHG0PB-lkp@intel.com/config)
compiler: nds32le-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/d51c5e7a3791e9e748200416f85456c826d3030e
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Todd-Kjos/binder-Prevent-untranslated-sender-data-from-being-copied-to-target/20211124-031908
git checkout d51c5e7a3791e9e748200416f85456c826d3030e
# save the config file to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=nds32

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

In file included from include/asm-generic/bug.h:22,
from ./arch/nds32/include/generated/asm/bug.h:1,
from include/linux/bug.h:5,
from include/linux/thread_info.h:13,
from include/asm-generic/preempt.h:5,
from ./arch/nds32/include/generated/asm/preempt.h:1,
from include/linux/preempt.h:78,
from include/linux/spinlock.h:55,
from include/linux/fdtable.h:11,
from drivers/android/binder.c:45:
drivers/android/binder.c: In function 'binder_transaction':
>> drivers/android/binder.c:2711:30: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
2711 | (u64)user_buffer,
| ^
include/linux/printk.h:418:33: note: in definition of macro 'printk_index_wrap'
418 | _p_func(_fmt, ##__VA_ARGS__); \
| ^~~~~~~~~~~
include/linux/printk.h:640:17: note: in expansion of macro 'printk'
640 | printk(fmt, ##__VA_ARGS__); \
| ^~~~~~
include/linux/printk.h:660:9: note: in expansion of macro 'printk_ratelimited'
660 | printk_ratelimited(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
| ^~~~~~~~~~~~~~~~~~
drivers/android/binder.c:139:25: note: in expansion of macro 'pr_info_ratelimited'
139 | pr_info_ratelimited(x); \
| ^~~~~~~~~~~~~~~~~~~
drivers/android/binder.c:2707:17: note: in expansion of macro 'binder_debug'
2707 | binder_debug(BINDER_DEBUG_TRANSACTION,
| ^~~~~~~~~~~~
drivers/android/binder.c:2720:30: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
2720 | (u64)user_buffer,
| ^
include/linux/printk.h:418:33: note: in definition of macro 'printk_index_wrap'
418 | _p_func(_fmt, ##__VA_ARGS__); \
| ^~~~~~~~~~~
include/linux/printk.h:640:17: note: in expansion of macro 'printk'
640 | printk(fmt, ##__VA_ARGS__); \
| ^~~~~~
include/linux/printk.h:660:9: note: in expansion of macro 'printk_ratelimited'
660 | printk_ratelimited(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
| ^~~~~~~~~~~~~~~~~~
drivers/android/binder.c:139:25: note: in expansion of macro 'pr_info_ratelimited'
139 | pr_info_ratelimited(x); \
| ^~~~~~~~~~~~~~~~~~~
drivers/android/binder.c:2716:17: note: in expansion of macro 'binder_debug'
2716 | binder_debug(BINDER_DEBUG_TRANSACTION,
| ^~~~~~~~~~~~


vim +2711 drivers/android/binder.c

2457
2458 static void binder_transaction(struct binder_proc *proc,
2459 struct binder_thread *thread,
2460 struct binder_transaction_data *tr, int reply,
2461 binder_size_t extra_buffers_size)
2462 {
2463 int ret;
2464 struct binder_transaction *t;
2465 struct binder_work *w;
2466 struct binder_work *tcomplete;
2467 binder_size_t buffer_offset = 0;
2468 binder_size_t off_start_offset, off_end_offset;
2469 binder_size_t off_min;
2470 binder_size_t sg_buf_offset, sg_buf_end_offset;
2471 binder_size_t user_offset = 0;
2472 struct binder_proc *target_proc = NULL;
2473 struct binder_thread *target_thread = NULL;
2474 struct binder_node *target_node = NULL;
2475 struct binder_transaction *in_reply_to = NULL;
2476 struct binder_transaction_log_entry *e;
2477 uint32_t return_error = 0;
2478 uint32_t return_error_param = 0;
2479 uint32_t return_error_line = 0;
2480 binder_size_t last_fixup_obj_off = 0;
2481 binder_size_t last_fixup_min_off = 0;
2482 struct binder_context *context = proc->context;
2483 int t_debug_id = atomic_inc_return(&binder_last_id);
2484 char *secctx = NULL;
2485 u32 secctx_sz = 0;
2486 const void __user *user_buffer = (const void __user *)
2487 (uintptr_t)tr->data.ptr.buffer;
2488
2489 e = binder_transaction_log_add(&binder_transaction_log);
2490 e->debug_id = t_debug_id;
2491 e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY);
2492 e->from_proc = proc->pid;
2493 e->from_thread = thread->pid;
2494 e->target_handle = tr->target.handle;
2495 e->data_size = tr->data_size;
2496 e->offsets_size = tr->offsets_size;
2497 strscpy(e->context_name, proc->context->name, BINDERFS_MAX_NAME);
2498
2499 if (reply) {
2500 binder_inner_proc_lock(proc);
2501 in_reply_to = thread->transaction_stack;
2502 if (in_reply_to == NULL) {
2503 binder_inner_proc_unlock(proc);
2504 binder_user_error("%d:%d got reply transaction with no transaction stack\n",
2505 proc->pid, thread->pid);
2506 return_error = BR_FAILED_REPLY;
2507 return_error_param = -EPROTO;
2508 return_error_line = __LINE__;
2509 goto err_empty_call_stack;
2510 }
2511 if (in_reply_to->to_thread != thread) {
2512 spin_lock(&in_reply_to->lock);
2513 binder_user_error("%d:%d got reply transaction with bad transaction stack, transaction %d has target %d:%d\n",
2514 proc->pid, thread->pid, in_reply_to->debug_id,
2515 in_reply_to->to_proc ?
2516 in_reply_to->to_proc->pid : 0,
2517 in_reply_to->to_thread ?
2518 in_reply_to->to_thread->pid : 0);
2519 spin_unlock(&in_reply_to->lock);
2520 binder_inner_proc_unlock(proc);
2521 return_error = BR_FAILED_REPLY;
2522 return_error_param = -EPROTO;
2523 return_error_line = __LINE__;
2524 in_reply_to = NULL;
2525 goto err_bad_call_stack;
2526 }
2527 thread->transaction_stack = in_reply_to->to_parent;
2528 binder_inner_proc_unlock(proc);
2529 binder_set_nice(in_reply_to->saved_priority);
2530 target_thread = binder_get_txn_from_and_acq_inner(in_reply_to);
2531 if (target_thread == NULL) {
2532 /* annotation for sparse */
2533 __release(&target_thread->proc->inner_lock);
2534 return_error = BR_DEAD_REPLY;
2535 return_error_line = __LINE__;
2536 goto err_dead_binder;
2537 }
2538 if (target_thread->transaction_stack != in_reply_to) {
2539 binder_user_error("%d:%d got reply transaction with bad target transaction stack %d, expected %d\n",
2540 proc->pid, thread->pid,
2541 target_thread->transaction_stack ?
2542 target_thread->transaction_stack->debug_id : 0,
2543 in_reply_to->debug_id);
2544 binder_inner_proc_unlock(target_thread->proc);
2545 return_error = BR_FAILED_REPLY;
2546 return_error_param = -EPROTO;
2547 return_error_line = __LINE__;
2548 in_reply_to = NULL;
2549 target_thread = NULL;
2550 goto err_dead_binder;
2551 }
2552 target_proc = target_thread->proc;
2553 target_proc->tmp_ref++;
2554 binder_inner_proc_unlock(target_thread->proc);
2555 } else {
2556 if (tr->target.handle) {
2557 struct binder_ref *ref;
2558
2559 /*
2560 * There must already be a strong ref
2561 * on this node. If so, do a strong
2562 * increment on the node to ensure it
2563 * stays alive until the transaction is
2564 * done.
2565 */
2566 binder_proc_lock(proc);
2567 ref = binder_get_ref_olocked(proc, tr->target.handle,
2568 true);
2569 if (ref) {
2570 target_node = binder_get_node_refs_for_txn(
2571 ref->node, &target_proc,
2572 &return_error);
2573 } else {
2574 binder_user_error("%d:%d got transaction to invalid handle, %u\n",
2575 proc->pid, thread->pid, tr->target.handle);
2576 return_error = BR_FAILED_REPLY;
2577 }
2578 binder_proc_unlock(proc);
2579 } else {
2580 mutex_lock(&context->context_mgr_node_lock);
2581 target_node = context->binder_context_mgr_node;
2582 if (target_node)
2583 target_node = binder_get_node_refs_for_txn(
2584 target_node, &target_proc,
2585 &return_error);
2586 else
2587 return_error = BR_DEAD_REPLY;
2588 mutex_unlock(&context->context_mgr_node_lock);
2589 if (target_node && target_proc->pid == proc->pid) {
2590 binder_user_error("%d:%d got transaction to context manager from process owning it\n",
2591 proc->pid, thread->pid);
2592 return_error = BR_FAILED_REPLY;
2593 return_error_param = -EINVAL;
2594 return_error_line = __LINE__;
2595 goto err_invalid_target_handle;
2596 }
2597 }
2598 if (!target_node) {
2599 /*
2600 * return_error is set above
2601 */
2602 return_error_param = -EINVAL;
2603 return_error_line = __LINE__;
2604 goto err_dead_binder;
2605 }
2606 e->to_node = target_node->debug_id;
2607 if (WARN_ON(proc == target_proc)) {
2608 return_error = BR_FAILED_REPLY;
2609 return_error_param = -EINVAL;
2610 return_error_line = __LINE__;
2611 goto err_invalid_target_handle;
2612 }
2613 if (security_binder_transaction(proc->cred,
2614 target_proc->cred) < 0) {
2615 return_error = BR_FAILED_REPLY;
2616 return_error_param = -EPERM;
2617 return_error_line = __LINE__;
2618 goto err_invalid_target_handle;
2619 }
2620 binder_inner_proc_lock(proc);
2621
2622 w = list_first_entry_or_null(&thread->todo,
2623 struct binder_work, entry);
2624 if (!(tr->flags & TF_ONE_WAY) && w &&
2625 w->type == BINDER_WORK_TRANSACTION) {
2626 /*
2627 * Do not allow new outgoing transaction from a
2628 * thread that has a transaction at the head of
2629 * its todo list. Only need to check the head
2630 * because binder_select_thread_ilocked picks a
2631 * thread from proc->waiting_threads to enqueue
2632 * the transaction, and nothing is queued to the
2633 * todo list while the thread is on waiting_threads.
2634 */
2635 binder_user_error("%d:%d new transaction not allowed when there is a transaction on thread todo\n",
2636 proc->pid, thread->pid);
2637 binder_inner_proc_unlock(proc);
2638 return_error = BR_FAILED_REPLY;
2639 return_error_param = -EPROTO;
2640 return_error_line = __LINE__;
2641 goto err_bad_todo_list;
2642 }
2643
2644 if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
2645 struct binder_transaction *tmp;
2646
2647 tmp = thread->transaction_stack;
2648 if (tmp->to_thread != thread) {
2649 spin_lock(&tmp->lock);
2650 binder_user_error("%d:%d got new transaction with bad transaction stack, transaction %d has target %d:%d\n",
2651 proc->pid, thread->pid, tmp->debug_id,
2652 tmp->to_proc ? tmp->to_proc->pid : 0,
2653 tmp->to_thread ?
2654 tmp->to_thread->pid : 0);
2655 spin_unlock(&tmp->lock);
2656 binder_inner_proc_unlock(proc);
2657 return_error = BR_FAILED_REPLY;
2658 return_error_param = -EPROTO;
2659 return_error_line = __LINE__;
2660 goto err_bad_call_stack;
2661 }
2662 while (tmp) {
2663 struct binder_thread *from;
2664
2665 spin_lock(&tmp->lock);
2666 from = tmp->from;
2667 if (from && from->proc == target_proc) {
2668 atomic_inc(&from->tmp_ref);
2669 target_thread = from;
2670 spin_unlock(&tmp->lock);
2671 break;
2672 }
2673 spin_unlock(&tmp->lock);
2674 tmp = tmp->from_parent;
2675 }
2676 }
2677 binder_inner_proc_unlock(proc);
2678 }
2679 if (target_thread)
2680 e->to_thread = target_thread->pid;
2681 e->to_proc = target_proc->pid;
2682
2683 /* TODO: reuse incoming transaction for reply */
2684 t = kzalloc(sizeof(*t), GFP_KERNEL);
2685 if (t == NULL) {
2686 return_error = BR_FAILED_REPLY;
2687 return_error_param = -ENOMEM;
2688 return_error_line = __LINE__;
2689 goto err_alloc_t_failed;
2690 }
2691 INIT_LIST_HEAD(&t->fd_fixups);
2692 binder_stats_created(BINDER_STAT_TRANSACTION);
2693 spin_lock_init(&t->lock);
2694
2695 tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
2696 if (tcomplete == NULL) {
2697 return_error = BR_FAILED_REPLY;
2698 return_error_param = -ENOMEM;
2699 return_error_line = __LINE__;
2700 goto err_alloc_tcomplete_failed;
2701 }
2702 binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
2703
2704 t->debug_id = t_debug_id;
2705
2706 if (reply)
2707 binder_debug(BINDER_DEBUG_TRANSACTION,
2708 "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld-%lld\n",
2709 proc->pid, thread->pid, t->debug_id,
2710 target_proc->pid, target_thread->pid,
> 2711 (u64)user_buffer,
2712 (u64)tr->data.ptr.offsets,
2713 (u64)tr->data_size, (u64)tr->offsets_size,
2714 (u64)extra_buffers_size);
2715 else
2716 binder_debug(BINDER_DEBUG_TRANSACTION,
2717 "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld-%lld\n",
2718 proc->pid, thread->pid, t->debug_id,
2719 target_proc->pid, target_node->debug_id,
2720 (u64)user_buffer,
2721 (u64)tr->data.ptr.offsets,
2722 (u64)tr->data_size, (u64)tr->offsets_size,
2723 (u64)extra_buffers_size);
2724
2725 if (!reply && !(tr->flags & TF_ONE_WAY))
2726 t->from = thread;
2727 else
2728 t->from = NULL;
2729 t->sender_euid = proc->cred->euid;
2730 t->to_proc = target_proc;
2731 t->to_thread = target_thread;
2732 t->code = tr->code;
2733 t->flags = tr->flags;
2734 t->priority = task_nice(current);
2735
2736 if (target_node && target_node->txn_security_ctx) {
2737 u32 secid;
2738 size_t added_size;
2739
2740 security_cred_getsecid(proc->cred, &secid);
2741 ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
2742 if (ret) {
2743 return_error = BR_FAILED_REPLY;
2744 return_error_param = ret;
2745 return_error_line = __LINE__;
2746 goto err_get_secctx_failed;
2747 }
2748 added_size = ALIGN(secctx_sz, sizeof(u64));
2749 extra_buffers_size += added_size;
2750 if (extra_buffers_size < added_size) {
2751 /* integer overflow of extra_buffers_size */
2752 return_error = BR_FAILED_REPLY;
2753 return_error_param = -EINVAL;
2754 return_error_line = __LINE__;
2755 goto err_bad_extra_size;
2756 }
2757 }
2758
2759 trace_binder_transaction(reply, t, target_node);
2760
2761 t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,
2762 tr->offsets_size, extra_buffers_size,
2763 !reply && (t->flags & TF_ONE_WAY), current->tgid);
2764 if (IS_ERR(t->buffer)) {
2765 /*
2766 * -ESRCH indicates VMA cleared. The target is dying.
2767 */
2768 return_error_param = PTR_ERR(t->buffer);
2769 return_error = return_error_param == -ESRCH ?
2770 BR_DEAD_REPLY : BR_FAILED_REPLY;
2771 return_error_line = __LINE__;
2772 t->buffer = NULL;
2773 goto err_binder_alloc_buf_failed;
2774 }
2775 if (secctx) {
2776 int err;
2777 size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
2778 ALIGN(tr->offsets_size, sizeof(void *)) +
2779 ALIGN(extra_buffers_size, sizeof(void *)) -
2780 ALIGN(secctx_sz, sizeof(u64));
2781
2782 t->security_ctx = (uintptr_t)t->buffer->user_data + buf_offset;
2783 err = binder_alloc_copy_to_buffer(&target_proc->alloc,
2784 t->buffer, buf_offset,
2785 secctx, secctx_sz);
2786 if (err) {
2787 t->security_ctx = 0;
2788 WARN_ON(1);
2789 }
2790 security_release_secctx(secctx, secctx_sz);
2791 secctx = NULL;
2792 }
2793 t->buffer->debug_id = t->debug_id;
2794 t->buffer->transaction = t;
2795 t->buffer->target_node = target_node;
2796 t->buffer->clear_on_free = !!(t->flags & TF_CLEAR_BUF);
2797 trace_binder_transaction_alloc_buf(t->buffer);
2798
2799 if (binder_alloc_copy_user_to_buffer(
2800 &target_proc->alloc,
2801 t->buffer,
2802 ALIGN(tr->data_size, sizeof(void *)),
2803 (const void __user *)
2804 (uintptr_t)tr->data.ptr.offsets,
2805 tr->offsets_size)) {
2806 binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
2807 proc->pid, thread->pid);
2808 return_error = BR_FAILED_REPLY;
2809 return_error_param = -EFAULT;
2810 return_error_line = __LINE__;
2811 goto err_copy_data_failed;
2812 }
2813 if (!IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))) {
2814 binder_user_error("%d:%d got transaction with invalid offsets size, %lld\n",
2815 proc->pid, thread->pid, (u64)tr->offsets_size);
2816 return_error = BR_FAILED_REPLY;
2817 return_error_param = -EINVAL;
2818 return_error_line = __LINE__;
2819 goto err_bad_offset;
2820 }
2821 if (!IS_ALIGNED(extra_buffers_size, sizeof(u64))) {
2822 binder_user_error("%d:%d got transaction with unaligned buffers size, %lld\n",
2823 proc->pid, thread->pid,
2824 (u64)extra_buffers_size);
2825 return_error = BR_FAILED_REPLY;
2826 return_error_param = -EINVAL;
2827 return_error_line = __LINE__;
2828 goto err_bad_offset;
2829 }
2830 off_start_offset = ALIGN(tr->data_size, sizeof(void *));
2831 buffer_offset = off_start_offset;
2832 off_end_offset = off_start_offset + tr->offsets_size;
2833 sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
2834 sg_buf_end_offset = sg_buf_offset + extra_buffers_size -
2835 ALIGN(secctx_sz, sizeof(u64));
2836 off_min = 0;
2837 for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
2838 buffer_offset += sizeof(binder_size_t)) {
2839 struct binder_object_header *hdr;
2840 size_t object_size;
2841 struct binder_object object;
2842 binder_size_t object_offset;
2843 binder_size_t copy_size;
2844
2845 if (binder_alloc_copy_from_buffer(&target_proc->alloc,
2846 &object_offset,
2847 t->buffer,
2848 buffer_offset,
2849 sizeof(object_offset))) {
2850 return_error = BR_FAILED_REPLY;
2851 return_error_param = -EINVAL;
2852 return_error_line = __LINE__;
2853 goto err_bad_offset;
2854 }
2855
2856 /*
2857 * Copy the source user buffer up to the next object
2858 * that will be processed.
2859 */
2860 copy_size = object_offset - user_offset;
2861 if (copy_size && (user_offset > object_offset ||
2862 binder_alloc_copy_user_to_buffer(
2863 &target_proc->alloc,
2864 t->buffer, user_offset,
2865 user_buffer + user_offset,
2866 copy_size))) {
2867 binder_user_error("%d:%d got transaction with invalid data ptr\n",
2868 proc->pid, thread->pid);
2869 return_error = BR_FAILED_REPLY;
2870 return_error_param = -EFAULT;
2871 return_error_line = __LINE__;
2872 goto err_copy_data_failed;
2873 }
2874 object_size = binder_get_object(target_proc, user_buffer,
2875 t->buffer, object_offset, &object);
2876 if (object_size == 0 || object_offset < off_min) {
2877 binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n",
2878 proc->pid, thread->pid,
2879 (u64)object_offset,
2880 (u64)off_min,
2881 (u64)t->buffer->data_size);
2882 return_error = BR_FAILED_REPLY;
2883 return_error_param = -EINVAL;
2884 return_error_line = __LINE__;
2885 goto err_bad_offset;
2886 }
2887 /*
2888 * Set offset to the next buffer fragment to be
2889 * copied
2890 */
2891 user_offset = object_offset + object_size;
2892
2893 hdr = &object.hdr;
2894 off_min = object_offset + object_size;
2895 switch (hdr->type) {
2896 case BINDER_TYPE_BINDER:
2897 case BINDER_TYPE_WEAK_BINDER: {
2898 struct flat_binder_object *fp;
2899
2900 fp = to_flat_binder_object(hdr);
2901 ret = binder_translate_binder(fp, t, thread);
2902
2903 if (ret < 0 ||
2904 binder_alloc_copy_to_buffer(&target_proc->alloc,
2905 t->buffer,
2906 object_offset,
2907 fp, sizeof(*fp))) {
2908 return_error = BR_FAILED_REPLY;
2909 return_error_param = ret;
2910 return_error_line = __LINE__;
2911 goto err_translate_failed;
2912 }
2913 } break;
2914 case BINDER_TYPE_HANDLE:
2915 case BINDER_TYPE_WEAK_HANDLE: {
2916 struct flat_binder_object *fp;
2917
2918 fp = to_flat_binder_object(hdr);
2919 ret = binder_translate_handle(fp, t, thread);
2920 if (ret < 0 ||
2921 binder_alloc_copy_to_buffer(&target_proc->alloc,
2922 t->buffer,
2923 object_offset,
2924 fp, sizeof(*fp))) {
2925 return_error = BR_FAILED_REPLY;
2926 return_error_param = ret;
2927 return_error_line = __LINE__;
2928 goto err_translate_failed;
2929 }
2930 } break;
2931
2932 case BINDER_TYPE_FD: {
2933 struct binder_fd_object *fp = to_binder_fd_object(hdr);
2934 binder_size_t fd_offset = object_offset +
2935 (uintptr_t)&fp->fd - (uintptr_t)fp;
2936 int ret = binder_translate_fd(fp->fd, fd_offset, t,
2937 thread, in_reply_to);
2938
2939 fp->pad_binder = 0;
2940 if (ret < 0 ||
2941 binder_alloc_copy_to_buffer(&target_proc->alloc,
2942 t->buffer,
2943 object_offset,
2944 fp, sizeof(*fp))) {
2945 return_error = BR_FAILED_REPLY;
2946 return_error_param = ret;
2947 return_error_line = __LINE__;
2948 goto err_translate_failed;
2949 }
2950 } break;
2951 case BINDER_TYPE_FDA: {
2952 struct binder_object ptr_object;
2953 binder_size_t parent_offset;
2954 struct binder_fd_array_object *fda =
2955 to_binder_fd_array_object(hdr);
2956 size_t num_valid = (buffer_offset - off_start_offset) /
2957 sizeof(binder_size_t);
2958 struct binder_buffer_object *parent =
2959 binder_validate_ptr(target_proc, t->buffer,
2960 &ptr_object, fda->parent,
2961 off_start_offset,
2962 &parent_offset,
2963 num_valid);
2964 if (!parent) {
2965 binder_user_error("%d:%d got transaction with invalid parent offset or type\n",
2966 proc->pid, thread->pid);
2967 return_error = BR_FAILED_REPLY;
2968 return_error_param = -EINVAL;
2969 return_error_line = __LINE__;
2970 goto err_bad_parent;
2971 }
2972 if (!binder_validate_fixup(target_proc, t->buffer,
2973 off_start_offset,
2974 parent_offset,
2975 fda->parent_offset,
2976 last_fixup_obj_off,
2977 last_fixup_min_off)) {
2978 binder_user_error("%d:%d got transaction with out-of-order buffer fixup\n",
2979 proc->pid, thread->pid);
2980 return_error = BR_FAILED_REPLY;
2981 return_error_param = -EINVAL;
2982 return_error_line = __LINE__;
2983 goto err_bad_parent;
2984 }
2985 ret = binder_translate_fd_array(fda, parent, t, thread,
2986 in_reply_to);
2987 if (ret < 0 ||
2988 binder_alloc_copy_to_buffer(&target_proc->alloc,
2989 t->buffer,
2990 object_offset,
2991 fda, sizeof(*fda))) {
2992 return_error = BR_FAILED_REPLY;
2993 return_error_param = ret;
2994 return_error_line = __LINE__;
2995 goto err_translate_failed;
2996 }
2997 last_fixup_obj_off = parent_offset;
2998 last_fixup_min_off =
2999 fda->parent_offset + sizeof(u32) * fda->num_fds;
3000 } break;
3001 case BINDER_TYPE_PTR: {
3002 struct binder_buffer_object *bp =
3003 to_binder_buffer_object(hdr);
3004 size_t buf_left = sg_buf_end_offset - sg_buf_offset;
3005 size_t num_valid;
3006
3007 if (bp->length > buf_left) {
3008 binder_user_error("%d:%d got transaction with too large buffer\n",
3009 proc->pid, thread->pid);
3010 return_error = BR_FAILED_REPLY;
3011 return_error_param = -EINVAL;
3012 return_error_line = __LINE__;
3013 goto err_bad_offset;
3014 }
3015 if (binder_alloc_copy_user_to_buffer(
3016 &target_proc->alloc,
3017 t->buffer,
3018 sg_buf_offset,
3019 (const void __user *)
3020 (uintptr_t)bp->buffer,
3021 bp->length)) {
3022 binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
3023 proc->pid, thread->pid);
3024 return_error_param = -EFAULT;
3025 return_error = BR_FAILED_REPLY;
3026 return_error_line = __LINE__;
3027 goto err_copy_data_failed;
3028 }
3029 /* Fixup buffer pointer to target proc address space */
3030 bp->buffer = (uintptr_t)
3031 t->buffer->user_data + sg_buf_offset;
3032 sg_buf_offset += ALIGN(bp->length, sizeof(u64));
3033
3034 num_valid = (buffer_offset - off_start_offset) /
3035 sizeof(binder_size_t);
3036 ret = binder_fixup_parent(t, thread, bp,
3037 off_start_offset,
3038 num_valid,
3039 last_fixup_obj_off,
3040 last_fixup_min_off);
3041 if (ret < 0 ||
3042 binder_alloc_copy_to_buffer(&target_proc->alloc,
3043 t->buffer,
3044 object_offset,
3045 bp, sizeof(*bp))) {
3046 return_error = BR_FAILED_REPLY;
3047 return_error_param = ret;
3048 return_error_line = __LINE__;
3049 goto err_translate_failed;
3050 }
3051 last_fixup_obj_off = object_offset;
3052 last_fixup_min_off = 0;
3053 } break;
3054 default:
3055 binder_user_error("%d:%d got transaction with invalid object type, %x\n",
3056 proc->pid, thread->pid, hdr->type);
3057 return_error = BR_FAILED_REPLY;
3058 return_error_param = -EINVAL;
3059 return_error_line = __LINE__;
3060 goto err_bad_object_type;
3061 }
3062 }
3063 /* Done processing objects, copy the rest of the buffer */
3064 if (binder_alloc_copy_user_to_buffer(
3065 &target_proc->alloc,
3066 t->buffer, user_offset,
3067 user_buffer + user_offset,
3068 tr->data_size - user_offset)) {
3069 binder_user_error("%d:%d got transaction with invalid data ptr\n",
3070 proc->pid, thread->pid);
3071 return_error = BR_FAILED_REPLY;
3072 return_error_param = -EFAULT;
3073 return_error_line = __LINE__;
3074 goto err_copy_data_failed;
3075 }
3076 if (t->buffer->oneway_spam_suspect)
3077 tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
3078 else
3079 tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
3080 t->work.type = BINDER_WORK_TRANSACTION;
3081
3082 if (reply) {
3083 binder_enqueue_thread_work(thread, tcomplete);
3084 binder_inner_proc_lock(target_proc);
3085 if (target_thread->is_dead) {
3086 return_error = BR_DEAD_REPLY;
3087 binder_inner_proc_unlock(target_proc);
3088 goto err_dead_proc_or_thread;
3089 }
3090 BUG_ON(t->buffer->async_transaction != 0);
3091 binder_pop_transaction_ilocked(target_thread, in_reply_to);
3092 binder_enqueue_thread_work_ilocked(target_thread, &t->work);
3093 target_proc->outstanding_txns++;
3094 binder_inner_proc_unlock(target_proc);
3095 wake_up_interruptible_sync(&target_thread->wait);
3096 binder_free_transaction(in_reply_to);
3097 } else if (!(t->flags & TF_ONE_WAY)) {
3098 BUG_ON(t->buffer->async_transaction != 0);
3099 binder_inner_proc_lock(proc);
3100 /*
3101 * Defer the TRANSACTION_COMPLETE, so we don't return to
3102 * userspace immediately; this allows the target process to
3103 * immediately start processing this transaction, reducing
3104 * latency. We will then return the TRANSACTION_COMPLETE when
3105 * the target replies (or there is an error).
3106 */
3107 binder_enqueue_deferred_thread_work_ilocked(thread, tcomplete);
3108 t->need_reply = 1;
3109 t->from_parent = thread->transaction_stack;
3110 thread->transaction_stack = t;
3111 binder_inner_proc_unlock(proc);
3112 return_error = binder_proc_transaction(t,
3113 target_proc, target_thread);
3114 if (return_error) {
3115 binder_inner_proc_lock(proc);
3116 binder_pop_transaction_ilocked(thread, t);
3117 binder_inner_proc_unlock(proc);
3118 goto err_dead_proc_or_thread;
3119 }
3120 } else {
3121 BUG_ON(target_node == NULL);
3122 BUG_ON(t->buffer->async_transaction != 1);
3123 binder_enqueue_thread_work(thread, tcomplete);
3124 return_error = binder_proc_transaction(t, target_proc, NULL);
3125 if (return_error)
3126 goto err_dead_proc_or_thread;
3127 }
3128 if (target_thread)
3129 binder_thread_dec_tmpref(target_thread);
3130 binder_proc_dec_tmpref(target_proc);
3131 if (target_node)
3132 binder_dec_node_tmpref(target_node);
3133 /*
3134 * write barrier to synchronize with initialization
3135 * of log entry
3136 */
3137 smp_wmb();
3138 WRITE_ONCE(e->debug_id_done, t_debug_id);
3139 return;
3140
3141 err_dead_proc_or_thread:
3142 return_error_line = __LINE__;
3143 binder_dequeue_work(proc, tcomplete);
3144 err_translate_failed:
3145 err_bad_object_type:
3146 err_bad_offset:
3147 err_bad_parent:
3148 err_copy_data_failed:
3149 binder_free_txn_fixups(t);
3150 trace_binder_transaction_failed_buffer_release(t->buffer);
3151 binder_transaction_buffer_release(target_proc, NULL, t->buffer,
3152 buffer_offset, true);
3153 if (target_node)
3154 binder_dec_node_tmpref(target_node);
3155 target_node = NULL;
3156 t->buffer->transaction = NULL;
3157 binder_alloc_free_buf(&target_proc->alloc, t->buffer);
3158 err_binder_alloc_buf_failed:
3159 err_bad_extra_size:
3160 if (secctx)
3161 security_release_secctx(secctx, secctx_sz);
3162 err_get_secctx_failed:
3163 kfree(tcomplete);
3164 binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
3165 err_alloc_tcomplete_failed:
3166 if (trace_binder_txn_latency_free_enabled())
3167 binder_txn_latency_free(t);
3168 kfree(t);
3169 binder_stats_deleted(BINDER_STAT_TRANSACTION);
3170 err_alloc_t_failed:
3171 err_bad_todo_list:
3172 err_bad_call_stack:
3173 err_empty_call_stack:
3174 err_dead_binder:
3175 err_invalid_target_handle:
3176 if (target_thread)
3177 binder_thread_dec_tmpref(target_thread);
3178 if (target_proc)
3179 binder_proc_dec_tmpref(target_proc);
3180 if (target_node) {
3181 binder_dec_node(target_node, 1, 0);
3182 binder_dec_node_tmpref(target_node);
3183 }
3184
3185 binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
3186 "%d:%d transaction failed %d/%d, size %lld-%lld line %d\n",
3187 proc->pid, thread->pid, return_error, return_error_param,
3188 (u64)tr->data_size, (u64)tr->offsets_size,
3189 return_error_line);
3190
3191 {
3192 struct binder_transaction_log_entry *fe;
3193
3194 e->return_error = return_error;
3195 e->return_error_param = return_error_param;
3196 e->return_error_line = return_error_line;
3197 fe = binder_transaction_log_add(&binder_transaction_log_failed);
3198 *fe = *e;
3199 /*
3200 * write barrier to synchronize with initialization
3201 * of log entry
3202 */
3203 smp_wmb();
3204 WRITE_ONCE(e->debug_id_done, t_debug_id);
3205 WRITE_ONCE(fe->debug_id_done, t_debug_id);
3206 }
3207
3208 BUG_ON(thread->return_error.cmd != BR_OK);
3209 if (in_reply_to) {
3210 thread->return_error.cmd = BR_TRANSACTION_COMPLETE;
3211 binder_enqueue_thread_work(thread, &thread->return_error.work);
3212 binder_send_failed_reply(in_reply_to, return_error);
3213 } else {
3214 thread->return_error.cmd = return_error;
3215 binder_enqueue_thread_work(thread, &thread->return_error.work);
3216 }
3217 }
3218

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

\
 
 \ /
  Last update: 2021-11-25 03:10    [W:0.146 / U:3.028 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site