diff options
author | Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | 2005-05-05 22:35:15 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-05-05 22:35:15 +0200 |
commit | 476e19cfa131e2b6eedc4017b627cdc4ca419ffb (patch) | |
tree | 8c6881affa0d20a3ce2dd8d4f9a5b0ba588916c5 /net | |
parent | [DECNET]: Fix build after C99 netlink initializer change. (diff) | |
download | linux-476e19cfa131e2b6eedc4017b627cdc4ca419ffb.tar.xz linux-476e19cfa131e2b6eedc4017b627cdc4ca419ffb.zip |
[IPV6]: Fix OOPS when using IPV6_ADDRFORM
This causes sk->sk_prot to change, which makes the socket
release free the sock into the wrong SLAB cache. Fix this
by introducing sk_prot_creator so that we always remember
where the sock came from.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/sock.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index 98171ddd7e7d..92c0676e4708 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -635,7 +635,11 @@ struct sock *sk_alloc(int family, int priority, struct proto *prot, int zero_it) if (zero_it) { memset(sk, 0, prot->obj_size); sk->sk_family = family; - sk->sk_prot = prot; + /* + * See comment in struct sock definition to understand + * why we need sk_prot_creator -acme + */ + sk->sk_prot = sk->sk_prot_creator = prot; sock_lock_init(sk); } @@ -654,7 +658,7 @@ struct sock *sk_alloc(int family, int priority, struct proto *prot, int zero_it) void sk_free(struct sock *sk) { struct sk_filter *filter; - struct module *owner = sk->sk_prot->owner; + struct module *owner = sk->sk_prot_creator->owner; if (sk->sk_destruct) sk->sk_destruct(sk); @@ -672,8 +676,8 @@ void sk_free(struct sock *sk) __FUNCTION__, atomic_read(&sk->sk_omem_alloc)); security_sk_free(sk); - if (sk->sk_prot->slab != NULL) - kmem_cache_free(sk->sk_prot->slab, sk); + if (sk->sk_prot_creator->slab != NULL) + kmem_cache_free(sk->sk_prot_creator->slab, sk); else kfree(sk); module_put(owner); |