]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/iucv/af_iucv.c
[NET]: Make socket creation namespace safe.
[linux-2.6-omap-h63xx.git] / net / iucv / af_iucv.c
index d9e9ddb8eac5e68a22365e7e1cc1519a8649df04..53668585e947720cbfced1ebb02c82c61ec62e13 100644 (file)
@@ -213,12 +213,13 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio)
 {
        struct sock *sk;
 
-       sk = sk_alloc(PF_IUCV, prio, &iucv_proto, 1);
+       sk = sk_alloc(&init_net, PF_IUCV, prio, &iucv_proto, 1);
        if (!sk)
                return NULL;
 
        sock_init_data(sock, sk);
        INIT_LIST_HEAD(&iucv_sk(sk)->accept_q);
+       spin_lock_init(&iucv_sk(sk)->accept_q_lock);
        skb_queue_head_init(&iucv_sk(sk)->send_skb_q);
        skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q);
        iucv_sk(sk)->send_tag = 0;
@@ -239,7 +240,7 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio)
 }
 
 /* Create an IUCV socket */
-static int iucv_sock_create(struct socket *sock, int protocol)
+static int iucv_sock_create(struct net *net, struct socket *sock, int protocol)
 {
        struct sock *sk;
 
@@ -274,15 +275,25 @@ void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *sk)
 
 void iucv_accept_enqueue(struct sock *parent, struct sock *sk)
 {
+       unsigned long flags;
+       struct iucv_sock *par = iucv_sk(parent);
+
        sock_hold(sk);
-       list_add_tail(&iucv_sk(sk)->accept_q, &iucv_sk(parent)->accept_q);
+       spin_lock_irqsave(&par->accept_q_lock, flags);
+       list_add_tail(&iucv_sk(sk)->accept_q, &par->accept_q);
+       spin_unlock_irqrestore(&par->accept_q_lock, flags);
        iucv_sk(sk)->parent = parent;
        parent->sk_ack_backlog++;
 }
 
 void iucv_accept_unlink(struct sock *sk)
 {
+       unsigned long flags;
+       struct iucv_sock *par = iucv_sk(iucv_sk(sk)->parent);
+
+       spin_lock_irqsave(&par->accept_q_lock, flags);
        list_del_init(&iucv_sk(sk)->accept_q);
+       spin_unlock_irqrestore(&par->accept_q_lock, flags);
        iucv_sk(sk)->parent->sk_ack_backlog--;
        iucv_sk(sk)->parent = NULL;
        sock_put(sk);
@@ -298,8 +309,8 @@ struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock)
                lock_sock(sk);
 
                if (sk->sk_state == IUCV_CLOSED) {
-                       release_sock(sk);
                        iucv_accept_unlink(sk);
+                       release_sock(sk);
                        continue;
                }
 
@@ -879,6 +890,7 @@ static int iucv_callback_connreq(struct iucv_path *path,
        /* Find out if this path belongs to af_iucv. */
        read_lock(&iucv_sk_list.lock);
        iucv = NULL;
+       sk = NULL;
        sk_for_each(sk, node, &iucv_sk_list.head)
                if (sk->sk_state == IUCV_LISTEN &&
                    !memcmp(&iucv_sk(sk)->src_name, src_name, 8)) {