]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
af_unix: Remove dead code in unix_stream_read_generic().
authorKuniyuki Iwashima <kuniyu@amazon.com>
Wed, 29 May 2024 14:46:48 +0000 (07:46 -0700)
committerJakub Kicinski <kuba@kernel.org>
Sat, 1 Jun 2024 23:28:55 +0000 (16:28 -0700)
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>
net/unix/af_unix.c

index 25b49efc0926b00d51cb8aaa5c205d96ff900127..861793b489f6b80e2ff025e77de50f534c568774 100644 (file)
@@ -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;