@@ -1608,15 +1608,21 @@ static void binder_cleanup_transaction(struct binder_transaction *t,
1608
1608
/**
1609
1609
* binder_get_object() - gets object and checks for valid metadata
1610
1610
* @proc: binder_proc owning the buffer
1611
+ * @u: sender's user pointer to base of buffer
1611
1612
* @buffer: binder_buffer that we're parsing.
1612
1613
* @offset: offset in the @buffer at which to validate an object.
1613
1614
* @object: struct binder_object to read into
1614
1615
*
1615
- * Return: If there's a valid metadata object at @offset in @buffer, the
1616
+ * Copy the binder object at the given offset into @object. If @u is
1617
+ * provided then the copy is from the sender's buffer. If not, then
1618
+ * it is copied from the target's @buffer.
1619
+ *
1620
+ * Return: If there's a valid metadata object at @offset, the
1616
1621
* size of that object. Otherwise, it returns zero. The object
1617
1622
* is read into the struct binder_object pointed to by @object.
1618
1623
*/
1619
1624
static size_t binder_get_object (struct binder_proc * proc ,
1625
+ const void __user * u ,
1620
1626
struct binder_buffer * buffer ,
1621
1627
unsigned long offset ,
1622
1628
struct binder_object * object )
@@ -1626,10 +1632,16 @@ static size_t binder_get_object(struct binder_proc *proc,
1626
1632
size_t object_size = 0 ;
1627
1633
1628
1634
read_size = min_t (size_t , sizeof (* object ), buffer -> data_size - offset );
1629
- if (offset > buffer -> data_size || read_size < sizeof (* hdr ) ||
1630
- binder_alloc_copy_from_buffer (& proc -> alloc , object , buffer ,
1631
- offset , read_size ))
1635
+ if (offset > buffer -> data_size || read_size < sizeof (* hdr ))
1632
1636
return 0 ;
1637
+ if (u ) {
1638
+ if (copy_from_user (object , u + offset , read_size ))
1639
+ return 0 ;
1640
+ } else {
1641
+ if (binder_alloc_copy_from_buffer (& proc -> alloc , object , buffer ,
1642
+ offset , read_size ))
1643
+ return 0 ;
1644
+ }
1633
1645
1634
1646
/* Ok, now see if we read a complete object. */
1635
1647
hdr = & object -> hdr ;
@@ -1702,7 +1714,7 @@ static struct binder_buffer_object *binder_validate_ptr(
1702
1714
b , buffer_offset ,
1703
1715
sizeof (object_offset )))
1704
1716
return NULL ;
1705
- object_size = binder_get_object (proc , b , object_offset , object );
1717
+ object_size = binder_get_object (proc , NULL , b , object_offset , object );
1706
1718
if (!object_size || object -> hdr .type != BINDER_TYPE_PTR )
1707
1719
return NULL ;
1708
1720
if (object_offsetp )
@@ -1767,7 +1779,8 @@ static bool binder_validate_fixup(struct binder_proc *proc,
1767
1779
unsigned long buffer_offset ;
1768
1780
struct binder_object last_object ;
1769
1781
struct binder_buffer_object * last_bbo ;
1770
- size_t object_size = binder_get_object (proc , b , last_obj_offset ,
1782
+ size_t object_size = binder_get_object (proc , NULL , b ,
1783
+ last_obj_offset ,
1771
1784
& last_object );
1772
1785
if (object_size != sizeof (* last_bbo ))
1773
1786
return false;
@@ -1882,7 +1895,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
1882
1895
if (!binder_alloc_copy_from_buffer (& proc -> alloc , & object_offset ,
1883
1896
buffer , buffer_offset ,
1884
1897
sizeof (object_offset )))
1885
- object_size = binder_get_object (proc , buffer ,
1898
+ object_size = binder_get_object (proc , NULL , buffer ,
1886
1899
object_offset , & object );
1887
1900
if (object_size == 0 ) {
1888
1901
pr_err ("transaction release %d bad object at offset %lld, size %zd\n" ,
@@ -2455,6 +2468,7 @@ static void binder_transaction(struct binder_proc *proc,
2455
2468
binder_size_t off_start_offset , off_end_offset ;
2456
2469
binder_size_t off_min ;
2457
2470
binder_size_t sg_buf_offset , sg_buf_end_offset ;
2471
+ binder_size_t user_offset = 0 ;
2458
2472
struct binder_proc * target_proc = NULL ;
2459
2473
struct binder_thread * target_thread = NULL ;
2460
2474
struct binder_node * target_node = NULL ;
@@ -2469,6 +2483,8 @@ static void binder_transaction(struct binder_proc *proc,
2469
2483
int t_debug_id = atomic_inc_return (& binder_last_id );
2470
2484
char * secctx = NULL ;
2471
2485
u32 secctx_sz = 0 ;
2486
+ const void __user * user_buffer = (const void __user * )
2487
+ (uintptr_t )tr -> data .ptr .buffer ;
2472
2488
2473
2489
e = binder_transaction_log_add (& binder_transaction_log );
2474
2490
e -> debug_id = t_debug_id ;
@@ -2780,19 +2796,6 @@ static void binder_transaction(struct binder_proc *proc,
2780
2796
t -> buffer -> clear_on_free = !!(t -> flags & TF_CLEAR_BUF );
2781
2797
trace_binder_transaction_alloc_buf (t -> buffer );
2782
2798
2783
- if (binder_alloc_copy_user_to_buffer (
2784
- & target_proc -> alloc ,
2785
- t -> buffer , 0 ,
2786
- (const void __user * )
2787
- (uintptr_t )tr -> data .ptr .buffer ,
2788
- tr -> data_size )) {
2789
- binder_user_error ("%d:%d got transaction with invalid data ptr\n" ,
2790
- proc -> pid , thread -> pid );
2791
- return_error = BR_FAILED_REPLY ;
2792
- return_error_param = - EFAULT ;
2793
- return_error_line = __LINE__ ;
2794
- goto err_copy_data_failed ;
2795
- }
2796
2799
if (binder_alloc_copy_user_to_buffer (
2797
2800
& target_proc -> alloc ,
2798
2801
t -> buffer ,
@@ -2837,6 +2840,7 @@ static void binder_transaction(struct binder_proc *proc,
2837
2840
size_t object_size ;
2838
2841
struct binder_object object ;
2839
2842
binder_size_t object_offset ;
2843
+ binder_size_t copy_size ;
2840
2844
2841
2845
if (binder_alloc_copy_from_buffer (& target_proc -> alloc ,
2842
2846
& object_offset ,
@@ -2848,8 +2852,27 @@ static void binder_transaction(struct binder_proc *proc,
2848
2852
return_error_line = __LINE__ ;
2849
2853
goto err_bad_offset ;
2850
2854
}
2851
- object_size = binder_get_object (target_proc , t -> buffer ,
2852
- object_offset , & object );
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 );
2853
2876
if (object_size == 0 || object_offset < off_min ) {
2854
2877
binder_user_error ("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n" ,
2855
2878
proc -> pid , thread -> pid ,
@@ -2861,6 +2884,11 @@ static void binder_transaction(struct binder_proc *proc,
2861
2884
return_error_line = __LINE__ ;
2862
2885
goto err_bad_offset ;
2863
2886
}
2887
+ /*
2888
+ * Set offset to the next buffer fragment to be
2889
+ * copied
2890
+ */
2891
+ user_offset = object_offset + object_size ;
2864
2892
2865
2893
hdr = & object .hdr ;
2866
2894
off_min = object_offset + object_size ;
@@ -2956,9 +2984,14 @@ static void binder_transaction(struct binder_proc *proc,
2956
2984
}
2957
2985
ret = binder_translate_fd_array (fda , parent , t , thread ,
2958
2986
in_reply_to );
2959
- if (ret < 0 ) {
2987
+ if (!ret )
2988
+ ret = binder_alloc_copy_to_buffer (& target_proc -> alloc ,
2989
+ t -> buffer ,
2990
+ object_offset ,
2991
+ fda , sizeof (* fda ));
2992
+ if (ret ) {
2960
2993
return_error = BR_FAILED_REPLY ;
2961
- return_error_param = ret ;
2994
+ return_error_param = ret > 0 ? - EINVAL : ret ;
2962
2995
return_error_line = __LINE__ ;
2963
2996
goto err_translate_failed ;
2964
2997
}
@@ -3028,6 +3061,19 @@ static void binder_transaction(struct binder_proc *proc,
3028
3061
goto err_bad_object_type ;
3029
3062
}
3030
3063
}
3064
+ /* Done processing objects, copy the rest of the buffer */
3065
+ if (binder_alloc_copy_user_to_buffer (
3066
+ & target_proc -> alloc ,
3067
+ t -> buffer , user_offset ,
3068
+ user_buffer + user_offset ,
3069
+ tr -> data_size - user_offset )) {
3070
+ binder_user_error ("%d:%d got transaction with invalid data ptr\n" ,
3071
+ proc -> pid , thread -> pid );
3072
+ return_error = BR_FAILED_REPLY ;
3073
+ return_error_param = - EFAULT ;
3074
+ return_error_line = __LINE__ ;
3075
+ goto err_copy_data_failed ;
3076
+ }
3031
3077
if (t -> buffer -> oneway_spam_suspect )
3032
3078
tcomplete -> type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT ;
3033
3079
else
0 commit comments