diff options
| -rw-r--r-- | net/bridge/netfilter/ebt_among.c | 21 | 
1 files changed, 19 insertions, 2 deletions
| diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c index ce7152a12bd8..c5afb4232ecb 100644 --- a/net/bridge/netfilter/ebt_among.c +++ b/net/bridge/netfilter/ebt_among.c @@ -172,18 +172,35 @@ ebt_among_mt(const struct sk_buff *skb, struct xt_action_param *par)  	return true;  } +static bool poolsize_invalid(const struct ebt_mac_wormhash *w) +{ +	return w && w->poolsize >= (INT_MAX / sizeof(struct ebt_mac_wormhash_tuple)); +} +  static int ebt_among_mt_check(const struct xt_mtchk_param *par)  {  	const struct ebt_among_info *info = par->matchinfo;  	const struct ebt_entry_match *em =  		container_of(par->matchinfo, const struct ebt_entry_match, data); -	int expected_length = sizeof(struct ebt_among_info); +	unsigned int expected_length = sizeof(struct ebt_among_info);  	const struct ebt_mac_wormhash *wh_dst, *wh_src;  	int err; +	if (expected_length > em->match_size) +		return -EINVAL; +  	wh_dst = ebt_among_wh_dst(info); -	wh_src = ebt_among_wh_src(info); +	if (poolsize_invalid(wh_dst)) +		return -EINVAL; +  	expected_length += ebt_mac_wormhash_size(wh_dst); +	if (expected_length > em->match_size) +		return -EINVAL; + +	wh_src = ebt_among_wh_src(info); +	if (poolsize_invalid(wh_src)) +		return -EINVAL; +  	expected_length += ebt_mac_wormhash_size(wh_src);  	if (em->match_size != EBT_ALIGN(expected_length)) { | 
