diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2018-01-30 09:21:34 -0500 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2018-01-31 09:00:33 -0500 |
commit | 1a38956cce5eabd7b74f94bab70265e4df83165e (patch) | |
tree | bc408aea9549988755c7b51bbe780c18b7e88be7 | |
parent | 1e98ffea5a8935ec040ab72299e349cb44b8defd (diff) |
netfilter: ipt_CLUSTERIP: fix out-of-bounds accesses in clusterip_tg_check()
Commit 136e92bbec0a switched local_nodes from an array to a bitmask
but did not add proper bounds checks. As the result
clusterip_config_init_nodelist() can both over-read
ipt_clusterip_tgt_info.local_nodes and over-write
clusterip_config.local_nodes.
Add bounds checks for both.
Fixes: 136e92bbec0a ("[NETFILTER] CLUSTERIP: use a bitmap to store node responsibility data")
Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | net/ipv4/netfilter/ipt_CLUSTERIP.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 69060e3abe85..1e4a7209a3d2 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -431,7 +431,7 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) | |||
431 | struct ipt_clusterip_tgt_info *cipinfo = par->targinfo; | 431 | struct ipt_clusterip_tgt_info *cipinfo = par->targinfo; |
432 | const struct ipt_entry *e = par->entryinfo; | 432 | const struct ipt_entry *e = par->entryinfo; |
433 | struct clusterip_config *config; | 433 | struct clusterip_config *config; |
434 | int ret; | 434 | int ret, i; |
435 | 435 | ||
436 | if (par->nft_compat) { | 436 | if (par->nft_compat) { |
437 | pr_err("cannot use CLUSTERIP target from nftables compat\n"); | 437 | pr_err("cannot use CLUSTERIP target from nftables compat\n"); |
@@ -450,8 +450,18 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) | |||
450 | pr_info("Please specify destination IP\n"); | 450 | pr_info("Please specify destination IP\n"); |
451 | return -EINVAL; | 451 | return -EINVAL; |
452 | } | 452 | } |
453 | 453 | if (cipinfo->num_local_nodes > ARRAY_SIZE(cipinfo->local_nodes)) { | |
454 | /* FIXME: further sanity checks */ | 454 | pr_info("bad num_local_nodes %u\n", cipinfo->num_local_nodes); |
455 | return -EINVAL; | ||
456 | } | ||
457 | for (i = 0; i < cipinfo->num_local_nodes; i++) { | ||
458 | if (cipinfo->local_nodes[i] - 1 >= | ||
459 | sizeof(config->local_nodes) * 8) { | ||
460 | pr_info("bad local_nodes[%d] %u\n", | ||
461 | i, cipinfo->local_nodes[i]); | ||
462 | return -EINVAL; | ||
463 | } | ||
464 | } | ||
455 | 465 | ||
456 | config = clusterip_config_find_get(par->net, e->ip.dst.s_addr, 1); | 466 | config = clusterip_config_find_get(par->net, e->ip.dst.s_addr, 1); |
457 | if (!config) { | 467 | if (!config) { |