Commit e90d44a8 authored by Ralf Bächle's avatar Ralf Bächle

Add missing lock_kernel() to ax25_connect.

Implement proper locking in ax25_accept() and nr_accept().
Add back line of code lost in last manual merge.
parent 59a69ca1
...@@ -1376,6 +1376,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, ...@@ -1376,6 +1376,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
if (sk->state != TCP_ESTABLISHED) { if (sk->state != TCP_ESTABLISHED) {
/* Not in ABM, not in WAIT_UA -> failed */ /* Not in ABM, not in WAIT_UA -> failed */
sock->state = SS_UNCONNECTED; sock->state = SS_UNCONNECTED;
unlock_kernel();
return sock_error(sk); /* Always set at this point */ return sock_error(sk); /* Always set at this point */
} }
...@@ -1388,49 +1389,53 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, ...@@ -1388,49 +1389,53 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
{ {
struct sock *sk; struct task_struct *tsk = current;
struct sock *newsk; DECLARE_WAITQUEUE(wait, tsk);
struct sk_buff *skb; struct sk_buff *skb;
struct sock *newsk;
struct sock *sk;
int err = 0;
lock_kernel(); if (sock->state != SS_UNCONNECTED)
if (sock->state != SS_UNCONNECTED) {
unlock_kernel();
return -EINVAL; return -EINVAL;
}
if ((sk = sock->sk) == NULL) { if ((sk = sock->sk) == NULL)
unlock_kernel();
return -EINVAL; return -EINVAL;
}
lock_sock(sk);
if (sk->type != SOCK_SEQPACKET) { if (sk->type != SOCK_SEQPACKET) {
unlock_kernel(); err = -EOPNOTSUPP;
return -EOPNOTSUPP; goto out;
} }
if (sk->state != TCP_LISTEN) { if (sk->state != TCP_LISTEN) {
unlock_kernel(); err = -EINVAL;
return -EINVAL; goto out;
} }
/* /*
* The read queue this time is holding sockets ready to use * The read queue this time is holding sockets ready to use
* hooked into the SABM we saved * hooked into the SABM we saved
*/ */
do { add_wait_queue(sk->sleep, &wait);
if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) { for (;;) {
if (flags & O_NONBLOCK) { skb = skb_dequeue(&sk->receive_queue);
unlock_kernel(); if (skb)
return -EWOULDBLOCK; break;
}
interruptible_sleep_on(sk->sleep); current->state = TASK_INTERRUPTIBLE;
if (signal_pending(current)) { release_sock(sk);
unlock_kernel(); if (flags & O_NONBLOCK)
return -ERESTARTSYS; return -EWOULDBLOCK;
} if (!signal_pending(tsk)) {
schedule();
lock_sock(sk);
continue;
} }
} while (skb == NULL); return -ERESTARTSYS;
}
current->state = TASK_RUNNING;
remove_wait_queue(sk->sleep, &wait);
newsk = skb->sk; newsk = skb->sk;
newsk->pair = NULL; newsk->pair = NULL;
...@@ -1442,9 +1447,11 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -1442,9 +1447,11 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
sk->ack_backlog--; sk->ack_backlog--;
newsock->sk = newsk; newsock->sk = newsk;
newsock->state = SS_CONNECTED; newsock->state = SS_CONNECTED;
unlock_kernel();
return 0; out:
release_sock(sk);
return err;
} }
static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, static int ax25_getname(struct socket *sock, struct sockaddr *uaddr,
...@@ -1996,6 +2003,7 @@ static struct net_proto_family ax25_family_ops = { ...@@ -1996,6 +2003,7 @@ static struct net_proto_family ax25_family_ops = {
.create = ax25_create, .create = ax25_create,
}; };
static struct proto_ops ax25_proto_ops = {
.family = PF_AX25, .family = PF_AX25,
.release = ax25_release, .release = ax25_release,
......
...@@ -758,34 +758,50 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, ...@@ -758,34 +758,50 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr,
static int nr_accept(struct socket *sock, struct socket *newsock, int flags) static int nr_accept(struct socket *sock, struct socket *newsock, int flags)
{ {
struct sock *sk; struct task_struct *tsk = current;
struct sock *newsk; DECLARE_WAITQUEUE(wait, tsk);
struct sk_buff *skb; struct sk_buff *skb;
struct sock *newsk;
struct sock *sk;
int err = 0;
if ((sk = sock->sk) == NULL) if ((sk = sock->sk) == NULL)
return -EINVAL; return -EINVAL;
if (sk->type != SOCK_SEQPACKET) lock_sock(sk);
return -EOPNOTSUPP; if (sk->type != SOCK_SEQPACKET) {
err = -EOPNOTSUPP;
goto out;
}
if (sk->state != TCP_LISTEN) if (sk->state != TCP_LISTEN) {
return -EINVAL; err = -EINVAL;
goto out;
}
/* /*
* The write queue this time is holding sockets ready to use * The write queue this time is holding sockets ready to use
* hooked into the SABM we saved * hooked into the SABM we saved
*/ */
do { add_wait_queue(sk->sleep, &wait);
if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) { for (;;) {
if (flags & O_NONBLOCK) { skb = skb_dequeue(&sk->receive_queue);
return -EWOULDBLOCK; if (skb)
} break;
interruptible_sleep_on(sk->sleep);
if (signal_pending(current)) { current->state = TASK_INTERRUPTIBLE;
return -ERESTARTSYS; release_sock(sk);
} if (flags & O_NONBLOCK)
return -EWOULDBLOCK;
if (!signal_pending(tsk)) {
schedule();
lock_sock(sk);
continue;
} }
} while (skb == NULL); return -ERESTARTSYS;
}
current->state = TASK_RUNNING;
remove_wait_queue(sk->sleep, &wait);
newsk = skb->sk; newsk = skb->sk;
newsk->pair = NULL; newsk->pair = NULL;
...@@ -797,7 +813,8 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -797,7 +813,8 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags)
sk->ack_backlog--; sk->ack_backlog--;
newsock->sk = newsk; newsock->sk = newsk;
return 0; out:
return err;
} }
static int nr_getname(struct socket *sock, struct sockaddr *uaddr, static int nr_getname(struct socket *sock, struct sockaddr *uaddr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment