Skip to content

Commit c8d70a7

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: bridge: ebt_among: add more missing match size checks
ebt_among is special, it has a dynamic match size and is exempt from the central size checks. commit c4585a2 ("bridge: ebt_among: add missing match size checks") added validation for pool size, but missed fact that the macros ebt_among_wh_src/dst can already return out-of-bound result because they do not check value of wh_src/dst_ofs (an offset) vs. the size of the match that userspace gave to us. v2: check that offset has correct alignment. Paolo Abeni points out that we should also check that src/dst wormhash arrays do not overlap, and src + length lines up with start of dst (or vice versa). v3: compact wormhash_sizes_valid() part NB: Fixes tag is intentionally wrong, this bug exists from day one when match was added for 2.6 kernel. Tag is there so stable maintainers will notice this one too. Tested with same rules from the earlier patch. Fixes: c4585a2 ("bridge: ebt_among: add missing match size checks") Reported-by: <[email protected]> Signed-off-by: Florian Westphal <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent b1d0a5d commit c8d70a7

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

net/bridge/netfilter/ebt_among.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,28 @@ static bool poolsize_invalid(const struct ebt_mac_wormhash *w)
177177
return w && w->poolsize >= (INT_MAX / sizeof(struct ebt_mac_wormhash_tuple));
178178
}
179179

180+
static bool wormhash_offset_invalid(int off, unsigned int len)
181+
{
182+
if (off == 0) /* not present */
183+
return false;
184+
185+
if (off < (int)sizeof(struct ebt_among_info) ||
186+
off % __alignof__(struct ebt_mac_wormhash))
187+
return true;
188+
189+
off += sizeof(struct ebt_mac_wormhash);
190+
191+
return off > len;
192+
}
193+
194+
static bool wormhash_sizes_valid(const struct ebt_mac_wormhash *wh, int a, int b)
195+
{
196+
if (a == 0)
197+
a = sizeof(struct ebt_among_info);
198+
199+
return ebt_mac_wormhash_size(wh) + a == b;
200+
}
201+
180202
static int ebt_among_mt_check(const struct xt_mtchk_param *par)
181203
{
182204
const struct ebt_among_info *info = par->matchinfo;
@@ -189,6 +211,10 @@ static int ebt_among_mt_check(const struct xt_mtchk_param *par)
189211
if (expected_length > em->match_size)
190212
return -EINVAL;
191213

214+
if (wormhash_offset_invalid(info->wh_dst_ofs, em->match_size) ||
215+
wormhash_offset_invalid(info->wh_src_ofs, em->match_size))
216+
return -EINVAL;
217+
192218
wh_dst = ebt_among_wh_dst(info);
193219
if (poolsize_invalid(wh_dst))
194220
return -EINVAL;
@@ -201,6 +227,14 @@ static int ebt_among_mt_check(const struct xt_mtchk_param *par)
201227
if (poolsize_invalid(wh_src))
202228
return -EINVAL;
203229

230+
if (info->wh_src_ofs < info->wh_dst_ofs) {
231+
if (!wormhash_sizes_valid(wh_src, info->wh_src_ofs, info->wh_dst_ofs))
232+
return -EINVAL;
233+
} else {
234+
if (!wormhash_sizes_valid(wh_dst, info->wh_dst_ofs, info->wh_src_ofs))
235+
return -EINVAL;
236+
}
237+
204238
expected_length += ebt_mac_wormhash_size(wh_src);
205239

206240
if (em->match_size != EBT_ALIGN(expected_length)) {

0 commit comments

Comments
 (0)