Skip to content

Null deref when invoking dqlite_node_stop or dqlite_server_handover before start #848

@hgarrereyn

Description

@hgarrereyn

Hi, currently trying to invoke dqlite_node_stop or dqlite_server_handover on a node which has not yet been started results in a segmentation fault, trying to access a libuv object that has not yet been set up.

While this of course isn't the intended path, it seems like the kind of thing that could accidentally happen in a complex enough application, e.g. due to some error handling path.

Additionally, it seems like it would be easy to add a check to see if the node is already running before attempting these actions, returning an error rather than crashing.

Tested on 4ef89f32.

See the following testcase:

testcase.cpp

#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include <string>
#include <sys/stat.h>
#include <unistd.h>

extern "C" {
    #include "dqlite.h"
}

int main() {
    dqlite_node *n = nullptr;

    // Create a writable temporary directory for data_dir
    char tmpl[] = "/tmp/dqliteXXXXXX";
    char *dir = mkdtemp(tmpl);
    if (dir == nullptr) return 0;

    dqlite_node_id id = 1;               // valid nonzero id
    const char *address = "127.0.0.1:0"; // accepted address format

    if (dqlite_node_create(id, address, dir, &n) != 0 || n == nullptr)
        return 0;

    // Crash: stop called before the node has ever been started
    dqlite_node_stop(n);
    return 0;
}

crash report

{
  "Date": "2025-09-27T22:24:19.805571+00:00",
  "Uname": "Linux f2315d4dd311 5.15.0-140-generic #150-Ubuntu SMP Sat Apr 12 06:00:09 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux",
  "OS": "Ubuntu",
  "OSRelease": "22.04",
  "Architecture": "amd64",
  "ExecutablePath": "/tmp/tmp88t520eu/reproducer",
  "ProcEnviron": [
    "LIBAFL_EDGES_MAP_SIZE=800000",
    "PWD=/fuzz/workspace",
    "CXX=gf_libafl_cxx",
    "GRAPHFUZZ_USE_ASAN=1",
    "HOME=/root",
    "ASAN_OPTIONS=hard_rss_limit_mb=1024:detect_leaks=0",
    "TERM=xterm-256color",
    "SHLVL=1",
    "LD_LIBRARY_PATH=/fuzz/install/lib",
    "PATH=/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "CC=gf_libafl_cc",
    "DEBIAN_FRONTEND=noninteractive",
    "OLDPWD=/fuzz/src",
    "_=/usr/local/bin/agfi"
  ],
  "ProcCmdline": "/tmp/tmp88t520eu/reproducer",
  "Stdin": "",
  "ProcStatus": [],
  "ProcMaps": [],
  "ProcFiles": [],
  "NetworkConnections": [],
  "CrashSeverity": {
    "Type": "NOT_EXPLOITABLE",
    "ShortDescription": "SourceAvNearNull",
    "Description": "Access violation near NULL on source operand",
    "Explanation": "The target crashed on an access violation at an address matching the source operand of the current instruction. This likely indicates a read access violation, which may mean the application crashed on a simple NULL dereference to data structure that has no immediate effect on control of the processor."
  },
  "Stacktrace": [
    "    #0 0x7ffff7f9040f in uv_async_send (/lib/x86_64-linux-gnu/libuv.so.1+0xe40f) (BuildId: 54f0f8d9667009c05ed5cfab3c004ab86d575260)",
    "    #1 0x555555684a81 in dqlite_node_stop /fuzz/src/src/server.c:881:7",
    "    #2 0x555555681e8e in main /tmp/tmp88t520eu/reproducer.cpp:28:5",
    "    #3 0x7ffff78ccd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16",
    "    #4 0x7ffff78cce3f in __libc_start_main csu/../csu/libc-start.c:392:3",
    "    #5 0x5555555a6c04 in _start (/tmp/tmp88t520eu/reproducer+0x52c04) (BuildId: c379c86784532a1501ee47c3f649f89b1de1d87a)"
  ],
  "Registers": {},
  "Disassembly": [],
  "Package": "",
  "PackageVersion": "",
  "PackageArchitecture": "",
  "PackageDescription": "",
  "AsanReport": [
    "==155==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000200 (pc 0x7ffff7f9040f bp 0x7fffffffea70 sp 0x7fffffffe9d0 T0)",
    "==155==The signal is caused by a READ memory access.",
    "==155==Hint: address points to the zero page.",
    "    #0 0x7ffff7f9040f in uv_async_send (/lib/x86_64-linux-gnu/libuv.so.1+0xe40f) (BuildId: 54f0f8d9667009c05ed5cfab3c004ab86d575260)",
    "    #1 0x555555684a81 in dqlite_node_stop /fuzz/src/src/server.c:881:7",
    "    #2 0x555555681e8e in main /tmp/tmp88t520eu/reproducer.cpp:28:5",
    "    #3 0x7ffff78ccd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16",
    "    #4 0x7ffff78cce3f in __libc_start_main csu/../csu/libc-start.c:392:3",
    "    #5 0x5555555a6c04 in _start (/tmp/tmp88t520eu/reproducer+0x52c04) (BuildId: c379c86784532a1501ee47c3f649f89b1de1d87a)",
    "",
    "AddressSanitizer can not provide additional info.",
    "SUMMARY: AddressSanitizer: SEGV (/lib/x86_64-linux-gnu/libuv.so.1+0xe40f) (BuildId: 54f0f8d9667009c05ed5cfab3c004ab86d575260) in uv_async_send",
    "==155==ABORTING"
  ],
  "MsanReport": [],
  "UbsanReport": [],
  "LuaReport": [],
  "PythonReport": [],
  "GoReport": [],
  "JavaReport": [],
  "RustReport": [],
  "JsReport": [],
  "CSharpReport": [],
  "CrashLine": "/lib/x86_64-linux-gnu/libuv.so.1+0xe40f",
  "Source": []
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions