[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250110092641.85905-6-kuniyu@amazon.com>
Date: Fri, 10 Jan 2025 18:26:34 +0900
From: Kuniyuki Iwashima <kuniyu@...zon.com>
To: "David S. Miller" <davem@...emloft.net>, Eric Dumazet
<edumazet@...gle.com>, Jakub Kicinski <kuba@...nel.org>, Paolo Abeni
<pabeni@...hat.com>, Simon Horman <horms@...nel.org>
CC: Donald Hunter <donald.hunter@...hat.com>, Kuniyuki Iwashima
<kuniyu@...zon.com>, Kuniyuki Iwashima <kuni1840@...il.com>,
<netdev@...r.kernel.org>
Subject: [PATCH v1 net-next 05/12] af_unix: Set drop reason in unix_stream_connect().
connect() to a SOCK_STREAM socket could fail for various reasons.
Let's set drop reasons respectively:
* NO_SOCKET : No listening socket found
* RCV_SHUTDOWN : The listening socket called shutdown(SHUT_RD)
* SOCKET_RCVBUFF : The listening socket's accept queue is full
* INVALID_STATE : The client is in TCP_ESTABLISHED or TCP_LISTEN
* SECURITY_HOOK : LSM refused connect()
Signed-off-by: Kuniyuki Iwashima <kuniyu@...zon.com>
---
include/net/dropreason-core.h | 6 ++++++
net/unix/af_unix.c | 22 ++++++++++++++++++----
2 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
index 8823de6539d1..1b5e962f7f33 100644
--- a/include/net/dropreason-core.h
+++ b/include/net/dropreason-core.h
@@ -8,7 +8,9 @@
FN(NO_SOCKET) \
FN(SOCKET_CLOSE) \
FN(SOCKET_FILTER) \
+ FN(SOCKET_INVALID_STATE) \
FN(SOCKET_RCVBUFF) \
+ FN(SOCKET_RCV_SHUTDOWN) \
FN(PKT_TOO_SMALL) \
FN(TCP_CSUM) \
FN(UDP_CSUM) \
@@ -142,8 +144,12 @@ enum skb_drop_reason {
SKB_DROP_REASON_SOCKET_CLOSE,
/** @SKB_DROP_REASON_SOCKET_FILTER: dropped by socket filter */
SKB_DROP_REASON_SOCKET_FILTER,
+ /** @SKB_DROP_REASON_SOCKET_INVALID_STATE: sk->sk_state is invalid. */
+ SKB_DROP_REASON_SOCKET_INVALID_STATE,
/** @SKB_DROP_REASON_SOCKET_RCVBUFF: socket receive buff is full */
SKB_DROP_REASON_SOCKET_RCVBUFF,
+ /** @SKB_DROP_REASON_SOCKET_RCV_SHUTDOWN: socket is shutdown(SHUT_RD) */
+ SKB_DROP_REASON_SOCKET_RCV_SHUTDOWN,
/** @SKB_DROP_REASON_PKT_TOO_SMALL: packet size is too small */
SKB_DROP_REASON_PKT_TOO_SMALL,
/** @SKB_DROP_REASON_TCP_CSUM: TCP checksum error */
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 41b99984008a..b190ea8b8e9d 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1534,6 +1534,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
struct sock *sk = sock->sk, *newsk = NULL, *other = NULL;
struct unix_sock *u = unix_sk(sk), *newu, *otheru;
struct net *net = sock_net(sk);
+ enum skb_drop_reason reason;
struct sk_buff *skb = NULL;
unsigned char state;
long timeo;
@@ -1581,6 +1582,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
other = unix_find_other(net, sunaddr, addr_len, sk->sk_type);
if (IS_ERR(other)) {
err = PTR_ERR(other);
+ reason = SKB_DROP_REASON_NO_SOCKET;
goto out_free_skb;
}
@@ -1593,15 +1595,22 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
goto restart;
}
- if (other->sk_state != TCP_LISTEN ||
- other->sk_shutdown & RCV_SHUTDOWN) {
+ if (other->sk_state != TCP_LISTEN) {
err = -ECONNREFUSED;
+ reason = SKB_DROP_REASON_NO_SOCKET;
+ goto out_unlock;
+ }
+
+ if (other->sk_shutdown & RCV_SHUTDOWN) {
+ err = -ECONNREFUSED;
+ reason = SKB_DROP_REASON_SOCKET_RCV_SHUTDOWN;
goto out_unlock;
}
if (unix_recvq_full_lockless(other)) {
if (!timeo) {
err = -EAGAIN;
+ reason = SKB_DROP_REASON_SOCKET_RCVBUFF;
goto out_unlock;
}
@@ -1609,8 +1618,10 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
sock_put(other);
err = sock_intr_errno(timeo);
- if (signal_pending(current))
+ if (signal_pending(current)) {
+ reason = SKB_DROP_REASON_SOCKET_RCVBUFF;
goto out_free_skb;
+ }
goto restart;
}
@@ -1621,6 +1632,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
state = READ_ONCE(sk->sk_state);
if (unlikely(state != TCP_CLOSE)) {
err = state == TCP_ESTABLISHED ? -EISCONN : -EINVAL;
+ reason = SKB_DROP_REASON_SOCKET_INVALID_STATE;
goto out_unlock;
}
@@ -1629,12 +1641,14 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
if (unlikely(sk->sk_state != TCP_CLOSE)) {
err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EINVAL;
unix_state_unlock(sk);
+ reason = SKB_DROP_REASON_SOCKET_INVALID_STATE;
goto out_unlock;
}
err = security_unix_stream_connect(sk, other, newsk);
if (err) {
unix_state_unlock(sk);
+ reason = SKB_DROP_REASON_SECURITY_HOOK;
goto out_unlock;
}
@@ -1699,7 +1713,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
unix_state_unlock(other);
sock_put(other);
out_free_skb:
- kfree_skb(skb);
+ kfree_skb_reason(skb, reason);
out_free_sk:
unix_release_sock(newsk, 0);
out:
--
2.39.5 (Apple Git-154)
Powered by blists - more mailing lists