| From cfd0d84ba28c18b531648c9d4a35ecca89ad9901 Mon Sep 17 00:00:00 2001 |
| From: Todd Kjos <tkjos@google.com> |
| Date: Mon, 20 Dec 2021 11:01:50 -0800 |
| Subject: binder: fix async_free_space accounting for empty parcels |
| |
| From: Todd Kjos <tkjos@google.com> |
| |
| commit cfd0d84ba28c18b531648c9d4a35ecca89ad9901 upstream. |
| |
| In 4.13, commit 74310e06be4d ("android: binder: Move buffer out of area shared with user space") |
| fixed a kernel structure visibility issue. As part of that patch, |
| sizeof(void *) was used as the buffer size for 0-length data payloads so |
| the driver could detect abusive clients sending 0-length asynchronous |
| transactions to a server by enforcing limits on async_free_size. |
| |
| Unfortunately, on the "free" side, the accounting of async_free_space |
| did not add the sizeof(void *) back. The result was that up to 8-bytes of |
| async_free_space were leaked on every async transaction of 8-bytes or |
| less. These small transactions are uncommon, so this accounting issue |
| has gone undetected for several years. |
| |
| The fix is to use "buffer_size" (the allocated buffer size) instead of |
| "size" (the logical buffer size) when updating the async_free_space |
| during the free operation. These are the same except for this |
| corner case of asynchronous transactions with payloads < 8 bytes. |
| |
| Fixes: 74310e06be4d ("android: binder: Move buffer out of area shared with user space") |
| Signed-off-by: Todd Kjos <tkjos@google.com> |
| Cc: stable@vger.kernel.org # 4.14+ |
| Link: https://lore.kernel.org/r/20211220190150.2107077-1-tkjos@google.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/android/binder_alloc.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/drivers/android/binder_alloc.c |
| +++ b/drivers/android/binder_alloc.c |
| @@ -630,7 +630,7 @@ static void binder_free_buf_locked(struc |
| BUG_ON(buffer->data > alloc->buffer + alloc->buffer_size); |
| |
| if (buffer->async_transaction) { |
| - alloc->free_async_space += size + sizeof(struct binder_buffer); |
| + alloc->free_async_space += buffer_size + sizeof(struct binder_buffer); |
| |
| binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, |
| "%d: binder_free_buf size %zd async free %zd\n", |