aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTodd Kjos <tkjos@android.com>2019-06-28 12:50:12 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-07-01 02:42:47 -0400
commitbb4a2e48d5100ed3ff614df158a636bca3c6bf9f (patch)
tree6ec6135c5266d2db45f834de382b5388fecde7c8
parent25c7eabed5b219e975c8aee527ae202604d10911 (diff)
binder: return errors from buffer copy functions
The buffer copy functions assumed the caller would ensure correct alignment and that the memory to be copied was completely within the binder buffer. There have been a few cases discovered by syzkallar where a malformed transaction created by a user could violated the assumptions and resulted in a BUG_ON. The fix is to remove the BUG_ON and always return the error to be handled appropriately by the caller. Acked-by: Martijn Coenen <maco@android.com> Reported-by: syzbot+3ae18325f96190606754@syzkaller.appspotmail.com Fixes: bde4a19fc04f ("binder: use userspace pointer as base of buffer space") Suggested-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Todd Kjos <tkjos@google.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/android/binder.c153
-rw-r--r--drivers/android/binder_alloc.c44
-rw-r--r--drivers/android/binder_alloc.h22
3 files changed, 126 insertions, 93 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 8bf039fdeb91..38a59a630cd4 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2059,10 +2059,9 @@ static size_t binder_get_object(struct binder_proc *proc,
2059 2059
2060 read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset); 2060 read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
2061 if (offset > buffer->data_size || read_size < sizeof(*hdr) || 2061 if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
2062 !IS_ALIGNED(offset, sizeof(u32))) 2062 binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
2063 offset, read_size))
2063 return 0; 2064 return 0;
2064 binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
2065 offset, read_size);
2066 2065
2067 /* Ok, now see if we read a complete object. */ 2066 /* Ok, now see if we read a complete object. */
2068 hdr = &object->hdr; 2067 hdr = &object->hdr;
@@ -2131,8 +2130,10 @@ static struct binder_buffer_object *binder_validate_ptr(
2131 return NULL; 2130 return NULL;
2132 2131
2133 buffer_offset = start_offset + sizeof(binder_size_t) * index; 2132 buffer_offset = start_offset + sizeof(binder_size_t) * index;
2134 binder_alloc_copy_from_buffer(&proc->alloc, &object_offset, 2133 if (binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
2135 b, buffer_offset, sizeof(object_offset)); 2134 b, buffer_offset,
2135 sizeof(object_offset)))
2136 return NULL;
2136 object_size = binder_get_object(proc, b, object_offset, object); 2137 object_size = binder_get_object(proc, b, object_offset, object);
2137 if (!object_size || object->hdr.type != BINDER_TYPE_PTR) 2138 if (!object_size || object->hdr.type != BINDER_TYPE_PTR)
2138 return NULL; 2139 return NULL;
@@ -2212,10 +2213,12 @@ static bool binder_validate_fixup(struct binder_proc *proc,
2212 return false; 2213 return false;
2213 last_min_offset = last_bbo->parent_offset + sizeof(uintptr_t); 2214 last_min_offset = last_bbo->parent_offset + sizeof(uintptr_t);
2214 buffer_offset = objects_start_offset + 2215 buffer_offset = objects_start_offset +
2215 sizeof(binder_size_t) * last_bbo->parent, 2216 sizeof(binder_size_t) * last_bbo->parent;
2216 binder_alloc_copy_from_buffer(&proc->alloc, &last_obj_offset, 2217 if (binder_alloc_copy_from_buffer(&proc->alloc,
2217 b, buffer_offset, 2218 &last_obj_offset,
2218 sizeof(last_obj_offset)); 2219 b, buffer_offset,
2220 sizeof(last_obj_offset)))
2221 return false;
2219 } 2222 }
2220 return (fixup_offset >= last_min_offset); 2223 return (fixup_offset >= last_min_offset);
2221} 2224}
@@ -2301,15 +2304,15 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
2301 for (buffer_offset = off_start_offset; buffer_offset < off_end_offset; 2304 for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
2302 buffer_offset += sizeof(binder_size_t)) { 2305 buffer_offset += sizeof(binder_size_t)) {
2303 struct binder_object_header *hdr; 2306 struct binder_object_header *hdr;
2304 size_t object_size; 2307 size_t object_size = 0;
2305 struct binder_object object; 2308 struct binder_object object;
2306 binder_size_t object_offset; 2309 binder_size_t object_offset;
2307 2310
2308 binder_alloc_copy_from_buffer(&proc->alloc, &object_offset, 2311 if (!binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
2309 buffer, buffer_offset, 2312 buffer, buffer_offset,
2310 sizeof(object_offset)); 2313 sizeof(object_offset)))
2311 object_size = binder_get_object(proc, buffer, 2314 object_size = binder_get_object(proc, buffer,
2312 object_offset, &object); 2315 object_offset, &object);
2313 if (object_size == 0) { 2316 if (object_size == 0) {
2314 pr_err("transaction release %d bad object at offset %lld, size %zd\n", 2317 pr_err("transaction release %d bad object at offset %lld, size %zd\n",
2315 debug_id, (u64)object_offset, buffer->data_size); 2318 debug_id, (u64)object_offset, buffer->data_size);
@@ -2432,15 +2435,16 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
2432 for (fd_index = 0; fd_index < fda->num_fds; 2435 for (fd_index = 0; fd_index < fda->num_fds;
2433 fd_index++) { 2436 fd_index++) {
2434 u32 fd; 2437 u32 fd;
2438 int err;
2435 binder_size_t offset = fda_offset + 2439 binder_size_t offset = fda_offset +
2436 fd_index * sizeof(fd); 2440 fd_index * sizeof(fd);
2437 2441
2438 binder_alloc_copy_from_buffer(&proc->alloc, 2442 err = binder_alloc_copy_from_buffer(
2439 &fd, 2443 &proc->alloc, &fd, buffer,
2440 buffer, 2444 offset, sizeof(fd));
2441 offset, 2445 WARN_ON(err);
2442 sizeof(fd)); 2446 if (!err)
2443 binder_deferred_fd_close(fd); 2447 binder_deferred_fd_close(fd);
2444 } 2448 }
2445 } break; 2449 } break;
2446 default: 2450 default:
@@ -2683,11 +2687,12 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
2683 int ret; 2687 int ret;
2684 binder_size_t offset = fda_offset + fdi * sizeof(fd); 2688 binder_size_t offset = fda_offset + fdi * sizeof(fd);
2685 2689
2686 binder_alloc_copy_from_buffer(&target_proc->alloc, 2690 ret = binder_alloc_copy_from_buffer(&target_proc->alloc,
2687 &fd, t->buffer, 2691 &fd, t->buffer,
2688 offset, sizeof(fd)); 2692 offset, sizeof(fd));
2689 ret = binder_translate_fd(fd, offset, t, thread, 2693 if (!ret)
2690 in_reply_to); 2694 ret = binder_translate_fd(fd, offset, t, thread,
2695 in_reply_to);
2691 if (ret < 0) 2696 if (ret < 0)
2692 return ret; 2697 return ret;
2693 } 2698 }
@@ -2740,8 +2745,12 @@ static int binder_fixup_parent(struct binder_transaction *t,
2740 } 2745 }
2741 buffer_offset = bp->parent_offset + 2746 buffer_offset = bp->parent_offset +
2742 (uintptr_t)parent->buffer - (uintptr_t)b->user_data; 2747 (uintptr_t)parent->buffer - (uintptr_t)b->user_data;
2743 binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset, 2748 if (binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
2744 &bp->buffer, sizeof(bp->buffer)); 2749 &bp->buffer, sizeof(bp->buffer))) {
2750 binder_user_error("%d:%d got transaction with invalid parent offset\n",
2751 proc->pid, thread->pid);
2752 return -EINVAL;
2753 }
2745 2754
2746 return 0; 2755 return 0;
2747} 2756}
@@ -3160,15 +3169,20 @@ static void binder_transaction(struct binder_proc *proc,
3160 goto err_binder_alloc_buf_failed; 3169 goto err_binder_alloc_buf_failed;
3161 } 3170 }
3162 if (secctx) { 3171 if (secctx) {
3172 int err;
3163 size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) + 3173 size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
3164 ALIGN(tr->offsets_size, sizeof(void *)) + 3174 ALIGN(tr->offsets_size, sizeof(void *)) +
3165 ALIGN(extra_buffers_size, sizeof(void *)) - 3175 ALIGN(extra_buffers_size, sizeof(void *)) -
3166 ALIGN(secctx_sz, sizeof(u64)); 3176 ALIGN(secctx_sz, sizeof(u64));
3167 3177
3168 t->security_ctx = (uintptr_t)t->buffer->user_data + buf_offset; 3178 t->security_ctx = (uintptr_t)t->buffer->user_data + buf_offset;
3169 binder_alloc_copy_to_buffer(&target_proc->alloc, 3179 err = binder_alloc_copy_to_buffer(&target_proc->alloc,
3170 t->buffer, buf_offset, 3180 t->buffer, buf_offset,
3171 secctx, secctx_sz); 3181 secctx, secctx_sz);
3182 if (err) {
3183 t->security_ctx = 0;
3184 WARN_ON(1);
3185 }
3172 security_release_secctx(secctx, secctx_sz); 3186 security_release_secctx(secctx, secctx_sz);
3173 secctx = NULL; 3187 secctx = NULL;
3174 } 3188 }
@@ -3234,11 +3248,16 @@ static void binder_transaction(struct binder_proc *proc,
3234 struct binder_object object; 3248 struct binder_object object;
3235 binder_size_t object_offset; 3249 binder_size_t object_offset;
3236 3250
3237 binder_alloc_copy_from_buffer(&target_proc->alloc, 3251 if (binder_alloc_copy_from_buffer(&target_proc->alloc,
3238 &object_offset, 3252 &object_offset,
3239 t->buffer, 3253 t->buffer,
3240 buffer_offset, 3254 buffer_offset,
3241 sizeof(object_offset)); 3255 sizeof(object_offset))) {
3256 return_error = BR_FAILED_REPLY;
3257 return_error_param = -EINVAL;
3258 return_error_line = __LINE__;
3259 goto err_bad_offset;
3260 }
3242 object_size = binder_get_object(target_proc, t->buffer, 3261 object_size = binder_get_object(target_proc, t->buffer,
3243 object_offset, &object); 3262 object_offset, &object);
3244 if (object_size == 0 || object_offset < off_min) { 3263 if (object_size == 0 || object_offset < off_min) {
@@ -3262,15 +3281,17 @@ static void binder_transaction(struct binder_proc *proc,
3262 3281
3263 fp = to_flat_binder_object(hdr); 3282 fp = to_flat_binder_object(hdr);
3264 ret = binder_translate_binder(fp, t, thread); 3283 ret = binder_translate_binder(fp, t, thread);
3265 if (ret < 0) { 3284
3285 if (ret < 0 ||
3286 binder_alloc_copy_to_buffer(&target_proc->alloc,
3287 t->buffer,
3288 object_offset,
3289 fp, sizeof(*fp))) {
3266 return_error = BR_FAILED_REPLY; 3290 return_error = BR_FAILED_REPLY;
3267 return_error_param = ret; 3291 return_error_param = ret;
3268 return_error_line = __LINE__; 3292 return_error_line = __LINE__;
3269 goto err_translate_failed; 3293 goto err_translate_failed;
3270 } 3294 }
3271 binder_alloc_copy_to_buffer(&target_proc->alloc,
3272 t->buffer, object_offset,
3273 fp, sizeof(*fp));
3274 } break; 3295 } break;
3275 case BINDER_TYPE_HANDLE: 3296 case BINDER_TYPE_HANDLE:
3276 case BINDER_TYPE_WEAK_HANDLE: { 3297 case BINDER_TYPE_WEAK_HANDLE: {
@@ -3278,15 +3299,16 @@ static void binder_transaction(struct binder_proc *proc,
3278 3299
3279 fp = to_flat_binder_object(hdr); 3300 fp = to_flat_binder_object(hdr);
3280 ret = binder_translate_handle(fp, t, thread); 3301 ret = binder_translate_handle(fp, t, thread);
3281 if (ret < 0) { 3302 if (ret < 0 ||
3303 binder_alloc_copy_to_buffer(&target_proc->alloc,
3304 t->buffer,
3305 object_offset,
3306 fp, sizeof(*fp))) {
3282 return_error = BR_FAILED_REPLY; 3307 return_error = BR_FAILED_REPLY;
3283 return_error_param = ret; 3308 return_error_param = ret;
3284 return_error_line = __LINE__; 3309 return_error_line = __LINE__;
3285 goto err_translate_failed; 3310 goto err_translate_failed;
3286 } 3311 }
3287 binder_alloc_copy_to_buffer(&target_proc->alloc,
3288 t->buffer, object_offset,
3289 fp, sizeof(*fp));
3290 } break; 3312 } break;
3291 3313
3292 case BINDER_TYPE_FD: { 3314 case BINDER_TYPE_FD: {
@@ -3296,16 +3318,17 @@ static void binder_transaction(struct binder_proc *proc,
3296 int ret = binder_translate_fd(fp->fd, fd_offset, t, 3318 int ret = binder_translate_fd(fp->fd, fd_offset, t,
3297 thread, in_reply_to); 3319 thread, in_reply_to);
3298 3320
3299 if (ret < 0) { 3321 fp->pad_binder = 0;
3322 if (ret < 0 ||
3323 binder_alloc_copy_to_buffer(&target_proc->alloc,
3324 t->buffer,
3325 object_offset,
3326 fp, sizeof(*fp))) {
3300 return_error = BR_FAILED_REPLY; 3327 return_error = BR_FAILED_REPLY;
3301 return_error_param = ret; 3328 return_error_param = ret;
3302 return_error_line = __LINE__; 3329 return_error_line = __LINE__;
3303 goto err_translate_failed; 3330 goto err_translate_failed;
3304 } 3331 }
3305 fp->pad_binder = 0;
3306 binder_alloc_copy_to_buffer(&target_proc->alloc,
3307 t->buffer, object_offset,
3308 fp, sizeof(*fp));
3309 } break; 3332 } break;
3310 case BINDER_TYPE_FDA: { 3333 case BINDER_TYPE_FDA: {
3311 struct binder_object ptr_object; 3334 struct binder_object ptr_object;
@@ -3393,15 +3416,16 @@ static void binder_transaction(struct binder_proc *proc,
3393 num_valid, 3416 num_valid,
3394 last_fixup_obj_off, 3417 last_fixup_obj_off,
3395 last_fixup_min_off); 3418 last_fixup_min_off);
3396 if (ret < 0) { 3419 if (ret < 0 ||
3420 binder_alloc_copy_to_buffer(&target_proc->alloc,
3421 t->buffer,
3422 object_offset,
3423 bp, sizeof(*bp))) {
3397 return_error = BR_FAILED_REPLY; 3424 return_error = BR_FAILED_REPLY;
3398 return_error_param = ret; 3425 return_error_param = ret;
3399 return_error_line = __LINE__; 3426 return_error_line = __LINE__;
3400 goto err_translate_failed; 3427 goto err_translate_failed;
3401 } 3428 }
3402 binder_alloc_copy_to_buffer(&target_proc->alloc,
3403 t->buffer, object_offset,
3404 bp, sizeof(*bp));
3405 last_fixup_obj_off = object_offset; 3429 last_fixup_obj_off = object_offset;
3406 last_fixup_min_off = 0; 3430 last_fixup_min_off = 0;
3407 } break; 3431 } break;
@@ -4140,20 +4164,27 @@ static int binder_apply_fd_fixups(struct binder_proc *proc,
4140 trace_binder_transaction_fd_recv(t, fd, fixup->offset); 4164 trace_binder_transaction_fd_recv(t, fd, fixup->offset);
4141 fd_install(fd, fixup->file); 4165 fd_install(fd, fixup->file);
4142 fixup->file = NULL; 4166 fixup->file = NULL;
4143 binder_alloc_copy_to_buffer(&proc->alloc, t->buffer, 4167 if (binder_alloc_copy_to_buffer(&proc->alloc, t->buffer,
4144 fixup->offset, &fd, 4168 fixup->offset, &fd,
4145 sizeof(u32)); 4169 sizeof(u32))) {
4170 ret = -EINVAL;
4171 break;
4172 }
4146 } 4173 }
4147 list_for_each_entry_safe(fixup, tmp, &t->fd_fixups, fixup_entry) { 4174 list_for_each_entry_safe(fixup, tmp, &t->fd_fixups, fixup_entry) {
4148 if (fixup->file) { 4175 if (fixup->file) {
4149 fput(fixup->file); 4176 fput(fixup->file);
4150 } else if (ret) { 4177 } else if (ret) {
4151 u32 fd; 4178 u32 fd;
4152 4179 int err;
4153 binder_alloc_copy_from_buffer(&proc->alloc, &fd, 4180
4154 t->buffer, fixup->offset, 4181 err = binder_alloc_copy_from_buffer(&proc->alloc, &fd,
4155 sizeof(fd)); 4182 t->buffer,
4156 binder_deferred_fd_close(fd); 4183 fixup->offset,
4184 sizeof(fd));
4185 WARN_ON(err);
4186 if (!err)
4187 binder_deferred_fd_close(fd);
4157 } 4188 }
4158 list_del(&fixup->fixup_entry); 4189 list_del(&fixup->fixup_entry);
4159 kfree(fixup); 4190 kfree(fixup);
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index ce5603c2291c..6d79a1b0d446 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -1119,15 +1119,16 @@ binder_alloc_copy_user_to_buffer(struct binder_alloc *alloc,
1119 return 0; 1119 return 0;
1120} 1120}
1121 1121
1122static void binder_alloc_do_buffer_copy(struct binder_alloc *alloc, 1122static int binder_alloc_do_buffer_copy(struct binder_alloc *alloc,
1123 bool to_buffer, 1123 bool to_buffer,
1124 struct binder_buffer *buffer, 1124 struct binder_buffer *buffer,
1125 binder_size_t buffer_offset, 1125 binder_size_t buffer_offset,
1126 void *ptr, 1126 void *ptr,
1127 size_t bytes) 1127 size_t bytes)
1128{ 1128{
1129 /* All copies must be 32-bit aligned and 32-bit size */ 1129 /* All copies must be 32-bit aligned and 32-bit size */
1130 BUG_ON(!check_buffer(alloc, buffer, buffer_offset, bytes)); 1130 if (!check_buffer(alloc, buffer, buffer_offset, bytes))
1131 return -EINVAL;
1131 1132
1132 while (bytes) { 1133 while (bytes) {
1133 unsigned long size; 1134 unsigned long size;
@@ -1155,25 +1156,26 @@ static void binder_alloc_do_buffer_copy(struct binder_alloc *alloc,
1155 ptr = ptr + size; 1156 ptr = ptr + size;
1156 buffer_offset += size; 1157 buffer_offset += size;
1157 } 1158 }
1159 return 0;
1158} 1160}
1159 1161
1160void binder_alloc_copy_to_buffer(struct binder_alloc *alloc, 1162int binder_alloc_copy_to_buffer(struct binder_alloc *alloc,
1161 struct binder_buffer *buffer, 1163 struct binder_buffer *buffer,
1162 binder_size_t buffer_offset, 1164 binder_size_t buffer_offset,
1163 void *src, 1165 void *src,
1164 size_t bytes) 1166 size_t bytes)
1165{ 1167{
1166 binder_alloc_do_buffer_copy(alloc, true, buffer, buffer_offset, 1168 return binder_alloc_do_buffer_copy(alloc, true, buffer, buffer_offset,
1167 src, bytes); 1169 src, bytes);
1168} 1170}
1169 1171
1170void binder_alloc_copy_from_buffer(struct binder_alloc *alloc, 1172int binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
1171 void *dest, 1173 void *dest,
1172 struct binder_buffer *buffer, 1174 struct binder_buffer *buffer,
1173 binder_size_t buffer_offset, 1175 binder_size_t buffer_offset,
1174 size_t bytes) 1176 size_t bytes)
1175{ 1177{
1176 binder_alloc_do_buffer_copy(alloc, false, buffer, buffer_offset, 1178 return binder_alloc_do_buffer_copy(alloc, false, buffer, buffer_offset,
1177 dest, bytes); 1179 dest, bytes);
1178} 1180}
1179 1181
diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h
index 71bfa95f8e09..db9c1b984695 100644
--- a/drivers/android/binder_alloc.h
+++ b/drivers/android/binder_alloc.h
@@ -159,17 +159,17 @@ binder_alloc_copy_user_to_buffer(struct binder_alloc *alloc,
159 const void __user *from, 159 const void __user *from,
160 size_t bytes); 160 size_t bytes);
161 161
162void binder_alloc_copy_to_buffer(struct binder_alloc *alloc, 162int binder_alloc_copy_to_buffer(struct binder_alloc *alloc,
163 struct binder_buffer *buffer, 163 struct binder_buffer *buffer,
164 binder_size_t buffer_offset, 164 binder_size_t buffer_offset,
165 void *src, 165 void *src,
166 size_t bytes); 166 size_t bytes);
167 167
168void binder_alloc_copy_from_buffer(struct binder_alloc *alloc, 168int binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
169 void *dest, 169 void *dest,
170 struct binder_buffer *buffer, 170 struct binder_buffer *buffer,
171 binder_size_t buffer_offset, 171 binder_size_t buffer_offset,
172 size_t bytes); 172 size_t bytes);
173 173
174#endif /* _LINUX_BINDER_ALLOC_H */ 174#endif /* _LINUX_BINDER_ALLOC_H */
175 175