aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-01-30 09:21:34 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2018-01-31 09:00:33 -0500
commit1a38956cce5eabd7b74f94bab70265e4df83165e (patch)
treebc408aea9549988755c7b51bbe780c18b7e88be7
parent1e98ffea5a8935ec040ab72299e349cb44b8defd (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.c16
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) {