@cryptotaxi247 / netdata-1 / commits / fc83a2e9e

Release memory on shutdown - detect invalid extent in journal files (#19861)

* Release all memory for metasync thread * Cleanup * Validate extent index in journal entries to prevent invalid access * Proper free * Improve error logging for invalid extent index in journal file

Stelios Fragkakis committed Mar 14, 2025 at 23:53 UTC fc83a2e9e7503afa4758d64315862a5cd6f8d34a
2 files changed +21 -6
src/database/engine/pagecache.c
+8
@@ -530,6 +530,7 @@ static ALWAYS_INLINE_HOT size_t get_page_list_from_journal_v2(struct rrdengine_i
530 struct journal_page_header *page_list_header = (struct journal_page_header *) ((uint8_t *) j2_header + uuid_entry->page_offset);
531 struct journal_page_list *page_list = (struct journal_page_list *)((uint8_t *) page_list_header + sizeof(*page_list_header));
532 struct journal_extent_list *extent_list = (void *)((uint8_t *)j2_header + j2_header->extent_offset);
533 + uint32_t extent_entries = j2_header->extent_count;
534 uint32_t uuid_page_entries = page_list_header->entries;
535
536 for (uint32_t index = 0; index < uuid_page_entries; index++) {
@@ -545,6 +546,13 @@ static ALWAYS_INLINE_HOT size_t get_page_list_from_journal_v2(struct rrdengine_i
546 if(prc == PAGE_IS_IN_THE_FUTURE)
547 break;
548
549 + // Make sure index is valid for this file
550 + if (page_entry_in_journal->extent_index > extent_entries) {
551 + nd_log_limit_static_thread_var(erl, 60, 0);
552 + nd_log_limit(&erl, NDLS_DAEMON, NDLP_ERR, "DBENGINE: Invalid extent index in journalfile %u", datafile->fileno);
553 + break;
554 + }
555 +
556 uint32_t page_update_every_s = page_entry_in_journal->update_every_s;
557 size_t page_length = page_entry_in_journal->page_length;
558
src/database/sqlite/sqlite_metadata.c
+13 -6
@@ -2417,6 +2417,15 @@ static void start_metadata_hosts(uv_work_t *req)
2417 worker_is_idle();
2418 }
2419
2420 +static void close_callback(uv_handle_t *handle, void *data __maybe_unused)
2421 +{
2422 + if (handle->type == UV_TIMER) {
2423 + uv_timer_stop((uv_timer_t *)handle);
2424 + }
2425 +
2426 + uv_close(handle, NULL); // Automatically close and free the handle
2427 +}
2428 +
2429 static void metadata_event_loop(void *arg)
2430 {
2431 worker_register("METASYNC");
@@ -2430,7 +2439,6 @@ static void metadata_event_loop(void *arg)
2439 worker_register_job_name(METADATA_DEL_HOST_AE, "delete host alert entry");
2440
2441 int ret;
2433 - uv_loop_t *loop;
2442 unsigned cmd_batch_size;
2443 struct metadata_wc *wc = arg;
2444 enum metadata_opcode opcode;
@@ -2438,12 +2446,13 @@ static void metadata_event_loop(void *arg)
2446 wc->ar = aral_by_size_acquire(sizeof(struct metadata_cmd));
2447
2448 uv_thread_set_name_np("METASYNC");
2441 - loop = wc->loop = mallocz(sizeof(uv_loop_t));
2449 + uv_loop_t *loop = wc->loop = mallocz(sizeof(uv_loop_t));
2450 ret = uv_loop_init(loop);
2451 if (ret) {
2452 netdata_log_error("uv_loop_init(): %s", uv_strerror(ret));
2453 goto error_after_loop_init;
2454 }
2455 +
2456 loop->data = wc;
2457
2458 ret = uv_async_init(wc->loop, &wc->async, async_cb);
@@ -2619,17 +2628,15 @@ static void metadata_event_loop(void *arg)
2628 } while (opcode != METADATA_DATABASE_NOOP);
2629 }
2630
2622 - if (!uv_timer_stop(&wc->timer_req))
2623 - uv_close((uv_handle_t *)&wc->timer_req, NULL);
2631 + uv_walk(loop, (uv_walk_cb) close_callback, NULL);
2632 + uv_run(loop, UV_RUN_NOWAIT);
2633
2625 - uv_close((uv_handle_t *)&wc->async, NULL);
2634 int rc;
2635 do {
2636 rc = uv_loop_close(loop);
2637 } while (rc != UV_EBUSY);
2638
2639 buffer_free(work_buffer);
2632 - freez(loop);
2640 worker_unregister();
2641
2642 nd_log(NDLS_DAEMON, NDLP_DEBUG, "Shutting down metadata thread");