2021-11-23 19:17:47

by Todd Kjos

[permalink] [raw]
Subject: [PATCH 0/3] binder: Prevent untranslated sender data from being copied to target

Binder copies transactions directly from the sender buffer
to the target buffer and then fixes up BINDER_TYPE_PTR and
BINDER_TYPE_FDA objects. This means there is a brief time
when sender pointers and fds are visible to the target
process.

This series reworks the the sender to target copy to
avoid leaking any untranslated sender data from being
visible in the target.

Todd Kjos (3):
binder: defer copies of pre-patched txn data
binder: read pre-translated fds from sender buffer
binder: avoid potential data leakage when copying txn

drivers/android/binder.c | 442 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 387 insertions(+), 55 deletions(-)


2021-11-23 19:17:49

by Todd Kjos

[permalink] [raw]
Subject: [PATCH 1/3] binder: avoid potential data leakage when copying txn

Transactions are copied from the sender to the target
first and objects like BINDER_TYPE_PTR and BINDER_TYPE_FDA
are then fixed up. This means there is a short period where
the sender's version of these objects are visible to the
target prior to the fixups.

Instead of copying all of the data first, copy data only
after any needed fixups have been applied.

Signed-off-by: Todd Kjos <[email protected]>
---
drivers/android/binder.c | 95 +++++++++++++++++++++++++++++-----------
1 file changed, 70 insertions(+), 25 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 49fb74196d02..571d3c203557 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1608,15 +1608,21 @@ static void binder_cleanup_transaction(struct binder_transaction *t,
/**
* binder_get_object() - gets object and checks for valid metadata
* @proc: binder_proc owning the buffer
+ * @u: sender's user pointer to base of buffer
* @buffer: binder_buffer that we're parsing.
* @offset: offset in the @buffer at which to validate an object.
* @object: struct binder_object to read into
*
- * Return: If there's a valid metadata object at @offset in @buffer, the
+ * Copy the binder object at the given offset into @object. If @u is
+ * provided then the copy is from the sender's buffer. If not, then
+ * it is copied from the target's @buffer.
+ *
+ * Return: If there's a valid metadata object at @offset, the
* size of that object. Otherwise, it returns zero. The object
* is read into the struct binder_object pointed to by @object.
*/
static size_t binder_get_object(struct binder_proc *proc,
+ const void __user *u,
struct binder_buffer *buffer,
unsigned long offset,
struct binder_object *object)
@@ -1626,10 +1632,16 @@ static size_t binder_get_object(struct binder_proc *proc,
size_t object_size = 0;

read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
- if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
- binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
- offset, read_size))
+ if (offset > buffer->data_size || read_size < sizeof(*hdr))
return 0;
+ if (u) {
+ if (copy_from_user(object, u + offset, read_size))
+ return 0;
+ } else {
+ if (binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
+ offset, read_size))
+ return 0;
+ }

