summaryrefslogtreecommitdiff
path: root/net/unix/af_unix.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-06-26 09:13:27 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2025-06-26 09:13:27 -0700
commite34a79b96ab9d49ed8b605fee11099cf3efbb428 (patch)
tree5c8c3a3699f1ba09f74bf85a2cdd493f2b811e64 /net/unix/af_unix.c
parentee88bddf7f2f5d1f1da87dd7bedc734048b70e88 (diff)
parent85720e04d9af0b77f8092b12a06661a8d459d4a0 (diff)
Merge tag 'net-6.16-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Paolo Abeni: "Including fixes from bluetooth and wireless. Current release - regressions: - bridge: fix use-after-free during router port configuration Current release - new code bugs: - eth: wangxun: fix the creation of page_pool Previous releases - regressions: - netpoll: initialize UDP checksum field before checksumming - wifi: mac80211: finish link init before RCU publish - bluetooth: fix use-after-free in vhci_flush() - eth: - ionic: fix DMA mapping test - bnxt: properly flush XDP redirect lists Previous releases - always broken: - netlink: specs: enforce strict naming of properties - unix: don't leave consecutive consumed OOB skbs. - vsock: fix linux/vm_sockets.h userspace compilation errors - selftests: fix TCP packet checksum" * tag 'net-6.16-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (38 commits) net: libwx: fix the creation of page_pool net: selftests: fix TCP packet checksum atm: Release atm_dev_mutex after removing procfs in atm_dev_deregister(). netlink: specs: enforce strict naming of properties netlink: specs: tc: replace underscores with dashes in names netlink: specs: rt-link: replace underscores with dashes in names netlink: specs: mptcp: replace underscores with dashes in names netlink: specs: ovs_flow: replace underscores with dashes in names netlink: specs: devlink: replace underscores with dashes in names netlink: specs: dpll: replace underscores with dashes in names netlink: specs: ethtool: replace underscores with dashes in names netlink: specs: fou: replace underscores with dashes in names netlink: specs: nfsd: replace underscores with dashes in names net: enetc: Correct endianness handling in _enetc_rd_reg64 atm: idt77252: Add missing `dma_map_error()` bnxt: properly flush XDP redirect lists vsock/uapi: fix linux/vm_sockets.h userspace compilation errors wifi: mac80211: finish link init before RCU publish wifi: iwlwifi: mvm: assume '1' as the default mac_config_cmd version selftest: af_unix: Add tests for -ECONNRESET. ...
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r--net/unix/af_unix.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 22e170fb5dda..52b155123985 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -660,6 +660,11 @@ static void unix_sock_destructor(struct sock *sk)
#endif
}
+static unsigned int unix_skb_len(const struct sk_buff *skb)
+{
+ return skb->len - UNIXCB(skb).consumed;
+}
+
static void unix_release_sock(struct sock *sk, int embrion)
{
struct unix_sock *u = unix_sk(sk);
@@ -694,10 +699,16 @@ static void unix_release_sock(struct sock *sk, int embrion)
if (skpair != NULL) {
if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
+ struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
+
+#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
+ if (skb && !unix_skb_len(skb))
+ skb = skb_peek_next(skb, &sk->sk_receive_queue);
+#endif
unix_state_lock(skpair);
/* No more writes */
WRITE_ONCE(skpair->sk_shutdown, SHUTDOWN_MASK);
- if (!skb_queue_empty_lockless(&sk->sk_receive_queue) || embrion)
+ if (skb || embrion)
WRITE_ONCE(skpair->sk_err, ECONNRESET);
unix_state_unlock(skpair);
skpair->sk_state_change(skpair);
@@ -2661,11 +2672,6 @@ static long unix_stream_data_wait(struct sock *sk, long timeo,
return timeo;
}
-static unsigned int unix_skb_len(const struct sk_buff *skb)
-{
- return skb->len - UNIXCB(skb).consumed;
-}
-
struct unix_stream_read_state {
int (*recv_actor)(struct sk_buff *, int, int,
struct unix_stream_read_state *);
@@ -2680,11 +2686,11 @@ struct unix_stream_read_state {
#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
static int unix_stream_recv_urg(struct unix_stream_read_state *state)
{
+ struct sk_buff *oob_skb, *read_skb = NULL;
struct socket *sock = state->socket;
struct sock *sk = sock->sk;
struct unix_sock *u = unix_sk(sk);
int chunk = 1;
- struct sk_buff *oob_skb;
mutex_lock(&u->iolock);
unix_state_lock(sk);
@@ -2699,9 +2705,16 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state)
oob_skb = u->oob_skb;
- if (!(state->flags & MSG_PEEK))
+ if (!(state->flags & MSG_PEEK)) {
WRITE_ONCE(u->oob_skb, NULL);
+ if (oob_skb->prev != (struct sk_buff *)&sk->sk_receive_queue &&
+ !unix_skb_len(oob_skb->prev)) {
+ read_skb = oob_skb->prev;
+ __skb_unlink(read_skb, &sk->sk_receive_queue);
+ }
+ }
+
spin_unlock(&sk->sk_receive_queue.lock);
unix_state_unlock(sk);
@@ -2712,6 +2725,8 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state)
mutex_unlock(&u->iolock);
+ consume_skb(read_skb);
+
if (chunk < 0)
return -EFAULT;