[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250110092641.85905-8-kuniyu@amazon.com>
Date: Fri, 10 Jan 2025 18:26:36 +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 07/12] af_unix: Set drop reason in unix_stream_sendmsg().
sendmsg() to a SOCK_STREAM socket could fail for various reasons.
Let's set drop reasons respectively.
* NOMEM : Failed to allocate SCM_RIGHTS-related structs
* UNIX_INFLIGHT_FD_LIMIT : The number of inflight fd reached RLIMIT_NOFILE
* SKB_UCOPY_FAULT : Failed to copy data from iov_iter to skb
* SOCKET_CLOSE : The peer socket was close()d
* SOCKET_RCV_SHUTDOWN : The peer socket called shutdown(SHUT_RD)
unix_scm_err_to_reason() will be reused in queue_oob() and
unix_dgram_sendmsg().
Signed-off-by: Kuniyuki Iwashima <kuniyu@...zon.com>
---
include/net/dropreason-core.h | 6 +++++
net/unix/af_unix.c | 41 ++++++++++++++++++++++++++++++-----
2 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
index 1b5e962f7f33..dea6bbe3ceaa 100644
--- a/include/net/dropreason-core.h
+++ b/include/net/dropreason-core.h
@@ -11,6 +11,7 @@
FN(SOCKET_INVALID_STATE) \
FN(SOCKET_RCVBUFF) \
FN(SOCKET_RCV_SHUTDOWN) \
+ FN(UNIX_INFLIGHT_FD_LIMIT) \
FN(PKT_TOO_SMALL) \
FN(TCP_CSUM) \
FN(UDP_CSUM) \
@@ -150,6 +151,11 @@ enum skb_drop_reason {
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_UNIX_INFLIGHT_FD_LIMIT: too many file descriptors
+ * are passed via SCM_RIGHTS but not yet received, reaching RLIMIT_NOFILE.
+ */
+ SKB_DROP_REASON_UNIX_INFLIGHT_FD_LIMIT,
/** @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 6505eeab9957..17b9e9bce055 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1907,6 +1907,22 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen
return err;
}
+static enum skb_drop_reason unix_scm_err_to_reason(int err)
+{
+ switch (err) {
+ case -ENOMEM:
+ return SKB_DROP_REASON_NOMEM;
+ case -ETOOMANYREFS:
+ return SKB_DROP_REASON_UNIX_INFLIGHT_FD_LIMIT;
+ }
+
+ DEBUG_NET_WARN_ONCE(1,
+ "Define a drop reason for %d in unix_scm_to_skb().",
+ err);
+
+ return SKB_DROP_REASON_NOT_SPECIFIED;
+}
+
static bool unix_passcred_enabled(const struct socket *sock,
const struct sock *other)
{
@@ -2249,6 +2265,7 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other
static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
size_t len)
{
+ enum skb_drop_reason reason;
struct sock *sk = sock->sk;
struct sk_buff *skb = NULL;
struct sock *other = NULL;
@@ -2314,8 +2331,10 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
/* Only send the fds in the first buffer */
err = unix_scm_to_skb(&scm, skb, !fds_sent);
- if (err < 0)
+ if (err < 0) {
+ reason = unix_scm_err_to_reason(err);
goto out_free;
+ }
fds_sent = true;
@@ -2323,8 +2342,10 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
skb->ip_summed = CHECKSUM_UNNECESSARY;
err = skb_splice_from_iter(skb, &msg->msg_iter, size,
sk->sk_allocation);
- if (err < 0)
+ if (err < 0) {
+ reason = SKB_DROP_REASON_SKB_UCOPY_FAULT;
goto out_free;
+ }
size = err;
refcount_add(size, &sk->sk_wmem_alloc);
@@ -2333,15 +2354,23 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
skb->data_len = data_len;
skb->len = size;
err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, size);
- if (err)
+ if (err) {
+ reason = SKB_DROP_REASON_SKB_UCOPY_FAULT;
goto out_free;
+ }
}
unix_state_lock(other);
- if (sock_flag(other, SOCK_DEAD) ||
- (other->sk_shutdown & RCV_SHUTDOWN))
+ if (sock_flag(other, SOCK_DEAD)) {
+ reason = SKB_DROP_REASON_SOCKET_CLOSE;
goto out_pipe_unlock;
+ }
+
+ if (other->sk_shutdown & RCV_SHUTDOWN) {
+ reason = SKB_DROP_REASON_SOCKET_RCV_SHUTDOWN;
+ goto out_pipe_unlock;
+ }
maybe_add_creds(skb, sock, other);
scm_stat_add(other, skb);
@@ -2371,7 +2400,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
send_sig(SIGPIPE, current, 0);
err = -EPIPE;
out_free:
- kfree_skb(skb);
+ kfree_skb_reason(skb, reason);
out_err:
scm_destroy(&scm);
return sent ? : err;
--
2.39.5 (Apple Git-154)
Powered by blists - more mailing lists