mirror of
https://github.com/meshtastic/firmware.git
synced 2025-09-06 03:29:17 +00:00
Use loopCanSleep instead of a lock in Router
This commit is contained in:
parent
08c82b53b7
commit
091b174e2b
@ -1,4 +1,5 @@
|
|||||||
// Fuzzer implementation that sends MeshPackets to Router::enqueueReceivedMessage.
|
// Fuzzer implementation that sends MeshPackets to Router::enqueueReceivedMessage.
|
||||||
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <pb_decode.h>
|
#include <pb_decode.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -15,7 +16,30 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
constexpr uint32_t nodeId = 0x12345678;
|
constexpr uint32_t nodeId = 0x12345678;
|
||||||
|
// Set to true when lateInitVariant finishes. Used to ensure lateInitVariant was called during startup.
|
||||||
bool hasBeenConfigured = false;
|
bool hasBeenConfigured = false;
|
||||||
|
|
||||||
|
// These are used to block the Arduino loop() function until a fuzzer input is ready. This is
|
||||||
|
// an optimization that prevents a sleep from happening before the loop is run. The Arduino loop
|
||||||
|
// function calls loopCanSleep() before sleeping. loopCanSleep is implemented here in the fuzzer
|
||||||
|
// and blocks until startLoop() is called to signal for the loop to run.
|
||||||
|
bool fuzzerRunning = false; // Set to true once LLVMFuzzerTestOneInput has started running.
|
||||||
|
bool loopCanRun = true; // The main Arduino loop() can run when this is true.
|
||||||
|
bool loopIsWaiting = false; // The main Arduino loop() is waiting to be signaled to run.
|
||||||
|
std::mutex loopLock;
|
||||||
|
std::condition_variable loopCV;
|
||||||
|
|
||||||
|
// Start the loop for one test case and wait till the loop has completed. This ensures fuzz
|
||||||
|
// test cases do not overlap with one another. This helps the fuzzer attribute a crash to the
|
||||||
|
// single, currently running, test case.
|
||||||
|
void runLoopOnce()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lck(loopLock);
|
||||||
|
fuzzerRunning = true;
|
||||||
|
loopCanRun = true;
|
||||||
|
loopCV.notify_one();
|
||||||
|
loopCV.wait(lck, [] { return !loopCanRun && loopIsWaiting; });
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// Called just prior to starting Meshtastic. Allows for setting config values before startup.
|
// Called just prior to starting Meshtastic. Allows for setting config values before startup.
|
||||||
@ -71,6 +95,22 @@ void lateInitVariant()
|
|||||||
hasBeenConfigured = true;
|
hasBeenConfigured = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called in the main Arduino loop function to determine if the loop can delay/sleep before running again.
|
||||||
|
// We use this as a way to block the loop from sleeping and to start the loop function immediately when a
|
||||||
|
// fuzzer input is ready.
|
||||||
|
bool loopCanSleep()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lck(loopLock);
|
||||||
|
loopIsWaiting = true;
|
||||||
|
loopCV.notify_one();
|
||||||
|
loopCV.wait(lck, [] { return loopCanRun; });
|
||||||
|
loopIsWaiting = false;
|
||||||
|
if (!fuzzerRunning)
|
||||||
|
return true; // The loop can sleep before the fuzzer starts.
|
||||||
|
loopCanRun = false; // Only run the loop once before waiting again.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
int portduino_main(int argc, char **argv); // Renamed "main" function from Meshtastic binary.
|
int portduino_main(int argc, char **argv); // Renamed "main" function from Meshtastic binary.
|
||||||
|
|
||||||
@ -134,13 +174,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t length)
|
|||||||
if (p.pki_encrypted && config.security.admin_key_count)
|
if (p.pki_encrypted && config.security.admin_key_count)
|
||||||
memcpy(&p.public_key, &config.security.admin_key[0], sizeof(p.public_key));
|
memcpy(&p.public_key, &config.security.admin_key[0], sizeof(p.public_key));
|
||||||
|
|
||||||
// Ideally only one packet, the one generated by the fuzzer, is being processed by the firmware at
|
|
||||||
// a time. We acquire a lock here, and the router unlocks it after it has processed all queued packets.
|
|
||||||
// Grabbing the lock again, below, should block until the queue has been emptied.
|
|
||||||
router->inProgressLock.lock();
|
|
||||||
router->enqueueReceivedMessage(packetPool.allocCopy(p));
|
router->enqueueReceivedMessage(packetPool.allocCopy(p));
|
||||||
|
runLoopOnce();
|
||||||
const std::lock_guard<std::mutex> lck(router->inProgressLock);
|
|
||||||
return 0; // Accept: The input may be added to the corpus.
|
return 0; // Accept: The input may be added to the corpus.
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -70,10 +70,6 @@ int32_t Router::runOnce()
|
|||||||
perhapsHandleReceived(mp);
|
perhapsHandleReceived(mp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
||||||
inProgressLock.unlock();
|
|
||||||
return 5;
|
|
||||||
#endif
|
|
||||||
// LOG_DEBUG("Sleep forever!");
|
// LOG_DEBUG("Sleep forever!");
|
||||||
return INT32_MAX; // Wait a long time - until we get woken for the message queue
|
return INT32_MAX; // Wait a long time - until we get woken for the message queue
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,6 @@
|
|||||||
#include "RadioInterface.h"
|
#include "RadioInterface.h"
|
||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
|
|
||||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
||||||
#include <mutex>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mesh aware router that supports multiple interfaces.
|
* A mesh aware router that supports multiple interfaces.
|
||||||
*/
|
*/
|
||||||
@ -90,12 +86,6 @@ class Router : protected concurrency::OSThread
|
|||||||
before us */
|
before us */
|
||||||
uint32_t rxDupe = 0, txRelayCanceled = 0;
|
uint32_t rxDupe = 0, txRelayCanceled = 0;
|
||||||
|
|
||||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
||||||
// Used by router_fuzzer.cpp to detect when the Router has finished processing a packet.
|
|
||||||
// See LLVMFuzzerTestOneInput in router_fuzzer.cpp & Router::runOnce for how this is used.
|
|
||||||
std::mutex inProgressLock;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class RoutingModule;
|
friend class RoutingModule;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user