From: Brooke Basile <brookebas...@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 <ivansprun...@ioactive.com>
Suggested-by: Kees Cook <keesc...@chromium.org>
Signed-off-by: Brooke Basile <brookebas...@gmail.com>
Acked-by: Felipe Balbi <ba...@kernel.org>
Cc: stable <sta...@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gre...@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
@@ -14,6 +14,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
@@ -21,21 +22,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) \


Reply via email to