diff options
author | Cong Wang <xiyou.wangcong@gmail.com> | 2020-02-03 07:30:53 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-02-28 19:22:27 +0300 |
commit | 829e0a0ae2dc7aaeb46f716be3f52f498de2bdd8 (patch) | |
tree | 857bba71a68de36c8254add6f2da5386a4c5a4c9 /net/netfilter | |
parent | 86502c68b81eb98fc0f0c6bd87cda01cb7a4cd9d (diff) | |
download | linux-829e0a0ae2dc7aaeb46f716be3f52f498de2bdd8.tar.xz |
netfilter: xt_hashlimit: limit the max size of hashtable
commit 8d0015a7ab76b8b1e89a3e5f5710a6e5103f2dd5 upstream.
The user-specified hashtable size is unbound, this could
easily lead to an OOM or a hung task as we hold the global
mutex while allocating and initializing the new hashtable.
Add a max value to cap both cfg->size and cfg->max, as
suggested by Florian.
Reported-and-tested-by: syzbot+adf6c6c2be1c3a718121@syzkaller.appspotmail.com
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Reviewed-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/xt_hashlimit.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index ced3fc8fad7c..6520d9ec1297 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -851,6 +851,8 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par) return hashlimit_mt_common(skb, par, hinfo, &info->cfg, 3); } +#define HASHLIMIT_MAX_SIZE 1048576 + static int hashlimit_mt_check_common(const struct xt_mtchk_param *par, struct xt_hashlimit_htable **hinfo, struct hashlimit_cfg3 *cfg, @@ -861,6 +863,14 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par, if (cfg->gc_interval == 0 || cfg->expire == 0) return -EINVAL; + if (cfg->size > HASHLIMIT_MAX_SIZE) { + cfg->size = HASHLIMIT_MAX_SIZE; + pr_info_ratelimited("size too large, truncated to %u\n", cfg->size); + } + if (cfg->max > HASHLIMIT_MAX_SIZE) { + cfg->max = HASHLIMIT_MAX_SIZE; + pr_info_ratelimited("max too large, truncated to %u\n", cfg->max); + } if (par->family == NFPROTO_IPV4) { if (cfg->srcmask > 32 || cfg->dstmask > 32) return -EINVAL; |