summaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2018-02-18 21:01:45 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2018-02-25 14:04:53 -0500
commitc4585a2823edf4d1326da44d1524ecbfda26bb37 (patch)
treedd0673555c832ca71348c3753e4c2c9f3a5e4dc3 /net/bridge
parentb078556aecd791b0e5cb3a59f4c3a14273b52121 (diff)
netfilter: bridge: ebt_among: add missing match size checks
ebt_among is special, it has a dynamic match size and is exempt from the central size checks. Therefore it must check that the size of the match structure provided from userspace is sane by making sure em->match_size is at least the minimum size of the expected structure. The module has such a check, but its only done after accessing a structure that might be out of bounds. tested with: ebtables -A INPUT ... \ --among-dst fe:fe:fe:fe:fe:fe --among-dst fe:fe:fe:fe:fe:fe --among-src fe:fe:fe:fe:ff:f,fe:fe:fe:fe:fe:fb,fe:fe:fe:fe:fc:fd,fe:fe:fe:fe:fe:fd,fe:fe:fe:fe:fe:fe --among-src fe:fe:fe:fe:ff:f,fe:fe:fe:fe:fe:fa,fe:fe:fe:fe:fe:fd,fe:fe:fe:fe:fe:fe,fe:fe:fe:fe:fe:fe Reported-by: <syzbot+fe0b19af568972814355@syzkaller.appspotmail.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/netfilter/ebt_among.c21
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)
172 return true; 172 return true;
173} 173}
174 174
175static bool poolsize_invalid(const struct ebt_mac_wormhash *w)
176{
177 return w && w->poolsize >= (INT_MAX / sizeof(struct ebt_mac_wormhash_tuple));
178}
179
175static int ebt_among_mt_check(const struct xt_mtchk_param *par) 180static int ebt_among_mt_check(const struct xt_mtchk_param *par)
176{ 181{
177 const struct ebt_among_info *info = par->matchinfo; 182 const struct ebt_among_info *info = par->matchinfo;
178 const struct ebt_entry_match *em = 183 const struct ebt_entry_match *em =
179 container_of(par->matchinfo, const struct ebt_entry_match, data); 184 container_of(par->matchinfo, const struct ebt_entry_match, data);
180 int expected_length = sizeof(struct ebt_among_info); 185 unsigned int expected_length = sizeof(struct ebt_among_info);
181 const struct ebt_mac_wormhash *wh_dst, *wh_src; 186 const struct ebt_mac_wormhash *wh_dst, *wh_src;
182 int err; 187 int err;
183 188
189 if (expected_length > em->match_size)
190 return -EINVAL;
191
184 wh_dst = ebt_among_wh_dst(info); 192 wh_dst = ebt_among_wh_dst(info);
185 wh_src = ebt_among_wh_src(info); 193 if (poolsize_invalid(wh_dst))
194 return -EINVAL;
195
186 expected_length += ebt_mac_wormhash_size(wh_dst); 196 expected_length += ebt_mac_wormhash_size(wh_dst);
197 if (expected_length > em->match_size)
198 return -EINVAL;
199
200 wh_src = ebt_among_wh_src(info);
201 if (poolsize_invalid(wh_src))
202 return -EINVAL;
203
187 expected_length += ebt_mac_wormhash_size(wh_src); 204 expected_length += ebt_mac_wormhash_size(wh_src);
188 205
189 if (em->match_size != EBT_ALIGN(expected_length)) { 206 if (em->match_size != EBT_ALIGN(expected_length)) {