From 10ee8d85e07e0d1bcd10d56bfa3ccbaaa8cfba8b Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 29 Nov 2016 22:05:17 +0100 Subject: send: send packet initiation only after requeuing to prevent race Signed-off-by: Jason A. Donenfeld --- src/send.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src/send.c') diff --git a/src/send.c b/src/send.c index b2ae84b..5f3f165 100644 --- a/src/send.c +++ b/src/send.c @@ -158,11 +158,6 @@ int packet_send_queue(struct wireguard_peer *peer) switch (packet_create_data(&queue, peer, message_create_data_done)) { case 0: break; - case -ENOKEY: - /* ENOKEY means that we don't have a valid session for the peer, which - * means we should initiate a session, and then requeue everything. */ - packet_queue_handshake_initiation(peer); - goto requeue; case -EBUSY: /* EBUSY happens when the parallel workers are all filled up, in which * case we should requeue everything. */ @@ -170,7 +165,7 @@ int packet_send_queue(struct wireguard_peer *peer) /* First, we mark that we should try to do this later, when existing * jobs are done. */ peer->need_resend_queue = true; - requeue: + /* We stick the remaining skbs from local_queue at the top of the peer's * queue again, setting the top of local_queue to be the skb that begins * the requeueing. */ @@ -178,6 +173,16 @@ int packet_send_queue(struct wireguard_peer *peer) skb_queue_splice(&queue, &peer->tx_packet_queue); spin_unlock_irqrestore(&peer->tx_packet_queue.lock, flags); break; + case -ENOKEY: + /* ENOKEY means that we don't have a valid session for the peer, which + * means we should initiate a session, but after requeuing like above. */ + + spin_lock_irqsave(&peer->tx_packet_queue.lock, flags); + skb_queue_splice(&queue, &peer->tx_packet_queue); + spin_unlock_irqrestore(&peer->tx_packet_queue.lock, flags); + + packet_queue_handshake_initiation(peer); + break; default: /* If we failed for any other reason, we want to just free the packets and * forget about them. We do this unlocked, since we're the only ones with -- cgit v1.2.3