net/rose: Fix to not accept on connected socket
Subsystems (2)
PATCH v2 1/1 net/rose: Fix to not accept on connected socket
If listen() and accept() are called on a rose socket that connect() is successful, accept() succeeds immediately. This is because rose_connect() queues the skb to sk->sk_receive_queue, and rose_accept() dequeues it.
This creates a child socket with the sk of the parent rose socket, which can cause confusion.
Fix rose_listen() to return -EINVAL if the socket has already been successfully connected, and add lock_sock to prevent this issue.
--- net/rose/af_rose.c | 8 ++++++++ 1 file changed, 8 insertions(+)
net/rose/af_rose.c +8 -0
@@ -488,6 +488,12 @@ static int rose_listen(struct socket *sock, int backlog) {struct sock *sk = sock->sk; +lock_sock (sk); +if (sock->state !=SS_UNCONNECTED ) { +release_sock (sk); +return -EINVAL ; + } +if (sk->sk_state !=TCP_LISTEN ) {struct rose_sock *rose =rose_sk (sk);
@@ -497,8 +503,10 @@ static int rose_listen(struct socket *sock, int backlog)memset (rose->dest_digis,0 ,AX25_ADDR_LEN *ROSE_MAX_DIGIS ); sk->sk_max_ack_backlog = backlog; sk->sk_state =TCP_LISTEN ; +release_sock (sk);return 0 ; } +release_sock (sk);return -EOPNOTSUPP ; }
Signature · 1 line
2.25.1
From: Hyunwoo Kim <[email protected]> Date: Mon, 23 Jan 2023 11:40:20 -0800
Quoted 5 lines
If
listen()andaccept()are called on a rose socket thatconnect()is successful,accept()succeeds immediately. This is becauserose_connect()queues the skb tosk->sk_receive_queue, androse_accept()dequeues it.
Quoted 8 lines
This creates a child socket with the sk of the parent rose socket, which can cause confusion.
Fix
rose_listen()to return-EINVALif the socket has already been successfully connected, and addlock_sockto prevent this issue.Signed-off-by Hyunwoo Kim <[email protected]>
Quoted 34 lines
--- net/rose/af_rose.c | 8 ++++++++ 1 file changed, 8 insertions(+)net/rose/af_rose.c +8
-0@@ -488,6 +488,12 @@ static int rose_listen(struct socket *sock, int backlog) {struct sock *sk = sock->sk; +lock_sock (sk); +if (sock->state !=SS_UNCONNECTED ) { +release_sock (sk); +return -EINVAL ; + } +if (sk->sk_state !=TCP_LISTEN ) {struct rose_sock *rose =rose_sk (sk);@@ -497,8 +503,10 @@ static int rose_listen(struct socket *sock, int backlog)memset (rose->dest_digis,0 ,AX25_ADDR_LEN *ROSE_MAX_DIGIS ); sk->sk_max_ack_backlog = backlog; sk->sk_state =TCP_LISTEN ; +release_sock (sk);return 0 ; } +release_sock (sk);return -EOPNOTSUPP ; }Signature · 1 line
2.25.1
From: Kuniyuki Iwashima <[email protected]> Date: Tue, 24 Jan 2023 18:08:09 -0800
Quoted 6 lines
From: Hyunwoo Kim <[email protected]> Date: Mon, 23 Jan 2023 11:40:20 -0800Quoted 4 lines
If
listen()andaccept()are called on a rose socket thatconnect()is successful,accept()succeeds immediately. This is becauserose_connect()queues the skb tosk->sk_receive_queue, androse_accept()dequeues it.
Same comment for the netrom patch here.
https://lore.kernel.org/netdev/[email protected]/
The skb which the problematic accept() dequeues is created by sendmsg(), not connect(), right ?
Quoted 47 lines
Quoted 9 lines
This creates a child socket with the sk of the parent rose socket, which can cause confusion.
Fix
rose_listen()to return-EINVALif the socket has already been successfully connected, and addlock_sockto prevent this issue.Signed-off-by Hyunwoo Kim <[email protected]>Reviewed-by Kuniyuki Iwashima <[email protected]>Quoted 34 lines
--- net/rose/af_rose.c | 8 ++++++++ 1 file changed, 8 insertions(+)net/rose/af_rose.c +8
-0@@ -488,6 +488,12 @@ static int rose_listen(struct socket *sock, int backlog) {struct sock *sk = sock->sk; +lock_sock (sk); +if (sock->state !=SS_UNCONNECTED ) { +release_sock (sk); +return -EINVAL ; + } +if (sk->sk_state !=TCP_LISTEN ) {struct rose_sock *rose =rose_sk (sk);@@ -497,8 +503,10 @@ static int rose_listen(struct socket *sock, int backlog)memset (rose->dest_digis,0 ,AX25_ADDR_LEN *ROSE_MAX_DIGIS ); sk->sk_max_ack_backlog = backlog; sk->sk_state =TCP_LISTEN ; +release_sock (sk);return 0 ; } +release_sock (sk);return -EOPNOTSUPP ; }Signature · 1 line
2.25.1