Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

binder: add flag to clear buffer on txn complete

Add a per-transaction flag to indicate that the buffer
must be cleared when the transaction is complete to
prevent copies of sensitive data from being preserved
in memory.

Signed-off-by: Todd Kjos <tkjos@google.com>
Link: https://lore.kernel.org/r/20201120233743.3617529-1-tkjos@google.com
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Todd Kjos and committed by
Greg Kroah-Hartman
0f966cba d1b928ee

+53 -1
+1
drivers/android/binder.c
··· 2756 2756 t->buffer->debug_id = t->debug_id; 2757 2757 t->buffer->transaction = t; 2758 2758 t->buffer->target_node = target_node; 2759 + t->buffer->clear_on_free = !!(t->flags & TF_CLEAR_BUF); 2759 2760 trace_binder_transaction_alloc_buf(t->buffer); 2760 2761 2761 2762 if (binder_alloc_copy_user_to_buffer(
+48
drivers/android/binder_alloc.c
··· 696 696 binder_insert_free_buffer(alloc, buffer); 697 697 } 698 698 699 + static void binder_alloc_clear_buf(struct binder_alloc *alloc, 700 + struct binder_buffer *buffer); 699 701 /** 700 702 * binder_alloc_free_buf() - free a binder buffer 701 703 * @alloc: binder_alloc for this proc ··· 708 706 void binder_alloc_free_buf(struct binder_alloc *alloc, 709 707 struct binder_buffer *buffer) 710 708 { 709 + /* 710 + * We could eliminate the call to binder_alloc_clear_buf() 711 + * from binder_alloc_deferred_release() by moving this to 712 + * binder_alloc_free_buf_locked(). However, that could 713 + * increase contention for the alloc mutex if clear_on_free 714 + * is used frequently for large buffers. The mutex is not 715 + * needed for correctness here. 716 + */ 717 + if (buffer->clear_on_free) { 718 + binder_alloc_clear_buf(alloc, buffer); 719 + buffer->clear_on_free = false; 720 + } 711 721 mutex_lock(&alloc->mutex); 712 722 binder_free_buf_locked(alloc, buffer); 713 723 mutex_unlock(&alloc->mutex); ··· 816 802 /* Transaction should already have been freed */ 817 803 BUG_ON(buffer->transaction); 818 804 805 + if (buffer->clear_on_free) { 806 + binder_alloc_clear_buf(alloc, buffer); 807 + buffer->clear_on_free = false; 808 + } 819 809 binder_free_buf_locked(alloc, buffer); 820 810 buffers++; 821 811 } ··· 1151 1133 lru_page = &alloc->pages[index]; 1152 1134 *pgoffp = pgoff; 1153 1135 return lru_page->page_ptr; 1136 + } 1137 + 1138 + /** 1139 + * binder_alloc_clear_buf() - zero out buffer 1140 + * @alloc: binder_alloc for this proc 1141 + * @buffer: binder buffer to be cleared 1142 + * 1143 + * memset the given buffer to 0 1144 + */ 1145 + static void binder_alloc_clear_buf(struct binder_alloc *alloc, 1146 + struct binder_buffer *buffer) 1147 + { 1148 + size_t bytes = binder_alloc_buffer_size(alloc, buffer); 1149 + binder_size_t buffer_offset = 0; 1150 + 1151 + while (bytes) { 1152 + unsigned long size; 1153 + struct page *page; 1154 + pgoff_t pgoff; 1155 + void *kptr; 1156 + 1157 + page = binder_alloc_get_page(alloc, buffer, 1158 + buffer_offset, &pgoff); 1159 + size = min_t(size_t, bytes, PAGE_SIZE - pgoff); 1160 + kptr = kmap(page) + pgoff; 1161 + memset(kptr, 0, size); 1162 + kunmap(page); 1163 + bytes -= size; 1164 + buffer_offset += size; 1165 + } 1154 1166 } 1155 1167 1156 1168 /**
+3 -1
drivers/android/binder_alloc.h
··· 23 23 * @entry: entry alloc->buffers 24 24 * @rb_node: node for allocated_buffers/free_buffers rb trees 25 25 * @free: %true if buffer is free 26 + * @clear_on_free: %true if buffer must be zeroed after use 26 27 * @allow_user_free: %true if user is allowed to free buffer 27 28 * @async_transaction: %true if buffer is in use for an async txn 28 29 * @debug_id: unique ID for debugging ··· 42 41 struct rb_node rb_node; /* free entry by size or allocated entry */ 43 42 /* by address */ 44 43 unsigned free:1; 44 + unsigned clear_on_free:1; 45 45 unsigned allow_user_free:1; 46 46 unsigned async_transaction:1; 47 - unsigned debug_id:29; 47 + unsigned debug_id:28; 48 48 49 49 struct binder_transaction *transaction; 50 50
+1
include/uapi/linux/android/binder.h
··· 248 248 TF_ROOT_OBJECT = 0x04, /* contents are the component's root object */ 249 249 TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */ 250 250 TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */ 251 + TF_CLEAR_BUF = 0x20, /* clear buffer on txn complete */ 251 252 }; 252 253 253 254 struct binder_transaction_data {