net: Fix sock freeing before sock_init_data() with __sk_free()
Subsystems (4)
PATCH 1/1 net: Fix sock freeing before sock_init_data() with __sk_free()
After recent changes sk_free() frees socks conditionally and depends on sk_wmem_alloc beeing set e.g. in sock_init_data(). But in some cases sk_free() is called earlier, usually after other alloc errors. This patch fixes it by exporting and using __sk_free() directly.
---
include/net/sock.h | 1 + net/ax25/af_ax25.c | 6 +++--- net/core/sock.c | 6 ++++-- net/irda/af_irda.c | 4 ++-- net/tipc/socket.c | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-)
include/net/sock.h +1 -0
@@ -935,6 +935,7 @@ extern void release_sock(struct sock *sk);extern struct sock *sk_alloc (struct net *net,int family,gfp_t priority,struct proto *prot); +extern void __sk_free (struct sock *sk);extern void sk_free (struct sock *sk);extern void sk_release_kernel (struct sock *sk); extern struct sock *sk_clone(const struct sock *sk,
net/ax25/af_ax25.c +3 -3
@@ -851,7 +851,7 @@ static int ax25_create(struct net *net, struct socket *sock, int protocol) ax25 = sk->sk_protinfo =ax25_create_cb ();if (!ax25) { -sk_free (sk); +__sk_free (sk);return -ENOMEM ; }
@@ -876,7 +876,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)return NULL ;if ((ax25 =ax25_create_cb ()) ==NULL ) { -sk_free (sk); +__sk_free (sk);return NULL ; }
@@ -886,7 +886,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)case SOCK_SEQPACKET :break ;default : -sk_free (sk); +__sk_free (sk);ax25_cb_put (ax25);return NULL ; }
net/core/sock.c +4 -2
@@ -1031,7 +1031,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority, }EXPORT_SYMBOL (sk_alloc); -static void __sk_free (struct sock *sk) +void __sk_free (struct sock *sk) {struct sk_filter *filter;
@@ -1054,13 +1054,15 @@ static void __sk_free(struct sock *sk)put_net (sock_net (sk));sk_prot_free (sk->sk_prot_creator, sk); } +EXPORT_SYMBOL (__sk_free);void sk_free (struct sock *sk) {/* * We substract one from sk_wmem_alloc and can know if * some packets are still in some tx queue. -* If not null, sock_wfree() will call __sk_free(sk) later +* If not null, sock_wfree() will call __sk_free(sk) later. +* (Before sock_init_data() etc. use __sk_free() instead.) */ if (atomic_dec_and_test (&sk->sk_wmem_alloc))__sk_free (sk);
net/irda/af_irda.c +2 -2
@@ -1118,12 +1118,12 @@ static int irda_create(struct net *net, struct socket *sock, int protocol) self->max_sdu_size_rx =TTP_SAR_UNBOUND ;break ;default : -sk_free (sk); +__sk_free (sk);return -ESOCKTNOSUPPORT ; }break ;default : -sk_free (sk); +__sk_free (sk);return -ESOCKTNOSUPPORT ; }
net/tipc/socket.c +1 -1
@@ -228,7 +228,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol) tp_ptr =tipc_createport_raw (sk, &dispatch, &wakeupdispatch,TIPC_LOW_IMPORTANCE );if (unlikely (!tp_ptr)) { -sk_free (sk); +__sk_free (sk);return -ENOMEM ; }
Quoted 112 lines · Jarek Poplawski
After recent changes
sk_free()frees socks conditionally and depends onsk_wmem_allocbeeing set e.g. insock_init_data(). But in some casessk_free()is called earlier, usually after other alloc errors. This patch fixes it by exporting and using__sk_free()directly.Signed-off-by Jarek Poplawski <[email protected]>---
include/net/sock.h | 1 + net/ax25/af_ax25.c | 6 +++--- net/core/sock.c | 6 ++++-- net/irda/af_irda.c | 4 ++-- net/tipc/socket.c | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-)include/net/sock.h +1
-0@@ -935,6 +935,7 @@ extern void release_sock(struct sock *sk);extern struct sock *sk_alloc (struct net *net,int family,gfp_t priority,struct proto *prot); +extern void __sk_free (struct sock *sk);extern void sk_free (struct sock *sk);extern void sk_release_kernel (struct sock *sk); extern struct sock *sk_clone(const struct sock *sk,net/ax25/af_ax25.c +3
-3@@ -851,7 +851,7 @@ static int ax25_create(struct net *net, struct socket *sock, int protocol) ax25 = sk->sk_protinfo =ax25_create_cb ();if (!ax25) { -sk_free (sk); +__sk_free (sk);return -ENOMEM ; }@@ -876,7 +876,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)return NULL ;if ((ax25 =ax25_create_cb ()) ==NULL ) { -sk_free (sk); +__sk_free (sk);return NULL ; }@@ -886,7 +886,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)case SOCK_SEQPACKET :break ;default : -sk_free (sk); +__sk_free (sk);ax25_cb_put (ax25);return NULL ; }net/core/sock.c +4
-2@@ -1031,7 +1031,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority, }EXPORT_SYMBOL (sk_alloc); -static void __sk_free (struct sock *sk) +void __sk_free (struct sock *sk) {struct sk_filter *filter;@@ -1054,13 +1054,15 @@ static void __sk_free(struct sock *sk)put_net (sock_net (sk));sk_prot_free (sk->sk_prot_creator, sk); } +EXPORT_SYMBOL (__sk_free);void sk_free (struct sock *sk) {/* * We substract one from sk_wmem_alloc and can know if * some packets are still in some tx queue. -* If not null, sock_wfree() will call __sk_free(sk) later +* If not null, sock_wfree() will call __sk_free(sk) later. +* (Before sock_init_data() etc. use __sk_free() instead.) */ if (atomic_dec_and_test (&sk->sk_wmem_alloc))__sk_free (sk);net/irda/af_irda.c +2
-2@@ -1118,12 +1118,12 @@ static int irda_create(struct net *net, struct socket *sock, int protocol) self->max_sdu_size_rx =TTP_SAR_UNBOUND ;break ;default : -sk_free (sk); +__sk_free (sk);return -ESOCKTNOSUPPORT ; }break ;default : -sk_free (sk); +__sk_free (sk);return -ESOCKTNOSUPPORT ; }net/tipc/socket.c +0
-0
net/tipc/socket.c static int tipc_create(struct net *net, struct socket *sock, int protocol)
Quoted 9 lines
net/tipc/socket.c +1
-2@@ -228,7 +228,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol) tp_ptr =tipc_createport_raw (sk, &dispatch, &wakeupdispatch,TIPC_LOW_IMPORTANCE );if (unlikely (!tp_ptr)) { -sk_free (sk); +__sk_free (sk);return -ENOMEM ; } --
Very nice catch Jarek, but dont you think it would be cleaner to make sure we can call sk_free() right after sk_alloc() instead, and not exporting __sk_free() ?
ie initialize wmem_alloc in sk_alloc() instead of initializing it in sock_init_data() ?
Quoted 5 lines · Eric Dumazet
Quoted 4 lines · Jarek Poplawski
After recent changes
sk_free()frees socks conditionally and depends onsk_wmem_allocbeeing set e.g. insock_init_data(). But in some casessk_free()is called earlier, usually after other alloc errors. This patch fixes it by exporting and using__sk_free()directly.
...
Quoted 7 lines
Very nice catch Jarek, but dont you think it would be cleaner to make sure we can call
sk_free()right aftersk_alloc()instead, and not exporting__sk_free()?ie initialize
wmem_allocinsk_alloc()instead of initializing it insock_init_data()?
Most probably it should be better. But I meant this fix for -net and didn't wan't to break too much... So, if you're sure it's OK feel free to send your version. (Or it could be changed like this in the -next.)
Jarek P.
Quoted 11 lines · Jarek Poplawski
Quoted 5 lines · Eric Dumazet
Quoted 4 lines · Jarek Poplawski
After recent changes
sk_free()frees socks conditionally and depends onsk_wmem_allocbeeing set e.g. insock_init_data(). But in some casessk_free()is called earlier, usually after other alloc errors. This patch fixes it by exporting and using__sk_free()directly....
Quoted 4 lines
Very nice catch Jarek, but dont you think it would be cleaner to make sure we can call
sk_free()right aftersk_alloc()instead, and not exporting__sk_free()?
Quoted 7 lines
Quoted 3 lines
ie initialize
wmem_allocinsk_alloc()instead of initializing it insock_init_data()?Most probably it should be better. But I meant this fix for -net and didn't wan't to break too much... So, if you're sure it's OK feel free to send your version. (Or it could be changed like this in the -next.)
Well, patch is yours, not mine, and I am confident it is OK.
We should check that no sk_alloc() user did a blind memset() or something strange like that, before calling sock_init_data() or sk_free()
net/core/sock.c +1 -1
@@ -1025,6 +1025,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority, sk->sk_prot = sk->sk_prot_creator = prot;sock_lock_init (sk);sock_net_set (sk,get_net (net)); +atomic_set (&sk->sk_wmem_alloc,1 ); }return sk;
@@ -1872,7 +1873,6 @@ void sock_init_data(struct socket *sock, struct sock *sk)*/ smp_wmb ();atomic_set (&sk->sk_refcnt,1 ); -atomic_set (&sk->sk_wmem_alloc,1 );atomic_set (&sk->sk_drops,0 ); }EXPORT_SYMBOL (sock_init_data);
Quoted 16 lines · Eric Dumazet
Quoted 15 lines · Jarek Poplawski
Quoted 5 lines · Eric Dumazet
Quoted 4 lines · Jarek Poplawski
After recent changes
sk_free()frees socks conditionally and depends onsk_wmem_allocbeeing set e.g. insock_init_data(). But in some casessk_free()is called earlier, usually after other alloc errors. This patch fixes it by exporting and using__sk_free()directly....
Quoted 7 lines
Very nice catch Jarek, but dont you think it would be cleaner to make sure we can call
sk_free()right aftersk_alloc()instead, and not exporting__sk_free()?ie initialize
wmem_allocinsk_alloc()instead of initializing it insock_init_data()?
Quoted 5 lines
Quoted 3 lines
Most probably it should be better. But I meant this fix for -net and didn't wan't to break too much... So, if you're sure it's OK feel free to send your version. (Or it could be changed like this in the -next.)
Well, patch is yours, not mine, and I am confident it is OK.
Well, it's from you, and I guess you'll sign off too, but if you think so...
Thanks,
Jarek P.
Quoted 25 lines
We should check that no
sk_alloc()user did a blindmemset()or something strange like that, before callingsock_init_data()orsk_free()net/core/sock.c +1
-1@@ -1025,6 +1025,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority, sk->sk_prot = sk->sk_prot_creator = prot;sock_lock_init (sk);sock_net_set (sk,get_net (net)); +atomic_set (&sk->sk_wmem_alloc,1 ); }return sk;@@ -1872,7 +1873,6 @@ void sock_init_data(struct socket *sock, struct sock *sk)*/ smp_wmb ();atomic_set (&sk->sk_refcnt,1 ); -atomic_set (&sk->sk_wmem_alloc,1 );atomic_set (&sk->sk_drops,0 ); }EXPORT_SYMBOL (sock_init_data);
Quoted 21 lines · Jarek Poplawski
Quoted 12 lines · Eric Dumazet
Quoted 11 lines · Jarek Poplawski
Quoted 5 lines · Eric Dumazet
Quoted 4 lines · Jarek Poplawski
After recent changes
sk_free()frees socks conditionally and depends onsk_wmem_allocbeeing set e.g. insock_init_data(). But in some casessk_free()is called earlier, usually after other alloc errors. This patch fixes it by exporting and using__sk_free()directly....
Quoted 4 lines
Very nice catch Jarek, but dont you think it would be cleaner to make sure we can call
sk_free()right aftersk_alloc()instead, and not exporting__sk_free()?Quoted 7 lines
Quoted 6 lines
Quoted 3 lines
ie initialize
wmem_allocinsk_alloc()instead of initializing it insock_init_data()?Most probably it should be better. But I meant this fix for -net and didn't wan't to break too much... So, if you're sure it's OK feel free to send your version. (Or it could be changed like this in the -next.)
Well, patch is yours, not mine, and I am confident it is OK.
Quoted 8 lines
Well, it's from you, and I guess you'll sign off too, but if you think so...
Signed-off-by Jarek Poplawski <[email protected]>Thanks,
Jarek P.
Give me a few hours to review sk_alloc() call sites, test patch and officially submit it.
Thanks
Quoted 2 lines · Eric Dumazet
Quoted 1 line · Jarek Poplawski
On Mon, Aug 31, 2009 at 08:50:25AM +0200, Eric Dumazet wrote:
...
Quoted 7 lines
Quoted 7 lines
Quoted 1 line
Well, patch is yours, not mine, and I am confident it is OK.
Well, it's from you, and I guess you'll sign off too, but if you think so...
Signed-off-by Jarek Poplawski <[email protected]>
Quoted 7 lines
Quoted 3 lines
Thanks,
Jarek P.Give me a few hours to review
sk_alloc()call sites, test patch and officially submit it.Thanks
Hmm... but you're "confident it is OK"?! (You know, I could've risked my life or something... ;-)
Jarek P.
PATCH 1/1 net: sk_free() should be allowed right after sk_alloc()
In reply to Eric DumazetFrom: Jarek Poplawski <[email protected]>
After commit 2b85a34e911bf483c27cfdd124aeb1605145dc80 (net: No more expensive sock_hold()/sock_put() on each tx) sk_free() frees socks conditionally and depends
on sk_wmem_alloc beeing set e.g. in sock_init_data(). But in some cases sk_free() is called earlier, usually after other alloc errors.
Fix is to move sk_wmem_alloc initialization from sock_init_data() to sk_alloc() itself.
---
net/core/sock.c +1 -1
@@ -1025,6 +1025,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority, sk->sk_prot = sk->sk_prot_creator = prot;sock_lock_init (sk);sock_net_set (sk,get_net (net)); +atomic_set (&sk->sk_wmem_alloc,1 ); }return sk;
@@ -1872,7 +1873,6 @@ void sock_init_data(struct socket *sock, struct sock *sk)*/ smp_wmb ();atomic_set (&sk->sk_refcnt,1 ); -atomic_set (&sk->sk_wmem_alloc,1 );atomic_set (&sk->sk_drops,0 ); }EXPORT_SYMBOL (sock_init_data);
Re: [PATCH] net: sk_free() should be allowed right after sk_alloc()
Quoted 6 lines · Eric Dumazet
From: Jarek Poplawski <[email protected]>
After commit
2b85a34e911bf483c27cfdd124aeb1605145dc80(net: No more expensive sock_hold()/sock_put() on each tx)sk_free()frees socks conditionally and depends
onsk_wmem_allocbeeing set e.g. insock_init_data(). But in some
Very nice, but I hope David could fix btw. my "beeing" misspelling.
Thanks everyone,
Jarek P.
Quoted 29 lines
cases
sk_free()is called earlier, usually after other alloc errors.Fix is to move
sk_wmem_allocinitialization fromsock_init_data()tosk_alloc()itself.Signed-off-by Jarek Poplawski <[email protected]>Signed-off-by Eric Dumazet <[email protected]>---
net/core/sock.c +1
-1@@ -1025,6 +1025,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority, sk->sk_prot = sk->sk_prot_creator = prot;sock_lock_init (sk);sock_net_set (sk,get_net (net)); +atomic_set (&sk->sk_wmem_alloc,1 ); }return sk;@@ -1872,7 +1873,6 @@ void sock_init_data(struct socket *sock, struct sock *sk)*/ smp_wmb ();atomic_set (&sk->sk_refcnt,1 ); -atomic_set (&sk->sk_wmem_alloc,1 );atomic_set (&sk->sk_drops,0 ); }EXPORT_SYMBOL (sock_init_data);
David Miller
maintainerRe: [PATCH] net: sk_free() should be allowed right after sk_alloc()
From: Jarek Poplawski <[email protected]>
Date: Mon, 31 Aug 2009 09:30:19 +0000
Quoted 9 lines · Eric Dumazet
Quoted 6 lines
From: Jarek Poplawski <[email protected]>
After commit
2b85a34e911bf483c27cfdd124aeb1605145dc80(net: No more expensive sock_hold()/sock_put() on each tx)sk_free()frees socks conditionally and depends
onsk_wmem_allocbeeing set e.g. insock_init_data(). But in someVery nice, but I hope David could fix btw. my "beeing" misspelling.
I will :-)
Re: [PATCH] net: sk_free() should be allowed right after sk_alloc()
Quoted 6 lines · David Miller
From: Jarek Poplawski <[email protected]>
Date: Mon, 31 Aug 2009 09:30:19 +0000Quoted 3 lines · Eric Dumazet
Quoted 2 lines
From: Jarek Poplawski <[email protected]>
Quoted 7 lines
Quoted 5 lines
Quoted 4 lines
After commit
2b85a34e911bf483c27cfdd124aeb1605145dc80(net: No more expensive sock_hold()/sock_put() on each tx)sk_free()frees socks conditionally and depends
onsk_wmem_allocbeeing set e.g. insock_init_data(). But in someVery nice, but I hope David could fix btw. my "beeing" misspelling.
I will :-)
Thanks :)
Re: [PATCH] net: sk_free() should be allowed right after sk_alloc()
From: Eric Dumazet <[email protected]>
Date: Mon, 31 Aug 2009 14:12:02 +0200
Quoted 11 lines
Quoted 10 lines · David Miller
From: Jarek Poplawski <[email protected]>
Date: Mon, 31 Aug 2009 09:30:19 +0000Quoted 7 lines · Eric Dumazet
Quoted 6 lines
From: Jarek Poplawski <[email protected]>
After commit
2b85a34e911bf483c27cfdd124aeb1605145dc80(net: No more expensive sock_hold()/sock_put() on each tx)sk_free()frees socks conditionally and depends
onsk_wmem_allocbeeing set e.g. insock_init_data(). But in some
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Very nice, but I hope David could fix btw. my "beeing" misspelling.
I will :-)
Thanks :)
Applied to net-2.6, thanks everyone.