Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=ac57b3a9ce280763296f99e32187a0b4384d9389
Commit:     ac57b3a9ce280763296f99e32187a0b4384d9389
Parent:     bfb6709d0b239af5e3ce5859aae926e1b79ba84b
Author:     Denis Lunev <[EMAIL PROTECTED]>
AuthorDate: Wed Apr 18 17:05:58 2007 -0700
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Wed Apr 18 17:05:58 2007 -0700

    [NETLINK]: Don't attach callback to a going-away netlink socket
    
    There is a race between netlink_dump_start() and netlink_release()
    that can lead to the situation when a netlink socket with non-zero
    callback is freed.
    
    Here it is:
    
    CPU1:                           CPU2
    netlink_release():              netlink_dump_start():
    
                                    sk = netlink_lookup(); /* OK */
    
    netlink_remove();
    
    spin_lock(&nlk->cb_lock);
    if (nlk->cb) { /* false */
      ...
    }
    spin_unlock(&nlk->cb_lock);
    
                                    spin_lock(&nlk->cb_lock);
                                    if (nlk->cb) { /* false */
                                             ...
                                    }
                                    nlk->cb = cb;
                                    spin_unlock(&nlk->cb_lock);
                                    ...
    sock_orphan(sk);
    /*
     * proceed with releasing
     * the socket
     */
    
    The proposal it to make sock_orphan before detaching the callback
    in netlink_release() and to check for the sock to be SOCK_DEAD in
    netlink_dump_start() before setting a new callback.
    
    Signed-off-by: Denis Lunev <[EMAIL PROTECTED]>
    Signed-off-by: Kirill Korotaev <[EMAIL PROTECTED]>
    Signed-off-by: Pavel Emelianov <[EMAIL PROTECTED]>
    Acked-by: Patrick McHardy <[EMAIL PROTECTED]>
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 net/netlink/af_netlink.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index e73d8f5..c48b0f4 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -443,6 +443,7 @@ static int netlink_release(struct socket *sock)
                return 0;
 
        netlink_remove(sk);
+       sock_orphan(sk);
        nlk = nlk_sk(sk);
 
        spin_lock(&nlk->cb_lock);
@@ -457,7 +458,6 @@ static int netlink_release(struct socket *sock)
        /* OK. Socket is unlinked, and, therefore,
           no new packets will arrive */
 
-       sock_orphan(sk);
        sock->sk = NULL;
        wake_up_interruptible_all(&nlk->wait);
 
@@ -1412,9 +1412,9 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff 
*skb,
                return -ECONNREFUSED;
        }
        nlk = nlk_sk(sk);
-       /* A dump is in progress... */
+       /* A dump or destruction is in progress... */
        spin_lock(&nlk->cb_lock);
-       if (nlk->cb) {
+       if (nlk->cb || sock_flag(sk, SOCK_DEAD)) {
                spin_unlock(&nlk->cb_lock);
                netlink_destroy_callback(cb);
                sock_put(sk);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to