Skip to content

Commit e81fdf7

Browse files
committed
Merge branch 'af_unix-set-skb-drop-reason-in-every-kfree_skb-path'
Kuniyuki Iwashima says: ==================== af_unix: Set skb drop reason in every kfree_skb() path. There is a potential user for skb drop reason for AF_UNIX. This series replaces some kfree_skb() in connect() and sendmsg() paths and sets skb drop reason for the rest of kfree_skb() in AF_UNIX. Link: https://lore.kernel.org/netdev/CAAf2ycmZHti95WaBR3s+L5Epm1q7sXmvZ-EqCK=-oZj=45tOwQ@mail.gmail.com/ v2: https://lore.kernel.org/20250112040810.14145-1-kuniyu@amazon.com/ v1: https://lore.kernel.org/20250110092641.85905-1-kuniyu@amazon.com/ ==================== Link: https://patch.msgid.link/20250116053441.5758-1-kuniyu@amazon.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 3a0b7fa + 085e6cb commit e81fdf7

File tree

3 files changed

+55
-42
lines changed

3 files changed

+55
-42
lines changed

include/net/dropreason-core.h

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66
#define DEFINE_DROP_REASON(FN, FNe) \
77
FN(NOT_SPECIFIED) \
88
FN(NO_SOCKET) \
9+
FN(SOCKET_CLOSE) \
10+
FN(SOCKET_FILTER) \
11+
FN(SOCKET_RCVBUFF) \
12+
FN(UNIX_DISCONNECT) \
13+
FN(UNIX_SKIP_OOB) \
914
FN(PKT_TOO_SMALL) \
1015
FN(TCP_CSUM) \
11-
FN(SOCKET_FILTER) \
1216
FN(UDP_CSUM) \
1317
FN(NETFILTER_DROP) \
1418
FN(OTHERHOST) \
@@ -18,7 +22,6 @@
1822
FN(UNICAST_IN_L2_MULTICAST) \
1923
FN(XFRM_POLICY) \
2024
FN(IP_NOPROTO) \
21-
FN(SOCKET_RCVBUFF) \
2225
FN(PROTO_MEM) \
2326
FN(TCP_AUTH_HDR) \
2427
FN(TCP_MD5NOTFOUND) \
@@ -138,12 +141,27 @@ enum skb_drop_reason {
138141
* 3) no valid child socket during 3WHS process
139142
*/
140143
SKB_DROP_REASON_NO_SOCKET,
144+
/** @SKB_DROP_REASON_SOCKET_CLOSE: socket is close()d */
145+
SKB_DROP_REASON_SOCKET_CLOSE,
146+
/** @SKB_DROP_REASON_SOCKET_FILTER: dropped by socket filter */
147+
SKB_DROP_REASON_SOCKET_FILTER,
148+
/** @SKB_DROP_REASON_SOCKET_RCVBUFF: socket receive buff is full */
149+
SKB_DROP_REASON_SOCKET_RCVBUFF,
150+
/**
151+
* @SKB_DROP_REASON_UNIX_DISCONNECT: recv queue is purged when SOCK_DGRAM
152+
* or SOCK_SEQPACKET socket re-connect()s to another socket or notices
153+
* during send() that the peer has been close()d.
154+
*/
155+
SKB_DROP_REASON_UNIX_DISCONNECT,
156+
/**
157+
* @SKB_DROP_REASON_UNIX_SKIP_OOB: Out-Of-Band data is skipped by
158+
* recv() without MSG_OOB so dropped.
159+
*/
160+
SKB_DROP_REASON_UNIX_SKIP_OOB,
141161
/** @SKB_DROP_REASON_PKT_TOO_SMALL: packet size is too small */
142162
SKB_DROP_REASON_PKT_TOO_SMALL,
143163
/** @SKB_DROP_REASON_TCP_CSUM: TCP checksum error */
144164
SKB_DROP_REASON_TCP_CSUM,
145-
/** @SKB_DROP_REASON_SOCKET_FILTER: dropped by socket filter */
146-
SKB_DROP_REASON_SOCKET_FILTER,
147165
/** @SKB_DROP_REASON_UDP_CSUM: UDP checksum error */
148166
SKB_DROP_REASON_UDP_CSUM,
149167
/** @SKB_DROP_REASON_NETFILTER_DROP: dropped by netfilter */
@@ -174,8 +192,6 @@ enum skb_drop_reason {
174192
SKB_DROP_REASON_XFRM_POLICY,
175193
/** @SKB_DROP_REASON_IP_NOPROTO: no support for IP protocol */
176194
SKB_DROP_REASON_IP_NOPROTO,
177-
/** @SKB_DROP_REASON_SOCKET_RCVBUFF: socket receive buff is full */
178-
SKB_DROP_REASON_SOCKET_RCVBUFF,
179195
/**
180196
* @SKB_DROP_REASON_PROTO_MEM: proto memory limitation, such as
181197
* udp packet drop out of udp_memory_allocated.

net/unix/af_unix.c

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,9 @@ static void unix_write_space(struct sock *sk)
622622
static void unix_dgram_disconnected(struct sock *sk, struct sock *other)
623623
{
624624
if (!skb_queue_empty(&sk->sk_receive_queue)) {
625-
skb_queue_purge(&sk->sk_receive_queue);
625+
skb_queue_purge_reason(&sk->sk_receive_queue,
626+
SKB_DROP_REASON_UNIX_DISCONNECT);
627+
626628
wake_up_interruptible_all(&unix_sk(sk)->peer_wait);
627629

628630
/* If one link of bidirectional dgram pipe is disconnected,
@@ -640,7 +642,7 @@ static void unix_sock_destructor(struct sock *sk)
640642
{
641643
struct unix_sock *u = unix_sk(sk);
642644

643-
skb_queue_purge(&sk->sk_receive_queue);
645+
skb_queue_purge_reason(&sk->sk_receive_queue, SKB_DROP_REASON_SOCKET_CLOSE);
644646

645647
DEBUG_NET_WARN_ON_ONCE(refcount_read(&sk->sk_wmem_alloc));
646648
DEBUG_NET_WARN_ON_ONCE(!sk_unhashed(sk));
@@ -715,8 +717,8 @@ static void unix_release_sock(struct sock *sk, int embrion)
715717
if (state == TCP_LISTEN)
716718
unix_release_sock(skb->sk, 1);
717719

718-
/* passed fds are erased in the kfree_skb hook */
719-
kfree_skb(skb);
720+
/* passed fds are erased in the kfree_skb hook */
721+
kfree_skb_reason(skb, SKB_DROP_REASON_SOCKET_CLOSE);
720722
}
721723