/* Ok, now see if we read a complete object. */
hdr = &object->hdr;
@@ -1702,7 +1714,7 @@ static struct binder_buffer_object *binder_validate_ptr(
b, buffer_offset,
sizeof(object_offset)))
return NULL;
- object_size = binder_get_object(proc, b, object_offset, object);
+ object_size = binder_get_object(proc, NULL, b, object_offset, object);
if (!object_size || object->hdr.type != BINDER_TYPE_PTR)
return NULL;
if (object_offsetp)
@@ -1767,7 +1779,8 @@ static bool binder_validate_fixup(struct binder_proc *proc,
unsigned long buffer_offset;
struct binder_object last_object;
struct binder_buffer_object *last_bbo;
- size_t object_size = binder_get_object(proc, b, last_obj_offset,
+ size_t object_size = binder_get_object(proc, NULL, b,
+ last_obj_offset,
&last_object);
if (object_size != sizeof(*last_bbo))
return false;
@@ -1882,7 +1895,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
if (!binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
buffer, buffer_offset,
sizeof(object_offset)))
- object_size = binder_get_object(proc, buffer,
+ object_size = binder_get_object(proc, NULL, buffer,
object_offset, &object);
if (object_size == 0) {
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,
binder_size_t off_start_offset, off_end_offset;
binder_size_t off_min;
binder_size_t sg_buf_offset, sg_buf_end_offset;
+ binder_size_t user_offset = 0;
struct binder_proc *target_proc = NULL;
struct binder_thread *target_thread = NULL;
struct binder_node *target_node = NULL;
@@ -2469,6 +2483,8 @@ static void binder_transaction(struct binder_proc *proc,
int t_debug_id = atomic_inc_return(&binder_last_id);
char *secctx = NULL;
u32 secctx_sz = 0;
+ const void __user *user_buffer = (const void __user *)
+ (uintptr_t)tr->data.ptr.buffer;

e = binder_transaction_log_add(&binder_transaction_log);
e->debug_id = t_debug_id;
@@ -2692,7 +2708,7 @@ static void binder_transaction(struct binder_proc *proc,
"%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld-%lld\n",
proc->pid, thread->pid, t->debug_id,
target_proc->pid, target_thread->pid,
- (u64)tr->data.ptr.buffer,
+ (u64)user_buffer,
(u64)tr->data.ptr.offsets,
(u64)tr->data_size, (u64)tr->offsets_size,
(u64)extra_buffers_size);
@@ -2701,7 +2717,7 @@ static void binder_transaction(struct binder_proc *proc,
"%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld-%lld\n",
proc->pid, thread->pid, t->debug_id,
target_proc->pid, target_node->debug_id,
- (u64)tr->data.ptr.buffer,
+ (u64)user_buffer,
(u64)tr->data.ptr.offsets,
(u64)tr->data_size, (u64)tr->offsets_size,
(u64)extra_buffers_size);
@@ -2780,19 +2796,6 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer->clear_on_free = !!(t->flags & TF_CLEAR_BUF);
trace_binder_transaction_alloc_buf(t->buffer);

- if (binder_alloc_copy_user_to_buffer(
- &target_proc->alloc,
- t->buffer, 0,
- (const void __user *)
- (uintptr_t)tr->data.ptr.buffer,
- tr->data_size)) {
- binder_user_error("%d:%d got transaction with invalid data ptr\n",
- proc->pid, thread->pid);
- return_error = BR_FAILED_REPLY;
- return_error_param = -EFAULT;
- return_error_line = __LINE__;
- goto err_copy_data_failed;
- }
if (binder_alloc_copy_user_to_buffer(
&target_proc->alloc,
t->buffer,
@@ -2837,6 +2840,7 @@ static void binder_transaction(struct binder_proc *proc,
size_t object_size;
struct binder_object object;
binder_size_t object_offset;
+ binder_size_t copy_size;

if (binder_alloc_copy_from_buffer(&target_proc->alloc,
&object_offset,
@@ -2848,8 +2852,27 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_offset;
}
- object_size = binder_get_object(target_proc, t->buffer,
- object_offset, &object);
+
+ /*
+ * Copy the source user buffer up to the next object
+ * that will be processed.
+ */
+ copy_size = object_offset - user_offset;
+ if (copy_size && (user_offset > object_offset ||
+ binder_alloc_copy_user_to_buffer(
+ &target_proc->alloc,
+ t->buffer, user_offset,
+ user_buffer + user_offset,
+ copy_size))) {
+ binder_user_error("%d:%d got transaction with invalid data ptr\n",
+ proc->pid, thread->pid);
+ return_error = BR_FAILED_REPLY;
+ return_error_param = -EFAULT;
+ return_error_line = __LINE__;
+ goto err_copy_data_failed;
+ }
+ object_size = binder_get_object(target_proc, user_buffer,
+ t->buffer, object_offset, &object);
if (object_size == 0 || object_offset < off_min) {
binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n",
proc->pid, thread->pid,
@@ -2861,6 +2884,11 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_offset;
}
+ /*
+ * Set offset to the next buffer fragment to be
+ * copied
+ */
+ user_offset = object_offset + object_size;

hdr = &object.hdr;
off_min = object_offset + object_size;
@@ -2956,7 +2984,11 @@ static void binder_transaction(struct binder_proc *proc,
}
ret = binder_translate_fd_array(fda, parent, t, thread,
in_reply_to);
- if (ret < 0) {
+ if (ret < 0 ||
+ binder_alloc_copy_to_buffer(&target_proc->alloc,
+ t->buffer,
+ object_offset,
+ fda, sizeof(*fda))) {
return_error = BR_FAILED_REPLY;
return_error_param = ret;
return_error_line = __LINE__;
@@ -3028,6 +3060,19 @@ static void binder_transaction(struct binder_proc *proc,
goto err_bad_object_type;
}
}
+ /* Done processing objects, copy the rest of the buffer */
+ if (binder_alloc_copy_user_to_buffer(
+ &target_proc->alloc,
+ t->buffer, user_offset,
+ user_buffer + user_offset,
+ tr->data_size - user_offset)) {
+ binder_user_error("%d:%d got transaction with invalid data ptr\n",
+ proc->pid, thread->pid);
+ return_error = BR_FAILED_REPLY;
+ return_error_param = -EFAULT;
+ return_error_line = __LINE__;
+ goto err_copy_data_failed;
+ }
if (t->buffer->oneway_spam_suspect)
tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
else
--
2.34.0.rc2.393.gf8c9666880-goog


2021-11-23 19:17:55

by Todd Kjos

[permalink] [raw]
Subject: [PATCH 2/3] binder: read pre-translated fds from sender buffer

Since we are no longer going to copy the pre-fixup
data from the target buffer, we need to read
pre-translated FD array information from the source
buffer.

Signed-off-by: Todd Kjos <[email protected]>
---
drivers/android/binder.c | 40 +++++++++++++++++++++++++++++++++-------
1 file changed, 33 insertions(+), 7 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 571d3c203557..2300fa8e09d5 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2234,15 +2234,17 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
}

static int binder_translate_fd_array(struct binder_fd_array_object *fda,
+ const void __user *u,
struct binder_buffer_object *parent,
+ struct binder_buffer_object *uparent,
struct binder_transaction *t,
struct binder_thread *thread,
struct binder_transaction *in_reply_to)
{
binder_size_t fdi, fd_buf_size;
binder_size_t fda_offset;
+ const void __user *ufda_base;
struct binder_proc *proc = thread->proc;
- struct binder_proc *target_proc = t->to_proc;

fd_buf_size = sizeof(u32) * fda->num_fds;
if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
@@ -2266,7 +2268,10 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
*/
fda_offset = (parent->buffer - (uintptr_t)t->buffer->user_data) +
fda->parent_offset;
- if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32))) {
+ ufda_base = (void __user *)uparent->buffer + fda->parent_offset;
+
+ if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32)) ||
+ !IS_ALIGNED((unsigned long)ufda_base, sizeof(u32))) {
binder_user_error("%d:%d parent offset not aligned correctly.\n",
proc->pid, thread->pid);
return -EINVAL;
@@ -2275,10 +2280,9 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
u32 fd;
int ret;
binder_size_t offset = fda_offset + fdi * sizeof(fd);
+ binder_size_t uoffset = fdi * sizeof(fd);

- ret = binder_alloc_copy_from_buffer(&target_proc->alloc,
- &fd, t->buffer,
- offset, sizeof(fd));
+ ret = copy_from_user(&fd, ufda_base + uoffset, sizeof(fd));
if (!ret)
ret = binder_translate_fd(fd, offset, t, thread,
in_reply_to);
@@ -2951,6 +2955,8 @@ static void binder_transaction(struct binder_proc *proc,
case BINDER_TYPE_FDA: {
struct binder_object ptr_object;
binder_size_t parent_offset;
+ struct binder_object user_object;
+ size_t user_parent_size;
struct binder_fd_array_object *fda =
to_binder_fd_array_object(hdr);
size_t num_valid = (buffer_offset - off_start_offset) /
@@ -2982,8 +2988,28 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_parent;
}
- ret = binder_translate_fd_array(fda, parent, t, thread,
- in_reply_to);
+
+ /*
+ * We need to read the user version of the parent
+ * object to get the original user offset
+ */
+ user_parent_size =
+ binder_get_object(proc, user_buffer, t->buffer,
+ parent_offset, &user_object);
+ if (user_parent_size != sizeof(user_object.bbo)) {
+ binder_user_error("%d:%d invalid ptr object size: %lld vs %lld\n",
+ proc->pid, thread->pid,
+ user_parent_size,
+ sizeof(user_object.bbo));
+ return_error = BR_FAILED_REPLY;
+ return_error_param = -EINVAL;
+ return_error_line = __LINE__;
+ goto err_bad_parent;
+ }
+ ret = binder_translate_fd_array(fda, user_buffer,
+ parent,
+ &user_object.bbo, t,
+ thread, in_reply_to);
if (ret < 0 ||
binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer,
--
2.34.0.rc2.393.gf8c9666880-goog


2021-11-23 19:17:57

by Todd Kjos

[permalink] [raw]
Subject: [PATCH 3/3] binder: defer copies of pre-patched txn data

BINDER_TYPE_PTR objects point to memory areas in the
source process to be copied into the target buffer
as part of a transaction. This implements a scatter-
gather model where non-contiguous memory in a source
process is "gathered" into a contiguous region in
the target buffer.

The data can include pointers that must be fixed up
to correctly point to the copied data. To avoid making
source process pointers visible to the target process,
this patch defers the copy until the fixups are known
and then copies and fixeups are done together.

There is a special case of BINDER_TYPE_FDA which applies
the fixup later in the target process context. In this
case the user data is skipped (so no untranslated fds
become visible to the target).

Signed-off-by: Todd Kjos <[email protected]>
---
drivers/android/binder.c | 311 +++++++++++++++++++++++++++++++++++----
1 file changed, 286 insertions(+), 25 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 2300fa8e09d5..56dc814b8dde 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2233,7 +2233,258 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
return ret;
}

-static int binder_translate_fd_array(struct binder_fd_array_object *fda,
+/**
+ * struct binder_ptr_fixup - data to be fixed-up in target buffer
+ * @offset offset in target buffer to fixup
+ * @skip_size bytes to skip in copy (fixup will be written later)
+ * @fixup_data data to write at fixup offset
+ * @node list node
+ *
+ * This is used for the pointer fixup list (pf) which is created and consumed
+ * during binder_transaction() and is only accessed locally. No
+ * locking is necessary.
+ *
+ * The list is ordered by @offset.
+ */
+struct binder_ptr_fixup {
+ binder_size_t offset;
+ size_t skip_size;
+ binder_uintptr_t fixup_data;
+ struct list_head node;
+};
+
+/**
+ * struct binder_sg_copy - scatter-gather data to be copied
+ * @offset offset in target buffer
+ * @uaddr user address in source buffer
+ * @length bytes to copy
+ * @node list node
+ *
+ * This is used for the sg copy list (sgc) which is created and consumed
+ * during binder_transaction() and is only accessed locally. No
+ * locking is necessary.
+ *
+ * The list is ordered by @offset.
+ */
+struct binder_sg_copy {
+ binder_size_t offset;
+ const void __user *uaddr;
+ size_t length;
+ struct list_head node;
+};
+
+/**
+ * binder_do_deferred_txn_copies() - copy and fixup scatter-gather data
+ * @alloc: binder_alloc associated with @buffer
+ * @buffer: binder buffer in target process
+ * @sgc_head: list_head of scatter-gather copy list
+ * @pf_head: list_head of pointer fixup list
+ *
+ * Processes all elements of @sgc_head, applying fixups from @pf_head
+ * and copying the scatter-gather data from the source process' user
+ * buffer to the target's buffer. It is expected that the list creation
+ * and processing all occurs during binder_transaction() so these lists
+ * are only accessed in local context.
+ *
+ * Return: 0=success, else -errno
+ */
+static int binder_do_deferred_txn_copies(struct binder_alloc *alloc,
+ struct binder_buffer *buffer,
+ struct list_head *sgc_head,
+ struct list_head *pf_head)
+{
+ int ret = 0;
+ struct list_head *entry, *tmp;
+ struct binder_ptr_fixup *pf =
+ list_first_entry_or_null(pf_head, struct binder_ptr_fixup,
+ node);
+
+ list_for_each_safe(entry, tmp, sgc_head) {
+ size_t bytes_copied = 0;
+ struct binder_sg_copy *sgc =
+ container_of(entry, struct binder_sg_copy, node);
+
+ while (bytes_copied < sgc->length) {
+ size_t copy_size;
+ size_t bytes_left = sgc->length - bytes_copied;
+ size_t offset = sgc->offset + bytes_copied;
+
+ /*
+ * We copy up to the fixup (pointed to by pf)
+ */
+ copy_size = pf ? min(bytes_left, (size_t)pf->offset - offset)
+ : bytes_left;
+ if (!ret && copy_size)
+ ret = binder_alloc_copy_user_to_buffer(
+ alloc, buffer,
+ offset,
+ sgc->uaddr + bytes_copied,
+ copy_size);
+ bytes_copied += copy_size;
+ if (copy_size != bytes_left) {
+ BUG_ON(!pf);
+ /* we stopped at a fixup offset */
+ if (pf->skip_size) {
+ /*
+ * we are just skipping. This is for
+ * BINDER_TYPE_FDA where the translated
+ * fds will be fixed up when we get
+ * to target context.
+ */
+ bytes_copied += pf->skip_size;
+ } else {
+ /* apply the fixup indicated by pf */
+ if (!ret)
+ ret = binder_alloc_copy_to_buffer(
+ alloc, buffer,
+ pf->offset,
+ &pf->fixup_data,
+ sizeof(pf->fixup_data));
+ bytes_copied += sizeof(pf->fixup_data);
+ }
+ list_del(&pf->node);
+ kfree(pf);
+ pf = list_first_entry_or_null(pf_head,
+ struct binder_ptr_fixup, node);
+ }
+ }
+ list_del(&sgc->node);
+ kfree(sgc);
+ }
+ BUG_ON(!list_empty(pf_head));
+ BUG_ON(!list_empty(sgc_head));
+
+ return ret;
+}
+
+/**
+ * binder_cleanup_deferred_txn_lists() - free specified lists
+ * @sgc_head: list_head of scatter-gather copy list
+ * @pf_head: list_head of pointer fixup list
+ *
+ * Called to clean up @sgc_head and @pf_head if there is an
+ * error.
+ */
+static void binder_cleanup_deferred_txn_lists(struct list_head *sgc_head,
+ struct list_head *pf_head)
+{
+ struct list_head *entry, *tmp;
+
+ list_for_each_safe(entry, tmp, sgc_head) {
+ struct binder_sg_copy *sgc =
+ container_of(entry, struct binder_sg_copy, node);
+ list_del(&sgc->node);
+ kfree(sgc);
+ }
+ list_for_each_safe(entry, tmp, pf_head) {
+ struct binder_ptr_fixup *pf =
+ container_of(entry, struct binder_ptr_fixup, node);
+ list_del(&pf->node);
+ kfree(pf);
+ }
+}
+
+/**
+ * binder_defer_copy() - queue a scatter-gather buffer for copy
+ * @sgc_head: list_head of scatter-gather copy list
+ * @offset: binder buffer offset in target process
+ * @uaddr: user address in source process
+ * @length: bytes to copy
+ *
+ * Specify a scatter-gather block to be copied. The actual copy must
+ * be deferred until all the needed fixups are identified and queued.
+ * Then the copy and fixups are done together so un-translated values
+ * from the source are never visible in the target buffer.
+ *
+ * We are guaranteed that repeated calls to this function will have
+ * monotonically increasing @offset values so the list will naturally
+ * be ordered.
+ *
+ * Return: 0=success, else -errno
+ */
+static int binder_defer_copy(struct list_head *sgc_head, binder_size_t offset,
+ const void __user *uaddr, size_t length)
+{
+ struct binder_sg_copy *bc = kzalloc(sizeof(*bc), GFP_KERNEL);
+
+ if (!bc)
+ return -ENOMEM;
+
+ bc->offset = offset;
+ bc->uaddr = uaddr;
+ bc->length = length;
+ INIT_LIST_HEAD(&bc->node);
+
+ /*
+ * We are guaranteed that the deferred copies are in-order
+ * so just add to the tail.
+ */
+ list_add_tail(&bc->node, sgc_head);
+
+ return 0;
+}
+
+/**
+ * binder_add_fixup() - queue a fixup to be applied to sg copy
+ * @pf_head: list_head of binder ptr fixup list
+ * @offset: binder buffer offset in target process
+ * @fixup: bytes to be copied for fixup
+ * @skip_size: bytes to skip when copying (fixup will be applied later)
+ *
+ * Add the specified fixup to a list ordered by @offset. When copying
+ * the scatter-gather buffers, the fixup will be copied instead of
+ * data from the source buffer. For BINDER_TYPE_FDA fixups, the fixup
+ * will be applied later (in target process context), so we just skip
+ * the bytes specified by @skip_size. If @skip_size is 0, we copy the
+ * value in @fixup.
+ *
+ * This function is called *mostly* in @offset order, but there are
+ * exceptions. Since out-of-order inserts are relatively uncommon,
+ * we insert the new element by searching backward from the tail of
+ * the list.
+ *
+ * Return: 0=success, else -errno
+ */
+static int binder_add_fixup(struct list_head *pf_head, binder_size_t offset,
+ binder_uintptr_t fixup, size_t skip_size)
+{
+ struct binder_ptr_fixup *pf = kzalloc(sizeof(*pf), GFP_KERNEL);
+ struct list_head *tmp;
+
+ if (!pf)
+ return -ENOMEM;
+
+ pf->offset = offset;
+ pf->fixup_data = fixup;
+ pf->skip_size = skip_size;
+ INIT_LIST_HEAD(&pf->node);
+
+ /* Fixups are *mostly* added in-order, but there are some
+ * exceptions. Look backwards through list for insertion point.
+ */
+ if (!list_empty(pf_head)) {
+ list_for_each_prev(tmp, pf_head) {
+ struct binder_ptr_fixup *tmppf =
+ list_entry(tmp, struct binder_ptr_fixup, node);
+
+ if (tmppf->offset < pf->offset) {
+ list_add(&pf->node, tmp);
+ return 0;
+ }
+ }
+ /*
+ * if we get here, then the new offset is the lowest so
+ * insert at the head
+ */
+ list_add(&pf->node, pf_head);
+ return 0;
+ }
+ list_add_tail(&pf->node, pf_head);
+ return 0;
+}
+
+static int binder_translate_fd_array(struct list_head *pf_head,
+ struct binder_fd_array_object *fda,
const void __user *u,
struct binder_buffer_object *parent,
struct binder_buffer_object *uparent,
@@ -2245,6 +2496,7 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
binder_size_t fda_offset;
const void __user *ufda_base;
struct binder_proc *proc = thread->proc;
+ int ret;

fd_buf_size = sizeof(u32) * fda->num_fds;
if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
@@ -2276,9 +2528,12 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
proc->pid, thread->pid);
return -EINVAL;
}
+ ret = binder_add_fixup(pf_head, fda_offset, 0, fda->num_fds * sizeof(u32));
+ if (ret)
+ return ret;
+
for (fdi = 0; fdi < fda->num_fds; fdi++) {
u32 fd;
- int ret;
binder_size_t offset = fda_offset + fdi * sizeof(fd);
binder_size_t uoffset = fdi * sizeof(fd);

@@ -2292,7 +2547,8 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
return 0;
}

-static int binder_fixup_parent(struct binder_transaction *t,
+static int binder_fixup_parent(struct list_head *pf_head,
+ struct binder_transaction *t,
struct binder_thread *thread,
struct binder_buffer_object *bp,
binder_size_t off_start_offset,
@@ -2338,14 +2594,7 @@ static int binder_fixup_parent(struct binder_transaction *t,
}
buffer_offset = bp->parent_offset +
(uintptr_t)parent->buffer - (uintptr_t)b->user_data;
- if (binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
- &bp->buffer, sizeof(bp->buffer))) {
- binder_user_error("%d:%d got transaction with invalid parent offset\n",
- proc->pid, thread->pid);
- return -EINVAL;
- }
-
- return 0;
+ return binder_add_fixup(pf_head, buffer_offset, bp->buffer, 0);
}

/**
@@ -2487,8 +2736,12 @@ static void binder_transaction(struct binder_proc *proc,
int t_debug_id = atomic_inc_return(&binder_last_id);
char *secctx = NULL;
u32 secctx_sz = 0;
+ struct list_head sgc_head;
+ struct list_head pf_head;
const void __user *user_buffer = (const void __user *)
(uintptr_t)tr->data.ptr.buffer;
+ INIT_LIST_HEAD(&sgc_head);
+ INIT_LIST_HEAD(&pf_head);

e = binder_transaction_log_add(&binder_transaction_log);
e->debug_id = t_debug_id;
@@ -3006,8 +3259,8 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_parent;
}
- ret = binder_translate_fd_array(fda, user_buffer,
- parent,
+ ret = binder_translate_fd_array(&pf_head, fda,
+ user_buffer, parent,
&user_object.bbo, t,
thread, in_reply_to);
if (ret < 0 ||
@@ -3038,19 +3291,14 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_offset;
}
- if (binder_alloc_copy_user_to_buffer(
- &target_proc->alloc,
- t->buffer,
- sg_buf_offset,
- (const void __user *)
- (uintptr_t)bp->buffer,
- bp->length)) {
- binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
- proc->pid, thread->pid);
- return_error_param = -EFAULT;
+ ret = binder_defer_copy(&sgc_head, sg_buf_offset,
+ (const void __user *)(uintptr_t)bp->buffer,
+ bp->length);
+ if (ret) {
return_error = BR_FAILED_REPLY;
+ return_error_param = ret;
return_error_line = __LINE__;
- goto err_copy_data_failed;
+ goto err_translate_failed;
}
/* Fixup buffer pointer to target proc address space */
bp->buffer = (uintptr_t)
@@ -3059,7 +3307,8 @@ static void binder_transaction(struct binder_proc *proc,

num_valid = (buffer_offset - off_start_offset) /
sizeof(binder_size_t);
- ret = binder_fixup_parent(t, thread, bp,
+ ret = binder_fixup_parent(&pf_head, t,
+ thread, bp,
off_start_offset,
num_valid,
last_fixup_obj_off,
@@ -3099,6 +3348,17 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_copy_data_failed;
}
+
+ ret = binder_do_deferred_txn_copies(&target_proc->alloc, t->buffer,
+ &sgc_head, &pf_head);
+ if (ret) {
+ binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
+ proc->pid, thread->pid);
+ return_error = BR_FAILED_REPLY;
+ return_error_param = ret;
+ return_error_line = __LINE__;
+ goto err_copy_data_failed;
+ }
if (t->buffer->oneway_spam_suspect)
tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
else
@@ -3172,6 +3432,7 @@ static void binder_transaction(struct binder_proc *proc,
err_bad_offset:
err_bad_parent:
err_copy_data_failed:
+ binder_cleanup_deferred_txn_lists(&sgc_head, &pf_head);
binder_free_txn_fixups(t);
trace_binder_transaction_failed_buffer_release(t->buffer);
binder_transaction_buffer_release(target_proc, NULL, t->buffer,
--
2.34.0.rc2.393.gf8c9666880-goog


2021-11-24 07:50:39

by Martijn Coenen

[permalink] [raw]
Subject: Re: [PATCH 1/3] binder: avoid potential data leakage when copying txn

On Tue, Nov 23, 2021 at 8:17 PM 'Todd Kjos' via kernel-team
<[email protected]> wrote:
>
> Transactions are copied from the sender to the target
> first and objects like BINDER_TYPE_PTR and BINDER_TYPE_FDA
> are then fixed up. This means there is a short period where
> the sender's version of these objects are visible to the
> target prior to the fixups.
>
> Instead of copying all of the data first, copy data only
> after any needed fixups have been applied.
>
> Signed-off-by: Todd Kjos <[email protected]>
Reviewed-by: Martijn Coenen <[email protected]>

> ---
> drivers/android/binder.c | 95 +++++++++++++++++++++++++++++-----------
> 1 file changed, 70 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 49fb74196d02..571d3c203557 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -1608,15 +1608,21 @@ static void binder_cleanup_transaction(struct binder_transaction *t,
> /**
> * binder_get_object() - gets object and checks for valid metadata
> * @proc: binder_proc owning the buffer
> + * @u: sender's user pointer to base of buffer
> * @buffer: binder_buffer that we're parsing.
> * @offset: offset in the @buffer at which to validate an object.
> * @object: struct binder_object to read into
> *
> - * Return: If there's a valid metadata object at @offset in @buffer, the
> + * Copy the binder object at the given offset into @object. If @u is
> + * provided then the copy is from the sender's buffer. If not, then
> + * it is copied from the target's @buffer.
> + *
> + * Return: If there's a valid metadata object at @offset, the
> * size of that object. Otherwise, it returns zero. The object
> * is read into the struct binder_object pointed to by @object.
> */
> static size_t binder_get_object(struct binder_proc *proc,
> + const void __user *u,
> struct binder_buffer *buffer,
> unsigned long offset,
> struct binder_object *object)
> @@ -1626,10 +1632,16 @@ static size_t binder_get_object(struct binder_proc *proc,
> size_t object_size = 0;
>
> read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
> - if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
> - binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
> - offset, read_size))
> + if (offset > buffer->data_size || read_size < sizeof(*hdr))
> return 0;
> + if (u) {
> + if (copy_from_user(object, u + offset, read_size))
> + return 0;
> + } else {
> + if (binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
> + offset, read_size))
> + return 0;
> + }
>
> /* Ok, now see if we read a complete object. */
> hdr = &object->hdr;
> @@ -1702,7 +1714,7 @@ static struct binder_buffer_object *binder_validate_ptr(
> b, buffer_offset,
> sizeof(object_offset)))
> return NULL;
> - object_size = binder_get_object(proc, b, object_offset, object);
> + object_size = binder_get_object(proc, NULL, b, object_offset, object);
> if (!object_size || object->hdr.type != BINDER_TYPE_PTR)
> return NULL;
> if (object_offsetp)
> @@ -1767,7 +1779,8 @@ static bool binder_validate_fixup(struct binder_proc *proc,
> unsigned long buffer_offset;
> struct binder_object last_object;
> struct binder_buffer_object *last_bbo;
> - size_t object_size = binder_get_object(proc, b, last_obj_offset,
> + size_t object_size = binder_get_object(proc, NULL, b,
> + last_obj_offset,
> &last_object);
> if (object_size != sizeof(*last_bbo))
> return false;
> @@ -1882,7 +1895,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
> if (!binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
> buffer, buffer_offset,
> sizeof(object_offset)))
> - object_size = binder_get_object(proc, buffer,
> + object_size = binder_get_object(proc, NULL, buffer,
> object_offset, &object);
> if (object_size == 0) {
> 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,
> binder_size_t off_start_offset, off_end_offset;
> binder_size_t off_min;
> binder_size_t sg_buf_offset, sg_buf_end_offset;
> + binder_size_t user_offset = 0;
> struct binder_proc *target_proc = NULL;
> struct binder_thread *target_thread = NULL;
> struct binder_node *target_node = NULL;
> @@ -2469,6 +2483,8 @@ static void binder_transaction(struct binder_proc *proc,
> int t_debug_id = atomic_inc_return(&binder_last_id);
> char *secctx = NULL;
> u32 secctx_sz = 0;
> + const void __user *user_buffer = (const void __user *)
> + (uintptr_t)tr->data.ptr.buffer;
>
> e = binder_transaction_log_add(&binder_transaction_log);
> e->debug_id = t_debug_id;
> @@ -2692,7 +2708,7 @@ static void binder_transaction(struct binder_proc *proc,
> "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld-%lld\n",
> proc->pid, thread->pid, t->debug_id,
> target_proc->pid, target_thread->pid,
> - (u64)tr->data.ptr.buffer,
> + (u64)user_buffer,
> (u64)tr->data.ptr.offsets,
> (u64)tr->data_size, (u64)tr->offsets_size,
> (u64)extra_buffers_size);
> @@ -2701,7 +2717,7 @@ static void binder_transaction(struct binder_proc *proc,
> "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld-%lld\n",
> proc->pid, thread->pid, t->debug_id,
> target_proc->pid, target_node->debug_id,
> - (u64)tr->data.ptr.buffer,
> + (u64)user_buffer,
> (u64)tr->data.ptr.offsets,
> (u64)tr->data_size, (u64)tr->offsets_size,
> (u64)extra_buffers_size);
> @@ -2780,19 +2796,6 @@ static void binder_transaction(struct binder_proc *proc,
> t->buffer->clear_on_free = !!(t->flags & TF_CLEAR_BUF);
> trace_binder_transaction_alloc_buf(t->buffer);
>
> - if (binder_alloc_copy_user_to_buffer(
> - &target_proc->alloc,
> - t->buffer, 0,
> - (const void __user *)
> - (uintptr_t)tr->data.ptr.buffer,
> - tr->data_size)) {
> - binder_user_error("%d:%d got transaction with invalid data ptr\n",
> - proc->pid, thread->pid);
> - return_error = BR_FAILED_REPLY;
> - return_error_param = -EFAULT;
> - return_error_line = __LINE__;
> - goto err_copy_data_failed;
> - }
> if (binder_alloc_copy_user_to_buffer(
> &target_proc->alloc,
> t->buffer,
> @@ -2837,6 +2840,7 @@ static void binder_transaction(struct binder_proc *proc,
> size_t object_size;
> struct binder_object object;
> binder_size_t object_offset;
> + binder_size_t copy_size;
>
> if (binder_alloc_copy_from_buffer(&target_proc->alloc,
> &object_offset,
> @@ -2848,8 +2852,27 @@ static void binder_transaction(struct binder_proc *proc,
> return_error_line = __LINE__;
> goto err_bad_offset;
> }
> - object_size = binder_get_object(target_proc, t->buffer,
> - object_offset, &object);
> +
> + /*
> + * Copy the source user buffer up to the next object
> + * that will be processed.
> + */
> + copy_size = object_offset - user_offset;
> + if (copy_size && (user_offset > object_offset ||
> + binder_alloc_copy_user_to_buffer(
> + &target_proc->alloc,
> + t->buffer, user_offset,
> + user_buffer + user_offset,
> + copy_size))) {
> + binder_user_error("%d:%d got transaction with invalid data ptr\n",
> + proc->pid, thread->pid);
> + return_error = BR_FAILED_REPLY;
> + return_error_param = -EFAULT;
> + return_error_line = __LINE__;
> + goto err_copy_data_failed;
> + }
> + object_size = binder_get_object(target_proc, user_buffer,
> + t->buffer, object_offset, &object);
> if (object_size == 0 || object_offset < off_min) {
> binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n",
> proc->pid, thread->pid,
> @@ -2861,6 +2884,11 @@ static void binder_transaction(struct binder_proc *proc,
> return_error_line = __LINE__;
> goto err_bad_offset;
> }
> + /*
> + * Set offset to the next buffer fragment to be
> + * copied
> + */
> + user_offset = object_offset + object_size;
>
> hdr = &object.hdr;
> off_min = object_offset + object_size;
> @@ -2956,7 +2984,11 @@ static void binder_transaction(struct binder_proc *proc,
> }
> ret = binder_translate_fd_array(fda, parent, t, thread,
> in_reply_to);
> - if (ret < 0) {
> + if (ret < 0 ||
> + binder_alloc_copy_to_buffer(&target_proc->alloc,
> + t->buffer,
> + object_offset,
> + fda, sizeof(*fda))) {
> return_error = BR_FAILED_REPLY;
> return_error_param = ret;
> return_error_line = __LINE__;
> @@ -3028,6 +3060,19 @@ static void binder_transaction(struct binder_proc *proc,
> goto err_bad_object_type;
> }
> }
> + /* Done processing objects, copy the rest of the buffer */
> + if (binder_alloc_copy_user_to_buffer(
> + &target_proc->alloc,
> + t->buffer, user_offset,
> + user_buffer + user_offset,
> + tr->data_size - user_offset)) {
> + binder_user_error("%d:%d got transaction with invalid data ptr\n",
> + proc->pid, thread->pid);
> + return_error = BR_FAILED_REPLY;
> + return_error_param = -EFAULT;
> + return_error_line = __LINE__;
> + goto err_copy_data_failed;
> + }
> if (t->buffer->oneway_spam_suspect)
> tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
> else
> --
> 2.34.0.rc2.393.gf8c9666880-goog
>
>

2021-11-24 07:50:52

by Martijn Coenen

[permalink] [raw]
Subject: Re: [PATCH 2/3] binder: read pre-translated fds from sender buffer

On Tue, Nov 23, 2021 at 8:17 PM 'Todd Kjos' via kernel-team
<[email protected]> wrote:
>
> Since we are no longer going to copy the pre-fixup
> data from the target buffer, we need to read
> pre-translated FD array information from the source
> buffer.
>
> Signed-off-by: Todd Kjos <[email protected]>
Reviewed-by: Martijn Coenen <[email protected]>

> ---
> drivers/android/binder.c | 40 +++++++++++++++++++++++++++++++++-------
> 1 file changed, 33 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 571d3c203557..2300fa8e09d5 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2234,15 +2234,17 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
> }
>
> static int binder_translate_fd_array(struct binder_fd_array_object *fda,
> + const void __user *u,
> struct binder_buffer_object *parent,
> + struct binder_buffer_object *uparent,
> struct binder_transaction *t,
> struct binder_thread *thread,
> struct binder_transaction *in_reply_to)
> {
> binder_size_t fdi, fd_buf_size;
> binder_size_t fda_offset;
> + const void __user *ufda_base;
> struct binder_proc *proc = thread->proc;
> - struct binder_proc *target_proc = t->to_proc;
>
> fd_buf_size = sizeof(u32) * fda->num_fds;
> if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
> @@ -2266,7 +2268,10 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
> */
> fda_offset = (parent->buffer - (uintptr_t)t->buffer->user_data) +
> fda->parent_offset;
> - if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32))) {
> + ufda_base = (void __user *)uparent->buffer + fda->parent_offset;
> +
> + if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32)) ||
> + !IS_ALIGNED((unsigned long)ufda_base, sizeof(u32))) {
> binder_user_error("%d:%d parent offset not aligned correctly.\n",
> proc->pid, thread->pid);
> return -EINVAL;
> @@ -2275,10 +2280,9 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
> u32 fd;
> int ret;
> binder_size_t offset = fda_offset + fdi * sizeof(fd);
> + binder_size_t uoffset = fdi * sizeof(fd);
>
> - ret = binder_alloc_copy_from_buffer(&target_proc->alloc,
> - &fd, t->buffer,
> - offset, sizeof(fd));
> + ret = copy_from_user(&fd, ufda_base + uoffset, sizeof(fd));
> if (!ret)
> ret = binder_translate_fd(fd, offset, t, thread,
> in_reply_to);
> @@ -2951,6 +2955,8 @@ static void binder_transaction(struct binder_proc *proc,
> case BINDER_TYPE_FDA: {
> struct binder_object ptr_object;
> binder_size_t parent_offset;
> + struct binder_object user_object;
> + size_t user_parent_size;
> struct binder_fd_array_object *fda =
> to_binder_fd_array_object(hdr);
> size_t num_valid = (buffer_offset - off_start_offset) /
> @@ -2982,8 +2988,28 @@ static void binder_transaction(struct binder_proc *proc,
> return_error_line = __LINE__;
> goto err_bad_parent;
> }
> - ret = binder_translate_fd_array(fda, parent, t, thread,
> - in_reply_to);
> +
> + /*
> + * We need to read the user version of the parent
> + * object to get the original user offset
> + */
> + user_parent_size =
> + binder_get_object(proc, user_buffer, t->buffer,
> + parent_offset, &user_object);
> + if (user_parent_size != sizeof(user_object.bbo)) {
> + binder_user_error("%d:%d invalid ptr object size: %lld vs %lld\n",
> + proc->pid, thread->pid,
> + user_parent_size,
> + sizeof(user_object.bbo));
> + return_error = BR_FAILED_REPLY;
> + return_error_param = -EINVAL;
> + return_error_line = __LINE__;
> + goto err_bad_parent;
> + }
> + ret = binder_translate_fd_array(fda, user_buffer,
> + parent,
> + &user_object.bbo, t,
> + thread, in_reply_to);
> if (ret < 0 ||
> binder_alloc_copy_to_buffer(&target_proc->alloc,
> t->buffer,
> --
> 2.34.0.rc2.393.gf8c9666880-goog
>
>

2021-11-24 07:51:07

by Martijn Coenen

[permalink] [raw]
Subject: Re: [PATCH 3/3] binder: defer copies of pre-patched txn data

On Tue, Nov 23, 2021 at 8:17 PM 'Todd Kjos' via kernel-team
<[email protected]> wrote:
>
> BINDER_TYPE_PTR objects point to memory areas in the
> source process to be copied into the target buffer
> as part of a transaction. This implements a scatter-
> gather model where non-contiguous memory in a source
> process is "gathered" into a contiguous region in
> the target buffer.
>
> The data can include pointers that must be fixed up
> to correctly point to the copied data. To avoid making
> source process pointers visible to the target process,
> this patch defers the copy until the fixups are known
> and then copies and fixeups are done together.
>
> There is a special case of BINDER_TYPE_FDA which applies
> the fixup later in the target process context. In this
> case the user data is skipped (so no untranslated fds
> become visible to the target).
>
> Signed-off-by: Todd Kjos <[email protected]>
Reviewed-by: Martijn Coenen <[email protected]>

> ---
> drivers/android/binder.c | 311 +++++++++++++++++++++++++++++++++++----
> 1 file changed, 286 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 2300fa8e09d5..56dc814b8dde 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2233,7 +2233,258 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
> return ret;
> }
>
> -static int binder_translate_fd_array(struct binder_fd_array_object *fda,
> +/**
> + * struct binder_ptr_fixup - data to be fixed-up in target buffer
> + * @offset offset in target buffer to fixup
> + * @skip_size bytes to skip in copy (fixup will be written later)
> + * @fixup_data data to write at fixup offset
> + * @node list node
> + *
> + * This is used for the pointer fixup list (pf) which is created and consumed
> + * during binder_transaction() and is only accessed locally. No
> + * locking is necessary.
> + *
> + * The list is ordered by @offset.
> + */
> +struct binder_ptr_fixup {
> + binder_size_t offset;
> + size_t skip_size;
> + binder_uintptr_t fixup_data;
> + struct list_head node;
> +};
> +
> +/**
> + * struct binder_sg_copy - scatter-gather data to be copied
> + * @offset offset in target buffer
> + * @uaddr user address in source buffer
> + * @length bytes to copy
> + * @node list node
> + *
> + * This is used for the sg copy list (sgc) which is created and consumed
> + * during binder_transaction() and is only accessed locally. No
> + * locking is necessary.
> + *
> + * The list is ordered by @offset.
> + */
> +struct binder_sg_copy {
> + binder_size_t offset;
> + const void __user *uaddr;
> + size_t length;
> + struct list_head node;
> +};
> +
> +/**
> + * binder_do_deferred_txn_copies() - copy and fixup scatter-gather data
> + * @alloc: binder_alloc associated with @buffer
> + * @buffer: binder buffer in target process
> + * @sgc_head: list_head of scatter-gather copy list
> + * @pf_head: list_head of pointer fixup list
> + *
> + * Processes all elements of @sgc_head, applying fixups from @pf_head
> + * and copying the scatter-gather data from the source process' user
> + * buffer to the target's buffer. It is expected that the list creation
> + * and processing all occurs during binder_transaction() so these lists
> + * are only accessed in local context.
> + *
> + * Return: 0=success, else -errno
> + */
> +static int binder_do_deferred_txn_copies(struct binder_alloc *alloc,
> + struct binder_buffer *buffer,
> + struct list_head *sgc_head,
> + struct list_head *pf_head)
> +{
> + int ret = 0;
> + struct list_head *entry, *tmp;
> + struct binder_ptr_fixup *pf =
> + list_first_entry_or_null(pf_head, struct binder_ptr_fixup,
> + node);
> +
> + list_for_each_safe(entry, tmp, sgc_head) {
> + size_t bytes_copied = 0;
> + struct binder_sg_copy *sgc =
> + container_of(entry, struct binder_sg_copy, node);
> +
> + while (bytes_copied < sgc->length) {
> + size_t copy_size;
> + size_t bytes_left = sgc->length - bytes_copied;
> + size_t offset = sgc->offset + bytes_copied;
> +
> + /*
> + * We copy up to the fixup (pointed to by pf)
> + */
> + copy_size = pf ? min(bytes_left, (size_t)pf->offset - offset)
> + : bytes_left;
> + if (!ret && copy_size)
> + ret = binder_alloc_copy_user_to_buffer(
> + alloc, buffer,
> + offset,
> + sgc->uaddr + bytes_copied,
> + copy_size);
> + bytes_copied += copy_size;
> + if (copy_size != bytes_left) {
> + BUG_ON(!pf);
> + /* we stopped at a fixup offset */
> + if (pf->skip_size) {
> + /*
> + * we are just skipping. This is for
> + * BINDER_TYPE_FDA where the translated
> + * fds will be fixed up when we get
> + * to target context.
> + */
> + bytes_copied += pf->skip_size;
> + } else {
> + /* apply the fixup indicated by pf */
> + if (!ret)
> + ret = binder_alloc_copy_to_buffer(
> + alloc, buffer,
> + pf->offset,
> + &pf->fixup_data,
> + sizeof(pf->fixup_data));
> + bytes_copied += sizeof(pf->fixup_data);
> + }
> + list_del(&pf->node);
> + kfree(pf);
> + pf = list_first_entry_or_null(pf_head,
> + struct binder_ptr_fixup, node);
> + }
> + }
> + list_del(&sgc->node);
> + kfree(sgc);
> + }
> + BUG_ON(!list_empty(pf_head));
> + BUG_ON(!list_empty(sgc_head));
> +
> + return ret;
> +}
> +
> +/**
> + * binder_cleanup_deferred_txn_lists() - free specified lists
> + * @sgc_head: list_head of scatter-gather copy list
> + * @pf_head: list_head of pointer fixup list
> + *
> + * Called to clean up @sgc_head and @pf_head if there is an
> + * error.
> + */
> +static void binder_cleanup_deferred_txn_lists(struct list_head *sgc_head,
> + struct list_head *pf_head)
> +{
> + struct list_head *entry, *tmp;
> +
> + list_for_each_safe(entry, tmp, sgc_head) {
> + struct binder_sg_copy *sgc =
> + container_of(entry, struct binder_sg_copy, node);
> + list_del(&sgc->node);
> + kfree(sgc);
> + }
> + list_for_each_safe(entry, tmp, pf_head) {
> + struct binder_ptr_fixup *pf =
> + container_of(entry, struct binder_ptr_fixup, node);
> + list_del(&pf->node);
> + kfree(pf);
> + }
> +}
> +
> +/**
> + * binder_defer_copy() - queue a scatter-gather buffer for copy
> + * @sgc_head: list_head of scatter-gather copy list
> + * @offset: binder buffer offset in target process
> + * @uaddr: user address in source process
> + * @length: bytes to copy
> + *
> + * Specify a scatter-gather block to be copied. The actual copy must
> + * be deferred until all the needed fixups are identified and queued.
> + * Then the copy and fixups are done together so un-translated values
> + * from the source are never visible in the target buffer.
> + *
> + * We are guaranteed that repeated calls to this function will have
> + * monotonically increasing @offset values so the list will naturally
> + * be ordered.
> + *
> + * Return: 0=success, else -errno
> + */
> +static int binder_defer_copy(struct list_head *sgc_head, binder_size_t offset,
> + const void __user *uaddr, size_t length)
> +{
> + struct binder_sg_copy *bc = kzalloc(sizeof(*bc), GFP_KERNEL);
> +
> + if (!bc)
> + return -ENOMEM;
> +
> + bc->offset = offset;
> + bc->uaddr = uaddr;
> + bc->length = length;
> + INIT_LIST_HEAD(&bc->node);
> +
> + /*
> + * We are guaranteed that the deferred copies are in-order
> + * so just add to the tail.
> + */
> + list_add_tail(&bc->node, sgc_head);
> +
> + return 0;
> +}
> +
> +/**
> + * binder_add_fixup() - queue a fixup to be applied to sg copy
> + * @pf_head: list_head of binder ptr fixup list
> + * @offset: binder buffer offset in target process
> + * @fixup: bytes to be copied for fixup
> + * @skip_size: bytes to skip when copying (fixup will be applied later)
> + *
> + * Add the specified fixup to a list ordered by @offset. When copying
> + * the scatter-gather buffers, the fixup will be copied instead of
> + * data from the source buffer. For BINDER_TYPE_FDA fixups, the fixup
> + * will be applied later (in target process context), so we just skip
> + * the bytes specified by @skip_size. If @skip_size is 0, we copy the
> + * value in @fixup.
> + *
> + * This function is called *mostly* in @offset order, but there are
> + * exceptions. Since out-of-order inserts are relatively uncommon,
> + * we insert the new element by searching backward from the tail of
> + * the list.
> + *
> + * Return: 0=success, else -errno
> + */
> +static int binder_add_fixup(struct list_head *pf_head, binder_size_t offset,
> + binder_uintptr_t fixup, size_t skip_size)
> +{
> + struct binder_ptr_fixup *pf = kzalloc(sizeof(*pf), GFP_KERNEL);
> + struct list_head *tmp;
> +
> + if (!pf)
> + return -ENOMEM;
> +
> + pf->offset = offset;
> + pf->fixup_data = fixup;
> + pf->skip_size = skip_size;
> + INIT_LIST_HEAD(&pf->node);
> +
> + /* Fixups are *mostly* added in-order, but there are some
> + * exceptions. Look backwards through list for insertion point.
> + */
> + if (!list_empty(pf_head)) {
> + list_for_each_prev(tmp, pf_head) {
> + struct binder_ptr_fixup *tmppf =
> + list_entry(tmp, struct binder_ptr_fixup, node);
> +
> + if (tmppf->offset < pf->offset) {
> + list_add(&pf->node, tmp);
> + return 0;
> + }
> + }
> + /*
> + * if we get here, then the new offset is the lowest so
> + * insert at the head
> + */
> + list_add(&pf->node, pf_head);
> + return 0;
> + }
> + list_add_tail(&pf->node, pf_head);
> + return 0;
> +}
> +
> +static int binder_translate_fd_array(struct list_head *pf_head,
> + struct binder_fd_array_object *fda,
> const void __user *u,
> struct binder_buffer_object *parent,
> struct binder_buffer_object *uparent,
> @@ -2245,6 +2496,7 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
> binder_size_t fda_offset;
> const void __user *ufda_base;
> struct binder_proc *proc = thread->proc;
> + int ret;
>
> fd_buf_size = sizeof(u32) * fda->num_fds;
> if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
> @@ -2276,9 +2528,12 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
> proc->pid, thread->pid);
> return -EINVAL;
> }
> + ret = binder_add_fixup(pf_head, fda_offset, 0, fda->num_fds * sizeof(u32));
> + if (ret)
> + return ret;
> +
> for (fdi = 0; fdi < fda->num_fds; fdi++) {
> u32 fd;
> - int ret;
> binder_size_t offset = fda_offset + fdi * sizeof(fd);
> binder_size_t uoffset = fdi * sizeof(fd);
>
> @@ -2292,7 +2547,8 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
> return 0;
> }
>
> -static int binder_fixup_parent(struct binder_transaction *t,
> +static int binder_fixup_parent(struct list_head *pf_head,
> + struct binder_transaction *t,
> struct binder_thread *thread,
> struct binder_buffer_object *bp,
> binder_size_t off_start_offset,
> @@ -2338,14 +2594,7 @@ static int binder_fixup_parent(struct binder_transaction *t,
> }
> buffer_offset = bp->parent_offset +
> (uintptr_t)parent->buffer - (uintptr_t)b->user_data;
> - if (binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
> - &bp->buffer, sizeof(bp->buffer))) {
> - binder_user_error("%d:%d got transaction with invalid parent offset\n",
> - proc->pid, thread->pid);
> - return -EINVAL;
> - }
> -
> - return 0;
> + return binder_add_fixup(pf_head, buffer_offset, bp->buffer, 0);
> }
>
> /**
> @@ -2487,8 +2736,12 @@ static void binder_transaction(struct binder_proc *proc,
> int t_debug_id = atomic_inc_return(&binder_last_id);
> char *secctx = NULL;
> u32 secctx_sz = 0;
> + struct list_head sgc_head;
> + struct list_head pf_head;
> const void __user *user_buffer = (const void __user *)
> (uintptr_t)tr->data.ptr.buffer;
> + INIT_LIST_HEAD(&sgc_head);
> + INIT_LIST_HEAD(&pf_head);
>
> e = binder_transaction_log_add(&binder_transaction_log);
> e->debug_id = t_debug_id;
> @@ -3006,8 +3259,8 @@ static void binder_transaction(struct binder_proc *proc,
> return_error_line = __LINE__;
> goto err_bad_parent;
> }
> - ret = binder_translate_fd_array(fda, user_buffer,
> - parent,
> + ret = binder_translate_fd_array(&pf_head, fda,
> + user_buffer, parent,
> &user_object.bbo, t,
> thread, in_reply_to);
> if (ret < 0 ||
> @@ -3038,19 +3291,14 @@ static void binder_transaction(struct binder_proc *proc,
> return_error_line = __LINE__;
> goto err_bad_offset;
> }
> - if (binder_alloc_copy_user_to_buffer(
> - &target_proc->alloc,
> - t->buffer,
> - sg_buf_offset,
> - (const void __user *)
> - (uintptr_t)bp->buffer,
> - bp->length)) {
> - binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
> - proc->pid, thread->pid);
> - return_error_param = -EFAULT;
> + ret = binder_defer_copy(&sgc_head, sg_buf_offset,
> + (const void __user *)(uintptr_t)bp->buffer,
> + bp->length);
> + if (ret) {
> return_error = BR_FAILED_REPLY;
> + return_error_param = ret;
> return_error_line = __LINE__;
> - goto err_copy_data_failed;
> + goto err_translate_failed;
> }
> /* Fixup buffer pointer to target proc address space */
> bp->buffer = (uintptr_t)
> @@ -3059,7 +3307,8 @@ static void binder_transaction(struct binder_proc *proc,
>
> num_valid = (buffer_offset - off_start_offset) /
> sizeof(binder_size_t);
> - ret = binder_fixup_parent(t, thread, bp,
> + ret = binder_fixup_parent(&pf_head, t,
> + thread, bp,
> off_start_offset,
> num_valid,
> last_fixup_obj_off,
> @@ -3099,6 +3348,17 @@ static void binder_transaction(struct binder_proc *proc,
> return_error_line = __LINE__;
> goto err_copy_data_failed;
> }
> +
> + ret = binder_do_deferred_txn_copies(&target_proc->alloc, t->buffer,
> + &sgc_head, &pf_head);
> + if (ret) {
> + binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
> + proc->pid, thread->pid);
> + return_error = BR_FAILED_REPLY;
> + return_error_param = ret;
> + return_error_line = __LINE__;
> + goto err_copy_data_failed;
> + }
> if (t->buffer->oneway_spam_suspect)
> tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
> else
> @@ -3172,6 +3432,7 @@ static void binder_transaction(struct binder_proc *proc,
> err_bad_offset:
> err_bad_parent:
> err_copy_data_failed:
> + binder_cleanup_deferred_txn_lists(&sgc_head, &pf_head);
> binder_free_txn_fixups(t);
> trace_binder_transaction_failed_buffer_release(t->buffer);
> binder_transaction_buffer_release(target_proc, NULL, t->buffer,
> --
> 2.34.0.rc2.393.gf8c9666880-goog
>
>

2021-11-24 08:08:34

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 0/3] binder: Prevent untranslated sender data from being copied to target

On Tue, Nov 23, 2021 at 11:17:34AM -0800, Todd Kjos wrote:
> Binder copies transactions directly from the sender buffer
> to the target buffer and then fixes up BINDER_TYPE_PTR and
> BINDER_TYPE_FDA objects. This means there is a brief time
> when sender pointers and fds are visible to the target
> process.
>
> This series reworks the the sender to target copy to
> avoid leaking any untranslated sender data from being
> visible in the target.
>
> Todd Kjos (3):
> binder: defer copies of pre-patched txn data
> binder: read pre-translated fds from sender buffer
> binder: avoid potential data leakage when copying txn
>
> drivers/android/binder.c | 442 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
> 1 file changed, 387 insertions(+), 55 deletions(-)

Are these changes needed now in 5.16-final and also in stable kernels?

Or can they wait until 5.17-rc1?

thanks,

greg k-h

2021-11-24 11:10:29

by Dan Carpenter

[permalink] [raw]
Subject: Re: [PATCH 3/3] binder: defer copies of pre-patched txn data

On Tue, Nov 23, 2021 at 11:17:37AM -0800, Todd Kjos wrote:
> +/**
> + * binder_do_deferred_txn_copies() - copy and fixup scatter-gather data
> + * @alloc: binder_alloc associated with @buffer
> + * @buffer: binder buffer in target process
> + * @sgc_head: list_head of scatter-gather copy list
> + * @pf_head: list_head of pointer fixup list
> + *
> + * Processes all elements of @sgc_head, applying fixups from @pf_head
> + * and copying the scatter-gather data from the source process' user
> + * buffer to the target's buffer. It is expected that the list creation
> + * and processing all occurs during binder_transaction() so these lists
> + * are only accessed in local context.
> + *
> + * Return: 0=success, else -errno
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This function is supposed to return negatives on error.

> + */
> +static int binder_do_deferred_txn_copies(struct binder_alloc *alloc,
> + struct binder_buffer *buffer,
> + struct list_head *sgc_head,
> + struct list_head *pf_head)
> +{
> + int ret = 0;
> + struct list_head *entry, *tmp;
> + struct binder_ptr_fixup *pf =
> + list_first_entry_or_null(pf_head, struct binder_ptr_fixup,
> + node);
> +
> + list_for_each_safe(entry, tmp, sgc_head) {
> + size_t bytes_copied = 0;
> + struct binder_sg_copy *sgc =
> + container_of(entry, struct binder_sg_copy, node);
> +
> + while (bytes_copied < sgc->length) {
> + size_t copy_size;
> + size_t bytes_left = sgc->length - bytes_copied;
> + size_t offset = sgc->offset + bytes_copied;
> +
> + /*
> + * We copy up to the fixup (pointed to by pf)
> + */
> + copy_size = pf ? min(bytes_left, (size_t)pf->offset - offset)
> + : bytes_left;
> + if (!ret && copy_size)
> + ret = binder_alloc_copy_user_to_buffer(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
"ret" is the number of bytes remaining to be copied.


> + alloc, buffer,
> + offset,
> + sgc->uaddr + bytes_copied,
> + copy_size);
> + bytes_copied += copy_size;
> + if (copy_size != bytes_left) {
> + BUG_ON(!pf);
> + /* we stopped at a fixup offset */
> + if (pf->skip_size) {
> + /*
> + * we are just skipping. This is for
> + * BINDER_TYPE_FDA where the translated
> + * fds will be fixed up when we get
> + * to target context.
> + */
> + bytes_copied += pf->skip_size;
> + } else {
> + /* apply the fixup indicated by pf */
> + if (!ret)
> + ret = binder_alloc_copy_to_buffer(
> + alloc, buffer,
> + pf->offset,
> + &pf->fixup_data,
> + sizeof(pf->fixup_data));
> + bytes_copied += sizeof(pf->fixup_data);
> + }
> + list_del(&pf->node);
> + kfree(pf);
> + pf = list_first_entry_or_null(pf_head,
> + struct binder_ptr_fixup, node);
> + }
> + }
> + list_del(&sgc->node);
> + kfree(sgc);
> + }
> + BUG_ON(!list_empty(pf_head));
> + BUG_ON(!list_empty(sgc_head));
> +
> + return ret;
> +}
> +
> +/**
> + * binder_cleanup_deferred_txn_lists() - free specified lists
> + * @sgc_head: list_head of scatter-gather copy list
> + * @pf_head: list_head of pointer fixup list
> + *
> + * Called to clean up @sgc_head and @pf_head if there is an
> + * error.
> + */
> +static void binder_cleanup_deferred_txn_lists(struct list_head *sgc_head,
> + struct list_head *pf_head)
> +{
> + struct list_head *entry, *tmp;
> +
> + list_for_each_safe(entry, tmp, sgc_head) {
> + struct binder_sg_copy *sgc =
> + container_of(entry, struct binder_sg_copy, node);
> + list_del(&sgc->node);
> + kfree(sgc);
> + }
> + list_for_each_safe(entry, tmp, pf_head) {
> + struct binder_ptr_fixup *pf =
> + container_of(entry, struct binder_ptr_fixup, node);
> + list_del(&pf->node);
> + kfree(pf);
> + }
> +}
> +
> +/**
> + * binder_defer_copy() - queue a scatter-gather buffer for copy
> + * @sgc_head: list_head of scatter-gather copy list
> + * @offset: binder buffer offset in target process
> + * @uaddr: user address in source process
> + * @length: bytes to copy
> + *
> + * Specify a scatter-gather block to be copied. The actual copy must
> + * be deferred until all the needed fixups are identified and queued.
> + * Then the copy and fixups are done together so un-translated values
> + * from the source are never visible in the target buffer.
> + *
> + * We are guaranteed that repeated calls to this function will have
> + * monotonically increasing @offset values so the list will naturally
> + * be ordered.
> + *
> + * Return: 0=success, else -errno
> + */
> +static int binder_defer_copy(struct list_head *sgc_head, binder_size_t offset,
> + const void __user *uaddr, size_t length)
> +{
> + struct binder_sg_copy *bc = kzalloc(sizeof(*bc), GFP_KERNEL);
> +
> + if (!bc)
> + return -ENOMEM;
> +
> + bc->offset = offset;
> + bc->uaddr = uaddr;
> + bc->length = length;
> + INIT_LIST_HEAD(&bc->node);
> +
> + /*
> + * We are guaranteed that the deferred copies are in-order
> + * so just add to the tail.
> + */
> + list_add_tail(&bc->node, sgc_head);
> +
> + return 0;
> +}
> +
> +/**
> + * binder_add_fixup() - queue a fixup to be applied to sg copy
> + * @pf_head: list_head of binder ptr fixup list
> + * @offset: binder buffer offset in target process
> + * @fixup: bytes to be copied for fixup
> + * @skip_size: bytes to skip when copying (fixup will be applied later)
> + *
> + * Add the specified fixup to a list ordered by @offset. When copying
> + * the scatter-gather buffers, the fixup will be copied instead of
> + * data from the source buffer. For BINDER_TYPE_FDA fixups, the fixup
> + * will be applied later (in target process context), so we just skip
> + * the bytes specified by @skip_size. If @skip_size is 0, we copy the
> + * value in @fixup.
> + *
> + * This function is called *mostly* in @offset order, but there are
> + * exceptions. Since out-of-order inserts are relatively uncommon,
> + * we insert the new element by searching backward from the tail of
> + * the list.
> + *
> + * Return: 0=success, else -errno
> + */
> +static int binder_add_fixup(struct list_head *pf_head, binder_size_t offset,
> + binder_uintptr_t fixup, size_t skip_size)
> +{
> + struct binder_ptr_fixup *pf = kzalloc(sizeof(*pf), GFP_KERNEL);
> + struct list_head *tmp;
> +
> + if (!pf)
> + return -ENOMEM;
> +
> + pf->offset = offset;
> + pf->fixup_data = fixup;
> + pf->skip_size = skip_size;
> + INIT_LIST_HEAD(&pf->node);
> +
> + /* Fixups are *mostly* added in-order, but there are some
> + * exceptions. Look backwards through list for insertion point.
> + */
> + if (!list_empty(pf_head)) {

This condition is not required. If list is empty we add it to the tail,
but when there is only one item on the list, the first and last item are
going to be the same.

> + list_for_each_prev(tmp, pf_head) {
> + struct binder_ptr_fixup *tmppf =
> + list_entry(tmp, struct binder_ptr_fixup, node);
> +
> + if (tmppf->offset < pf->offset) {
> + list_add(&pf->node, tmp);
> + return 0;
> + }
> + }
> + /*
> + * if we get here, then the new offset is the lowest so
> + * insert at the head
> + */
> + list_add(&pf->node, pf_head);
> + return 0;
> + }
> + list_add_tail(&pf->node, pf_head);
> + return 0;
> +}
> +

regards,
dan carpenter

2021-11-24 12:41:28

by Dan Carpenter

[permalink] [raw]
Subject: Re: [PATCH 2/3] binder: read pre-translated fds from sender buffer

On Tue, Nov 23, 2021 at 11:17:36AM -0800, Todd Kjos wrote:
> Since we are no longer going to copy the pre-fixup
> data from the target buffer, we need to read
> pre-translated FD array information from the source
> buffer.
>

The commit message is really misleading. From the commit message it
sounds like the commit is changing runtime but it's not. What I want is
a commit message like this:

This patch is to prepare for an up coming patch where we read
pre-translated fds from the sender buffer and translate them before
copying them to the target. It does not change run time.

The patch adds two new parameters to binder_translate_fd_array() to
hold the sender buffer and sender buffer parent. These parameters let
us call copy_from_user() directly instead of using
binder_alloc_copy_from_buffer() which is a cleanup. Also the patch
adds some new alignment checks. Previously the alignment checks would
have been done in a different place, but this lets us print more
useful error messages.


> Signed-off-by: Todd Kjos <[email protected]>
> ---
> drivers/android/binder.c | 40 +++++++++++++++++++++++++++++++++-------
> 1 file changed, 33 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 571d3c203557..2300fa8e09d5 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2234,15 +2234,17 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
> }
>
> static int binder_translate_fd_array(struct binder_fd_array_object *fda,
> + const void __user *u,

I wish we could use sender/target terminology everywhere. Please change
every place that has "u" or "user" to either "sender" or "target" as
appropriate.

> struct binder_buffer_object *parent,
> + struct binder_buffer_object *uparent,
^

> struct binder_transaction *t,
> struct binder_thread *thread,
> struct binder_transaction *in_reply_to)
> {
> binder_size_t fdi, fd_buf_size;
> binder_size_t fda_offset;
> + const void __user *ufda_base;
^

> struct binder_proc *proc = thread->proc;
> - struct binder_proc *target_proc = t->to_proc;
>
> fd_buf_size = sizeof(u32) * fda->num_fds;
> if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
> @@ -2266,7 +2268,10 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
> */> fda_offset = (parent->buffer - (uintptr_t)t->buffer->user_data) +
> fda->parent_offset;
> - if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32))) {
> + ufda_base = (void __user *)uparent->buffer + fda->parent_offset;
> +
> + if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32)) ||
> + !IS_ALIGNED((unsigned long)ufda_base, sizeof(u32))) {
> binder_user_error("%d:%d parent offset not aligned correctly.\n",
> proc->pid, thread->pid);
> return -EINVAL;
> @@ -2275,10 +2280,9 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
> u32 fd;
> int ret;
> binder_size_t offset = fda_offset + fdi * sizeof(fd);
> + binder_size_t uoffset = fdi * sizeof(fd);
>
> - ret = binder_alloc_copy_from_buffer(&target_proc->alloc,
> - &fd, t->buffer,
> - offset, sizeof(fd));
> + ret = copy_from_user(&fd, ufda_base + uoffset, sizeof(fd));
> if (!ret)
> ret = binder_translate_fd(fd, offset, t, thread,
> in_reply_to);

This is something from the original code but if the copy_from_user()
fails, then we just skip that "fd" without informing the user. It feels
wrong. Does that not lead to a bug in the target app?


> @@ -2951,6 +2955,8 @@ static void binder_transaction(struct binder_proc *proc,
> case BINDER_TYPE_FDA: {
> struct binder_object ptr_object;
> binder_size_t parent_offset;
> + struct binder_object user_object;
> + size_t user_parent_size;
> struct binder_fd_array_object *fda =
> to_binder_fd_array_object(hdr);
> size_t num_valid = (buffer_offset - off_start_offset) /
> @@ -2982,8 +2988,28 @@ static void binder_transaction(struct binder_proc *proc,
> return_error_line = __LINE__;
> goto err_bad_parent;
> }
> - ret = binder_translate_fd_array(fda, parent, t, thread,
> - in_reply_to);
> +
> + /*
> + * We need to read the user version of the parent
> + * object to get the original user offset
> + */
> + user_parent_size =
> + binder_get_object(proc, user_buffer, t->buffer,
> + parent_offset, &user_object);
> + if (user_parent_size != sizeof(user_object.bbo)) {
> + binder_user_error("%d:%d invalid ptr object size: %lld vs %lld\n",

Apparently %lld breaks the build on my .config. The correct format for
size_t is %zd.

> + proc->pid, thread->pid,
> + user_parent_size,
> + sizeof(user_object.bbo));
> + return_error = BR_FAILED_REPLY;
> + return_error_param = -EINVAL;
> + return_error_line = __LINE__;
> + goto err_bad_parent;
> + }
> + ret = binder_translate_fd_array(fda, user_buffer,
> + parent,
> + &user_object.bbo, t,
> + thread, in_reply_to);

regards,
dan carpenter


2021-11-24 12:46:42

by Dan Carpenter

[permalink] [raw]
Subject: Re: [PATCH 3/3] binder: defer copies of pre-patched txn data

On Tue, Nov 23, 2021 at 11:17:37AM -0800, Todd Kjos wrote:
> +static int binder_do_deferred_txn_copies(struct binder_alloc *alloc,
> + struct binder_buffer *buffer,
> + struct list_head *sgc_head,
> + struct list_head *pf_head)
> +{
> + int ret = 0;
> + struct list_head *entry, *tmp;
> + struct binder_ptr_fixup *pf =
> + list_first_entry_or_null(pf_head, struct binder_ptr_fixup,
> + node);
> +
> + list_for_each_safe(entry, tmp, sgc_head) {
^^^^^^^^^^^^^^^^^^^
All the list_for_each() loops can be changed to list_for_each_entry().


list_for_each_entry_safe(sgc, tmp, sgc_head, node) {

regards,
dan carpenter



> + size_t bytes_copied = 0;
> + struct binder_sg_copy *sgc =
> + container_of(entry, struct binder_sg_copy, node);
> +


2021-11-24 13:03:37

by Dan Carpenter

[permalink] [raw]
Subject: Re: [PATCH 1/3] binder: avoid potential data leakage when copying txn

On Tue, Nov 23, 2021 at 11:17:35AM -0800, Todd Kjos wrote:
> Transactions are copied from the sender to the target
> first and objects like BINDER_TYPE_PTR and BINDER_TYPE_FDA
> are then fixed up. This means there is a short period where
> the sender's version of these objects are visible to the
> target prior to the fixups.
>
> Instead of copying all of the data first, copy data only
> after any needed fixups have been applied.
>

This patch needs a fixes tag.

So this patch basically fixes the simple part of the info leak and
patch 3 fixes the complicated part. Have I understood that correctly?

> @@ -2956,7 +2984,11 @@ static void binder_transaction(struct binder_proc *proc,
> }
> ret = binder_translate_fd_array(fda, parent, t, thread,
> in_reply_to);
> - if (ret < 0) {
> + if (ret < 0 ||
> + binder_alloc_copy_to_buffer(&target_proc->alloc,
> + t->buffer,
> + object_offset,
> + fda, sizeof(*fda))) {
> return_error = BR_FAILED_REPLY;
> return_error_param = ret;

"ret" is not a negative error code if binder_translate_fd_array()
succeeds but binder_alloc_copy_to_buffer() fails.


> return_error_line = __LINE__;
> @@ -3028,6 +3060,19 @@ static void binder_transaction(struct binder_proc *proc,
> goto err_bad_object_type;
> }
> }

regards,
dan carpenter

2021-11-24 15:54:31

by Todd Kjos

[permalink] [raw]
Subject: Re: [PATCH 0/3] binder: Prevent untranslated sender data from being copied to target

On Wed, Nov 24, 2021 at 12:08 AM Greg KH <[email protected]> wrote:
>
> On Tue, Nov 23, 2021 at 11:17:34AM -0800, Todd Kjos wrote:
> > Binder copies transactions directly from the sender buffer
> > to the target buffer and then fixes up BINDER_TYPE_PTR and
> > BINDER_TYPE_FDA objects. This means there is a brief time
> > when sender pointers and fds are visible to the target
> > process.
> >
> > This series reworks the the sender to target copy to
> > avoid leaking any untranslated sender data from being
> > visible in the target.
> >
> > Todd Kjos (3):
> > binder: defer copies of pre-patched txn data
> > binder: read pre-translated fds from sender buffer
> > binder: avoid potential data leakage when copying txn
> >
> > drivers/android/binder.c | 442 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
> > 1 file changed, 387 insertions(+), 55 deletions(-)
>
> Are these changes needed now in 5.16-final and also in stable kernels?
>
> Or can they wait until 5.17-rc1?

They can wait until 5.17-rc1.

>
> thanks,
>
> greg k-h

2021-11-24 20:11:45

by Todd Kjos

[permalink] [raw]
Subject: Re: [PATCH 1/3] binder: avoid potential data leakage when copying txn

On Wed, Nov 24, 2021 at 5:01 AM Dan Carpenter <[email protected]> wrote:
>
> On Tue, Nov 23, 2021 at 11:17:35AM -0800, Todd Kjos wrote:
> > Transactions are copied from the sender to the target
> > first and objects like BINDER_TYPE_PTR and BINDER_TYPE_FDA
> > are then fixed up. This means there is a short period where
> > the sender's version of these objects are visible to the
> > target prior to the fixups.
> >
> > Instead of copying all of the data first, copy data only
> > after any needed fixups have been applied.
> >
>
> This patch needs a fixes tag.

Sure, it goes back to the original submission, so I'll add:

Fixes: 457b9a6f09f0 ("Staging: android: add binder driver")

>
> So this patch basically fixes the simple part of the info leak and
> patch 3 fixes the complicated part. Have I understood that correctly?

Yes.

>
> > @@ -2956,7 +2984,11 @@ static void binder_transaction(struct binder_proc *proc,
> > }
> > ret = binder_translate_fd_array(fda, parent, t, thread,
> > in_reply_to);
> > - if (ret < 0) {
> > + if (ret < 0 ||
> > + binder_alloc_copy_to_buffer(&target_proc->alloc,
> > + t->buffer,
> > + object_offset,
> > + fda, sizeof(*fda))) {
> > return_error = BR_FAILED_REPLY;
> > return_error_param = ret;
>
> "ret" is not a negative error code if binder_translate_fd_array()
> succeeds but binder_alloc_copy_to_buffer() fails.

You are right. return_error_param would be 0 in this case. Will
capture the return of binder_alloc_copy_to_buffer(). Thanks.

>
>
> > return_error_line = __LINE__;
> > @@ -3028,6 +3060,19 @@ static void binder_transaction(struct binder_proc *proc,
> > goto err_bad_object_type;
> > }
> > }
>
> regards,
> dan carpenter
>
> --
> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
>

2021-11-24 20:33:41

by Todd Kjos

[permalink] [raw]
Subject: Re: [PATCH 2/3] binder: read pre-translated fds from sender buffer

On Wed, Nov 24, 2021 at 4:37 AM Dan Carpenter <[email protected]> wrote:
>
> On Tue, Nov 23, 2021 at 11:17:36AM -0800, Todd Kjos wrote:
> > Since we are no longer going to copy the pre-fixup
> > data from the target buffer, we need to read
> > pre-translated FD array information from the source
> > buffer.
> >
>
> The commit message is really misleading. From the commit message it
> sounds like the commit is changing runtime but it's not. What I want is
> a commit message like this:
>
> This patch is to prepare for an up coming patch where we read
> pre-translated fds from the sender buffer and translate them before
> copying them to the target. It does not change run time.
>
> The patch adds two new parameters to binder_translate_fd_array() to
> hold the sender buffer and sender buffer parent. These parameters let
> us call copy_from_user() directly instead of using
> binder_alloc_copy_from_buffer() which is a cleanup. Also the patch
> adds some new alignment checks. Previously the alignment checks would
> have been done in a different place, but this lets us print more
> useful error messages.

Got it. Will fix in update.

>
>
> > Signed-off-by: Todd Kjos <[email protected]>
> > ---
> > drivers/android/binder.c | 40 +++++++++++++++++++++++++++++++++-------
> > 1 file changed, 33 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > index 571d3c203557..2300fa8e09d5 100644
> > --- a/drivers/android/binder.c
> > +++ b/drivers/android/binder.c
> > @@ -2234,15 +2234,17 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
> > }
> >
> > static int binder_translate_fd_array(struct binder_fd_array_object *fda,
> > + const void __user *u,
>
> I wish we could use sender/target terminology everywhere. Please change
> every place that has "u" or "user" to either "sender" or "target" as
> appropriate.

Ok (all "u/user" cases are sender).

>
> > struct binder_buffer_object *parent,
> > + struct binder_buffer_object *uparent,
> ^
>
> > struct binder_transaction *t,
> > struct binder_thread *thread,
> > struct binder_transaction *in_reply_to)
> > {
> > binder_size_t fdi, fd_buf_size;
> > binder_size_t fda_offset;
> > + const void __user *ufda_base;
> ^
>
> > struct binder_proc *proc = thread->proc;
> > - struct binder_proc *target_proc = t->to_proc;
> >
> > fd_buf_size = sizeof(u32) * fda->num_fds;
> > if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
> > @@ -2266,7 +2268,10 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
> > */> fda_offset = (parent->buffer - (uintptr_t)t->buffer->user_data) +
> > fda->parent_offset;
> > - if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32))) {
> > + ufda_base = (void __user *)uparent->buffer + fda->parent_offset;
> > +
> > + if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32)) ||
> > + !IS_ALIGNED((unsigned long)ufda_base, sizeof(u32))) {
> > binder_user_error("%d:%d parent offset not aligned correctly.\n",
> > proc->pid, thread->pid);
> > return -EINVAL;
> > @@ -2275,10 +2280,9 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
> > u32 fd;
> > int ret;
> > binder_size_t offset = fda_offset + fdi * sizeof(fd);
> > + binder_size_t uoffset = fdi * sizeof(fd);
> >
> > - ret = binder_alloc_copy_from_buffer(&target_proc->alloc,
> > - &fd, t->buffer,
> > - offset, sizeof(fd));
> > + ret = copy_from_user(&fd, ufda_base + uoffset, sizeof(fd));
> > if (!ret)
> > ret = binder_translate_fd(fd, offset, t, thread,
> > in_reply_to);
>
> This is something from the original code but if the copy_from_user()
> fails, then we just skip that "fd" without informing the user.

Here is the whole code fragment(the diff doesn't include the "if
(ret<0) return ret"):

ret = copy_from_user(&fd, ufda_base + uoffset, sizeof(fd));
if (!ret)
ret = binder_translate_fd(fd, offset, t, thread, in_reply_to);
if (ret < 0)
return ret;

I agree -- if copy_from_user() for some reason doesn't copy the whole
buffer, it might return a positive integer. Then it would skip
binder_translate_fd(), but not return. That should probably be
something like:

if (ret)
return ret > 0 ? -EINVAL : ret;

Will fix in next version.

> It feels wrong. Does that not lead to a bug in the target app?
>

If copy_from_user() returned a positive integer, we would translate
some random fd. Most likely it would be invalid, but it might not be.
Definitely would be a bug.

>
> > @@ -2951,6 +2955,8 @@ static void binder_transaction(struct binder_proc *proc,
> > case BINDER_TYPE_FDA: {
> > struct binder_object ptr_object;
> > binder_size_t parent_offset;
> > + struct binder_object user_object;
> > + size_t user_parent_size;
> > struct binder_fd_array_object *fda =
> > to_binder_fd_array_object(hdr);
> > size_t num_valid = (buffer_offset - off_start_offset) /
> > @@ -2982,8 +2988,28 @@ static void binder_transaction(struct binder_proc *proc,
> > return_error_line = __LINE__;
> > goto err_bad_parent;
> > }
> > - ret = binder_translate_fd_array(fda, parent, t, thread,
> > - in_reply_to);
> > +
> > + /*
> > + * We need to read the user version of the parent
> > + * object to get the original user offset
> > + */
> > + user_parent_size =
> > + binder_get_object(proc, user_buffer, t->buffer,
> > + parent_offset, &user_object);
> > + if (user_parent_size != sizeof(user_object.bbo)) {
> > + binder_user_error("%d:%d invalid ptr object size: %lld vs %lld\n",
>
> Apparently %lld breaks the build on my .config. The correct format for
> size_t is %zd.
>
> > + proc->pid, thread->pid,
> > + user_parent_size,
> > + sizeof(user_object.bbo));
> > + return_error = BR_FAILED_REPLY;
> > + return_error_param = -EINVAL;
> > + return_error_line = __LINE__;
> > + goto err_bad_parent;
> > + }
> > + ret = binder_translate_fd_array(fda, user_buffer,
> > + parent,
> > + &user_object.bbo, t,
> > + thread, in_reply_to);
>
> regards,
> dan carpenter
>
> --
> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
>

2021-11-24 20:37:47

by Todd Kjos

[permalink] [raw]
Subject: Re: [PATCH 3/3] binder: defer copies of pre-patched txn data

On Wed, Nov 24, 2021 at 4:44 AM Dan Carpenter <[email protected]> wrote:
>
> On Tue, Nov 23, 2021 at 11:17:37AM -0800, Todd Kjos wrote:
> > +static int binder_do_deferred_txn_copies(struct binder_alloc *alloc,
> > + struct binder_buffer *buffer,
> > + struct list_head *sgc_head,
> > + struct list_head *pf_head)
> > +{
> > + int ret = 0;
> > + struct list_head *entry, *tmp;
> > + struct binder_ptr_fixup *pf =
> > + list_first_entry_or_null(pf_head, struct binder_ptr_fixup,
> > + node);
> > +
> > + list_for_each_safe(entry, tmp, sgc_head) {
> ^^^^^^^^^^^^^^^^^^^
> All the list_for_each() loops can be changed to list_for_each_entry().
>
>
> list_for_each_entry_safe(sgc, tmp, sgc_head, node) {

Will change. Thanks for the suggestion.

>
> regards,
> dan carpenter
>
>
>
> > + size_t bytes_copied = 0;
> > + struct binder_sg_copy *sgc =
> > + container_of(entry, struct binder_sg_copy, node);
> > +
>
> --
> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
>

2021-11-24 20:40:01

by Todd Kjos

[permalink] [raw]
Subject: Re: [PATCH 3/3] binder: defer copies of pre-patched txn data

On Wed, Nov 24, 2021 at 3:10 AM Dan Carpenter <[email protected]> wrote:
>
> On Tue, Nov 23, 2021 at 11:17:37AM -0800, Todd Kjos wrote:
> > +/**
> > + * binder_do_deferred_txn_copies() - copy and fixup scatter-gather data
> > + * @alloc: binder_alloc associated with @buffer
> > + * @buffer: binder buffer in target process
> > + * @sgc_head: list_head of scatter-gather copy list
> > + * @pf_head: list_head of pointer fixup list
> > + *
> > + * Processes all elements of @sgc_head, applying fixups from @pf_head
> > + * and copying the scatter-gather data from the source process' user
> > + * buffer to the target's buffer. It is expected that the list creation
> > + * and processing all occurs during binder_transaction() so these lists
> > + * are only accessed in local context.
> > + *
> > + * Return: 0=success, else -errno
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> This function is supposed to return negatives on error.
>
> > + */
> > +static int binder_do_deferred_txn_copies(struct binder_alloc *alloc,
> > + struct binder_buffer *buffer,
> > + struct list_head *sgc_head,
> > + struct list_head *pf_head)
> > +{
> > + int ret = 0;
> > + struct list_head *entry, *tmp;
> > + struct binder_ptr_fixup *pf =
> > + list_first_entry_or_null(pf_head, struct binder_ptr_fixup,
> > + node);
> > +
> > + list_for_each_safe(entry, tmp, sgc_head) {
> > + size_t bytes_copied = 0;
> > + struct binder_sg_copy *sgc =
> > + container_of(entry, struct binder_sg_copy, node);
> > +
> > + while (bytes_copied < sgc->length) {
> > + size_t copy_size;
> > + size_t bytes_left = sgc->length - bytes_copied;
> > + size_t offset = sgc->offset + bytes_copied;
> > +
> > + /*
> > + * We copy up to the fixup (pointed to by pf)
> > + */
> > + copy_size = pf ? min(bytes_left, (size_t)pf->offset - offset)
> > + : bytes_left;
> > + if (!ret && copy_size)
> > + ret = binder_alloc_copy_user_to_buffer(
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> "ret" is the number of bytes remaining to be copied.

Good catch. Thanks. Will fix.

>
>
> > + alloc, buffer,
> > + offset,
> > + sgc->uaddr + bytes_copied,
> > + copy_size);
> > + bytes_copied += copy_size;
> > + if (copy_size != bytes_left) {
> > + BUG_ON(!pf);
> > + /* we stopped at a fixup offset */
> > + if (pf->skip_size) {
> > + /*
> > + * we are just skipping. This is for
> > + * BINDER_TYPE_FDA where the translated
> > + * fds will be fixed up when we get
> > + * to target context.
> > + */
> > + bytes_copied += pf->skip_size;
> > + } else {
> > + /* apply the fixup indicated by pf */
> > + if (!ret)
> > + ret = binder_alloc_copy_to_buffer(
> > + alloc, buffer,
> > + pf->offset,
> > + &pf->fixup_data,
> > + sizeof(pf->fixup_data));
> > + bytes_copied += sizeof(pf->fixup_data);
> > + }
> > + list_del(&pf->node);
> > + kfree(pf);
> > + pf = list_first_entry_or_null(pf_head,
> > + struct binder_ptr_fixup, node);
> > + }
> > + }
> > + list_del(&sgc->node);
> > + kfree(sgc);
> > + }
> > + BUG_ON(!list_empty(pf_head));
> > + BUG_ON(!list_empty(sgc_head));
> > +
> > + return ret;
> > +}
> > +
> > +/**
> > + * binder_cleanup_deferred_txn_lists() - free specified lists
> > + * @sgc_head: list_head of scatter-gather copy list
> > + * @pf_head: list_head of pointer fixup list
> > + *
> > + * Called to clean up @sgc_head and @pf_head if there is an
> > + * error.
> > + */
> > +static void binder_cleanup_deferred_txn_lists(struct list_head *sgc_head,
> > + struct list_head *pf_head)
> > +{
> > + struct list_head *entry, *tmp;
> > +
> > + list_for_each_safe(entry, tmp, sgc_head) {
> > + struct binder_sg_copy *sgc =
> > + container_of(entry, struct binder_sg_copy, node);
> > + list_del(&sgc->node);
> > + kfree(sgc);
> > + }
> > + list_for_each_safe(entry, tmp, pf_head) {
> > + struct binder_ptr_fixup *pf =
> > + container_of(entry, struct binder_ptr_fixup, node);
> > + list_del(&pf->node);
> > + kfree(pf);
> > + }
> > +}
> > +
> > +/**
> > + * binder_defer_copy() - queue a scatter-gather buffer for copy
> > + * @sgc_head: list_head of scatter-gather copy list
> > + * @offset: binder buffer offset in target process
> > + * @uaddr: user address in source process
> > + * @length: bytes to copy
> > + *
> > + * Specify a scatter-gather block to be copied. The actual copy must
> > + * be deferred until all the needed fixups are identified and queued.
> > + * Then the copy and fixups are done together so un-translated values
> > + * from the source are never visible in the target buffer.
> > + *
> > + * We are guaranteed that repeated calls to this function will have
> > + * monotonically increasing @offset values so the list will naturally
> > + * be ordered.
> > + *
> > + * Return: 0=success, else -errno
> > + */
> > +static int binder_defer_copy(struct list_head *sgc_head, binder_size_t offset,
> > + const void __user *uaddr, size_t length)
> > +{
> > + struct binder_sg_copy *bc = kzalloc(sizeof(*bc), GFP_KERNEL);
> > +
> > + if (!bc)
> > + return -ENOMEM;
> > +
> > + bc->offset = offset;
> > + bc->uaddr = uaddr;
> > + bc->length = length;
> > + INIT_LIST_HEAD(&bc->node);
> > +
> > + /*
> > + * We are guaranteed that the deferred copies are in-order
> > + * so just add to the tail.
> > + */
> > + list_add_tail(&bc->node, sgc_head);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * binder_add_fixup() - queue a fixup to be applied to sg copy
> > + * @pf_head: list_head of binder ptr fixup list
> > + * @offset: binder buffer offset in target process
> > + * @fixup: bytes to be copied for fixup
> > + * @skip_size: bytes to skip when copying (fixup will be applied later)
> > + *
> > + * Add the specified fixup to a list ordered by @offset. When copying
> > + * the scatter-gather buffers, the fixup will be copied instead of
> > + * data from the source buffer. For BINDER_TYPE_FDA fixups, the fixup
> > + * will be applied later (in target process context), so we just skip
> > + * the bytes specified by @skip_size. If @skip_size is 0, we copy the
> > + * value in @fixup.
> > + *
> > + * This function is called *mostly* in @offset order, but there are
> > + * exceptions. Since out-of-order inserts are relatively uncommon,
> > + * we insert the new element by searching backward from the tail of
> > + * the list.
> > + *
> > + * Return: 0=success, else -errno
> > + */
> > +static int binder_add_fixup(struct list_head *pf_head, binder_size_t offset,
> > + binder_uintptr_t fixup, size_t skip_size)
> > +{
> > + struct binder_ptr_fixup *pf = kzalloc(sizeof(*pf), GFP_KERNEL);
> > + struct list_head *tmp;
> > +
> > + if (!pf)
> > + return -ENOMEM;
> > +
> > + pf->offset = offset;
> > + pf->fixup_data = fixup;
> > + pf->skip_size = skip_size;
> > + INIT_LIST_HEAD(&pf->node);
> > +
> > + /* Fixups are *mostly* added in-order, but there are some
> > + * exceptions. Look backwards through list for insertion point.
> > + */
> > + if (!list_empty(pf_head)) {
>
> This condition is not required. If list is empty we add it to the tail,
> but when there is only one item on the list, the first and last item are
> going to be the same.

Good point.

>
> > + list_for_each_prev(tmp, pf_head) {
> > + struct binder_ptr_fixup *tmppf =
> > + list_entry(tmp, struct binder_ptr_fixup, node);
> > +
> > + if (tmppf->offset < pf->offset) {
> > + list_add(&pf->node, tmp);
> > + return 0;
> > + }
> > + }
> > + /*
> > + * if we get here, then the new offset is the lowest so
> > + * insert at the head
> > + */
> > + list_add(&pf->node, pf_head);
> > + return 0;
> > + }
> > + list_add_tail(&pf->node, pf_head);
> > + return 0;
> > +}
> > +
>
> regards,
> dan carpenter

Dan, Thanks for the detailed review on all 3 patches.

>
> --
> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
>

2021-11-25 02:10:10

by kernel test robot

[permalink] [raw]
Subject: Re: [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/[email protected]/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 <[email protected]>

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/[email protected]

2021-11-25 06:40:18

by Dan Carpenter

[permalink] [raw]
Subject: Re: [PATCH 2/3] binder: read pre-translated fds from sender buffer

On Wed, Nov 24, 2021 at 12:33:20PM -0800, Todd Kjos wrote:
> I agree -- if copy_from_user() for some reason doesn't copy the whole
> buffer, it might return a positive integer. Then it would skip
> binder_translate_fd(), but not return. That should probably be
> something like:
>
> if (ret)
> return ret > 0 ? -EINVAL : ret;
>
> Will fix in next version.

It should really be a separate patch at the start of the series because
it's from the original code and unrelated.

regards,
dan carpenter


2021-11-25 12:24:06

by kernel test robot

[permalink] [raw]
Subject: Re: [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-20211125]
[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: ia64-randconfig-s032-20211123 (https://download.01.org/0day-ci/archive/20211125/[email protected]/config)
compiler: ia64-linux-gcc (GCC) 11.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.4-dirty
# 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 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=ia64 SHELL=/bin/bash drivers/android/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>


sparse warnings: (new ones prefixed by >>)
>> drivers/android/binder.c:2707:17: sparse: sparse: cast removes address space '__user' of expression
drivers/android/binder.c:2716:17: sparse: sparse: cast removes address space '__user' of expression
drivers/android/binder.c:4507:24: sparse: sparse: incorrect type in return expression (different base types) @@ expected restricted __poll_t @@ got int @@
drivers/android/binder.c:4507:24: sparse: expected restricted __poll_t
drivers/android/binder.c:4507:24: sparse: got int

vim +/__user +2707 drivers/android/binder.c

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

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]