Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 849d2b00 authored by Brooke Basile's avatar Brooke Basile Committed by Greg Kroah-Hartman
Browse files

USB: gadget: u_f: add overflow checks to VLA macros



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: default avatarIlja Van Sprundel <ivansprundel@ioactive.com>
Suggested-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarBrooke Basile <brookebasile@gmail.com>
Acked-by: default avatarFelipe Balbi <balbi@kernel.org>
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 676057c7
Loading
Loading
Loading
Loading
+27 −11
Original line number Diff line number Diff line
@@ -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,20 +25,35 @@

#define vla_item(groupname, type, name, n) \
	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;\
		size_t size = (n) * sizeof(type);			       \
		groupname##__next = offset + size;			       \
			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##__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;\
		size_t size = groupname##_##name##__sz;			       \
		groupname##__next = offset + size;			       \
			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;								\
	})