| From b1cd1b65afba95971fa457dfdb2c941c60d38c5b Mon Sep 17 00:00:00 2001 |
| From: Brooke Basile <brookebasile@gmail.com> |
| Date: Tue, 25 Aug 2020 09:05:08 -0400 |
| Subject: USB: gadget: u_f: add overflow checks to VLA macros |
| |
| From: Brooke Basile <brookebasile@gmail.com> |
| |
| commit b1cd1b65afba95971fa457dfdb2c941c60d38c5b upstream. |
| |
| size can potentially hold an overflowed value if its assigned expression |
| is left unchecked, leading to a smaller than needed allocation when |
| vla_group_size() is used by callers to allocate memory. |
| To fix this, add a test for saturation before declaring variables and an |
| overflow check to (n) * sizeof(type). |
| If the expression results in overflow, vla_group_size() will return SIZE_MAX. |
| |
| Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com> |
| Suggested-by: Kees Cook <keescook@chromium.org> |
| Signed-off-by: Brooke Basile <brookebasile@gmail.com> |
| Acked-by: Felipe Balbi <balbi@kernel.org> |
| Cc: stable <stable@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/gadget/u_f.h | 38 +++++++++++++++++++++++++++----------- |
| 1 file changed, 27 insertions(+), 11 deletions(-) |
| |
| --- a/drivers/usb/gadget/u_f.h |
| +++ b/drivers/usb/gadget/u_f.h |
| @@ -17,6 +17,7 @@ |
| #define __U_F_H__ |
| |
| #include <linux/usb/gadget.h> |
| +#include <linux/overflow.h> |
| |
| /* Variable Length Array Macros **********************************************/ |
| #define vla_group(groupname) size_t groupname##__next = 0 |
| @@ -24,21 +25,36 @@ |
| |
| #define vla_item(groupname, type, name, n) \ |
| size_t groupname##_##name##__offset = ({ \ |
| - size_t align_mask = __alignof__(type) - 1; \ |
| - size_t offset = (groupname##__next + align_mask) & ~align_mask;\ |
| - size_t size = (n) * sizeof(type); \ |
| - groupname##__next = offset + size; \ |
| + size_t offset = 0; \ |
| + if (groupname##__next != SIZE_MAX) { \ |
| + size_t align_mask = __alignof__(type) - 1; \ |
| + size_t offset = (groupname##__next + align_mask) \ |
| + & ~align_mask; \ |
| + size_t size = array_size(n, sizeof(type)); \ |
| + if (check_add_overflow(offset, size, \ |
| + &groupname##__next)) { \ |
| + groupname##__next = SIZE_MAX; \ |
| + offset = 0; \ |
| + } \ |
| + } \ |
| offset; \ |
| }) |
| |
| #define vla_item_with_sz(groupname, type, name, n) \ |
| - size_t groupname##_##name##__sz = (n) * sizeof(type); \ |
| - size_t groupname##_##name##__offset = ({ \ |
| - size_t align_mask = __alignof__(type) - 1; \ |
| - size_t offset = (groupname##__next + align_mask) & ~align_mask;\ |
| - size_t size = groupname##_##name##__sz; \ |
| - groupname##__next = offset + size; \ |
| - offset; \ |
| + size_t groupname##_##name##__sz = array_size(n, sizeof(type)); \ |
| + size_t groupname##_##name##__offset = ({ \ |
| + size_t offset = 0; \ |
| + if (groupname##__next != SIZE_MAX) { \ |
| + size_t align_mask = __alignof__(type) - 1; \ |
| + size_t offset = (groupname##__next + align_mask) \ |
| + & ~align_mask; \ |
| + if (check_add_overflow(offset, groupname##_##name##__sz,\ |
| + &groupname##__next)) { \ |
| + groupname##__next = SIZE_MAX; \ |
| + offset = 0; \ |
| + } \ |
| + } \ |
| + offset; \ |
| }) |
| |
| #define vla_ptr(ptr, groupname, name) \ |