diff options
author | Jan Engelhardt <jengelh@medozas.de> | 2008-10-08 05:35:17 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2008-10-08 05:35:17 -0400 |
commit | 367c679007fa4f990eb7ee381326ec59d8148b0e (patch) | |
tree | a543f22332eba9ef972ed8ea6e66448921671ef7 | |
parent | 147c3844ad381b58715a6ee2ea697594e3c06284 (diff) |
netfilter: xtables: do centralized checkentry call (1/2)
It used to be that {ip,ip6,etc}_tables called extension->checkentry
themselves, but this can be moved into the xtables core.
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | include/linux/netfilter/x_tables.h | 6 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtables.c | 24 | ||||
-rw-r--r-- | net/ipv4/netfilter/arp_tables.c | 10 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 23 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 23 | ||||
-rw-r--r-- | net/netfilter/x_tables.c | 12 | ||||
-rw-r--r-- | net/sched/act_ipt.c | 14 |
7 files changed, 45 insertions, 67 deletions
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 6989b22716e6..85aa42785a5e 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h | |||
@@ -330,10 +330,12 @@ extern void xt_unregister_matches(struct xt_match *match, unsigned int n); | |||
330 | 330 | ||
331 | extern int xt_check_match(const struct xt_match *match, unsigned short family, | 331 | extern int xt_check_match(const struct xt_match *match, unsigned short family, |
332 | unsigned int size, const char *table, unsigned int hook, | 332 | unsigned int size, const char *table, unsigned int hook, |
333 | unsigned short proto, int inv_proto); | 333 | unsigned short proto, int inv_proto, |
334 | const void *entry, void *matchinfo); | ||
334 | extern int xt_check_target(const struct xt_target *target, unsigned short family, | 335 | extern int xt_check_target(const struct xt_target *target, unsigned short family, |
335 | unsigned int size, const char *table, unsigned int hook, | 336 | unsigned int size, const char *table, unsigned int hook, |
336 | unsigned short proto, int inv_proto); | 337 | unsigned short proto, int inv_proto, |
338 | const void *entry, void *targinfo); | ||
337 | 339 | ||
338 | extern struct xt_table *xt_register_table(struct net *net, | 340 | extern struct xt_table *xt_register_table(struct net *net, |
339 | struct xt_table *table, | 341 | struct xt_table *table, |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 7d8ead52d25f..7ee72b71d3cb 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -340,15 +340,11 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e, | |||
340 | m->u.match = match; | 340 | m->u.match = match; |
341 | 341 | ||
342 | ret = xt_check_match(match, NFPROTO_BRIDGE, m->match_size, | 342 | ret = xt_check_match(match, NFPROTO_BRIDGE, m->match_size, |
343 | name, hookmask, e->ethproto, e->invflags & EBT_IPROTO); | 343 | name, hookmask, e->ethproto, e->invflags & EBT_IPROTO, |
344 | e, m->data); | ||
344 | if (ret < 0) { | 345 | if (ret < 0) { |
345 | module_put(match->me); | 346 | module_put(match->me); |
346 | return ret; | 347 | return ret; |
347 | } else if (match->checkentry != NULL && | ||
348 | !match->checkentry(name, e, NULL, m->data, hookmask)) { | ||
349 | module_put(match->me); | ||
350 | BUGPRINT("match->check failed\n"); | ||
351 | return -EINVAL; | ||
352 | } | 348 | } |
353 | 349 | ||
354 | (*cnt)++; | 350 | (*cnt)++; |
@@ -377,15 +373,11 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e, | |||
377 | w->u.watcher = watcher; | 373 | w->u.watcher = watcher; |
378 | 374 | ||
379 | ret = xt_check_target(watcher, NFPROTO_BRIDGE, w->watcher_size, | 375 | ret = xt_check_target(watcher, NFPROTO_BRIDGE, w->watcher_size, |
380 | name, hookmask, e->ethproto, e->invflags & EBT_IPROTO); | 376 | name, hookmask, e->ethproto, e->invflags & EBT_IPROTO, |
377 | e, w->data); | ||
381 | if (ret < 0) { | 378 | if (ret < 0) { |
382 | module_put(watcher->me); | 379 | module_put(watcher->me); |
383 | return ret; | 380 | return ret; |
384 | } else if (watcher->checkentry != NULL && | ||
385 | !watcher->checkentry(name, e, NULL, w->data, hookmask)) { | ||
386 | module_put(watcher->me); | ||
387 | BUGPRINT("watcher->check failed\n"); | ||
388 | return -EINVAL; | ||
389 | } | 381 | } |
390 | 382 | ||
391 | (*cnt)++; | 383 | (*cnt)++; |
@@ -692,15 +684,11 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, | |||
692 | } | 684 | } |
693 | 685 | ||
694 | ret = xt_check_target(target, NFPROTO_BRIDGE, t->target_size, | 686 | ret = xt_check_target(target, NFPROTO_BRIDGE, t->target_size, |
695 | name, hookmask, e->ethproto, e->invflags & EBT_IPROTO); | 687 | name, hookmask, e->ethproto, e->invflags & EBT_IPROTO, |
688 | e, t->data); | ||
696 | if (ret < 0) { | 689 | if (ret < 0) { |
697 | module_put(target->me); | 690 | module_put(target->me); |
698 | goto cleanup_watchers; | 691 | goto cleanup_watchers; |
699 | } else if (t->u.target->checkentry && | ||
700 | !t->u.target->checkentry(name, e, NULL, t->data, hookmask)) { | ||
701 | module_put(t->u.target->me); | ||
702 | ret = -EINVAL; | ||
703 | goto cleanup_watchers; | ||
704 | } | 692 | } |
705 | (*cnt)++; | 693 | (*cnt)++; |
706 | return 0; | 694 | return 0; |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index b4a9a1799c94..ae525a9afbec 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -465,15 +465,13 @@ static inline int check_target(struct arpt_entry *e, const char *name) | |||
465 | 465 | ||
466 | ret = xt_check_target(target, NFPROTO_ARP, | 466 | ret = xt_check_target(target, NFPROTO_ARP, |
467 | t->u.target_size - sizeof(*t), | 467 | t->u.target_size - sizeof(*t), |
468 | name, e->comefrom, 0, 0); | 468 | name, e->comefrom, 0, 0, e, t->data); |
469 | if (!ret && t->u.kernel.target->checkentry | 469 | if (ret < 0) { |
470 | && !t->u.kernel.target->checkentry(name, e, target, t->data, | ||
471 | e->comefrom)) { | ||
472 | duprintf("arp_tables: check failed for `%s'.\n", | 470 | duprintf("arp_tables: check failed for `%s'.\n", |
473 | t->u.kernel.target->name); | 471 | t->u.kernel.target->name); |
474 | ret = -EINVAL; | 472 | return ret; |
475 | } | 473 | } |
476 | return ret; | 474 | return 0; |
477 | } | 475 | } |
478 | 476 | ||
479 | static inline int | 477 | static inline int |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 4e7c719445c2..b4c74a7a807c 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -616,17 +616,14 @@ check_match(struct ipt_entry_match *m, const char *name, | |||
616 | match = m->u.kernel.match; | 616 | match = m->u.kernel.match; |
617 | ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m), | 617 | ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m), |
618 | name, hookmask, ip->proto, | 618 | name, hookmask, ip->proto, |
619 | ip->invflags & IPT_INV_PROTO); | 619 | ip->invflags & IPT_INV_PROTO, ip, m->data); |
620 | if (!ret && m->u.kernel.match->checkentry | 620 | if (ret < 0) { |
621 | && !m->u.kernel.match->checkentry(name, ip, match, m->data, | ||
622 | hookmask)) { | ||
623 | duprintf("ip_tables: check failed for `%s'.\n", | 621 | duprintf("ip_tables: check failed for `%s'.\n", |
624 | m->u.kernel.match->name); | 622 | m->u.kernel.match->name); |
625 | ret = -EINVAL; | 623 | return ret; |
626 | } | 624 | } |
627 | if (!ret) | 625 | ++*i; |
628 | (*i)++; | 626 | return 0; |
629 | return ret; | ||
630 | } | 627 | } |
631 | 628 | ||
632 | static int | 629 | static int |
@@ -668,15 +665,13 @@ static int check_target(struct ipt_entry *e, const char *name) | |||
668 | target = t->u.kernel.target; | 665 | target = t->u.kernel.target; |
669 | ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), | 666 | ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), |
670 | name, e->comefrom, e->ip.proto, | 667 | name, e->comefrom, e->ip.proto, |
671 | e->ip.invflags & IPT_INV_PROTO); | 668 | e->ip.invflags & IPT_INV_PROTO, e, t->data); |
672 | if (!ret && t->u.kernel.target->checkentry | 669 | if (ret < 0) { |
673 | && !t->u.kernel.target->checkentry(name, e, target, t->data, | ||
674 | e->comefrom)) { | ||
675 | duprintf("ip_tables: check failed for `%s'.\n", | 670 | duprintf("ip_tables: check failed for `%s'.\n", |
676 | t->u.kernel.target->name); | 671 | t->u.kernel.target->name); |
677 | ret = -EINVAL; | 672 | return ret; |
678 | } | 673 | } |
679 | return ret; | 674 | return 0; |
680 | } | 675 | } |
681 | 676 | ||
682 | static int | 677 | static int |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 0b4557e03431..12c41b8d365b 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -642,17 +642,14 @@ static int check_match(struct ip6t_entry_match *m, const char *name, | |||
642 | match = m->u.kernel.match; | 642 | match = m->u.kernel.match; |
643 | ret = xt_check_match(match, AF_INET6, m->u.match_size - sizeof(*m), | 643 | ret = xt_check_match(match, AF_INET6, m->u.match_size - sizeof(*m), |
644 | name, hookmask, ipv6->proto, | 644 | name, hookmask, ipv6->proto, |
645 | ipv6->invflags & IP6T_INV_PROTO); | 645 | ipv6->invflags & IP6T_INV_PROTO, ipv6, m->data); |
646 | if (!ret && m->u.kernel.match->checkentry | 646 | if (ret < 0) { |
647 | && !m->u.kernel.match->checkentry(name, ipv6, match, m->data, | ||
648 | hookmask)) { | ||
649 | duprintf("ip_tables: check failed for `%s'.\n", | 647 | duprintf("ip_tables: check failed for `%s'.\n", |
650 | m->u.kernel.match->name); | 648 | m->u.kernel.match->name); |
651 | ret = -EINVAL; | 649 | return ret; |
652 | } | 650 | } |
653 | if (!ret) | 651 | ++*i; |
654 | (*i)++; | 652 | return 0; |
655 | return ret; | ||
656 | } | 653 | } |
657 | 654 | ||
658 | static int | 655 | static int |
@@ -694,15 +691,13 @@ static int check_target(struct ip6t_entry *e, const char *name) | |||
694 | target = t->u.kernel.target; | 691 | target = t->u.kernel.target; |
695 | ret = xt_check_target(target, AF_INET6, t->u.target_size - sizeof(*t), | 692 | ret = xt_check_target(target, AF_INET6, t->u.target_size - sizeof(*t), |
696 | name, e->comefrom, e->ipv6.proto, | 693 | name, e->comefrom, e->ipv6.proto, |
697 | e->ipv6.invflags & IP6T_INV_PROTO); | 694 | e->ipv6.invflags & IP6T_INV_PROTO, e, t->data); |
698 | if (!ret && t->u.kernel.target->checkentry | 695 | if (ret < 0) { |
699 | && !t->u.kernel.target->checkentry(name, e, target, t->data, | ||
700 | e->comefrom)) { | ||
701 | duprintf("ip_tables: check failed for `%s'.\n", | 696 | duprintf("ip_tables: check failed for `%s'.\n", |
702 | t->u.kernel.target->name); | 697 | t->u.kernel.target->name); |
703 | ret = -EINVAL; | 698 | return ret; |
704 | } | 699 | } |
705 | return ret; | 700 | return 0; |
706 | } | 701 | } |
707 | 702 | ||
708 | static int | 703 | static int |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 3b1fc40cc274..d1f2fb3e8f2d 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -323,7 +323,8 @@ EXPORT_SYMBOL_GPL(xt_find_revision); | |||
323 | 323 | ||
324 | int xt_check_match(const struct xt_match *match, unsigned short family, | 324 | int xt_check_match(const struct xt_match *match, unsigned short family, |
325 | unsigned int size, const char *table, unsigned int hook_mask, | 325 | unsigned int size, const char *table, unsigned int hook_mask, |
326 | unsigned short proto, int inv_proto) | 326 | unsigned short proto, int inv_proto, const void *entry, |
327 | void *matchinfo) | ||
327 | { | 328 | { |
328 | if (XT_ALIGN(match->matchsize) != size && | 329 | if (XT_ALIGN(match->matchsize) != size && |
329 | match->matchsize != -1) { | 330 | match->matchsize != -1) { |
@@ -351,6 +352,9 @@ int xt_check_match(const struct xt_match *match, unsigned short family, | |||
351 | xt_prefix[family], match->name, match->proto); | 352 | xt_prefix[family], match->name, match->proto); |
352 | return -EINVAL; | 353 | return -EINVAL; |
353 | } | 354 | } |
355 | if (match->checkentry != NULL && | ||
356 | !match->checkentry(table, entry, match, matchinfo, hook_mask)) | ||
357 | return -EINVAL; | ||
354 | return 0; | 358 | return 0; |
355 | } | 359 | } |
356 | EXPORT_SYMBOL_GPL(xt_check_match); | 360 | EXPORT_SYMBOL_GPL(xt_check_match); |
@@ -469,7 +473,8 @@ EXPORT_SYMBOL_GPL(xt_compat_match_to_user); | |||
469 | 473 | ||
470 | int xt_check_target(const struct xt_target *target, unsigned short family, | 474 | int xt_check_target(const struct xt_target *target, unsigned short family, |
471 | unsigned int size, const char *table, unsigned int hook_mask, | 475 | unsigned int size, const char *table, unsigned int hook_mask, |
472 | unsigned short proto, int inv_proto) | 476 | unsigned short proto, int inv_proto, const void *entry, |
477 | void *targinfo) | ||
473 | { | 478 | { |
474 | if (XT_ALIGN(target->targetsize) != size) { | 479 | if (XT_ALIGN(target->targetsize) != size) { |
475 | printk("%s_tables: %s target: invalid size %Zu != %u\n", | 480 | printk("%s_tables: %s target: invalid size %Zu != %u\n", |
@@ -493,6 +498,9 @@ int xt_check_target(const struct xt_target *target, unsigned short family, | |||
493 | xt_prefix[family], target->name, target->proto); | 498 | xt_prefix[family], target->name, target->proto); |
494 | return -EINVAL; | 499 | return -EINVAL; |
495 | } | 500 | } |
501 | if (target->checkentry != NULL && | ||
502 | !target->checkentry(table, entry, target, targinfo, hook_mask)) | ||
503 | return -EINVAL; | ||
496 | return 0; | 504 | return 0; |
497 | } | 505 | } |
498 | EXPORT_SYMBOL_GPL(xt_check_target); | 506 | EXPORT_SYMBOL_GPL(xt_check_target); |
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index d1263b3c96c3..79ea19375caf 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
@@ -51,20 +51,12 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int | |||
51 | t->u.kernel.target = target; | 51 | t->u.kernel.target = target; |
52 | 52 | ||
53 | ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), | 53 | ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), |
54 | table, hook, 0, 0); | 54 | table, hook, 0, 0, NULL, t->data); |
55 | if (ret) { | 55 | if (ret < 0) { |
56 | module_put(t->u.kernel.target->me); | 56 | module_put(t->u.kernel.target->me); |
57 | return ret; | 57 | return ret; |
58 | } | 58 | } |
59 | if (t->u.kernel.target->checkentry | 59 | return 0; |
60 | && !t->u.kernel.target->checkentry(table, NULL, | ||
61 | t->u.kernel.target, t->data, | ||
62 | hook)) { | ||
63 | module_put(t->u.kernel.target->me); | ||
64 | ret = -EINVAL; | ||
65 | } | ||
66 | |||
67 | return ret; | ||
68 | } | 60 | } |
69 | 61 | ||
70 | static void ipt_destroy_target(struct ipt_entry_target *t) | 62 | static void ipt_destroy_target(struct ipt_entry_target *t) |