diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2016-11-29 22:05:17 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2016-11-29 22:13:52 +0100 |
commit | 10ee8d85e07e0d1bcd10d56bfa3ccbaaa8cfba8b (patch) | |
tree | 3c29e6c5da8bceaec2cc714cd4333ef01970ad62 /src/send.c | |
parent | 92a8e5054807e1c314fbc4b56cbdfed4d2108c75 (diff) |
send: send packet initiation only after requeuing to prevent race
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src/send.c')
-rw-r--r-- | src/send.c | 17 |
1 files changed, 11 insertions, 6 deletions
@@ -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 |