722724
if (path.dentry)
@@ -1699,7 +1701,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
16991701
unix_state_unlock(other);
17001702
sock_put(other);
17011703
out_free_skb:
1702-
kfree_skb(skb);
1704+
consume_skb(skb);
17031705
out_free_sk:
17041706
unix_release_sock(newsk, 0);
17051707
out:
@@ -2170,7 +2172,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
21702172
out_sock_put:
21712173
sock_put(other);
21722174
out_free:
2173-
kfree_skb(skb);
2175+
consume_skb(skb);
21742176
out:
21752177
scm_destroy(&scm);
21762178
return err;
@@ -2187,33 +2189,30 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other
21872189
{
21882190
struct unix_sock *ousk = unix_sk(other);
21892191
struct sk_buff *skb;
2190-
int err = 0;
2192+
int err;
21912193

21922194
skb = sock_alloc_send_skb(sock->sk, 1, msg->msg_flags & MSG_DONTWAIT, &err);
21932195

21942196
if (!skb)
21952197
return err;
21962198

21972199
err = unix_scm_to_skb(scm, skb, !fds_sent);
2198-
if (err < 0) {
2199-
kfree_skb(skb);
2200-
return err;
2201-
}
2200+
if (err < 0)
2201+
goto out;
2202+
22022203
skb_put(skb, 1);
22032204
err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, 1);
22042205

2205-
if (err) {
2206-
kfree_skb(skb);
2207-
return err;
2208-
}
2206+
if (err)
2207+
goto out;
22092208

22102209
unix_state_lock(other);
22112210

22122211
if (sock_flag(other, SOCK_DEAD) ||
22132212
(other->sk_shutdown & RCV_SHUTDOWN)) {
22142213
unix_state_unlock(other);
2215-
kfree_skb(skb);
2216-
return -EPIPE;
2214+
err = -EPIPE;
2215+
goto out;
22172216
}
22182217

