diff options
-rw-r--r-- | Kernel/CoreDump.cpp | 4 | ||||
-rw-r--r-- | Userland/Applications/CrashReporter/main.cpp | 8 | ||||
-rw-r--r-- | Userland/Libraries/LibCoreDump/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibCoreDump/Reader.cpp | 19 | ||||
-rw-r--r-- | Userland/Libraries/LibCoreDump/Reader.h | 6 | ||||
-rw-r--r-- | Userland/Services/CrashDaemon/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Userland/Services/CrashDaemon/main.cpp | 41 | ||||
-rw-r--r-- | Userland/Services/SystemServer/main.cpp | 3 |
8 files changed, 70 insertions, 15 deletions
diff --git a/Kernel/CoreDump.cpp b/Kernel/CoreDump.cpp index 706f2997ab..a6a6d5db25 100644 --- a/Kernel/CoreDump.cpp +++ b/Kernel/CoreDump.cpp @@ -72,7 +72,7 @@ RefPtr<FileDescription> CoreDump::create_target_file(const Process& process, con return nullptr; } auto dump_directory_metadata = dump_directory.value()->inode().metadata(); - if (dump_directory_metadata.uid != 0 || dump_directory_metadata.gid != 0 || dump_directory_metadata.mode != 040755) { + if (dump_directory_metadata.uid != 0 || dump_directory_metadata.gid != 0 || dump_directory_metadata.mode != 040777) { dbgln("Refusing to put core dump in sketchy directory '{}'", output_directory); return nullptr; } @@ -329,7 +329,7 @@ KResult CoreDump::write() if (result.is_error()) return result; - return m_fd->chmod(0400); // Make coredump file readable + return m_fd->chmod(0600); // Make coredump file read/writable } } diff --git a/Userland/Applications/CrashReporter/main.cpp b/Userland/Applications/CrashReporter/main.cpp index e1a02b2874..14f0e7bf68 100644 --- a/Userland/Applications/CrashReporter/main.cpp +++ b/Userland/Applications/CrashReporter/main.cpp @@ -30,6 +30,7 @@ #include <AK/URL.h> #include <Applications/CrashReporter/CrashReporterWindowGML.h> #include <LibCore/ArgsParser.h> +#include <LibCore/File.h> #include <LibCoreDump/Backtrace.h> #include <LibCoreDump/Reader.h> #include <LibDesktop/AppFile.h> @@ -118,10 +119,12 @@ int main(int argc, char** argv) } const char* coredump_path = nullptr; + bool unlink_after_use = false; Core::ArgsParser args_parser; args_parser.set_general_help("Show information from an application crash coredump."); args_parser.add_positional_argument(coredump_path, "Coredump path", "coredump-path"); + args_parser.add_option(unlink_after_use, "Delete the coredump after its parsed", "unlink", 0); args_parser.parse(argc, argv); Vector<TitleAndText> thread_backtraces; @@ -155,6 +158,11 @@ int main(int argc, char** argv) termination_signal = coredump->process_termination_signal(); } + if (unlink_after_use) { + if (Core::File::remove(coredump_path, Core::File::RecursionMode::Disallowed, false).is_error()) + dbgln("Failed deleting coredump file"); + } + auto app = GUI::Application::construct(argc, argv); if (pledge("stdio recvfd sendfd accept rpath unix", nullptr) < 0) { diff --git a/Userland/Libraries/LibCoreDump/CMakeLists.txt b/Userland/Libraries/LibCoreDump/CMakeLists.txt index f6a9457d30..d1b05fed07 100644 --- a/Userland/Libraries/LibCoreDump/CMakeLists.txt +++ b/Userland/Libraries/LibCoreDump/CMakeLists.txt @@ -4,4 +4,4 @@ set(SOURCES ) serenity_lib(LibCoreDump coredump) -target_link_libraries(LibCoreDump LibC LibCore LibDebug) +target_link_libraries(LibCoreDump LibC LibCompress LibCore LibDebug) diff --git a/Userland/Libraries/LibCoreDump/Reader.cpp b/Userland/Libraries/LibCoreDump/Reader.cpp index 24a97293fc..fee4fd2f6a 100644 --- a/Userland/Libraries/LibCoreDump/Reader.cpp +++ b/Userland/Libraries/LibCoreDump/Reader.cpp @@ -26,6 +26,7 @@ #include <AK/JsonObject.h> #include <AK/JsonValue.h> +#include <LibCompress/Gzip.h> #include <LibCoreDump/Reader.h> #include <signal_numbers.h> #include <string.h> @@ -37,12 +38,12 @@ OwnPtr<Reader> Reader::create(const String& path) auto file_or_error = MappedFile::map(path); if (file_or_error.is_error()) return {}; - return adopt_own(*new Reader(file_or_error.release_value())); + return adopt_own(*new Reader(file_or_error.value()->bytes())); } -Reader::Reader(NonnullRefPtr<MappedFile> coredump_file) - : m_coredump_file(move(coredump_file)) - , m_coredump_image(m_coredump_file->bytes()) +Reader::Reader(ReadonlyBytes coredump_bytes) + : m_coredump_buffer(decompress_coredump(coredump_bytes)) + , m_coredump_image(m_coredump_buffer.bytes()) { size_t index = 0; m_coredump_image.for_each_program_header([this, &index](auto pheader) { @@ -56,6 +57,16 @@ Reader::Reader(NonnullRefPtr<MappedFile> coredump_file) VERIFY(m_notes_segment_index != -1); } +ByteBuffer Reader::decompress_coredump(const ReadonlyBytes& raw_coredump) +{ + if (!Compress::GzipDecompressor::is_likely_compressed(raw_coredump)) + return ByteBuffer::copy(raw_coredump); // handle old format core dumps (uncompressed) + auto decompressed_coredump = Compress::GzipDecompressor::decompress_all(raw_coredump); + if (!decompressed_coredump.has_value()) + return ByteBuffer::copy(raw_coredump); // if we didnt manage to decompress it, try and parse it as decompressed core dump + return decompressed_coredump.value(); +} + Reader::~Reader() { } diff --git a/Userland/Libraries/LibCoreDump/Reader.h b/Userland/Libraries/LibCoreDump/Reader.h index 7fd3aaf715..8cf111d759 100644 --- a/Userland/Libraries/LibCoreDump/Reader.h +++ b/Userland/Libraries/LibCoreDump/Reader.h @@ -70,7 +70,9 @@ public: HashMap<String, String> metadata() const; private: - Reader(NonnullRefPtr<MappedFile>); + Reader(ReadonlyBytes); + + static ByteBuffer decompress_coredump(const ReadonlyBytes&); class NotesEntryIterator { public: @@ -92,7 +94,7 @@ private: // as getters with the appropriate (non-JsonValue) types. const JsonObject process_info() const; - NonnullRefPtr<MappedFile> m_coredump_file; + ByteBuffer m_coredump_buffer; ELF::Image m_coredump_image; ssize_t m_notes_segment_index { -1 }; }; diff --git a/Userland/Services/CrashDaemon/CMakeLists.txt b/Userland/Services/CrashDaemon/CMakeLists.txt index 5dcf13aacb..232c4d5a84 100644 --- a/Userland/Services/CrashDaemon/CMakeLists.txt +++ b/Userland/Services/CrashDaemon/CMakeLists.txt @@ -3,4 +3,4 @@ set(SOURCES ) serenity_bin(CrashDaemon) -target_link_libraries(CrashDaemon LibC LibCore LibCoreDump) +target_link_libraries(CrashDaemon LibC LibCompress LibCore LibCoreDump) diff --git a/Userland/Services/CrashDaemon/main.cpp b/Userland/Services/CrashDaemon/main.cpp index 6b27e3d41b..bed4770beb 100644 --- a/Userland/Services/CrashDaemon/main.cpp +++ b/Userland/Services/CrashDaemon/main.cpp @@ -25,6 +25,9 @@ */ #include <AK/LexicalPath.h> +#include <AK/MappedFile.h> +#include <LibCompress/Gzip.h> +#include <LibCore/File.h> #include <LibCore/FileWatcher.h> #include <LibCoreDump/Backtrace.h> #include <LibCoreDump/Reader.h> @@ -49,6 +52,33 @@ static void wait_until_coredump_is_ready(const String& coredump_path) } } +static bool compress_coredump(const String& coredump_path) +{ + auto file_or_error = MappedFile::map(coredump_path); + if (file_or_error.is_error()) { + dbgln("Could not open coredump '{}': {}", coredump_path, file_or_error.error()); + return false; + } + auto coredump_file = file_or_error.value(); + auto compressed_coredump = Compress::GzipCompressor::compress_all(coredump_file->bytes()); + if (!compressed_coredump.has_value()) { + dbgln("Could not compress coredump '{}'", coredump_path); + return false; + } + auto output_path = String::formatted("{}.gz", coredump_path); + auto output_file_or_error = Core::File::open(output_path, Core::File::WriteOnly); + if (output_file_or_error.is_error()) { + dbgln("Could not open '{}' for writing: {}", output_path, output_file_or_error.error()); + return false; + } + auto output_file = output_file_or_error.value(); + if (!output_file->write(compressed_coredump.value().data(), compressed_coredump.value().size())) { + dbgln("Could not write compressed coredump '{}'", output_path); + return false; + } + return true; +} + static void print_backtrace(const String& coredump_path) { auto coredump = CoreDump::Reader::create(coredump_path); @@ -70,10 +100,10 @@ static void print_backtrace(const String& coredump_path) }); } -static void launch_crash_reporter(const String& coredump_path) +static void launch_crash_reporter(const String& coredump_path, bool unlink_after_use) { pid_t child; - const char* argv[] = { "CrashReporter", coredump_path.characters(), nullptr, nullptr }; + const char* argv[] = { "CrashReporter", coredump_path.characters(), unlink_after_use ? "--unlink" : nullptr, nullptr, nullptr }; if ((errno = posix_spawn(&child, "/bin/CrashReporter", nullptr, nullptr, const_cast<char**>(argv), environ))) { perror("posix_spawn"); } else { @@ -84,7 +114,7 @@ static void launch_crash_reporter(const String& coredump_path) int main() { - if (pledge("stdio rpath proc exec", nullptr) < 0) { + if (pledge("stdio rpath wpath cpath proc exec", nullptr) < 0) { perror("pledge"); return 1; } @@ -96,9 +126,12 @@ int main() if (event.value().type != Core::FileWatcherEvent::Type::ChildAdded) continue; auto coredump_path = event.value().child_path; + if (coredump_path.ends_with(".gz")) + continue; // stops compress_coredump from accidentally triggering us dbgln("New coredump file: {}", coredump_path); wait_until_coredump_is_ready(coredump_path); + auto compressed = compress_coredump(coredump_path); print_backtrace(coredump_path); - launch_crash_reporter(coredump_path); + launch_crash_reporter(coredump_path, compressed); } } diff --git a/Userland/Services/SystemServer/main.cpp b/Userland/Services/SystemServer/main.cpp index 8773dc3b45..b7da5d2965 100644 --- a/Userland/Services/SystemServer/main.cpp +++ b/Userland/Services/SystemServer/main.cpp @@ -185,7 +185,8 @@ static void create_tmp_coredump_directory() { dbgln("Creating /tmp/coredump directory"); auto old_umask = umask(0); - auto rc = mkdir("/tmp/coredump", 0755); + // FIXME: the coredump directory should be made read-only once CrashDaemon is no longer responsible for compressing coredumps + auto rc = mkdir("/tmp/coredump", 0777); if (rc < 0) { perror("mkdir(/tmp/coredump)"); VERIFY_NOT_REACHED(); |