PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/kernel-2.6/324-skb1-sk_forward_alloc.patch

http://wl500g.googlecode.com/
Patch | 128 lines | 115 code | 13 blank | 0 comment | 0 complexity | 92779f833543cb50b5036cab753dcaec MD5 | raw file
Possible License(s): GPL-2.0
  1. From 9d410c796067686b1e032d54ce475b7055537138
  2. From: Eric Dumazet
  3. Date: Fri, 30 Oct 2009 05:03:53 +0000
  4. Subject: [PATCH] net: fix sk_forward_alloc corruption
  5. On UDP sockets, we must call skb_free_datagram() with socket locked,
  6. or risk sk_forward_alloc corruption. This requirement is not respected
  7. in SUNRPC.
  8. Add a convenient helper, skb_free_datagram_locked() and use it in SUNRPC
  9. Reported-by: Francis Moreau <francis.moro@gmail.com>
  10. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
  11. Signed-off-by: David S. Miller <davem@davemloft.net>
  12. ---
  13. include/linux/skbuff.h | 2 ++
  14. net/core/datagram.c | 10 +++++++++-
  15. net/ipv4/udp.c | 4 +---
  16. net/ipv6/udp.c | 4 +---
  17. net/sunrpc/svcsock.c | 10 +++++-----
  18. 5 files changed, 18 insertions(+), 12 deletions(-)
  19. diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
  20. --- a/include/linux/skbuff.h
  21. +++ b/include/linux/skbuff.h
  22. @@ -1757,6 +1757,8 @@ extern int skb_copy_datagram_const_iovec(const struct sk_buff *from,
  23. int to_offset,
  24. int size);
  25. extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
  26. +extern void skb_free_datagram_locked(struct sock *sk,
  27. + struct sk_buff *skb);
  28. extern void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
  29. unsigned int flags);
  30. extern __wsum skb_checksum(const struct sk_buff *skb, int offset,
  31. diff --git a/net/core/datagram.c b/net/core/datagram.c
  32. --- a/net/core/datagram.c
  33. +++ b/net/core/datagram.c
  34. @@ -224,6 +224,15 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb)
  35. consume_skb(skb);
  36. sk_mem_reclaim_partial(sk);
  37. }
  38. +EXPORT_SYMBOL(skb_free_datagram);
  39. +
  40. +void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb)
  41. +{
  42. + lock_sock(sk);
  43. + skb_free_datagram(sk, skb);
  44. + release_sock(sk);
  45. +}
  46. +EXPORT_SYMBOL(skb_free_datagram_locked);
  47. /**
  48. * skb_kill_datagram - Free a datagram skbuff forcibly
  49. @@ -752,5 +761,4 @@ unsigned int datagram_poll(struct file *file, struct socket *sock,
  50. EXPORT_SYMBOL(datagram_poll);
  51. EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec);
  52. EXPORT_SYMBOL(skb_copy_datagram_iovec);
  53. -EXPORT_SYMBOL(skb_free_datagram);
  54. EXPORT_SYMBOL(skb_recv_datagram);
  55. diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
  56. --- a/net/ipv4/udp.c
  57. +++ b/net/ipv4/udp.c
  58. @@ -999,7 +999,7 @@ try_again:
  59. err = ulen;
  60. out_free:
  61. - skb_free_datagram(sk, skb);
  62. + skb_free_datagram_locked(sk, skb);
  63. out:
  64. return err;
  65. diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
  66. --- a/net/ipv6/udp.c
  67. +++ b/net/ipv6/udp.c
  68. @@ -288,7 +288,7 @@ try_again:
  69. err = ulen;
  70. out_free:
  71. - skb_free_datagram(sk, skb);
  72. + skb_free_datagram_locked(sk, skb);
  73. out:
  74. return err;
  75. diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
  76. --- a/net/sunrpc/svcsock.c
  77. +++ b/net/sunrpc/svcsock.c
  78. @@ -111,7 +111,7 @@ static void svc_release_skb(struct svc_rqst *rqstp)
  79. rqstp->rq_xprt_ctxt = NULL;
  80. dprintk("svc: service %p, releasing skb %p\n", rqstp, skb);
  81. - skb_free_datagram(rqstp->rq_sock->sk_sk, skb);
  82. + skb_free_datagram_locked(rqstp->rq_sock->sk_sk, skb);
  83. }
  84. }
  85. @@ -578,7 +578,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
  86. "svc: received unknown control message %d/%d; "
  87. "dropping RPC reply datagram\n",
  88. cmh->cmsg_level, cmh->cmsg_type);
  89. - skb_free_datagram(svsk->sk_sk, skb);
  90. + skb_free_datagram_locked(svsk->sk_sk, skb);
  91. return 0;
  92. }
  93. @@ -588,17 +588,17 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
  94. if (csum_partial_copy_to_xdr(&rqstp->rq_arg, skb)) {
  95. local_bh_enable();
  96. /* checksum error */
  97. - skb_free_datagram(svsk->sk_sk, skb);
  98. + skb_free_datagram_locked(svsk->sk_sk, skb);
  99. return 0;
  100. }
  101. local_bh_enable();
  102. - skb_free_datagram(svsk->sk_sk, skb);
  103. + skb_free_datagram_locked(svsk->sk_sk, skb);
  104. } else {
  105. /* we can use it in-place */
  106. rqstp->rq_arg.head[0].iov_base = skb->data + sizeof(struct udphdr);
  107. rqstp->rq_arg.head[0].iov_len = len;
  108. if (skb_checksum_complete(skb)) {
  109. - skb_free_datagram(svsk->sk_sk, skb);
  110. + skb_free_datagram_locked(svsk->sk_sk, skb);
  111. return 0;
  112. }
  113. rqstp->rq_skbuff = skb;
  114. --
  115. 1.7.4.1