summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/CoreDump.cpp4
-rw-r--r--Userland/Applications/CrashReporter/main.cpp8
-rw-r--r--Userland/Libraries/LibCoreDump/CMakeLists.txt2
-rw-r--r--Userland/Libraries/LibCoreDump/Reader.cpp19
-rw-r--r--Userland/Libraries/LibCoreDump/Reader.h6
-rw-r--r--Userland/Services/CrashDaemon/CMakeLists.txt2
-rw-r--r--Userland/Services/CrashDaemon/main.cpp41
-rw-r--r--Userland/Services/SystemServer/main.cpp3
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();