summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuniyuki Iwashima <kuniyu@amazon.com>2024-05-29 07:46:48 -0700
committerJakub Kicinski <kuba@kernel.org>2024-06-01 16:28:55 -0700
commitb5c089880723b2c18531c40e445235bd646a51d1 (patch)
tree694e5b292cb60aa58b3f43039ae161b92f812774
parent750ed239bfd61562d8ef7e5619d8c0035f4ecfa1 (diff)
downloadlinux-stable-b5c089880723b2c18531c40e445235bd646a51d1.tar.gz
linux-stable-b5c089880723b2c18531c40e445235bd646a51d1.tar.bz2
linux-stable-b5c089880723b2c18531c40e445235bd646a51d1.zip
af_unix: Remove dead code in unix_stream_read_generic().
When splice() support was added in commit 2b514574f7e8 ("net: af_unix: implement splice for stream af_unix sockets"), we had to release unix_sk(sk)->readlock (current iolock) before calling splice_to_pipe(). Due to the unlock, commit 73ed5d25dce0 ("af-unix: fix use-after-free with concurrent readers while splicing") added a safeguard in unix_stream_read_generic(); we had to bump the skb refcount before calling ->recv_actor() and then check if the skb was consumed by a concurrent reader. However, the pipe side locking was refactored, and since commit 25869262ef7a ("skb_splice_bits(): get rid of callback"), we can call splice_to_pipe() without releasing unix_sk(sk)->iolock. Now, the skb is always alive after the ->recv_actor() callback, so let's remove the unnecessary drop_skb logic. This is mostly the revert of commit 73ed5d25dce0 ("af-unix: fix use-after-free with concurrent readers while splicing"). Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> Link: https://lore.kernel.org/r/20240529144648.68591-1-kuniyu@amazon.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--net/unix/af_unix.c21
1 files changed, 2 insertions, 19 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 25b49efc0926..861793b489f6 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -654,8 +654,8 @@ static void unix_release_sock(struct sock *sk, int embrion)
while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
if (state == TCP_LISTEN)
unix_release_sock(skb->sk, 1);
+
/* passed fds are erased in the kfree_skb hook */
- UNIXCB(skb).consumed = skb->len;
kfree_skb(skb);
}
@@ -2704,9 +2704,8 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
skip = max(sk_peek_offset(sk, flags), 0);
do {
- int chunk;
- bool drop_skb;
struct sk_buff *skb, *last;
+ int chunk;
redo:
unix_state_lock(sk);
@@ -2802,11 +2801,7 @@ unlock:
}
chunk = min_t(unsigned int, unix_skb_len(skb) - skip, size);
- skb_get(skb);
chunk = state->recv_actor(skb, skip, chunk, state);
- drop_skb = !unix_skb_len(skb);
- /* skb is only safe to use if !drop_skb */
- consume_skb(skb);
if (chunk < 0) {
if (copied == 0)
copied = -EFAULT;
@@ -2815,18 +2810,6 @@ unlock:
copied += chunk;
size -= chunk;
- if (drop_skb) {
- /* the skb was touched by a concurrent reader;
- * we should not expect anything from this skb
- * anymore and assume it invalid - we can be
- * sure it was dropped from the socket queue
- *
- * let's report a short read
- */
- err = 0;
- break;
- }
-
/* Mark read part of skb as used */
if (!(flags & MSG_PEEK)) {
UNIXCB(skb).consumed += chunk;