]> Git Repo - linux.git/commitdiff
kcm: Fix error handling for SOCK_DGRAM in kcm_sendmsg().
authorKuniyuki Iwashima <[email protected]>
Tue, 12 Sep 2023 02:27:53 +0000 (19:27 -0700)
committerPaolo Abeni <[email protected]>
Thu, 14 Sep 2023 08:43:51 +0000 (10:43 +0200)
syzkaller found a memory leak in kcm_sendmsg(), and commit c821a88bd720
("kcm: Fix memory leak in error path of kcm_sendmsg()") suppressed it by
updating kcm_tx_msg(head)->last_skb if partial data is copied so that the
following sendmsg() will resume from the skb.

However, we cannot know how many bytes were copied when we get the error.
Thus, we could mess up the MSG_MORE queue.

When kcm_sendmsg() fails for SOCK_DGRAM, we should purge the queue as we
do so for UDP by udp_flush_pending_frames().

Even without this change, when the error occurred, the following sendmsg()
resumed from a wrong skb and the queue was messed up.  However, we have
yet to get such a report, and only syzkaller stumbled on it.  So, this
can be changed safely.

Note this does not change SOCK_SEQPACKET behaviour.

Fixes: c821a88bd720 ("kcm: Fix memory leak in error path of kcm_sendmsg()")
Fixes: ab7ac4eb9832 ("kcm: Kernel Connection Multiplexor module")
Signed-off-by: Kuniyuki Iwashima <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Paolo Abeni <[email protected]>
net/kcm/kcmsock.c

index 740539a218b7c94d500c0ae415f0369507eaee2b..dd1d8ffd5f5941a423a4ea43c1867709a101d0a0 100644 (file)
@@ -930,17 +930,18 @@ partial_message:
 out_error:
        kcm_push(kcm);
 
-       if (copied && sock->type == SOCK_SEQPACKET) {
+       if (sock->type == SOCK_SEQPACKET) {
                /* Wrote some bytes before encountering an
                 * error, return partial success.
                 */
-               goto partial_message;
-       }
-
-       if (head != kcm->seq_skb)
+               if (copied)
+                       goto partial_message;
+               if (head != kcm->seq_skb)
+                       kfree_skb(head);
+       } else {
                kfree_skb(head);
-       else if (copied)
-               kcm_tx_msg(head)->last_skb = skb;
+               kcm->seq_skb = NULL;
+       }
 
        err = sk_stream_error(sk, msg->msg_flags, err);
 
This page took 0.056601 seconds and 4 git commands to generate.