From ae5718fb3dd0a11a4c9a061bf86417d52d58a6b3 Mon Sep 17 00:00:00 2001 From: Martin Josefsson Date: Wed, 29 Nov 2006 02:35:08 +0100 Subject: [NETFILTER]: nf_conntrack: more sanity checks in protocol registration/unregistration Add some more sanity checks when registering/unregistering l3/l4 protocols. Signed-off-by: Martin Josefsson Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_l3proto.h | 2 +- include/net/netfilter/nf_conntrack_l4proto.h | 2 +- net/netfilter/nf_conntrack_core.c | 2 +- net/netfilter/nf_conntrack_proto.c | 55 +++++++++++++++++++++++++--- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index ffe23a1e0b9..11b4b29bfab 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -86,7 +86,7 @@ extern struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX]; /* Protocol registration. */ extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto); -extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto); +extern int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto); extern struct nf_conntrack_l3proto * nf_ct_l3proto_find_get(u_int16_t l3proto); diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index 0c6babd5439..5193e4857b1 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -102,7 +102,7 @@ extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p); /* Protocol registration. */ extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto); -extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto); +extern int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto); /* Generic netlink helpers */ extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb, diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 441a647b784..73615d32a80 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1198,7 +1198,7 @@ int __init nf_conntrack_init(void) /* Don't NEED lock here, but good form anyway. */ write_lock_bh(&nf_conntrack_lock); - for (i = 0; i < PF_MAX; i++) + for (i = 0; i < AF_MAX; i++) nf_ct_l3protos[i] = &nf_conntrack_l3proto_generic; write_unlock_bh(&nf_conntrack_lock); diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 330b9acc62d..a6a3b1ddd00 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c @@ -28,7 +28,7 @@ #include struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX] __read_mostly; -struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly; +struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX] __read_mostly; struct nf_conntrack_l4proto * __nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto) @@ -128,21 +128,40 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) { int ret = 0; + if (proto->l3proto >= AF_MAX) { + ret = -EBUSY; + goto out; + } + write_lock_bh(&nf_conntrack_lock); if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) { ret = -EBUSY; - goto out; + goto out_unlock; } nf_ct_l3protos[proto->l3proto] = proto; -out: - write_unlock_bh(&nf_conntrack_lock); +out_unlock: + write_unlock_bh(&nf_conntrack_lock); +out: return ret; } -void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) +int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) { + int ret = 0; + + if (proto->l3proto >= AF_MAX) { + ret = -EBUSY; + goto out; + } + write_lock_bh(&nf_conntrack_lock); + if (nf_ct_l3protos[proto->l3proto] != proto) { + write_unlock_bh(&nf_conntrack_lock); + ret = -EBUSY; + goto out; + } + nf_ct_l3protos[proto->l3proto] = &nf_conntrack_l3proto_generic; write_unlock_bh(&nf_conntrack_lock); @@ -151,6 +170,9 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) /* Remove all contrack entries for this protocol */ nf_ct_iterate_cleanup(kill_l3proto, proto); + +out: + return ret; } /* FIXME: Allow NULL functions and sub in pointers to generic for @@ -159,6 +181,11 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) { int ret = 0; + if (l4proto->l3proto >= PF_MAX) { + ret = -EBUSY; + goto out; + } + retry: write_lock_bh(&nf_conntrack_lock); if (nf_ct_protos[l4proto->l3proto]) { @@ -210,9 +237,22 @@ out: return ret; } -void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) +int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) { + int ret = 0; + + if (l4proto->l3proto >= PF_MAX) { + ret = -EBUSY; + goto out; + } + write_lock_bh(&nf_conntrack_lock); + if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] + != l4proto) { + write_unlock_bh(&nf_conntrack_lock); + ret = -EBUSY; + goto out; + } nf_ct_protos[l4proto->l3proto][l4proto->l4proto] = &nf_conntrack_l4proto_generic; write_unlock_bh(&nf_conntrack_lock); @@ -222,4 +262,7 @@ void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) /* Remove all contrack entries for this protocol */ nf_ct_iterate_cleanup(kill_l4proto, l4proto); + +out: + return ret; } -- cgit v1.2.3