diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 104be85bd..801e67d2e 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -120,9 +120,11 @@ namespace cryptonote core_rpc_server::core_rpc_server( core& cr , nodetool::node_server >& p2p + , bool restricted ) : m_core(cr) , m_p2p(p2p) + , m_restricted(restricted) , disable_rpc_ban(false) {} //------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 02b1c1552..31efccc36 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -73,6 +73,7 @@ namespace cryptonote core_rpc_server( core& cr , nodetool::node_server >& p2p + , bool restricted = false ); ~core_rpc_server(); diff --git a/tests/fuzz/fuzz_rpc/README.md b/tests/fuzz/fuzz_rpc/README.md index 05831c18e..7366b64fc 100644 --- a/tests/fuzz/fuzz_rpc/README.md +++ b/tests/fuzz/fuzz_rpc/README.md @@ -9,14 +9,14 @@ These are the main fuzzing entry points, containing `LLVMFuzzerTestOneInput`, wh ## `initialisation.cpp` / `initialisation.h` -This set of source files provides initialisation helper functions to configure the `core_rpc_server` class with dummy protocols, P2P, payment modules, and other components. It also includes functions to generate fake random blocks, miners, and transactions for use in fuzzing. +This set of source files provides initialisation helper functions to configure the `core_rpc_server` class with dummy protocols, P2P, and other components. It also includes functions to generate fake random blocks, miners, and transactions for use in fuzzing. ## `rpc_endpoints.cpp` / `rpc_endpoints.h` / `zmq_endpoints.cpp` / `zmq_endpoints.h` These source files handle the creation of the necessary request and response objects and the invocation of specific endpoint functions. These simulate real RPC requests / ZMQ requests for the purpose of fuzzing. There are three categories of RPC endpoint functions and only one for ZMQ endpoint functions: * **Safe**: Considered stable and unlikely to fail. -* **Risky**: More prone to failure and early exits, especially if no valid blockchain is generated or no payment modules are configured. +* **Risky**: More prone to failure and early exits, especially if no valid blockchain is generated. * **Priority**: Most critical RPC endpoint functions that will at least run once per iteration. # Building the Fuzzing Harnesses @@ -24,7 +24,7 @@ These source files handle the creation of the necessary request and response obj The same `fuzz_rpc.cpp` is compiled into two versions of the fuzzer, one with the `SAFE` macro defined and one without. Meanwhile, `fuzz_zmq` is compiled into a single version. * With `SAFE` defined: Only safe endpoint functions are fuzzed. -* Without `SAFE`: Both safe and risky functions are included in the fuzzing process, and payment modules are configured. +* Without `SAFE`: Both safe and risky functions are included in the fuzzing process. # Fuzzing Harness Flow @@ -35,8 +35,7 @@ Random data is used to generate selectors that choose an RPC endpoint function / ## `initialise_rpc_core` / `initialise_rpc_server` -At the start of each fuzzing iteration, a `core_rpc_server` object is created and initialised with dummy protocols, P2P, payment modules, and more. -If the `SAFE` macro is not defined, the payment module will also be initialised. +At the start of each fuzzing iteration, a `core_rpc_server` object is created and initialised with dummy protocols and P2P. The fuzz input selects whether the server runs in restricted or unrestricted RPC mode. This step is skipped for `fuzz_zmq`. ## `generate_random_blocks` diff --git a/tests/fuzz/fuzz_rpc/fuzz_rpc.cpp b/tests/fuzz/fuzz_rpc/fuzz_rpc.cpp index 1f38da381..365bd9aac 100644 --- a/tests/fuzz/fuzz_rpc/fuzz_rpc.cpp +++ b/tests/fuzz/fuzz_rpc/fuzz_rpc.cpp @@ -57,8 +57,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { // Initialise core and core_rpc_server auto core_env = initialise_rpc_core(); + if (!core_env) { + return 0; + } auto& dummy_core = core_env->core; - auto rpc_handler = initialise_rpc_server(*dummy_core, provider, !is_safe_mode); + auto rpc_handler = initialise_rpc_server(*dummy_core, provider.ConsumeBool()); // Generate random blocks/miners/transactions and push to the core blockchains if (!generate_random_blocks(*dummy_core, provider)) { diff --git a/tests/fuzz/fuzz_rpc/initialisation.cpp b/tests/fuzz/fuzz_rpc/initialisation.cpp index 9d9a8aeaf..7cac0320a 100644 --- a/tests/fuzz/fuzz_rpc/initialisation.cpp +++ b/tests/fuzz/fuzz_rpc/initialisation.cpp @@ -16,6 +16,7 @@ #include "serialization/binary_utils.h" #include "serialization/variant.h" +#include #include #include #include @@ -51,21 +52,29 @@ std::unique_ptr initialise_rpc_core() { cryptonote::core::init_options(desc); boost::program_options::variables_map vm; - // Add command line argument to configure the rpc core object to use regression testing mode (FAKECHAIN) - // Enabling FAKECHAIN mode allows skipping validation logic of the authors signature and transactions ID - // on valid blocks and transactions while keeping other logic - std::vector argv = {"fuzz", "--regtest"}; + // Add command line arguments to configure the rpc core object to use regression testing mode (FAKECHAIN) + // and a throwaway data directory. Enabling FAKECHAIN mode allows skipping validation logic of the authors + // signature and transactions ID on valid blocks and transactions while keeping other logic. + const boost::filesystem::path data_dir = boost::filesystem::temp_directory_path() / "monero-fuzz-rpc"; + std::vector args = {"fuzz", "--regtest", "--offline", "--data-dir", data_dir.string()}; + std::vector argv; + argv.reserve(args.size()); + for (const auto& arg : args) { + argv.push_back(arg.c_str()); + } boost::program_options::store(boost::program_options::parse_command_line(argv.size(), argv.data(), desc), vm); boost::program_options::notify(vm); // Initialise the dummy core with all the above settings - env->core->init(vm); + if (!env->core->init(vm)) { + return nullptr; + } return env; } // Build the core_rpc_server handler object with the configured dummy core object -std::unique_ptr initialise_rpc_server(cryptonote::core& dummy_core, FuzzedDataProvider& provider, bool need_payment) { +std::unique_ptr initialise_rpc_server(cryptonote::core& dummy_core, bool restricted) { // Create rpc server bundle object auto bundle = std::make_unique(); @@ -73,7 +82,7 @@ std::unique_ptr initialise_rpc_server(cryptonote::core& dummy_c bundle->proto_handler = std::make_unique>(dummy_core, nullptr, true); bundle->proto_handler->set_no_sync(false); bundle->dummy_p2p = std::make_unique>>(*bundle->proto_handler); - bundle->rpc = std::make_unique(dummy_core, *bundle->dummy_p2p); + bundle->rpc = std::make_unique(dummy_core, *bundle->dummy_p2p, restricted); return bundle; } diff --git a/tests/fuzz/fuzz_rpc/initialisation.h b/tests/fuzz/fuzz_rpc/initialisation.h index e892c410e..f3783a6d0 100644 --- a/tests/fuzz/fuzz_rpc/initialisation.h +++ b/tests/fuzz/fuzz_rpc/initialisation.h @@ -6,7 +6,7 @@ // Define templates for dummy protocol object template class nodetool::node_server>; -struct DummyProtocol : public cryptonote::i_cryptonote_protocol { +struct DummyProtocol final : public cryptonote::i_cryptonote_protocol { public: bool is_synchronized() const; bool relay_transactions(cryptonote::NOTIFY_NEW_TRANSACTIONS::request&, const boost::uuids::uuid&, epee::net_utils::zone, cryptonote::relay_method); @@ -25,7 +25,7 @@ struct CoreEnv { }; std::unique_ptr initialise_rpc_core(); -std::unique_ptr initialise_rpc_server(cryptonote::core&, FuzzedDataProvider&, bool); +std::unique_ptr initialise_rpc_server(cryptonote::core&, bool); bool generate_random_blocks(cryptonote::core&, FuzzedDataProvider&); extern std::vector cached_tx_hashes;