aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/arp_tables.c48
-rw-r--r--net/ipv4/netfilter/ip_tables.c68
-rw-r--r--net/ipv6/netfilter/ip6_tables.c59
3 files changed, 72 insertions, 103 deletions
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 413c2d0a1f3d..71b76ade00e1 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -375,6 +375,13 @@ static int mark_source_chains(struct xt_table_info *newinfo,
375 && unconditional(&e->arp)) { 375 && unconditional(&e->arp)) {
376 unsigned int oldpos, size; 376 unsigned int oldpos, size;
377 377
378 if (t->verdict < -NF_MAX_VERDICT - 1) {
379 duprintf("mark_source_chains: bad "
380 "negative verdict (%i)\n",
381 t->verdict);
382 return 0;
383 }
384
378 /* Return: backtrack through the last 385 /* Return: backtrack through the last
379 * big jump. 386 * big jump.
380 */ 387 */
@@ -404,6 +411,14 @@ static int mark_source_chains(struct xt_table_info *newinfo,
404 if (strcmp(t->target.u.user.name, 411 if (strcmp(t->target.u.user.name,
405 ARPT_STANDARD_TARGET) == 0 412 ARPT_STANDARD_TARGET) == 0
406 && newpos >= 0) { 413 && newpos >= 0) {
414 if (newpos > newinfo->size -
415 sizeof(struct arpt_entry)) {
416 duprintf("mark_source_chains: "
417 "bad verdict (%i)\n",
418 newpos);
419 return 0;
420 }
421
407 /* This a jump; chase it. */ 422 /* This a jump; chase it. */
408 duprintf("Jump rule %u -> %u\n", 423 duprintf("Jump rule %u -> %u\n",
409 pos, newpos); 424 pos, newpos);
@@ -426,8 +441,6 @@ static int mark_source_chains(struct xt_table_info *newinfo,
426static inline int standard_check(const struct arpt_entry_target *t, 441static inline int standard_check(const struct arpt_entry_target *t,
427 unsigned int max_offset) 442 unsigned int max_offset)
428{ 443{
429 struct arpt_standard_target *targ = (void *)t;
430
431 /* Check standard info. */ 444 /* Check standard info. */
432 if (t->u.target_size 445 if (t->u.target_size
433 != ARPT_ALIGN(sizeof(struct arpt_standard_target))) { 446 != ARPT_ALIGN(sizeof(struct arpt_standard_target))) {
@@ -437,18 +450,6 @@ static inline int standard_check(const struct arpt_entry_target *t,
437 return 0; 450 return 0;
438 } 451 }
439 452
440 if (targ->verdict >= 0
441 && targ->verdict > max_offset - sizeof(struct arpt_entry)) {
442 duprintf("arpt_standard_check: bad verdict (%i)\n",
443 targ->verdict);
444 return 0;
445 }
446
447 if (targ->verdict < -NF_MAX_VERDICT - 1) {
448 duprintf("arpt_standard_check: bad negative verdict (%i)\n",
449 targ->verdict);
450 return 0;
451 }
452 return 1; 453 return 1;
453} 454}
454 455
@@ -627,18 +628,20 @@ static int translate_table(const char *name,
627 } 628 }
628 } 629 }
629 630
631 if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
632 duprintf("Looping hook\n");
633 return -ELOOP;
634 }
635
630 /* Finally, each sanity check must pass */ 636 /* Finally, each sanity check must pass */
631 i = 0; 637 i = 0;
632 ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size, 638 ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size,
633 check_entry, name, size, &i); 639 check_entry, name, size, &i);
634 640
635 if (ret != 0) 641 if (ret != 0) {
636 goto cleanup; 642 ARPT_ENTRY_ITERATE(entry0, newinfo->size,
637 643 cleanup_entry, &i);
638 ret = -ELOOP; 644 return ret;
639 if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
640 duprintf("Looping hook\n");
641 goto cleanup;
642 } 645 }
643 646
644 /* And one copy for every other CPU */ 647 /* And one copy for every other CPU */
@@ -647,9 +650,6 @@ static int translate_table(const char *name,
647 memcpy(newinfo->entries[i], entry0, newinfo->size); 650 memcpy(newinfo->entries[i], entry0, newinfo->size);
648 } 651 }
649 652
650 return 0;
651cleanup:
652 ARPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
653 return ret; 653 return ret;
654} 654}
655 655
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 8a455439b128..2bddf8491982 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -401,6 +401,13 @@ mark_source_chains(struct xt_table_info *newinfo,
401 && unconditional(&e->ip)) { 401 && unconditional(&e->ip)) {
402 unsigned int oldpos, size; 402 unsigned int oldpos, size;
403 403
404 if (t->verdict < -NF_MAX_VERDICT - 1) {
405 duprintf("mark_source_chains: bad "
406 "negative verdict (%i)\n",
407 t->verdict);
408 return 0;
409 }
410
404 /* Return: backtrack through the last 411 /* Return: backtrack through the last
405 big jump. */ 412 big jump. */
406 do { 413 do {
@@ -438,6 +445,13 @@ mark_source_chains(struct xt_table_info *newinfo,
438 if (strcmp(t->target.u.user.name, 445 if (strcmp(t->target.u.user.name,
439 IPT_STANDARD_TARGET) == 0 446 IPT_STANDARD_TARGET) == 0
440 && newpos >= 0) { 447 && newpos >= 0) {
448 if (newpos > newinfo->size -
449 sizeof(struct ipt_entry)) {
450 duprintf("mark_source_chains: "
451 "bad verdict (%i)\n",
452 newpos);
453 return 0;
454 }
441 /* This a jump; chase it. */ 455 /* This a jump; chase it. */
442 duprintf("Jump rule %u -> %u\n", 456 duprintf("Jump rule %u -> %u\n",
443 pos, newpos); 457 pos, newpos);
@@ -470,27 +484,6 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i)
470} 484}
471 485
472static inline int 486static inline int
473standard_check(const struct ipt_entry_target *t,
474 unsigned int max_offset)
475{
476 struct ipt_standard_target *targ = (void *)t;
477
478 /* Check standard info. */
479 if (targ->verdict >= 0
480 && targ->verdict > max_offset - sizeof(struct ipt_entry)) {
481 duprintf("ipt_standard_check: bad verdict (%i)\n",
482 targ->verdict);
483 return 0;
484 }
485 if (targ->verdict < -NF_MAX_VERDICT - 1) {
486 duprintf("ipt_standard_check: bad negative verdict (%i)\n",
487 targ->verdict);
488 return 0;
489 }
490 return 1;
491}
492
493static inline int
494check_match(struct ipt_entry_match *m, 487check_match(struct ipt_entry_match *m,
495 const char *name, 488 const char *name,
496 const struct ipt_ip *ip, 489 const struct ipt_ip *ip,
@@ -576,12 +569,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
576 if (ret) 569 if (ret)
577 goto err; 570 goto err;
578 571
579 if (t->u.kernel.target == &ipt_standard_target) { 572 if (t->u.kernel.target->checkentry
580 if (!standard_check(t, size)) {
581 ret = -EINVAL;
582 goto err;
583 }
584 } else if (t->u.kernel.target->checkentry
585 && !t->u.kernel.target->checkentry(name, e, target, t->data, 573 && !t->u.kernel.target->checkentry(name, e, target, t->data,
586 e->comefrom)) { 574 e->comefrom)) {
587 duprintf("ip_tables: check failed for `%s'.\n", 575 duprintf("ip_tables: check failed for `%s'.\n",
@@ -718,17 +706,19 @@ translate_table(const char *name,
718 } 706 }
719 } 707 }
720 708
709 if (!mark_source_chains(newinfo, valid_hooks, entry0))
710 return -ELOOP;
711
721 /* Finally, each sanity check must pass */ 712 /* Finally, each sanity check must pass */
722 i = 0; 713 i = 0;
723 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, 714 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
724 check_entry, name, size, &i); 715 check_entry, name, size, &i);
725 716
726 if (ret != 0) 717 if (ret != 0) {
727 goto cleanup; 718 IPT_ENTRY_ITERATE(entry0, newinfo->size,
728 719 cleanup_entry, &i);
729 ret = -ELOOP; 720 return ret;
730 if (!mark_source_chains(newinfo, valid_hooks, entry0)) 721 }
731 goto cleanup;
732 722
733 /* And one copy for every other CPU */ 723 /* And one copy for every other CPU */
734 for_each_possible_cpu(i) { 724 for_each_possible_cpu(i) {
@@ -736,9 +726,6 @@ translate_table(const char *name,
736 memcpy(newinfo->entries[i], entry0, newinfo->size); 726 memcpy(newinfo->entries[i], entry0, newinfo->size);
737 } 727 }
738 728
739 return 0;
740cleanup:
741 IPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
742 return ret; 729 return ret;
743} 730}
744 731
@@ -1591,18 +1578,13 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
1591 if (ret) 1578 if (ret)
1592 goto err; 1579 goto err;
1593 1580
1594 ret = -EINVAL; 1581 if (t->u.kernel.target->checkentry
1595 if (t->u.kernel.target == &ipt_standard_target) {
1596 if (!standard_check(t, *size))
1597 goto err;
1598 } else if (t->u.kernel.target->checkentry
1599 && !t->u.kernel.target->checkentry(name, de, target, 1582 && !t->u.kernel.target->checkentry(name, de, target,
1600 t->data, de->comefrom)) { 1583 t->data, de->comefrom)) {
1601 duprintf("ip_tables: compat: check failed for `%s'.\n", 1584 duprintf("ip_tables: compat: check failed for `%s'.\n",
1602 t->u.kernel.target->name); 1585 t->u.kernel.target->name);
1603 goto err; 1586 ret = -EINVAL;
1604 } 1587 }
1605 ret = 0;
1606err: 1588err:
1607 return ret; 1589 return ret;
1608} 1590}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index f63fb86d7c7b..4eec4b3988b8 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -440,6 +440,13 @@ mark_source_chains(struct xt_table_info *newinfo,
440 && unconditional(&e->ipv6)) { 440 && unconditional(&e->ipv6)) {
441 unsigned int oldpos, size; 441 unsigned int oldpos, size;
442 442
443 if (t->verdict < -NF_MAX_VERDICT - 1) {
444 duprintf("mark_source_chains: bad "
445 "negative verdict (%i)\n",
446 t->verdict);
447 return 0;
448 }
449
443 /* Return: backtrack through the last 450 /* Return: backtrack through the last
444 big jump. */ 451 big jump. */
445 do { 452 do {
@@ -477,6 +484,13 @@ mark_source_chains(struct xt_table_info *newinfo,
477 if (strcmp(t->target.u.user.name, 484 if (strcmp(t->target.u.user.name,
478 IP6T_STANDARD_TARGET) == 0 485 IP6T_STANDARD_TARGET) == 0
479 && newpos >= 0) { 486 && newpos >= 0) {
487 if (newpos > newinfo->size -
488 sizeof(struct ip6t_entry)) {
489 duprintf("mark_source_chains: "
490 "bad verdict (%i)\n",
491 newpos);
492 return 0;
493 }
480 /* This a jump; chase it. */ 494 /* This a jump; chase it. */
481 duprintf("Jump rule %u -> %u\n", 495 duprintf("Jump rule %u -> %u\n",
482 pos, newpos); 496 pos, newpos);
@@ -509,27 +523,6 @@ cleanup_match(struct ip6t_entry_match *m, unsigned int *i)
509} 523}
510 524
511static inline int 525static inline int
512standard_check(const struct ip6t_entry_target *t,
513 unsigned int max_offset)
514{
515 struct ip6t_standard_target *targ = (void *)t;
516
517 /* Check standard info. */
518 if (targ->verdict >= 0
519 && targ->verdict > max_offset - sizeof(struct ip6t_entry)) {
520 duprintf("ip6t_standard_check: bad verdict (%i)\n",
521 targ->verdict);
522 return 0;
523 }
524 if (targ->verdict < -NF_MAX_VERDICT - 1) {
525 duprintf("ip6t_standard_check: bad negative verdict (%i)\n",
526 targ->verdict);
527 return 0;
528 }
529 return 1;
530}
531
532static inline int
533check_match(struct ip6t_entry_match *m, 526check_match(struct ip6t_entry_match *m,
534 const char *name, 527 const char *name,
535 const struct ip6t_ip6 *ipv6, 528 const struct ip6t_ip6 *ipv6,
@@ -616,12 +609,7 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
616 if (ret) 609 if (ret)
617 goto err; 610 goto err;
618 611
619 if (t->u.kernel.target == &ip6t_standard_target) { 612 if (t->u.kernel.target->checkentry
620 if (!standard_check(t, size)) {
621 ret = -EINVAL;
622 goto err;
623 }
624 } else if (t->u.kernel.target->checkentry
625 && !t->u.kernel.target->checkentry(name, e, target, t->data, 613 && !t->u.kernel.target->checkentry(name, e, target, t->data,
626 e->comefrom)) { 614 e->comefrom)) {
627 duprintf("ip_tables: check failed for `%s'.\n", 615 duprintf("ip_tables: check failed for `%s'.\n",
@@ -758,17 +746,19 @@ translate_table(const char *name,
758 } 746 }
759 } 747 }
760 748
749 if (!mark_source_chains(newinfo, valid_hooks, entry0))
750 return -ELOOP;
751
761 /* Finally, each sanity check must pass */ 752 /* Finally, each sanity check must pass */
762 i = 0; 753 i = 0;
763 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, 754 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
764 check_entry, name, size, &i); 755 check_entry, name, size, &i);
765 756
766 if (ret != 0) 757 if (ret != 0) {
767 goto cleanup; 758 IP6T_ENTRY_ITERATE(entry0, newinfo->size,
768 759 cleanup_entry, &i);
769 ret = -ELOOP; 760 return ret;
770 if (!mark_source_chains(newinfo, valid_hooks, entry0)) 761 }
771 goto cleanup;
772 762
773 /* And one copy for every other CPU */ 763 /* And one copy for every other CPU */
774 for_each_possible_cpu(i) { 764 for_each_possible_cpu(i) {
@@ -777,9 +767,6 @@ translate_table(const char *name,
777 } 767 }
778 768
779 return 0; 769 return 0;
780cleanup:
781 IP6T_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
782 return ret;
783} 770}
784 771
785/* Gets counters. */ 772/* Gets counters. */