diff options
| author | Rusty Russell <rusty@rustcorp.com.au> | 2003-04-27 12:28:47 -0700 |
|---|---|---|
| committer | David S. Miller <davem@nuts.ninka.net> | 2003-04-27 12:28:47 -0700 |
| commit | ce0041ef255121563bab8b747c1440c1bbf93ddf (patch) | |
| tree | 123967aebfb5f491257e5b638597c49563364049 | |
| parent | 90c1d5ebfecd53b5aac187777988d577b3f2e19c (diff) | |
[NETFILTER]: Add owner field to nf_hook_ops.
Adds an owner field to nf_hook_ops, and use it to hold the hook in place
for queued packets.
| -rw-r--r-- | include/linux/netfilter.h | 1 | ||||
| -rw-r--r-- | net/bridge/br_netfilter.c | 18 | ||||
| -rw-r--r-- | net/bridge/netfilter/ebtable_filter.c | 3 | ||||
| -rw-r--r-- | net/bridge/netfilter/ebtable_nat.c | 3 | ||||
| -rw-r--r-- | net/core/netfilter.c | 49 | ||||
| -rw-r--r-- | net/ipv4/netfilter/arptable_filter.c | 2 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_conntrack_standalone.c | 4 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_fw_compat.c | 4 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_nat_standalone.c | 4 | ||||
| -rw-r--r-- | net/ipv4/netfilter/iptable_filter.c | 3 | ||||
| -rw-r--r-- | net/ipv4/netfilter/iptable_mangle.c | 5 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6table_filter.c | 3 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6table_mangle.c | 5 | ||||
| -rw-r--r-- | net/sched/sch_ingress.c | 1 |
14 files changed, 75 insertions, 30 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index b1ae5446b0e2..3f3f29f11ad8 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -47,6 +47,7 @@ struct nf_hook_ops /* User fills in from here down. */ nf_hookfn *hook; + struct module *owner; int pf; int hooknum; /* Hooks are ordered in ascending priority. */ diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index e0a61b6b9ac2..9cf424a9b0b0 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -574,15 +574,15 @@ static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb, * ip_refrag() can return NF_STOLEN. */ static struct nf_hook_ops br_nf_ops[] = { - { { NULL, NULL }, br_nf_pre_routing, PF_BRIDGE, NF_BR_PRE_ROUTING, NF_BR_PRI_BRNF }, - { { NULL, NULL }, br_nf_local_in, PF_BRIDGE, NF_BR_LOCAL_IN, NF_BR_PRI_BRNF }, - { { NULL, NULL }, br_nf_forward, PF_BRIDGE, NF_BR_FORWARD, NF_BR_PRI_BRNF }, - { { NULL, NULL }, br_nf_local_out, PF_BRIDGE, NF_BR_LOCAL_OUT, NF_BR_PRI_FIRST }, - { { NULL, NULL }, br_nf_post_routing, PF_BRIDGE, NF_BR_POST_ROUTING, NF_BR_PRI_LAST }, - { { NULL, NULL }, ipv4_sabotage_in, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_FIRST }, - { { NULL, NULL }, ipv4_sabotage_out, PF_INET, NF_IP_FORWARD, NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD }, - { { NULL, NULL }, ipv4_sabotage_out, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT }, - { { NULL, NULL }, ipv4_sabotage_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_FIRST } + { { NULL, NULL }, br_nf_pre_routing, THIS_MODULE, PF_BRIDGE, NF_BR_PRE_ROUTING, NF_BR_PRI_BRNF }, + { { NULL, NULL }, br_nf_local_in, THIS_MODULE, PF_BRIDGE, NF_BR_LOCAL_IN, NF_BR_PRI_BRNF }, + { { NULL, NULL }, br_nf_forward, THIS_MODULE, PF_BRIDGE, NF_BR_FORWARD, NF_BR_PRI_BRNF }, + { { NULL, NULL }, br_nf_local_out, THIS_MODULE, PF_BRIDGE, NF_BR_LOCAL_OUT, NF_BR_PRI_FIRST }, + { { NULL, NULL }, br_nf_post_routing, THIS_MODULE, PF_BRIDGE, NF_BR_POST_ROUTING, NF_BR_PRI_LAST }, + { { NULL, NULL }, ipv4_sabotage_in, THIS_MODULE, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_FIRST }, + { { NULL, NULL }, ipv4_sabotage_out, THIS_MODULE, PF_INET, NF_IP_FORWARD, NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD }, + { { NULL, NULL }, ipv4_sabotage_out, THIS_MODULE, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT }, + { { NULL, NULL }, ipv4_sabotage_out, THIS_MODULE, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_FIRST } }; #define NUMHOOKS (sizeof(br_nf_ops)/sizeof(br_nf_ops[0])) diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index ce60c4ea527d..ee9394bb5e01 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c @@ -70,18 +70,21 @@ ebt_hook (unsigned int hook, struct sk_buff **pskb, const struct net_device *in, static struct nf_hook_ops ebt_ops_filter[] = { { .hook = ebt_hook, + .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_LOCAL_IN, .priority = NF_BR_PRI_FILTER_BRIDGED, }, { .hook = ebt_hook, + .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_FORWARD, .priority = NF_BR_PRI_FILTER_BRIDGED, }, { .hook = ebt_hook, + .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_LOCAL_OUT, .priority = NF_BR_PRI_FILTER_OTHER, diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index 8dcf54528612..ca39dac72f66 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c @@ -76,18 +76,21 @@ ebt_nat_src(unsigned int hook, struct sk_buff **pskb, const struct net_device *i static struct nf_hook_ops ebt_ops_nat[] = { { .hook = ebt_nat_dst, + .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_LOCAL_OUT, .priority = NF_BR_PRI_NAT_DST_OTHER, }, { .hook = ebt_nat_src, + .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_POST_ROUTING, .priority = NF_BR_PRI_NAT_SRC, }, { .hook = ebt_nat_dst, + .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_PRE_ROUTING, .priority = NF_BR_PRI_NAT_DST_BRIDGED, diff --git a/net/core/netfilter.c b/net/core/netfilter.c index 706f4ec6cceb..463490a7ea9a 100644 --- a/net/core/netfilter.c +++ b/net/core/netfilter.c @@ -350,6 +350,8 @@ static unsigned int nf_iterate(struct list_head *head, if (hook_thresh > elem->priority) continue; + /* Optimization: we don't need to hold module + reference here, since function can't sleep. --RR */ switch (elem->hook(hook, skb, indev, outdev, okfn)) { case NF_QUEUE: return NF_QUEUE; @@ -408,12 +410,12 @@ int nf_unregister_queue_handler(int pf) * Any packet that leaves via this function must come back * through nf_reinject(). */ -static void nf_queue(struct sk_buff *skb, - struct list_head *elem, - int pf, unsigned int hook, - struct net_device *indev, - struct net_device *outdev, - int (*okfn)(struct sk_buff *)) +static int nf_queue(struct sk_buff *skb, + struct list_head *elem, + int pf, unsigned int hook, + struct net_device *indev, + struct net_device *outdev, + int (*okfn)(struct sk_buff *)) { int status; struct nf_info *info; @@ -422,9 +424,10 @@ static void nf_queue(struct sk_buff *skb, struct net_device *physoutdev = NULL; #endif + /* QUEUE == DROP if noone is waiting, to be safe. */ if (!queue_handler[pf].outfn) { kfree_skb(skb); - return; + return 1; } info = kmalloc(sizeof(*info), GFP_ATOMIC); @@ -433,12 +436,16 @@ static void nf_queue(struct sk_buff *skb, printk(KERN_ERR "OOM queueing packet %p\n", skb); kfree_skb(skb); - return; + return 1; } *info = (struct nf_info) { (struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn }; + /* If it's going away, ignore hook. */ + if (!try_module_get(info->elem->owner)) + return 0; + /* Bump dev refs so they don't vanish while packet is out */ if (indev) dev_hold(indev); if (outdev) dev_hold(outdev); @@ -461,10 +468,12 @@ static void nf_queue(struct sk_buff *skb, if (physindev) dev_put(physindev); if (physoutdev) dev_put(physoutdev); #endif + module_put(info->elem->owner); kfree(info); kfree_skb(skb); - return; + return 1; } + return 1; } int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb, @@ -497,11 +506,13 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb, #endif elem = &nf_hooks[pf][hook]; + next_hook: verdict = nf_iterate(&nf_hooks[pf][hook], &skb, hook, indev, outdev, &elem, okfn, hook_thresh); if (verdict == NF_QUEUE) { NFDEBUG("nf_hook: Verdict = QUEUE.\n"); - nf_queue(skb, elem, pf, hook, indev, outdev, okfn); + if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn)) + goto next_hook; } switch (verdict) { @@ -527,15 +538,9 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, /* We don't have BR_NETPROTO_LOCK here */ br_read_lock_bh(BR_NETPROTO_LOCK); - for (i = nf_hooks[info->pf][info->hook].next; i != elem; i = i->next) { - if (i == &nf_hooks[info->pf][info->hook]) { - /* The module which sent it to userspace is gone. */ - NFDEBUG("%s: module disappeared, dropping packet.\n", - __FUNCTION__); - verdict = NF_DROP; - break; - } - } + + /* Drop reference to owner of hook which queued us. */ + module_put(info->elem->owner); /* Continue traversal iff userspace said ok... */ if (verdict == NF_REPEAT) { @@ -544,6 +549,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, } if (verdict == NF_ACCEPT) { + next_hook: verdict = nf_iterate(&nf_hooks[info->pf][info->hook], &skb, info->hook, info->indev, info->outdev, &elem, @@ -556,8 +562,9 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, break; case NF_QUEUE: - nf_queue(skb, elem, info->pf, info->hook, - info->indev, info->outdev, info->okfn); + if (!nf_queue(skb, elem, info->pf, info->hook, + info->indev, info->outdev, info->okfn)) + goto next_hook; break; case NF_DROP: diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index 0519b7930496..3387279f6908 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -133,11 +133,13 @@ static unsigned int arpt_hook(unsigned int hook, static struct nf_hook_ops arpt_ops[] = { { .hook = arpt_hook, + .owner = THIS_MODULE, .pf = NF_ARP, .hooknum = NF_ARP_IN, }, { .hook = arpt_hook, + .owner = THIS_MODULE, .pf = NF_ARP, .hooknum = NF_ARP_OUT, } diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index c939c329ecf1..d1704ed5723b 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -227,6 +227,7 @@ static unsigned int ip_conntrack_local(unsigned int hooknum, make it the first hook. */ static struct nf_hook_ops ip_conntrack_in_ops = { .hook = ip_conntrack_in, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_PRE_ROUTING, .priority = NF_IP_PRI_CONNTRACK, @@ -234,6 +235,7 @@ static struct nf_hook_ops ip_conntrack_in_ops = { static struct nf_hook_ops ip_conntrack_local_out_ops = { .hook = ip_conntrack_local, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_LOCAL_OUT, .priority = NF_IP_PRI_CONNTRACK, @@ -242,6 +244,7 @@ static struct nf_hook_ops ip_conntrack_local_out_ops = { /* Refragmenter; last chance. */ static struct nf_hook_ops ip_conntrack_out_ops = { .hook = ip_refrag, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_POST_ROUTING, .priority = NF_IP_PRI_LAST, @@ -249,6 +252,7 @@ static struct nf_hook_ops ip_conntrack_out_ops = { static struct nf_hook_ops ip_conntrack_local_in_ops = { .hook = ip_confirm, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_LOCAL_IN, .priority = NF_IP_PRI_LAST-1, diff --git a/net/ipv4/netfilter/ip_fw_compat.c b/net/ipv4/netfilter/ip_fw_compat.c index bc08c07dbb2b..470784e138ab 100644 --- a/net/ipv4/netfilter/ip_fw_compat.c +++ b/net/ipv4/netfilter/ip_fw_compat.c @@ -226,6 +226,7 @@ static int sock_fn(struct sock *sk, int optval, void *user, unsigned int len) static struct nf_hook_ops preroute_ops = { .hook = fw_in, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_PRE_ROUTING, .priority = NF_IP_PRI_FILTER, @@ -233,6 +234,7 @@ static struct nf_hook_ops preroute_ops = { static struct nf_hook_ops postroute_ops = { .hook = fw_in, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_POST_ROUTING, .priority = NF_IP_PRI_FILTER, @@ -240,6 +242,7 @@ static struct nf_hook_ops postroute_ops = { static struct nf_hook_ops forward_ops = { .hook = fw_in, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_FORWARD, .priority = NF_IP_PRI_FILTER, @@ -247,6 +250,7 @@ static struct nf_hook_ops forward_ops = { static struct nf_hook_ops local_in_ops = { .hook = fw_confirm, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_LOCAL_IN, .priority = NF_IP_PRI_LAST - 1, diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 5d84a14e8e82..69cf5c6ae27a 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -238,6 +238,7 @@ ip_nat_local_fn(unsigned int hooknum, /* Before packet filtering, change destination */ static struct nf_hook_ops ip_nat_in_ops = { .hook = ip_nat_fn, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_PRE_ROUTING, .priority = NF_IP_PRI_NAT_DST, @@ -246,6 +247,7 @@ static struct nf_hook_ops ip_nat_in_ops = { /* After packet filtering, change source */ static struct nf_hook_ops ip_nat_out_ops = { .hook = ip_nat_out, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_POST_ROUTING, .priority = NF_IP_PRI_NAT_SRC, @@ -254,6 +256,7 @@ static struct nf_hook_ops ip_nat_out_ops = { /* Before packet filtering, change destination */ static struct nf_hook_ops ip_nat_local_out_ops = { .hook = ip_nat_local_fn, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_LOCAL_OUT, .priority = NF_IP_PRI_NAT_DST, @@ -262,6 +265,7 @@ static struct nf_hook_ops ip_nat_local_out_ops = { #ifdef CONFIG_IP_NF_NAT_LOCAL static struct nf_hook_ops ip_nat_local_in_ops = { .hook = ip_nat_fn, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_LOCAL_IN, .priority = NF_IP_PRI_NAT_SRC, diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 81f13ed42c5a..05e7798d2973 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -125,18 +125,21 @@ ipt_local_out_hook(unsigned int hook, static struct nf_hook_ops ipt_ops[] = { { .hook = ipt_hook, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_LOCAL_IN, .priority = NF_IP_PRI_FILTER, }, { .hook = ipt_hook, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_FORWARD, .priority = NF_IP_PRI_FILTER, }, { .hook = ipt_local_out_hook, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_LOCAL_OUT, .priority = NF_IP_PRI_FILTER, diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 3c57d06e48fc..65232b030090 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -178,30 +178,35 @@ ipt_local_hook(unsigned int hook, static struct nf_hook_ops ipt_ops[] = { { .hook = ipt_route_hook, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_PRE_ROUTING, .priority = NF_IP_PRI_MANGLE, }, { .hook = ipt_route_hook, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_LOCAL_IN, .priority = NF_IP_PRI_MANGLE, }, { .hook = ipt_route_hook, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_FORWARD, .priority = NF_IP_PRI_MANGLE, }, { .hook = ipt_local_hook, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_LOCAL_OUT, .priority = NF_IP_PRI_MANGLE, }, { .hook = ipt_route_hook, + .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_POST_ROUTING, .priority = NF_IP_PRI_MANGLE, diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index e720778b3d32..dc034cb823f1 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -123,18 +123,21 @@ ip6t_local_out_hook(unsigned int hook, static struct nf_hook_ops ip6t_ops[] = { { .hook = ip6t_hook, + .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_IP6_LOCAL_IN, .priority = NF_IP6_PRI_FILTER, }, { .hook = ip6t_hook, + .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_IP6_FORWARD, .priority = NF_IP6_PRI_FILTER, }, { .hook = ip6t_local_out_hook, + .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_IP6_LOCAL_OUT, .priority = NF_IP6_PRI_FILTER, diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 848ce9c8b699..08b0c24b27a1 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -186,30 +186,35 @@ ip6t_local_hook(unsigned int hook, static struct nf_hook_ops ip6t_ops[] = { { .hook = ip6t_route_hook, + .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_IP6_PRE_ROUTING, .priority = NF_IP6_PRI_MANGLE, }, { .hook = ip6t_local_hook, + .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_IP6_LOCAL_IN, .priority = NF_IP6_PRI_MANGLE, }, { .hook = ip6t_route_hook, + .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_IP6_FORWARD, .priority = NF_IP6_PRI_MANGLE, }, { .hook = ip6t_local_hook, + .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_IP6_LOCAL_OUT, .priority = NF_IP6_PRI_MANGLE, }, { .hook = ip6t_route_hook, + .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_IP6_POST_ROUTING, .priority = NF_IP6_PRI_MANGLE, diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index c3457f94eca6..48a63bae0124 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c @@ -241,6 +241,7 @@ static struct nf_hook_ops ing_ops = { { NULL, NULL}, ing_hook, + THIS_MODULE, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_FILTER + 1 |
