diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/arp_tables.c | 48 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 68 |
2 files changed, 49 insertions, 67 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, | |||
426 | static inline int standard_check(const struct arpt_entry_target *t, | 441 | static 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; | ||
651 | cleanup: | ||
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 | ||
472 | static inline int | 486 | static inline int |
473 | standard_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 | |||
493 | static inline int | ||
494 | check_match(struct ipt_entry_match *m, | 487 | check_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; | ||
740 | cleanup: | ||
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; | ||
1606 | err: | 1588 | err: |
1607 | return ret; | 1589 | return ret; |
1608 | } | 1590 | } |