22192218
maybe_add_creds(skb, sock, other);
@@ -2228,6 +2227,9 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other
22282227
unix_state_unlock(other);
22292228
other->sk_data_ready(other);
22302229

2230+
return 0;
2231+
out:
2232+
consume_skb(skb);
22312233
return err;
22322234
}
22332235
#endif
@@ -2236,13 +2238,11 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
22362238
size_t len)
22372239
{
22382240
struct sock *sk = sock->sk;
2241+
struct sk_buff *skb = NULL;
22392242
struct sock *other = NULL;
2240-
int err, size;
2241-
struct sk_buff *skb;
2242-
int sent = 0;
22432243
struct scm_cookie scm;
22442244
bool fds_sent = false;
2245-
int data_len;
2245+
int err, sent = 0;
22462246

22472247
err = scm_send(sock, msg, &scm, false);
22482248
if (err < 0)
@@ -2271,16 +2271,12 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
22712271
}
22722272
}
22732273

2274-
if (READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN) {
2275-
if (!(msg->msg_flags & MSG_NOSIGNAL))
2276-
send_sig(SIGPIPE, current, 0);
2277-
2278-
err = -EPIPE;
2279-
goto out_err;
2280-
}
2274+
if (READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN)
2275+
goto out_pipe;
22812276

22822277
while (sent < len) {
2283-
size = len - sent;
2278+
int size = len - sent;
2279+
int data_len;
22842280

22852281
if (unlikely(msg->msg_flags & MSG_SPLICE_PAGES)) {
22862282
skb = sock_alloc_send_pskb(sk, 0, 0,
@@ -2333,7 +2329,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
23332329

23342330
if (sock_flag(other, SOCK_DEAD) ||
23352331
(other->sk_shutdown & RCV_SHUTDOWN))
2336-
goto out_pipe;
2332+
goto out_pipe_unlock;
23372333

23382334
maybe_add_creds(skb, sock, other);
23392335
scm_stat_add(other, skb);
@@ -2356,13 +2352,14 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
23562352

23572353
return sent;
23582354

2359-
out_pipe:
2355+
out_pipe_unlock:
23602356
unix_state_unlock(other);
2357+
out_pipe:
23612358
if (!sent && !(msg->msg_flags & MSG_NOSIGNAL))
23622359
send_sig(SIGPIPE, current, 0);
23632360
err = -EPIPE;
23642361
out_free:
2365-
kfree_skb(skb);
2362+
consume_skb(skb);
23662363
out_err:
23672364
scm_destroy(&scm);
23682365
return sent ? : err;
@@ -2695,7 +2692,7 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
26952692
spin_unlock(&sk->sk_receive_queue.lock);
26962693

26972694
consume_skb(read_skb);
2698-
kfree_skb(unread_skb);
2695+
kfree_skb_reason(unread_skb, SKB_DROP_REASON_UNIX_SKIP_OOB);
26992696

27002697
return skb;
27012698
}
@@ -2724,7 +2721,7 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
27242721

27252722
if (sock_flag(sk, SOCK_DEAD)) {
27262723
unix_state_unlock(sk);
2727-
kfree_skb(skb);
2724+
kfree_skb_reason(skb, SKB_DROP_REASON_SOCKET_CLOSE);
27282725
return -ECONNRESET;
27292726
}
27302727

@@ -2738,7 +2735,7 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
27382735
unix_state_unlock(sk);
27392736

27402737
if (drop) {
2741-
kfree_skb(skb);
2738+
kfree_skb_reason(skb, SKB_DROP_REASON_UNIX_SKIP_OOB);
27422739
return -EAGAIN;
27432740
}
27442741
}

net/unix/garbage.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ static void __unix_gc(struct work_struct *work)
573573
UNIXCB(skb).fp->dead = true;
574574
}
575575

576-
__skb_queue_purge(&hitlist);
576+
__skb_queue_purge_reason(&hitlist, SKB_DROP_REASON_SOCKET_CLOSE);
577577
skip_gc:
578578
WRITE_ONCE(gc_in_progress, false);
579579
}

0 commit comments

Comments
 (0)