diff options
author | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2012-05-13 21:47:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-16 15:38:49 -0400 |
commit | 26a5d3cc0b3d1ff23b5a94edb58226afe7f12a0c (patch) | |
tree | 046834414e20d334fc5172275a53c55d9722a714 /net | |
parent | 769b0daf6e18a05a6d4da94baab7edd12867350c (diff) |
netfilter: ipset: fix hash size checking in kernel
The hash size must fit both into u32 (jhash) and the max value of
size_t. The missing checking could lead to kernel crash, bug reported
by Seblu.
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_ip.c | 10 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_ipport.c | 10 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_ipportip.c | 10 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_ipportnet.c | 10 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_net.c | 10 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_netiface.c | 10 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_netport.c | 10 |
7 files changed, 49 insertions, 21 deletions
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c index 5139dea6019e..828ce46cb34b 100644 --- a/net/netfilter/ipset/ip_set_hash_ip.c +++ b/net/netfilter/ipset/ip_set_hash_ip.c | |||
@@ -364,6 +364,7 @@ hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
364 | { | 364 | { |
365 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; | 365 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; |
366 | u8 netmask, hbits; | 366 | u8 netmask, hbits; |
367 | size_t hsize; | ||
367 | struct ip_set_hash *h; | 368 | struct ip_set_hash *h; |
368 | 369 | ||
369 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) | 370 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) |
@@ -405,9 +406,12 @@ hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
405 | h->timeout = IPSET_NO_TIMEOUT; | 406 | h->timeout = IPSET_NO_TIMEOUT; |
406 | 407 | ||
407 | hbits = htable_bits(hashsize); | 408 | hbits = htable_bits(hashsize); |
408 | h->table = ip_set_alloc( | 409 | hsize = htable_size(hbits); |
409 | sizeof(struct htable) | 410 | if (hsize == 0) { |
410 | + jhash_size(hbits) * sizeof(struct hbucket)); | 411 | kfree(h); |
412 | return -ENOMEM; | ||
413 | } | ||
414 | h->table = ip_set_alloc(hsize); | ||
411 | if (!h->table) { | 415 | if (!h->table) { |
412 | kfree(h); | 416 | kfree(h); |
413 | return -ENOMEM; | 417 | return -ENOMEM; |
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c index 9c27e249c171..e8dbb498af8f 100644 --- a/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/net/netfilter/ipset/ip_set_hash_ipport.c | |||
@@ -449,6 +449,7 @@ hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
449 | struct ip_set_hash *h; | 449 | struct ip_set_hash *h; |
450 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; | 450 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; |
451 | u8 hbits; | 451 | u8 hbits; |
452 | size_t hsize; | ||
452 | 453 | ||
453 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) | 454 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) |
454 | return -IPSET_ERR_INVALID_FAMILY; | 455 | return -IPSET_ERR_INVALID_FAMILY; |
@@ -476,9 +477,12 @@ hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
476 | h->timeout = IPSET_NO_TIMEOUT; | 477 | h->timeout = IPSET_NO_TIMEOUT; |
477 | 478 | ||
478 | hbits = htable_bits(hashsize); | 479 | hbits = htable_bits(hashsize); |
479 | h->table = ip_set_alloc( | 480 | hsize = htable_size(hbits); |
480 | sizeof(struct htable) | 481 | if (hsize == 0) { |
481 | + jhash_size(hbits) * sizeof(struct hbucket)); | 482 | kfree(h); |
483 | return -ENOMEM; | ||
484 | } | ||
485 | h->table = ip_set_alloc(hsize); | ||
482 | if (!h->table) { | 486 | if (!h->table) { |
483 | kfree(h); | 487 | kfree(h); |
484 | return -ENOMEM; | 488 | return -ENOMEM; |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c index 9134057c0728..52f79d8ef741 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/net/netfilter/ipset/ip_set_hash_ipportip.c | |||
@@ -467,6 +467,7 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
467 | struct ip_set_hash *h; | 467 | struct ip_set_hash *h; |
468 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; | 468 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; |
469 | u8 hbits; | 469 | u8 hbits; |
470 | size_t hsize; | ||
470 | 471 | ||
471 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) | 472 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) |
472 | return -IPSET_ERR_INVALID_FAMILY; | 473 | return -IPSET_ERR_INVALID_FAMILY; |
@@ -494,9 +495,12 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
494 | h->timeout = IPSET_NO_TIMEOUT; | 495 | h->timeout = IPSET_NO_TIMEOUT; |
495 | 496 | ||
496 | hbits = htable_bits(hashsize); | 497 | hbits = htable_bits(hashsize); |
497 | h->table = ip_set_alloc( | 498 | hsize = htable_size(hbits); |
498 | sizeof(struct htable) | 499 | if (hsize == 0) { |
499 | + jhash_size(hbits) * sizeof(struct hbucket)); | 500 | kfree(h); |
501 | return -ENOMEM; | ||
502 | } | ||
503 | h->table = ip_set_alloc(hsize); | ||
500 | if (!h->table) { | 504 | if (!h->table) { |
501 | kfree(h); | 505 | kfree(h); |
502 | return -ENOMEM; | 506 | return -ENOMEM; |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index 5d05e6969862..97583f5af745 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c | |||
@@ -616,6 +616,7 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
616 | struct ip_set_hash *h; | 616 | struct ip_set_hash *h; |
617 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; | 617 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; |
618 | u8 hbits; | 618 | u8 hbits; |
619 | size_t hsize; | ||
619 | 620 | ||
620 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) | 621 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) |
621 | return -IPSET_ERR_INVALID_FAMILY; | 622 | return -IPSET_ERR_INVALID_FAMILY; |
@@ -645,9 +646,12 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
645 | h->timeout = IPSET_NO_TIMEOUT; | 646 | h->timeout = IPSET_NO_TIMEOUT; |
646 | 647 | ||
647 | hbits = htable_bits(hashsize); | 648 | hbits = htable_bits(hashsize); |
648 | h->table = ip_set_alloc( | 649 | hsize = htable_size(hbits); |
649 | sizeof(struct htable) | 650 | if (hsize == 0) { |
650 | + jhash_size(hbits) * sizeof(struct hbucket)); | 651 | kfree(h); |
652 | return -ENOMEM; | ||
653 | } | ||
654 | h->table = ip_set_alloc(hsize); | ||
651 | if (!h->table) { | 655 | if (!h->table) { |
652 | kfree(h); | 656 | kfree(h); |
653 | return -ENOMEM; | 657 | return -ENOMEM; |
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c index 7c3d945517cf..1721cdecc9f9 100644 --- a/net/netfilter/ipset/ip_set_hash_net.c +++ b/net/netfilter/ipset/ip_set_hash_net.c | |||
@@ -460,6 +460,7 @@ hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
460 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; | 460 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; |
461 | struct ip_set_hash *h; | 461 | struct ip_set_hash *h; |
462 | u8 hbits; | 462 | u8 hbits; |
463 | size_t hsize; | ||
463 | 464 | ||
464 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) | 465 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) |
465 | return -IPSET_ERR_INVALID_FAMILY; | 466 | return -IPSET_ERR_INVALID_FAMILY; |
@@ -489,9 +490,12 @@ hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
489 | h->timeout = IPSET_NO_TIMEOUT; | 490 | h->timeout = IPSET_NO_TIMEOUT; |
490 | 491 | ||
491 | hbits = htable_bits(hashsize); | 492 | hbits = htable_bits(hashsize); |
492 | h->table = ip_set_alloc( | 493 | hsize = htable_size(hbits); |
493 | sizeof(struct htable) | 494 | if (hsize == 0) { |
494 | + jhash_size(hbits) * sizeof(struct hbucket)); | 495 | kfree(h); |
496 | return -ENOMEM; | ||
497 | } | ||
498 | h->table = ip_set_alloc(hsize); | ||
495 | if (!h->table) { | 499 | if (!h->table) { |
496 | kfree(h); | 500 | kfree(h); |
497 | return -ENOMEM; | 501 | return -ENOMEM; |
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c index f24037ff4322..33bafc97ca6d 100644 --- a/net/netfilter/ipset/ip_set_hash_netiface.c +++ b/net/netfilter/ipset/ip_set_hash_netiface.c | |||
@@ -722,6 +722,7 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
722 | struct ip_set_hash *h; | 722 | struct ip_set_hash *h; |
723 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; | 723 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; |
724 | u8 hbits; | 724 | u8 hbits; |
725 | size_t hsize; | ||
725 | 726 | ||
726 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) | 727 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) |
727 | return -IPSET_ERR_INVALID_FAMILY; | 728 | return -IPSET_ERR_INVALID_FAMILY; |
@@ -752,9 +753,12 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
752 | h->ahash_max = AHASH_MAX_SIZE; | 753 | h->ahash_max = AHASH_MAX_SIZE; |
753 | 754 | ||
754 | hbits = htable_bits(hashsize); | 755 | hbits = htable_bits(hashsize); |
755 | h->table = ip_set_alloc( | 756 | hsize = htable_size(hbits); |
756 | sizeof(struct htable) | 757 | if (hsize == 0) { |
757 | + jhash_size(hbits) * sizeof(struct hbucket)); | 758 | kfree(h); |
759 | return -ENOMEM; | ||
760 | } | ||
761 | h->table = ip_set_alloc(hsize); | ||
758 | if (!h->table) { | 762 | if (!h->table) { |
759 | kfree(h); | 763 | kfree(h); |
760 | return -ENOMEM; | 764 | return -ENOMEM; |
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c index ce2e77100b64..3a5e198641d6 100644 --- a/net/netfilter/ipset/ip_set_hash_netport.c +++ b/net/netfilter/ipset/ip_set_hash_netport.c | |||
@@ -572,6 +572,7 @@ hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
572 | struct ip_set_hash *h; | 572 | struct ip_set_hash *h; |
573 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; | 573 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; |
574 | u8 hbits; | 574 | u8 hbits; |
575 | size_t hsize; | ||
575 | 576 | ||
576 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) | 577 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) |
577 | return -IPSET_ERR_INVALID_FAMILY; | 578 | return -IPSET_ERR_INVALID_FAMILY; |
@@ -601,9 +602,12 @@ hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
601 | h->timeout = IPSET_NO_TIMEOUT; | 602 | h->timeout = IPSET_NO_TIMEOUT; |
602 | 603 | ||
603 | hbits = htable_bits(hashsize); | 604 | hbits = htable_bits(hashsize); |
604 | h->table = ip_set_alloc( | 605 | hsize = htable_size(hbits); |
605 | sizeof(struct htable) | 606 | if (hsize == 0) { |
606 | + jhash_size(hbits) * sizeof(struct hbucket)); | 607 | kfree(h); |
608 | return -ENOMEM; | ||
609 | } | ||
610 | h->table = ip_set_alloc(hsize); | ||
607 | if (!h->table) { | 611 | if (!h->table) { |
608 | kfree(h); | 612 | kfree(h); |
609 | return -ENOMEM; | 613 | return -ENOMEM; |