From fb25c11f793eab560d98d8c527c0f67d484d034e Mon Sep 17 00:00:00 2001 From: Philipp Rudo Date: Mar 28 2022 16:39:31 +0000 Subject: use cycle detection when parsing the prink log_buf Resolves: bz2069200 Upstream: github.com/makedumpfile/makedumpfile.git Conflicts: None commit 68d120b30af5e930afafed81e79712af3c1a278c Author: Philipp Rudo Date: Mon Mar 14 17:04:31 2022 +0100 [PATCH v2 3/3] use cycle detection when parsing the prink log_buf The old printk mechanism (> v3.5.0 and < v5.10.0) had a fixed size buffer (log_buf) that contains all messages. The location for the next message is stored in log_next_idx. In case the log_buf runs full log_next_idx wraps around and starts overwriting old messages at the beginning of the buffer. The wraparound is denoted by a message with msg->len == 0. Following the behavior described above blindly in makedumpfile is dangerous as e.g. a memory corruption could overwrite (parts of) the log_buf. If the corruption adds a message with msg->len == 0 this leads to an endless loop when dumping the dmesg with makedumpfile appending the messages up to the corruption over and over again to the output file until file system is full. Fix this by using cycle detection and aboard once one is detected. While at it also verify that the index is within the log_buf and thus guard against corruptions with msg->len != 0. Reported-by: Audra Mitchell Suggested-by: Dave Wysochanski Signed-off-by: Philipp Rudo Reviewed-and-tested-by: Dave Wysochanski Signed-off-by: Philipp Rudo --- diff --git a/kexec-tools-2.0.23-03-_PATCH_v2_3_3_use_cycle_detection_when_parsing_the_prink_log_buf.patch b/kexec-tools-2.0.23-03-_PATCH_v2_3_3_use_cycle_detection_when_parsing_the_prink_log_buf.patch new file mode 100644 index 0000000..fc70613 --- /dev/null +++ b/kexec-tools-2.0.23-03-_PATCH_v2_3_3_use_cycle_detection_when_parsing_the_prink_log_buf.patch @@ -0,0 +1,118 @@ + commit 68d120b30af5e930afafed81e79712af3c1a278c + Author: Philipp Rudo + Date: Mon Mar 14 17:04:31 2022 +0100 + + [PATCH v2 3/3] use cycle detection when parsing the prink log_buf + + The old printk mechanism (> v3.5.0 and < v5.10.0) had a fixed size + buffer (log_buf) that contains all messages. The location for the next + message is stored in log_next_idx. In case the log_buf runs full + log_next_idx wraps around and starts overwriting old messages at the + beginning of the buffer. The wraparound is denoted by a message with + msg->len == 0. + + Following the behavior described above blindly in makedumpfile is + dangerous as e.g. a memory corruption could overwrite (parts of) the + log_buf. If the corruption adds a message with msg->len == 0 this leads + to an endless loop when dumping the dmesg with makedumpfile appending + the messages up to the corruption over and over again to the output file + until file system is full. Fix this by using cycle detection and aboard + once one is detected. + + While at it also verify that the index is within the log_buf and thus + guard against corruptions with msg->len != 0. + + Reported-by: Audra Mitchell + Suggested-by: Dave Wysochanski + Signed-off-by: Philipp Rudo + Reviewed-and-tested-by: Dave Wysochanski + + diff --git a/makedumpfile-1.7.0/makedumpfile.c b/makedumpfile-1.7.0/makedumpfile.c + index e72dba219eec198ec865045562f39a14b5a092eb..2b94446b8f2ad513da060e15821544ae32e1a2c6 100644 + --- a/makedumpfile-1.7.0/makedumpfile.c + +++ b/makedumpfile-1.7.0/makedumpfile.c + @@ -15,6 +15,7 @@ + */ + #include "makedumpfile.h" + #include "print_info.h" + +#include "detect_cycle.h" + #include "dwarf_info.h" + #include "elf_info.h" + #include "erase_info.h" + @@ -5526,10 +5527,11 @@ dump_dmesg() + unsigned long index, log_buf, log_end; + unsigned int log_first_idx, log_next_idx; + unsigned long long first_idx_sym; + + struct detect_cycle *dc = NULL; + unsigned long log_end_2_6_24; + unsigned log_end_2_6_25; + char *log_buffer = NULL, *log_ptr = NULL; + - char *ptr; + + char *ptr, *next_ptr; + + /* + * log_end has been changed to "unsigned" since linux-2.6.25. + @@ -5677,12 +5679,55 @@ dump_dmesg() + goto out; + } + ptr = log_buffer + log_first_idx; + + dc = dc_init(ptr, log_buffer, log_next); + while (ptr != log_buffer + log_next_idx) { + log_ptr = log_from_ptr(ptr, log_buffer); + if (!dump_log_entry(log_ptr, info->fd_dumpfile, + info->name_dumpfile)) + goto out; + ptr = log_next(ptr, log_buffer); + + if (dc_next(dc, (void **) &next_ptr)) { + + unsigned long len; + + int in_cycle; + + char *first; + + + + /* Clear everything we have already written... */ + + ftruncate(info->fd_dumpfile, 0); + + lseek(info->fd_dumpfile, 0, SEEK_SET); + + + + /* ...and only write up to the corruption. */ + + dc_find_start(dc, (void **) &first, &len); + + ptr = log_buffer + log_first_idx; + + in_cycle = FALSE; + + while (len) { + + log_ptr = log_from_ptr(ptr, log_buffer); + + if (!dump_log_entry(log_ptr, + + info->fd_dumpfile, + + info->name_dumpfile)) + + goto out; + + ptr = log_next(ptr, log_buffer); + + + + if (log_ptr == first) + + in_cycle = TRUE; + + + + if (in_cycle) + + len--; + + } + + ERRMSG("Cycle when parsing dmesg detected.\n"); + + ERRMSG("The printk log_buf is most likely corrupted.\n"); + + ERRMSG("log_buf = 0x%lx, idx = 0x%lx\n", log_buf, ptr - log_buffer); + + close_files_for_creating_dumpfile(); + + goto out; + + } + + if (next_ptr < log_buffer || + + next_ptr > log_buffer + log_buf_len - SIZE(printk_log)) { + + ERRMSG("Index outside log_buf detected.\n"); + + ERRMSG("The printk log_buf is most likely corrupted.\n"); + + ERRMSG("log_buf = 0x%lx, idx = 0x%lx\n", log_buf, ptr - log_buffer); + + close_files_for_creating_dumpfile(); + + goto out; + + } + + ptr = next_ptr; + } + if (!close_files_for_creating_dumpfile()) + goto out; + @@ -5692,6 +5737,7 @@ dump_dmesg() + out: + if (log_buffer) + free(log_buffer); + + free(dc); + + return ret; + } diff --git a/kexec-tools.spec b/kexec-tools.spec index 4ffc73d..de18616 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -115,6 +115,7 @@ Patch601: ./kexec-tools-2.0.22-01-s390_handle_R_390_PLT32DBL_reloc_entries_in_ma Patch602: ./kexec-tools-2.0.23-makedumpfile-sadump-kaslr-fix-failure-of-calculating-kaslr_.patch Patch603: ./kexec-tools-2.0.23-01-_PATCH_v2_1_3_add_generic_cycle_detection.patch Patch604: ./kexec-tools-2.0.23-02-_PATCH_v2_2_3_use_pointer_arithmetics_for_dump_dmesg.patch +Patch605: ./kexec-tools-2.0.23-03-_PATCH_v2_3_3_use_cycle_detection_when_parsing_the_prink_log_buf.patch %description kexec-tools provides /sbin/kexec binary that facilitates a new @@ -134,6 +135,7 @@ tar -z -x -v -f %{SOURCE19} %patch602 -p1 %patch603 -p1 %patch604 -p1 +%patch605 -p1 %ifarch ppc %define archdef ARCH=ppc