mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	binder: use userspace pointer as base of buffer space
Now that alloc->buffer points to the userspace vm_area rename buffer->data to buffer->user_data and rename local pointers that hold user addresses. Also use the "__user" tag to annotate all user pointers so sparse can flag cases where user pointer vaues are copied to kernel pointers. Refactor code to use offsets instead of user pointers. Signed-off-by: Todd Kjos <tkjos@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									c41358a5f5
								
							
						
					
					
						commit
						bde4a19fc0
					
				
					 5 changed files with 118 additions and 99 deletions
				
			
		| 
						 | 
					@ -2278,33 +2278,30 @@ static void binder_deferred_fd_close(int fd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void binder_transaction_buffer_release(struct binder_proc *proc,
 | 
					static void binder_transaction_buffer_release(struct binder_proc *proc,
 | 
				
			||||||
					      struct binder_buffer *buffer,
 | 
										      struct binder_buffer *buffer,
 | 
				
			||||||
					      binder_size_t *failed_at)
 | 
										      binder_size_t failed_at,
 | 
				
			||||||
 | 
										      bool is_failure)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	binder_size_t *offp, *off_start, *off_end;
 | 
					 | 
				
			||||||
	int debug_id = buffer->debug_id;
 | 
						int debug_id = buffer->debug_id;
 | 
				
			||||||
	binder_size_t off_start_offset;
 | 
						binder_size_t off_start_offset, buffer_offset, off_end_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	binder_debug(BINDER_DEBUG_TRANSACTION,
 | 
						binder_debug(BINDER_DEBUG_TRANSACTION,
 | 
				
			||||||
		     "%d buffer release %d, size %zd-%zd, failed at %pK\n",
 | 
							     "%d buffer release %d, size %zd-%zd, failed at %llx\n",
 | 
				
			||||||
		     proc->pid, buffer->debug_id,
 | 
							     proc->pid, buffer->debug_id,
 | 
				
			||||||
		     buffer->data_size, buffer->offsets_size, failed_at);
 | 
							     buffer->data_size, buffer->offsets_size,
 | 
				
			||||||
 | 
							     (unsigned long long)failed_at);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (buffer->target_node)
 | 
						if (buffer->target_node)
 | 
				
			||||||
		binder_dec_node(buffer->target_node, 1, 0);
 | 
							binder_dec_node(buffer->target_node, 1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	off_start_offset = ALIGN(buffer->data_size, sizeof(void *));
 | 
						off_start_offset = ALIGN(buffer->data_size, sizeof(void *));
 | 
				
			||||||
	off_start = (binder_size_t *)(buffer->data + off_start_offset);
 | 
						off_end_offset = is_failure ? failed_at :
 | 
				
			||||||
	if (failed_at)
 | 
									off_start_offset + buffer->offsets_size;
 | 
				
			||||||
		off_end = failed_at;
 | 
						for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
 | 
				
			||||||
	else
 | 
						     buffer_offset += sizeof(binder_size_t)) {
 | 
				
			||||||
		off_end = (void *)off_start + buffer->offsets_size;
 | 
					 | 
				
			||||||
	for (offp = off_start; offp < off_end; offp++) {
 | 
					 | 
				
			||||||
		struct binder_object_header *hdr;
 | 
							struct binder_object_header *hdr;
 | 
				
			||||||
		size_t object_size;
 | 
							size_t object_size;
 | 
				
			||||||
		struct binder_object object;
 | 
							struct binder_object object;
 | 
				
			||||||
		binder_size_t object_offset;
 | 
							binder_size_t object_offset;
 | 
				
			||||||
		binder_size_t buffer_offset = (uintptr_t)offp -
 | 
					 | 
				
			||||||
			(uintptr_t)buffer->data;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
 | 
							binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
 | 
				
			||||||
					      buffer, buffer_offset,
 | 
										      buffer, buffer_offset,
 | 
				
			||||||
| 
						 | 
					@ -2380,9 +2377,10 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 | 
				
			||||||
			struct binder_fd_array_object *fda;
 | 
								struct binder_fd_array_object *fda;
 | 
				
			||||||
			struct binder_buffer_object *parent;
 | 
								struct binder_buffer_object *parent;
 | 
				
			||||||
			struct binder_object ptr_object;
 | 
								struct binder_object ptr_object;
 | 
				
			||||||
			u32 *fd_array;
 | 
								binder_size_t fda_offset;
 | 
				
			||||||
			size_t fd_index;
 | 
								size_t fd_index;
 | 
				
			||||||
			binder_size_t fd_buf_size;
 | 
								binder_size_t fd_buf_size;
 | 
				
			||||||
 | 
								binder_size_t num_valid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (proc->tsk != current->group_leader) {
 | 
								if (proc->tsk != current->group_leader) {
 | 
				
			||||||
				/*
 | 
									/*
 | 
				
			||||||
| 
						 | 
					@ -2393,12 +2391,14 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								num_valid = (buffer_offset - off_start_offset) /
 | 
				
			||||||
 | 
											sizeof(binder_size_t);
 | 
				
			||||||
			fda = to_binder_fd_array_object(hdr);
 | 
								fda = to_binder_fd_array_object(hdr);
 | 
				
			||||||
			parent = binder_validate_ptr(proc, buffer, &ptr_object,
 | 
								parent = binder_validate_ptr(proc, buffer, &ptr_object,
 | 
				
			||||||
						     fda->parent,
 | 
											     fda->parent,
 | 
				
			||||||
						     off_start_offset,
 | 
											     off_start_offset,
 | 
				
			||||||
						     NULL,
 | 
											     NULL,
 | 
				
			||||||
						     offp - off_start);
 | 
											     num_valid);
 | 
				
			||||||
			if (!parent) {
 | 
								if (!parent) {
 | 
				
			||||||
				pr_err("transaction release %d bad parent offset\n",
 | 
									pr_err("transaction release %d bad parent offset\n",
 | 
				
			||||||
				       debug_id);
 | 
									       debug_id);
 | 
				
			||||||
| 
						 | 
					@ -2417,14 +2417,21 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 | 
				
			||||||
				       debug_id, (u64)fda->num_fds);
 | 
									       debug_id, (u64)fda->num_fds);
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			fd_array = (u32 *)(uintptr_t)
 | 
								/*
 | 
				
			||||||
				(parent->buffer + fda->parent_offset);
 | 
								 * the source data for binder_buffer_object is visible
 | 
				
			||||||
 | 
								 * to user-space and the @buffer element is the user
 | 
				
			||||||
 | 
								 * pointer to the buffer_object containing the fd_array.
 | 
				
			||||||
 | 
								 * Convert the address to an offset relative to
 | 
				
			||||||
 | 
								 * the base of the transaction buffer.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								fda_offset =
 | 
				
			||||||
 | 
								    (parent->buffer - (uintptr_t)buffer->user_data) +
 | 
				
			||||||
 | 
								    fda->parent_offset;
 | 
				
			||||||
			for (fd_index = 0; fd_index < fda->num_fds;
 | 
								for (fd_index = 0; fd_index < fda->num_fds;
 | 
				
			||||||
			     fd_index++) {
 | 
								     fd_index++) {
 | 
				
			||||||
				u32 fd;
 | 
									u32 fd;
 | 
				
			||||||
				binder_size_t offset =
 | 
									binder_size_t offset = fda_offset +
 | 
				
			||||||
					(uintptr_t)&fd_array[fd_index] -
 | 
										fd_index * sizeof(fd);
 | 
				
			||||||
					(uintptr_t)buffer->data;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				binder_alloc_copy_from_buffer(&proc->alloc,
 | 
									binder_alloc_copy_from_buffer(&proc->alloc,
 | 
				
			||||||
							      &fd,
 | 
												      &fd,
 | 
				
			||||||
| 
						 | 
					@ -2638,7 +2645,7 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
 | 
				
			||||||
				     struct binder_transaction *in_reply_to)
 | 
									     struct binder_transaction *in_reply_to)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	binder_size_t fdi, fd_buf_size;
 | 
						binder_size_t fdi, fd_buf_size;
 | 
				
			||||||
	u32 *fd_array;
 | 
						binder_size_t fda_offset;
 | 
				
			||||||
	struct binder_proc *proc = thread->proc;
 | 
						struct binder_proc *proc = thread->proc;
 | 
				
			||||||
	struct binder_proc *target_proc = t->to_proc;
 | 
						struct binder_proc *target_proc = t->to_proc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2655,8 +2662,16 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
 | 
				
			||||||
				  proc->pid, thread->pid, (u64)fda->num_fds);
 | 
									  proc->pid, thread->pid, (u64)fda->num_fds);
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	fd_array = (u32 *)(uintptr_t)(parent->buffer + fda->parent_offset);
 | 
						/*
 | 
				
			||||||
	if (!IS_ALIGNED((unsigned long)fd_array, sizeof(u32))) {
 | 
						 * the source data for binder_buffer_object is visible
 | 
				
			||||||
 | 
						 * to user-space and the @buffer element is the user
 | 
				
			||||||
 | 
						 * pointer to the buffer_object containing the fd_array.
 | 
				
			||||||
 | 
						 * Convert the address to an offset relative to
 | 
				
			||||||
 | 
						 * the base of the transaction buffer.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						fda_offset = (parent->buffer - (uintptr_t)t->buffer->user_data) +
 | 
				
			||||||
 | 
							fda->parent_offset;
 | 
				
			||||||
 | 
						if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32))) {
 | 
				
			||||||
		binder_user_error("%d:%d parent offset not aligned correctly.\n",
 | 
							binder_user_error("%d:%d parent offset not aligned correctly.\n",
 | 
				
			||||||
				  proc->pid, thread->pid);
 | 
									  proc->pid, thread->pid);
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -2664,9 +2679,7 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
 | 
				
			||||||
	for (fdi = 0; fdi < fda->num_fds; fdi++) {
 | 
						for (fdi = 0; fdi < fda->num_fds; fdi++) {
 | 
				
			||||||
		u32 fd;
 | 
							u32 fd;
 | 
				
			||||||
		int ret;
 | 
							int ret;
 | 
				
			||||||
		binder_size_t offset =
 | 
							binder_size_t offset = fda_offset + fdi * sizeof(fd);
 | 
				
			||||||
			(uintptr_t)&fd_array[fdi] -
 | 
					 | 
				
			||||||
			(uintptr_t)t->buffer->data;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		binder_alloc_copy_from_buffer(&target_proc->alloc,
 | 
							binder_alloc_copy_from_buffer(&target_proc->alloc,
 | 
				
			||||||
					      &fd, t->buffer,
 | 
										      &fd, t->buffer,
 | 
				
			||||||
| 
						 | 
					@ -2724,7 +2737,7 @@ static int binder_fixup_parent(struct binder_transaction *t,
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	buffer_offset = bp->parent_offset +
 | 
						buffer_offset = bp->parent_offset +
 | 
				
			||||||
			(uintptr_t)parent->buffer - (uintptr_t)b->data;
 | 
								(uintptr_t)parent->buffer - (uintptr_t)b->user_data;
 | 
				
			||||||
	binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
 | 
						binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
 | 
				
			||||||
				    &bp->buffer, sizeof(bp->buffer));
 | 
									    &bp->buffer, sizeof(bp->buffer));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2845,10 +2858,10 @@ static void binder_transaction(struct binder_proc *proc,
 | 
				
			||||||
	struct binder_transaction *t;
 | 
						struct binder_transaction *t;
 | 
				
			||||||
	struct binder_work *w;
 | 
						struct binder_work *w;
 | 
				
			||||||
	struct binder_work *tcomplete;
 | 
						struct binder_work *tcomplete;
 | 
				
			||||||
	binder_size_t *offp, *off_end, *off_start;
 | 
						binder_size_t buffer_offset = 0;
 | 
				
			||||||
	binder_size_t off_start_offset;
 | 
						binder_size_t off_start_offset, off_end_offset;
 | 
				
			||||||
	binder_size_t off_min;
 | 
						binder_size_t off_min;
 | 
				
			||||||
	u8 *sg_bufp, *sg_buf_end;
 | 
						binder_size_t sg_buf_offset, sg_buf_end_offset;
 | 
				
			||||||
	struct binder_proc *target_proc = NULL;
 | 
						struct binder_proc *target_proc = NULL;
 | 
				
			||||||
	struct binder_thread *target_thread = NULL;
 | 
						struct binder_thread *target_thread = NULL;
 | 
				
			||||||
	struct binder_node *target_node = NULL;
 | 
						struct binder_node *target_node = NULL;
 | 
				
			||||||
| 
						 | 
					@ -3141,7 +3154,7 @@ static void binder_transaction(struct binder_proc *proc,
 | 
				
			||||||
				    ALIGN(extra_buffers_size, sizeof(void *)) -
 | 
									    ALIGN(extra_buffers_size, sizeof(void *)) -
 | 
				
			||||||
				    ALIGN(secctx_sz, sizeof(u64));
 | 
									    ALIGN(secctx_sz, sizeof(u64));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		t->security_ctx = (uintptr_t)t->buffer->data + buf_offset;
 | 
							t->security_ctx = (uintptr_t)t->buffer->user_data + buf_offset;
 | 
				
			||||||
		binder_alloc_copy_to_buffer(&target_proc->alloc,
 | 
							binder_alloc_copy_to_buffer(&target_proc->alloc,
 | 
				
			||||||
					    t->buffer, buf_offset,
 | 
										    t->buffer, buf_offset,
 | 
				
			||||||
					    secctx, secctx_sz);
 | 
										    secctx, secctx_sz);
 | 
				
			||||||
| 
						 | 
					@ -3152,9 +3165,6 @@ static void binder_transaction(struct binder_proc *proc,
 | 
				
			||||||
	t->buffer->transaction = t;
 | 
						t->buffer->transaction = t;
 | 
				
			||||||
	t->buffer->target_node = target_node;
 | 
						t->buffer->target_node = target_node;
 | 
				
			||||||
	trace_binder_transaction_alloc_buf(t->buffer);
 | 
						trace_binder_transaction_alloc_buf(t->buffer);
 | 
				
			||||||
	off_start_offset = ALIGN(tr->data_size, sizeof(void *));
 | 
					 | 
				
			||||||
	off_start = (binder_size_t *)(t->buffer->data + off_start_offset);
 | 
					 | 
				
			||||||
	offp = off_start;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (binder_alloc_copy_user_to_buffer(
 | 
						if (binder_alloc_copy_user_to_buffer(
 | 
				
			||||||
				&target_proc->alloc,
 | 
									&target_proc->alloc,
 | 
				
			||||||
| 
						 | 
					@ -3200,17 +3210,18 @@ static void binder_transaction(struct binder_proc *proc,
 | 
				
			||||||
		return_error_line = __LINE__;
 | 
							return_error_line = __LINE__;
 | 
				
			||||||
		goto err_bad_offset;
 | 
							goto err_bad_offset;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	off_end = (void *)off_start + tr->offsets_size;
 | 
						off_start_offset = ALIGN(tr->data_size, sizeof(void *));
 | 
				
			||||||
	sg_bufp = (u8 *)(PTR_ALIGN(off_end, sizeof(void *)));
 | 
						buffer_offset = off_start_offset;
 | 
				
			||||||
	sg_buf_end = sg_bufp + extra_buffers_size;
 | 
						off_end_offset = off_start_offset + tr->offsets_size;
 | 
				
			||||||
 | 
						sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
 | 
				
			||||||
 | 
						sg_buf_end_offset = sg_buf_offset + extra_buffers_size;
 | 
				
			||||||
	off_min = 0;
 | 
						off_min = 0;
 | 
				
			||||||
	for (; offp < off_end; offp++) {
 | 
						for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
 | 
				
			||||||
 | 
						     buffer_offset += sizeof(binder_size_t)) {
 | 
				
			||||||
		struct binder_object_header *hdr;
 | 
							struct binder_object_header *hdr;
 | 
				
			||||||
		size_t object_size;
 | 
							size_t object_size;
 | 
				
			||||||
		struct binder_object object;
 | 
							struct binder_object object;
 | 
				
			||||||
		binder_size_t object_offset;
 | 
							binder_size_t object_offset;
 | 
				
			||||||
		binder_size_t buffer_offset =
 | 
					 | 
				
			||||||
			(uintptr_t)offp - (uintptr_t)t->buffer->data;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		binder_alloc_copy_from_buffer(&target_proc->alloc,
 | 
							binder_alloc_copy_from_buffer(&target_proc->alloc,
 | 
				
			||||||
					      &object_offset,
 | 
										      &object_offset,
 | 
				
			||||||
| 
						 | 
					@ -3290,12 +3301,14 @@ static void binder_transaction(struct binder_proc *proc,
 | 
				
			||||||
			binder_size_t parent_offset;
 | 
								binder_size_t parent_offset;
 | 
				
			||||||
			struct binder_fd_array_object *fda =
 | 
								struct binder_fd_array_object *fda =
 | 
				
			||||||
				to_binder_fd_array_object(hdr);
 | 
									to_binder_fd_array_object(hdr);
 | 
				
			||||||
 | 
								size_t num_valid = (buffer_offset - off_start_offset) *
 | 
				
			||||||
 | 
											sizeof(binder_size_t);
 | 
				
			||||||
			struct binder_buffer_object *parent =
 | 
								struct binder_buffer_object *parent =
 | 
				
			||||||
				binder_validate_ptr(target_proc, t->buffer,
 | 
									binder_validate_ptr(target_proc, t->buffer,
 | 
				
			||||||
						    &ptr_object, fda->parent,
 | 
											    &ptr_object, fda->parent,
 | 
				
			||||||
						    off_start_offset,
 | 
											    off_start_offset,
 | 
				
			||||||
						    &parent_offset,
 | 
											    &parent_offset,
 | 
				
			||||||
						    offp - off_start);
 | 
											    num_valid);
 | 
				
			||||||
			if (!parent) {
 | 
								if (!parent) {
 | 
				
			||||||
				binder_user_error("%d:%d got transaction with invalid parent offset or type\n",
 | 
									binder_user_error("%d:%d got transaction with invalid parent offset or type\n",
 | 
				
			||||||
						  proc->pid, thread->pid);
 | 
											  proc->pid, thread->pid);
 | 
				
			||||||
| 
						 | 
					@ -3332,9 +3345,8 @@ static void binder_transaction(struct binder_proc *proc,
 | 
				
			||||||
		case BINDER_TYPE_PTR: {
 | 
							case BINDER_TYPE_PTR: {
 | 
				
			||||||
			struct binder_buffer_object *bp =
 | 
								struct binder_buffer_object *bp =
 | 
				
			||||||
				to_binder_buffer_object(hdr);
 | 
									to_binder_buffer_object(hdr);
 | 
				
			||||||
			size_t buf_left = sg_buf_end - sg_bufp;
 | 
								size_t buf_left = sg_buf_end_offset - sg_buf_offset;
 | 
				
			||||||
			binder_size_t sg_buf_offset = (uintptr_t)sg_bufp -
 | 
								size_t num_valid;
 | 
				
			||||||
				(uintptr_t)t->buffer->data;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (bp->length > buf_left) {
 | 
								if (bp->length > buf_left) {
 | 
				
			||||||
				binder_user_error("%d:%d got transaction with too large buffer\n",
 | 
									binder_user_error("%d:%d got transaction with too large buffer\n",
 | 
				
			||||||
| 
						 | 
					@ -3359,12 +3371,15 @@ static void binder_transaction(struct binder_proc *proc,
 | 
				
			||||||
				goto err_copy_data_failed;
 | 
									goto err_copy_data_failed;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			/* Fixup buffer pointer to target proc address space */
 | 
								/* Fixup buffer pointer to target proc address space */
 | 
				
			||||||
			bp->buffer = (uintptr_t)sg_bufp;
 | 
								bp->buffer = (uintptr_t)
 | 
				
			||||||
			sg_bufp += ALIGN(bp->length, sizeof(u64));
 | 
									t->buffer->user_data + sg_buf_offset;
 | 
				
			||||||
 | 
								sg_buf_offset += ALIGN(bp->length, sizeof(u64));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								num_valid = (buffer_offset - off_start_offset) *
 | 
				
			||||||
 | 
										sizeof(binder_size_t);
 | 
				
			||||||
			ret = binder_fixup_parent(t, thread, bp,
 | 
								ret = binder_fixup_parent(t, thread, bp,
 | 
				
			||||||
						  off_start_offset,
 | 
											  off_start_offset,
 | 
				
			||||||
						  offp - off_start,
 | 
											  num_valid,
 | 
				
			||||||
						  last_fixup_obj_off,
 | 
											  last_fixup_obj_off,
 | 
				
			||||||
						  last_fixup_min_off);
 | 
											  last_fixup_min_off);
 | 
				
			||||||
			if (ret < 0) {
 | 
								if (ret < 0) {
 | 
				
			||||||
| 
						 | 
					@ -3456,7 +3471,8 @@ static void binder_transaction(struct binder_proc *proc,
 | 
				
			||||||
err_copy_data_failed:
 | 
					err_copy_data_failed:
 | 
				
			||||||
	binder_free_txn_fixups(t);
 | 
						binder_free_txn_fixups(t);
 | 
				
			||||||
	trace_binder_transaction_failed_buffer_release(t->buffer);
 | 
						trace_binder_transaction_failed_buffer_release(t->buffer);
 | 
				
			||||||
	binder_transaction_buffer_release(target_proc, t->buffer, offp);
 | 
						binder_transaction_buffer_release(target_proc, t->buffer,
 | 
				
			||||||
 | 
										  buffer_offset, true);
 | 
				
			||||||
	if (target_node)
 | 
						if (target_node)
 | 
				
			||||||
		binder_dec_node_tmpref(target_node);
 | 
							binder_dec_node_tmpref(target_node);
 | 
				
			||||||
	target_node = NULL;
 | 
						target_node = NULL;
 | 
				
			||||||
| 
						 | 
					@ -3557,7 +3573,7 @@ binder_free_buf(struct binder_proc *proc, struct binder_buffer *buffer)
 | 
				
			||||||
		binder_node_inner_unlock(buf_node);
 | 
							binder_node_inner_unlock(buf_node);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	trace_binder_transaction_buffer_release(buffer);
 | 
						trace_binder_transaction_buffer_release(buffer);
 | 
				
			||||||
	binder_transaction_buffer_release(proc, buffer, NULL);
 | 
						binder_transaction_buffer_release(proc, buffer, 0, false);
 | 
				
			||||||
	binder_alloc_free_buf(&proc->alloc, buffer);
 | 
						binder_alloc_free_buf(&proc->alloc, buffer);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4451,7 +4467,7 @@ static int binder_thread_read(struct binder_proc *proc,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		trd->data_size = t->buffer->data_size;
 | 
							trd->data_size = t->buffer->data_size;
 | 
				
			||||||
		trd->offsets_size = t->buffer->offsets_size;
 | 
							trd->offsets_size = t->buffer->offsets_size;
 | 
				
			||||||
		trd->data.ptr.buffer = (uintptr_t)t->buffer->data;
 | 
							trd->data.ptr.buffer = (uintptr_t)t->buffer->user_data;
 | 
				
			||||||
		trd->data.ptr.offsets = trd->data.ptr.buffer +
 | 
							trd->data.ptr.offsets = trd->data.ptr.buffer +
 | 
				
			||||||
					ALIGN(t->buffer->data_size,
 | 
										ALIGN(t->buffer->data_size,
 | 
				
			||||||
					    sizeof(void *));
 | 
										    sizeof(void *));
 | 
				
			||||||
| 
						 | 
					@ -5489,7 +5505,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
 | 
				
			||||||
		seq_printf(m, " node %d", buffer->target_node->debug_id);
 | 
							seq_printf(m, " node %d", buffer->target_node->debug_id);
 | 
				
			||||||
	seq_printf(m, " size %zd:%zd data %pK\n",
 | 
						seq_printf(m, " size %zd:%zd data %pK\n",
 | 
				
			||||||
		   buffer->data_size, buffer->offsets_size,
 | 
							   buffer->data_size, buffer->offsets_size,
 | 
				
			||||||
		   buffer->data);
 | 
							   buffer->user_data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void print_binder_work_ilocked(struct seq_file *m,
 | 
					static void print_binder_work_ilocked(struct seq_file *m,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,9 +69,8 @@ static size_t binder_alloc_buffer_size(struct binder_alloc *alloc,
 | 
				
			||||||
				       struct binder_buffer *buffer)
 | 
									       struct binder_buffer *buffer)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (list_is_last(&buffer->entry, &alloc->buffers))
 | 
						if (list_is_last(&buffer->entry, &alloc->buffers))
 | 
				
			||||||
		return (u8 *)alloc->buffer +
 | 
							return alloc->buffer + alloc->buffer_size - buffer->user_data;
 | 
				
			||||||
			alloc->buffer_size - (u8 *)buffer->data;
 | 
						return binder_buffer_next(buffer)->user_data - buffer->user_data;
 | 
				
			||||||
	return (u8 *)binder_buffer_next(buffer)->data - (u8 *)buffer->data;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void binder_insert_free_buffer(struct binder_alloc *alloc,
 | 
					static void binder_insert_free_buffer(struct binder_alloc *alloc,
 | 
				
			||||||
| 
						 | 
					@ -121,9 +120,9 @@ static void binder_insert_allocated_buffer_locked(
 | 
				
			||||||
		buffer = rb_entry(parent, struct binder_buffer, rb_node);
 | 
							buffer = rb_entry(parent, struct binder_buffer, rb_node);
 | 
				
			||||||
		BUG_ON(buffer->free);
 | 
							BUG_ON(buffer->free);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (new_buffer->data < buffer->data)
 | 
							if (new_buffer->user_data < buffer->user_data)
 | 
				
			||||||
			p = &parent->rb_left;
 | 
								p = &parent->rb_left;
 | 
				
			||||||
		else if (new_buffer->data > buffer->data)
 | 
							else if (new_buffer->user_data > buffer->user_data)
 | 
				
			||||||
			p = &parent->rb_right;
 | 
								p = &parent->rb_right;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			BUG();
 | 
								BUG();
 | 
				
			||||||
| 
						 | 
					@ -138,17 +137,17 @@ static struct binder_buffer *binder_alloc_prepare_to_free_locked(
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rb_node *n = alloc->allocated_buffers.rb_node;
 | 
						struct rb_node *n = alloc->allocated_buffers.rb_node;
 | 
				
			||||||
	struct binder_buffer *buffer;
 | 
						struct binder_buffer *buffer;
 | 
				
			||||||
	void *uptr;
 | 
						void __user *uptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uptr = (void *)user_ptr;
 | 
						uptr = (void __user *)user_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (n) {
 | 
						while (n) {
 | 
				
			||||||
		buffer = rb_entry(n, struct binder_buffer, rb_node);
 | 
							buffer = rb_entry(n, struct binder_buffer, rb_node);
 | 
				
			||||||
		BUG_ON(buffer->free);
 | 
							BUG_ON(buffer->free);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (uptr < buffer->data)
 | 
							if (uptr < buffer->user_data)
 | 
				
			||||||
			n = n->rb_left;
 | 
								n = n->rb_left;
 | 
				
			||||||
		else if (uptr > buffer->data)
 | 
							else if (uptr > buffer->user_data)
 | 
				
			||||||
			n = n->rb_right;
 | 
								n = n->rb_right;
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
| 
						 | 
					@ -188,9 +187,9 @@ struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
 | 
					static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
 | 
				
			||||||
				    void *start, void *end)
 | 
									    void __user *start, void __user *end)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	void *page_addr;
 | 
						void __user *page_addr;
 | 
				
			||||||
	unsigned long user_page_addr;
 | 
						unsigned long user_page_addr;
 | 
				
			||||||
	struct binder_lru_page *page;
 | 
						struct binder_lru_page *page;
 | 
				
			||||||
	struct vm_area_struct *vma = NULL;
 | 
						struct vm_area_struct *vma = NULL;
 | 
				
			||||||
| 
						 | 
					@ -357,8 +356,8 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
 | 
				
			||||||
	struct binder_buffer *buffer;
 | 
						struct binder_buffer *buffer;
 | 
				
			||||||
	size_t buffer_size;
 | 
						size_t buffer_size;
 | 
				
			||||||
	struct rb_node *best_fit = NULL;
 | 
						struct rb_node *best_fit = NULL;
 | 
				
			||||||
	void *has_page_addr;
 | 
						void __user *has_page_addr;
 | 
				
			||||||
	void *end_page_addr;
 | 
						void __user *end_page_addr;
 | 
				
			||||||
	size_t size, data_offsets_size;
 | 
						size_t size, data_offsets_size;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -456,15 +455,15 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
 | 
				
			||||||
		     "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n",
 | 
							     "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n",
 | 
				
			||||||
		      alloc->pid, size, buffer, buffer_size);
 | 
							      alloc->pid, size, buffer, buffer_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	has_page_addr =
 | 
						has_page_addr = (void __user *)
 | 
				
			||||||
		(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK);
 | 
							(((uintptr_t)buffer->user_data + buffer_size) & PAGE_MASK);
 | 
				
			||||||
	WARN_ON(n && buffer_size != size);
 | 
						WARN_ON(n && buffer_size != size);
 | 
				
			||||||
	end_page_addr =
 | 
						end_page_addr =
 | 
				
			||||||
		(void *)PAGE_ALIGN((uintptr_t)buffer->data + size);
 | 
							(void __user *)PAGE_ALIGN((uintptr_t)buffer->user_data + size);
 | 
				
			||||||
	if (end_page_addr > has_page_addr)
 | 
						if (end_page_addr > has_page_addr)
 | 
				
			||||||
		end_page_addr = has_page_addr;
 | 
							end_page_addr = has_page_addr;
 | 
				
			||||||
	ret = binder_update_page_range(alloc, 1,
 | 
						ret = binder_update_page_range(alloc, 1, (void __user *)
 | 
				
			||||||
	    (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr);
 | 
							PAGE_ALIGN((uintptr_t)buffer->user_data), end_page_addr);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ERR_PTR(ret);
 | 
							return ERR_PTR(ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -477,7 +476,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
 | 
				
			||||||
			       __func__, alloc->pid);
 | 
								       __func__, alloc->pid);
 | 
				
			||||||
			goto err_alloc_buf_struct_failed;
 | 
								goto err_alloc_buf_struct_failed;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		new_buffer->data = (u8 *)buffer->data + size;
 | 
							new_buffer->user_data = (u8 __user *)buffer->user_data + size;
 | 
				
			||||||
		list_add(&new_buffer->entry, &buffer->entry);
 | 
							list_add(&new_buffer->entry, &buffer->entry);
 | 
				
			||||||
		new_buffer->free = 1;
 | 
							new_buffer->free = 1;
 | 
				
			||||||
		binder_insert_free_buffer(alloc, new_buffer);
 | 
							binder_insert_free_buffer(alloc, new_buffer);
 | 
				
			||||||
| 
						 | 
					@ -503,8 +502,8 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
 | 
				
			||||||
	return buffer;
 | 
						return buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_alloc_buf_struct_failed:
 | 
					err_alloc_buf_struct_failed:
 | 
				
			||||||
	binder_update_page_range(alloc, 0,
 | 
						binder_update_page_range(alloc, 0, (void __user *)
 | 
				
			||||||
				 (void *)PAGE_ALIGN((uintptr_t)buffer->data),
 | 
									 PAGE_ALIGN((uintptr_t)buffer->user_data),
 | 
				
			||||||
				 end_page_addr);
 | 
									 end_page_addr);
 | 
				
			||||||
	return ERR_PTR(-ENOMEM);
 | 
						return ERR_PTR(-ENOMEM);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -539,14 +538,15 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
 | 
				
			||||||
	return buffer;
 | 
						return buffer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void *buffer_start_page(struct binder_buffer *buffer)
 | 
					static void __user *buffer_start_page(struct binder_buffer *buffer)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return (void *)((uintptr_t)buffer->data & PAGE_MASK);
 | 
						return (void __user *)((uintptr_t)buffer->user_data & PAGE_MASK);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void *prev_buffer_end_page(struct binder_buffer *buffer)
 | 
					static void __user *prev_buffer_end_page(struct binder_buffer *buffer)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return (void *)(((uintptr_t)(buffer->data) - 1) & PAGE_MASK);
 | 
						return (void __user *)
 | 
				
			||||||
 | 
							(((uintptr_t)(buffer->user_data) - 1) & PAGE_MASK);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void binder_delete_free_buffer(struct binder_alloc *alloc,
 | 
					static void binder_delete_free_buffer(struct binder_alloc *alloc,
 | 
				
			||||||
| 
						 | 
					@ -561,7 +561,8 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc,
 | 
				
			||||||
		to_free = false;
 | 
							to_free = false;
 | 
				
			||||||
		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
 | 
							binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
 | 
				
			||||||
				   "%d: merge free, buffer %pK share page with %pK\n",
 | 
									   "%d: merge free, buffer %pK share page with %pK\n",
 | 
				
			||||||
				   alloc->pid, buffer->data, prev->data);
 | 
									   alloc->pid, buffer->user_data,
 | 
				
			||||||
 | 
									   prev->user_data);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!list_is_last(&buffer->entry, &alloc->buffers)) {
 | 
						if (!list_is_last(&buffer->entry, &alloc->buffers)) {
 | 
				
			||||||
| 
						 | 
					@ -571,23 +572,24 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc,
 | 
				
			||||||
			binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
 | 
								binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
 | 
				
			||||||
					   "%d: merge free, buffer %pK share page with %pK\n",
 | 
										   "%d: merge free, buffer %pK share page with %pK\n",
 | 
				
			||||||
					   alloc->pid,
 | 
										   alloc->pid,
 | 
				
			||||||
					   buffer->data,
 | 
										   buffer->user_data,
 | 
				
			||||||
					   next->data);
 | 
										   next->user_data);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (PAGE_ALIGNED(buffer->data)) {
 | 
						if (PAGE_ALIGNED(buffer->user_data)) {
 | 
				
			||||||
		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
 | 
							binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
 | 
				
			||||||
				   "%d: merge free, buffer start %pK is page aligned\n",
 | 
									   "%d: merge free, buffer start %pK is page aligned\n",
 | 
				
			||||||
				   alloc->pid, buffer->data);
 | 
									   alloc->pid, buffer->user_data);
 | 
				
			||||||
		to_free = false;
 | 
							to_free = false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (to_free) {
 | 
						if (to_free) {
 | 
				
			||||||
		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
 | 
							binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
 | 
				
			||||||
				   "%d: merge free, buffer %pK do not share page with %pK or %pK\n",
 | 
									   "%d: merge free, buffer %pK do not share page with %pK or %pK\n",
 | 
				
			||||||
				   alloc->pid, buffer->data,
 | 
									   alloc->pid, buffer->user_data,
 | 
				
			||||||
				   prev->data, next ? next->data : NULL);
 | 
									   prev->user_data,
 | 
				
			||||||
 | 
									   next ? next->user_data : NULL);
 | 
				
			||||||
		binder_update_page_range(alloc, 0, buffer_start_page(buffer),
 | 
							binder_update_page_range(alloc, 0, buffer_start_page(buffer),
 | 
				
			||||||
					 buffer_start_page(buffer) + PAGE_SIZE);
 | 
										 buffer_start_page(buffer) + PAGE_SIZE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -613,8 +615,8 @@ static void binder_free_buf_locked(struct binder_alloc *alloc,
 | 
				
			||||||
	BUG_ON(buffer->free);
 | 
						BUG_ON(buffer->free);
 | 
				
			||||||
	BUG_ON(size > buffer_size);
 | 
						BUG_ON(size > buffer_size);
 | 
				
			||||||
	BUG_ON(buffer->transaction != NULL);
 | 
						BUG_ON(buffer->transaction != NULL);
 | 
				
			||||||
	BUG_ON(buffer->data < alloc->buffer);
 | 
						BUG_ON(buffer->user_data < alloc->buffer);
 | 
				
			||||||
	BUG_ON(buffer->data > alloc->buffer + alloc->buffer_size);
 | 
						BUG_ON(buffer->user_data > alloc->buffer + alloc->buffer_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (buffer->async_transaction) {
 | 
						if (buffer->async_transaction) {
 | 
				
			||||||
		alloc->free_async_space += size + sizeof(struct binder_buffer);
 | 
							alloc->free_async_space += size + sizeof(struct binder_buffer);
 | 
				
			||||||
| 
						 | 
					@ -625,8 +627,9 @@ static void binder_free_buf_locked(struct binder_alloc *alloc,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	binder_update_page_range(alloc, 0,
 | 
						binder_update_page_range(alloc, 0,
 | 
				
			||||||
		(void *)PAGE_ALIGN((uintptr_t)buffer->data),
 | 
							(void __user *)PAGE_ALIGN((uintptr_t)buffer->user_data),
 | 
				
			||||||
		(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK));
 | 
							(void __user *)(((uintptr_t)
 | 
				
			||||||
 | 
								  buffer->user_data + buffer_size) & PAGE_MASK));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rb_erase(&buffer->rb_node, &alloc->allocated_buffers);
 | 
						rb_erase(&buffer->rb_node, &alloc->allocated_buffers);
 | 
				
			||||||
	buffer->free = 1;
 | 
						buffer->free = 1;
 | 
				
			||||||
| 
						 | 
					@ -692,7 +695,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
 | 
				
			||||||
		goto err_already_mapped;
 | 
							goto err_already_mapped;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	alloc->buffer = (void *)vma->vm_start;
 | 
						alloc->buffer = (void __user *)vma->vm_start;
 | 
				
			||||||
	mutex_unlock(&binder_alloc_mmap_lock);
 | 
						mutex_unlock(&binder_alloc_mmap_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	alloc->pages = kcalloc((vma->vm_end - vma->vm_start) / PAGE_SIZE,
 | 
						alloc->pages = kcalloc((vma->vm_end - vma->vm_start) / PAGE_SIZE,
 | 
				
			||||||
| 
						 | 
					@ -712,7 +715,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
 | 
				
			||||||
		goto err_alloc_buf_struct_failed;
 | 
							goto err_alloc_buf_struct_failed;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	buffer->data = alloc->buffer;
 | 
						buffer->user_data = alloc->buffer;
 | 
				
			||||||
	list_add(&buffer->entry, &alloc->buffers);
 | 
						list_add(&buffer->entry, &alloc->buffers);
 | 
				
			||||||
	buffer->free = 1;
 | 
						buffer->free = 1;
 | 
				
			||||||
	binder_insert_free_buffer(alloc, buffer);
 | 
						binder_insert_free_buffer(alloc, buffer);
 | 
				
			||||||
| 
						 | 
					@ -773,7 +776,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc)
 | 
				
			||||||
		int i;
 | 
							int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
 | 
							for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
 | 
				
			||||||
			void *page_addr;
 | 
								void __user *page_addr;
 | 
				
			||||||
			bool on_lru;
 | 
								bool on_lru;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!alloc->pages[i].page_ptr)
 | 
								if (!alloc->pages[i].page_ptr)
 | 
				
			||||||
| 
						 | 
					@ -804,7 +807,7 @@ static void print_binder_buffer(struct seq_file *m, const char *prefix,
 | 
				
			||||||
				struct binder_buffer *buffer)
 | 
									struct binder_buffer *buffer)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	seq_printf(m, "%s %d: %pK size %zd:%zd:%zd %s\n",
 | 
						seq_printf(m, "%s %d: %pK size %zd:%zd:%zd %s\n",
 | 
				
			||||||
		   prefix, buffer->debug_id, buffer->data,
 | 
							   prefix, buffer->debug_id, buffer->user_data,
 | 
				
			||||||
		   buffer->data_size, buffer->offsets_size,
 | 
							   buffer->data_size, buffer->offsets_size,
 | 
				
			||||||
		   buffer->extra_buffers_size,
 | 
							   buffer->extra_buffers_size,
 | 
				
			||||||
		   buffer->transaction ? "active" : "delivered");
 | 
							   buffer->transaction ? "active" : "delivered");
 | 
				
			||||||
| 
						 | 
					@ -1056,7 +1059,7 @@ static inline bool check_buffer(struct binder_alloc *alloc,
 | 
				
			||||||
 * @pgoffp: address to copy final page offset to
 | 
					 * @pgoffp: address to copy final page offset to
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Lookup the struct page corresponding to the address
 | 
					 * Lookup the struct page corresponding to the address
 | 
				
			||||||
 * at @buffer_offset into @buffer->data. If @pgoffp is not
 | 
					 * at @buffer_offset into @buffer->user_data. If @pgoffp is not
 | 
				
			||||||
 * NULL, the byte-offset into the page is written there.
 | 
					 * NULL, the byte-offset into the page is written there.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * The caller is responsible to ensure that the offset points
 | 
					 * The caller is responsible to ensure that the offset points
 | 
				
			||||||
| 
						 | 
					@ -1073,7 +1076,7 @@ static struct page *binder_alloc_get_page(struct binder_alloc *alloc,
 | 
				
			||||||
					  pgoff_t *pgoffp)
 | 
										  pgoff_t *pgoffp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	binder_size_t buffer_space_offset = buffer_offset +
 | 
						binder_size_t buffer_space_offset = buffer_offset +
 | 
				
			||||||
		(buffer->data - alloc->buffer);
 | 
							(buffer->user_data - alloc->buffer);
 | 
				
			||||||
	pgoff_t pgoff = buffer_space_offset & ~PAGE_MASK;
 | 
						pgoff_t pgoff = buffer_space_offset & ~PAGE_MASK;
 | 
				
			||||||
	size_t index = buffer_space_offset >> PAGE_SHIFT;
 | 
						size_t index = buffer_space_offset >> PAGE_SHIFT;
 | 
				
			||||||
	struct binder_lru_page *lru_page;
 | 
						struct binder_lru_page *lru_page;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,7 +40,7 @@ struct binder_transaction;
 | 
				
			||||||
 * @data_size:          size of @transaction data
 | 
					 * @data_size:          size of @transaction data
 | 
				
			||||||
 * @offsets_size:       size of array of offsets
 | 
					 * @offsets_size:       size of array of offsets
 | 
				
			||||||
 * @extra_buffers_size: size of space for other objects (like sg lists)
 | 
					 * @extra_buffers_size: size of space for other objects (like sg lists)
 | 
				
			||||||
 * @data:               pointer to base of buffer space
 | 
					 * @user_data:          user pointer to base of buffer space
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Bookkeeping structure for binder transaction buffers
 | 
					 * Bookkeeping structure for binder transaction buffers
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -59,7 +59,7 @@ struct binder_buffer {
 | 
				
			||||||
	size_t data_size;
 | 
						size_t data_size;
 | 
				
			||||||
	size_t offsets_size;
 | 
						size_t offsets_size;
 | 
				
			||||||
	size_t extra_buffers_size;
 | 
						size_t extra_buffers_size;
 | 
				
			||||||
	void *data;
 | 
						void __user *user_data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -102,7 +102,7 @@ struct binder_alloc {
 | 
				
			||||||
	struct mutex mutex;
 | 
						struct mutex mutex;
 | 
				
			||||||
	struct vm_area_struct *vma;
 | 
						struct vm_area_struct *vma;
 | 
				
			||||||
	struct mm_struct *vma_vm_mm;
 | 
						struct mm_struct *vma_vm_mm;
 | 
				
			||||||
	void *buffer;
 | 
						void __user *buffer;
 | 
				
			||||||
	struct list_head buffers;
 | 
						struct list_head buffers;
 | 
				
			||||||
	struct rb_root free_buffers;
 | 
						struct rb_root free_buffers;
 | 
				
			||||||
	struct rb_root allocated_buffers;
 | 
						struct rb_root allocated_buffers;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,8 +105,8 @@ static bool check_buffer_pages_allocated(struct binder_alloc *alloc,
 | 
				
			||||||
	void *page_addr, *end;
 | 
						void *page_addr, *end;
 | 
				
			||||||
	int page_index;
 | 
						int page_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	end = (void *)PAGE_ALIGN((uintptr_t)buffer->data + size);
 | 
						end = (void *)PAGE_ALIGN((uintptr_t)buffer->user_data + size);
 | 
				
			||||||
	page_addr = buffer->data;
 | 
						page_addr = buffer->user_data;
 | 
				
			||||||
	for (; page_addr < end; page_addr += PAGE_SIZE) {
 | 
						for (; page_addr < end; page_addr += PAGE_SIZE) {
 | 
				
			||||||
		page_index = (page_addr - alloc->buffer) / PAGE_SIZE;
 | 
							page_index = (page_addr - alloc->buffer) / PAGE_SIZE;
 | 
				
			||||||
		if (!alloc->pages[page_index].page_ptr ||
 | 
							if (!alloc->pages[page_index].page_ptr ||
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -293,7 +293,7 @@ DEFINE_EVENT(binder_buffer_class, binder_transaction_failed_buffer_release,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TRACE_EVENT(binder_update_page_range,
 | 
					TRACE_EVENT(binder_update_page_range,
 | 
				
			||||||
	TP_PROTO(struct binder_alloc *alloc, bool allocate,
 | 
						TP_PROTO(struct binder_alloc *alloc, bool allocate,
 | 
				
			||||||
		 void *start, void *end),
 | 
							 void __user *start, void __user *end),
 | 
				
			||||||
	TP_ARGS(alloc, allocate, start, end),
 | 
						TP_ARGS(alloc, allocate, start, end),
 | 
				
			||||||
	TP_STRUCT__entry(
 | 
						TP_STRUCT__entry(
 | 
				
			||||||
		__field(int, proc)
 | 
							__field(int, proc)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue