From 8c9e75af5f36fc3e2bcbda5601a3e7b9c854839e Mon Sep 17 00:00:00 2001
From: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
Date: Wed, 21 Jun 2017 23:15:59 -0400
Subject: [PATCH] tls: prevent recursive call to flushRxQueue()

TlsSession::flushRxQueue() let TlsSession::handleDataPacket() to be called
causing a recursive call to TlsSession::flushRxQueue(), finally resulting
into application crash.

Solve that by testing if we're in flush opeation and just no-op in such case.

Change-Id: Ie4d52a9df495784e36e3691404f44cd8f66dbb6d
---
 src/security/tls_session.cpp | 15 +++++++++++++++
 src/security/tls_session.h   |  1 +
 2 files changed, 16 insertions(+)

diff --git a/src/security/tls_session.cpp b/src/security/tls_session.cpp
index 4a36762def..5753dacb07 100644
--- a/src/security/tls_session.cpp
+++ b/src/security/tls_session.cpp
@@ -941,10 +941,25 @@ TlsSession::handleDataPacket(std::vector<uint8_t>&& buf, uint64_t pkt_seq)
 void
 TlsSession::flushRxQueue()
 {
+    // RAII bool swap
+    class GuardedBoolSwap {
+    public:
+        explicit GuardedBoolSwap(bool& var) : var_ {var} { var_ = !var_; }
+        ~GuardedBoolSwap() { var_ = !var_; }
+    private:
+        bool& var_;
+    };
+
     std::unique_lock<std::mutex> lk {reorderBufMutex_};
     if (reorderBuffer_.empty())
         return;
 
+    // Prevent re-entrant access as the callbacks_.onRxData() is called in unprotected region
+    if (flushProcessing_)
+        return;
+
+    GuardedBoolSwap swap_flush_processing {flushProcessing_};
+
     auto item = std::begin(reorderBuffer_);
     auto next_offset = item->first;
     auto first_offset = next_offset;
diff --git a/src/security/tls_session.h b/src/security/tls_session.h
index de04573148..c36a79bfa2 100644
--- a/src/security/tls_session.h
+++ b/src/security/tls_session.h
@@ -219,6 +219,7 @@ private:
     std::list<std::vector<uint8_t>> rxQueue_ {};
 
     std::mutex reorderBufMutex_;
+    bool flushProcessing_ {false}; ///< protect against recursive call to flushRxQueue
     std::vector<uint8_t> rawPktBuf_; ///< gnutls incoming packet buffer
     uint64_t baseSeq_ {0}; ///< sequence number of first application data packet received
     uint64_t lastRxSeq_ {0}; ///< last received and valid packet sequence number
-- 
GitLab