diff options
author | Florian Westphal <fw@strlen.de> | 2019-07-29 11:58:10 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2019-07-30 07:37:44 -0400 |
commit | 3b48300d5cc7c7bed63fddb006c4046549ed4aec (patch) | |
tree | 426465a2f608a3943e748821242f41c336928d56 /net/bridge | |
parent | 91826ba13855f73e252fef68369b3b0e1ed25253 (diff) |
netfilter: ebtables: also count base chain policies
ebtables doesn't include the base chain policies in the rule count,
so we need to add them manually when we call into the x_tables core
to allocate space for the comapt offset table.
This lead syzbot to trigger:
WARNING: CPU: 1 PID: 9012 at net/netfilter/x_tables.c:649
xt_compat_add_offset.cold+0x11/0x36 net/netfilter/x_tables.c:649
Reported-by: syzbot+276ddebab3382bbf72db@syzkaller.appspotmail.com
Fixes: 2035f3ff8eaa ("netfilter: ebtables: compat: un-break 32bit setsockopt when no rules are present")
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/ebtables.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index fd84b48e48b5..c8177a89f52c 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -1770,20 +1770,28 @@ static int compat_calc_entry(const struct ebt_entry *e, | |||
1770 | return 0; | 1770 | return 0; |
1771 | } | 1771 | } |
1772 | 1772 | ||
1773 | static int ebt_compat_init_offsets(unsigned int number) | ||
1774 | { | ||
1775 | if (number > INT_MAX) | ||
1776 | return -EINVAL; | ||
1777 | |||
1778 | /* also count the base chain policies */ | ||
1779 | number += NF_BR_NUMHOOKS; | ||
1780 | |||
1781 | return xt_compat_init_offsets(NFPROTO_BRIDGE, number); | ||
1782 | } | ||
1773 | 1783 | ||
1774 | static int compat_table_info(const struct ebt_table_info *info, | 1784 | static int compat_table_info(const struct ebt_table_info *info, |
1775 | struct compat_ebt_replace *newinfo) | 1785 | struct compat_ebt_replace *newinfo) |
1776 | { | 1786 | { |
1777 | unsigned int size = info->entries_size; | 1787 | unsigned int size = info->entries_size; |
1778 | const void *entries = info->entries; | 1788 | const void *entries = info->entries; |
1789 | int ret; | ||
1779 | 1790 | ||
1780 | newinfo->entries_size = size; | 1791 | newinfo->entries_size = size; |
1781 | if (info->nentries) { | 1792 | ret = ebt_compat_init_offsets(info->nentries); |
1782 | int ret = xt_compat_init_offsets(NFPROTO_BRIDGE, | 1793 | if (ret) |
1783 | info->nentries); | 1794 | return ret; |
1784 | if (ret) | ||
1785 | return ret; | ||
1786 | } | ||
1787 | 1795 | ||
1788 | return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, | 1796 | return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, |
1789 | entries, newinfo); | 1797 | entries, newinfo); |
@@ -2234,11 +2242,9 @@ static int compat_do_replace(struct net *net, void __user *user, | |||
2234 | 2242 | ||
2235 | xt_compat_lock(NFPROTO_BRIDGE); | 2243 | xt_compat_lock(NFPROTO_BRIDGE); |
2236 | 2244 | ||
2237 | if (tmp.nentries) { | 2245 | ret = ebt_compat_init_offsets(tmp.nentries); |
2238 | ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries); | 2246 | if (ret < 0) |
2239 | if (ret < 0) | 2247 | goto out_unlock; |
2240 | goto out_unlock; | ||
2241 | } | ||
2242 | 2248 | ||
2243 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); | 2249 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); |
2244 | if (ret < 0) | 2250 | if (ret < 0) |