Validate journal file headers to prevent invalid memory access (#20013)
Stelios Fragkakis committed
Mar 31, 2025 at 21:11 UTC
72e26d423bc93082c154b1c282a981ef7fa77584
1 file changed
+17
src/database/engine/pagecache.c
+17
@@ -514,11 +514,20 @@ static ALWAYS_INLINE_HOT size_t get_page_list_from_journal_v2(struct rrdengine_i
514
continue;
515
516
time_t journal_start_time_s = (time_t)(j2_header->start_time_ut / USEC_PER_SEC);
517
+ size_t journal_v2_file_size = datafile->journalfile->mmap.size;
518
519
// the datafile possibly contains useful data for this query
520
521
size_t journal_metric_count = (size_t)j2_header->metric_count;
522
struct journal_metric_list *uuid_list = (struct journal_metric_list *)((uint8_t *) j2_header + j2_header->metric_offset);
523
+ size_t metric_offset = (uint8_t *) uuid_list - (uint8_t *) j2_header;
524
+ if (metric_offset >= journal_v2_file_size) {
525
+ nd_log_limit_static_thread_var(erl, 60, 0);
526
+ nd_log_limit(&erl, NDLS_DAEMON, NDLP_ERR, "DBENGINE: Invalid metric list header in journalfile %u of tier %u", datafile->fileno, datafile->tier);
527
+ journalfile_v2_data_release(datafile->journalfile);
528
+ continue;
529
+ }
530
+
531
struct journal_metric_list *uuid_entry = bsearch(uuid,uuid_list,journal_metric_count,sizeof(*uuid_list), journal_metric_uuid_compare);
532
533
if (unlikely(!uuid_entry)) {
@@ -528,6 +537,14 @@ static ALWAYS_INLINE_HOT size_t get_page_list_from_journal_v2(struct rrdengine_i
537
}
538
539
struct journal_page_header *page_list_header = (struct journal_page_header *) ((uint8_t *) j2_header + uuid_entry->page_offset);
540
+ size_t page_offset = (uint8_t *) page_list_header - (uint8_t *) j2_header;
541
+ if (page_offset >= journal_v2_file_size) {
542
+ nd_log_limit_static_thread_var(erl, 60, 0);
543
+ nd_log_limit(&erl, NDLS_DAEMON, NDLP_ERR, "DBENGINE: Invalid page list header in journalfile %u of tier %u", datafile->fileno, datafile->tier);
544
+ journalfile_v2_data_release(datafile->journalfile);
545
+ continue;
546
+ }
547
+
548
struct journal_page_list *page_list = (struct journal_page_list *)((uint8_t *) page_list_header + sizeof(*page_list_header));
549
struct journal_extent_list *extent_list = (void *)((uint8_t *)j2_header + j2_header->extent_offset);
550
uint32_t extent_entries = j2_header->extent_count;