lkml.org 
[lkml]   [2012]   [Oct]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[ 077/180] netlink: fix races after skb queueing
    2.6.32-longterm review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Eric Dumazet <eric.dumazet@gmail.com>

    [ Upstream commit 4a7e7c2ad540e54c75489a70137bf0ec15d3a127 ]

    As soon as an skb is queued into socket receive_queue, another thread
    can consume it, so we are not allowed to reference skb anymore, or risk
    use after free.

    Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Willy Tarreau <w@1wt.eu>
    ---
    net/netlink/af_netlink.c | 24 +++++++++++++-----------
    1 files changed, 13 insertions(+), 11 deletions(-)

    diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
    index 5a7dcdf..fc91ff6 100644
    --- a/net/netlink/af_netlink.c
    +++ b/net/netlink/af_netlink.c
    @@ -821,12 +821,19 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb,
    return 0;
    }

    -int netlink_sendskb(struct sock *sk, struct sk_buff *skb)
    +static int __netlink_sendskb(struct sock *sk, struct sk_buff *skb)
    {
    int len = skb->len;

    skb_queue_tail(&sk->sk_receive_queue, skb);
    sk->sk_data_ready(sk, len);
    + return len;
    +}
    +
    +int netlink_sendskb(struct sock *sk, struct sk_buff *skb)
    +{
    + int len = __netlink_sendskb(sk, skb);
    +
    sock_put(sk);
    return len;
    }
    @@ -951,8 +958,7 @@ static inline int netlink_broadcast_deliver(struct sock *sk,
    if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
    !test_bit(0, &nlk->state)) {
    skb_set_owner_r(skb, sk);
    - skb_queue_tail(&sk->sk_receive_queue, skb);
    - sk->sk_data_ready(sk, skb->len);
    + __netlink_sendskb(sk, skb);
    return atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf;
    }
    return -1;
    @@ -1665,10 +1671,8 @@ static int netlink_dump(struct sock *sk)

    if (sk_filter(sk, skb))
    kfree_skb(skb);
    - else {
    - skb_queue_tail(&sk->sk_receive_queue, skb);
    - sk->sk_data_ready(sk, skb->len);
    - }
    + else
    + __netlink_sendskb(sk, skb);
    return 0;
    }

    @@ -1680,10 +1684,8 @@ static int netlink_dump(struct sock *sk)

    if (sk_filter(sk, skb))
    kfree_skb(skb);
    - else {
    - skb_queue_tail(&sk->sk_receive_queue, skb);
    - sk->sk_data_ready(sk, skb->len);
    - }
    + else
    + __netlink_sendskb(sk, skb);

    if (cb->done)
    cb->done(cb);
    --
    1.7.2.1.45.g54fbc




    \
     
     \ /
      Last update: 2012-10-02 05:21    [W:8.511 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site