diff --git a/Kernel/Coredump.cpp b/Kernel/Coredump.cpp index 5c56d73e8bd..198955660ae 100644 --- a/Kernel/Coredump.cpp +++ b/Kernel/Coredump.cpp @@ -23,52 +23,39 @@ namespace Kernel { -OwnPtr Coredump::create(NonnullRefPtr process, const String& output_path) +KResultOr> Coredump::try_create(NonnullRefPtr process, StringView output_path) { if (!process->is_dumpable()) { dbgln("Refusing to generate coredump for non-dumpable process {}", process->pid().value()); - return {}; + return EPERM; } - auto fd = create_target_file(process, output_path); - if (!fd) - return {}; - return adopt_own_if_nonnull(new (nothrow) Coredump(move(process), fd.release_nonnull())); + auto description = TRY(try_create_target_file(process, output_path)); + return adopt_nonnull_own_or_enomem(new (nothrow) Coredump(move(process), move(description))); } -Coredump::Coredump(NonnullRefPtr process, NonnullRefPtr&& fd) +Coredump::Coredump(NonnullRefPtr process, NonnullRefPtr description) : m_process(move(process)) - , m_fd(move(fd)) + , m_description(move(description)) , m_num_program_headers(m_process->address_space().region_count() + 1) // +1 for NOTE segment { } -RefPtr Coredump::create_target_file(const Process& process, const String& output_path) +KResultOr> Coredump::try_create_target_file(Process const& process, StringView output_path) { auto output_directory = KLexicalPath::dirname(output_path); - auto dump_directory = VirtualFileSystem::the().open_directory(output_directory, VirtualFileSystem::the().root_custody()); - if (dump_directory.is_error()) { - dbgln("Can't find directory '{}' for coredump", output_directory); - return nullptr; - } - auto dump_directory_metadata = dump_directory.value()->inode().metadata(); + auto dump_directory = TRY(VirtualFileSystem::the().open_directory(output_directory, VirtualFileSystem::the().root_custody())); + auto dump_directory_metadata = dump_directory->inode().metadata(); if (dump_directory_metadata.uid != 0 || dump_directory_metadata.gid != 0 || dump_directory_metadata.mode != 040777) { dbgln("Refusing to put coredump in sketchy directory '{}'", output_directory); - return nullptr; + return EINVAL; } - auto fd_or_error = VirtualFileSystem::the().open( + return TRY(VirtualFileSystem::the().open( KLexicalPath::basename(output_path), O_CREAT | O_WRONLY | O_EXCL, S_IFREG, // We will enable reading from userspace when we finish generating the coredump file - *dump_directory.value(), - UidAndGid { process.uid(), process.gid() }); - - if (fd_or_error.is_error()) { - dbgln("Failed to open coredump '{}' for writing", output_path); - return nullptr; - } - - return fd_or_error.value(); + *dump_directory, + UidAndGid { process.uid(), process.gid() })); } KResult Coredump::write_elf_header() @@ -111,7 +98,7 @@ KResult Coredump::write_elf_header() elf_file_header.e_shnum = 0; elf_file_header.e_shstrndx = SHN_UNDEF; - TRY(m_fd->write(UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast(&elf_file_header)), sizeof(ElfW(Ehdr)))); + TRY(m_description->write(UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast(&elf_file_header)), sizeof(ElfW(Ehdr)))); return KSuccess; } @@ -139,7 +126,7 @@ KResult Coredump::write_program_headers(size_t notes_size) offset += phdr.p_filesz; - [[maybe_unused]] auto rc = m_fd->write(UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast(&phdr)), sizeof(ElfW(Phdr))); + [[maybe_unused]] auto rc = m_description->write(UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast(&phdr)), sizeof(ElfW(Phdr))); } ElfW(Phdr) notes_pheader {}; @@ -152,7 +139,7 @@ KResult Coredump::write_program_headers(size_t notes_size) notes_pheader.p_align = 0; notes_pheader.p_flags = 0; - TRY(m_fd->write(UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast(¬es_pheader)), sizeof(ElfW(Phdr)))); + TRY(m_description->write(UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast(¬es_pheader)), sizeof(ElfW(Phdr)))); return KSuccess; } @@ -180,7 +167,7 @@ KResult Coredump::write_regions() // (A page may not be backed by a physical page because it has never been faulted in when the process ran). src_buffer = UserOrKernelBuffer::for_kernel_buffer(zero_buffer); } - TRY(m_fd->write(src_buffer.value(), PAGE_SIZE)); + TRY(m_description->write(src_buffer.value(), PAGE_SIZE)); } } return KSuccess; @@ -188,7 +175,7 @@ KResult Coredump::write_regions() KResult Coredump::write_notes_segment(ByteBuffer& notes_segment) { - TRY(m_fd->write(UserOrKernelBuffer::for_kernel_buffer(notes_segment.data()), notes_segment.size())); + TRY(m_description->write(UserOrKernelBuffer::for_kernel_buffer(notes_segment.data()), notes_segment.size())); return KSuccess; } @@ -345,7 +332,7 @@ KResult Coredump::write() TRY(write_regions()); TRY(write_notes_segment(notes_segment)); - return m_fd->chmod(0600); // Make coredump file read/writable + return m_description->chmod(0600); // Make coredump file read/writable } } diff --git a/Kernel/Coredump.h b/Kernel/Coredump.h index de405fbe666..197b9feb83c 100644 --- a/Kernel/Coredump.h +++ b/Kernel/Coredump.h @@ -15,14 +15,14 @@ namespace Kernel { class Coredump { public: - static OwnPtr create(NonnullRefPtr, const String& output_path); + static KResultOr> try_create(NonnullRefPtr, StringView output_path); ~Coredump() = default; [[nodiscard]] KResult write(); private: - Coredump(NonnullRefPtr, NonnullRefPtr&&); - static RefPtr create_target_file(const Process&, const String& output_path); + Coredump(NonnullRefPtr, NonnullRefPtr); + static KResultOr> try_create_target_file(Process const&, StringView output_path); [[nodiscard]] KResult write_elf_header(); [[nodiscard]] KResult write_program_headers(size_t notes_size); @@ -36,7 +36,7 @@ private: KResultOr create_notes_metadata_data() const; NonnullRefPtr m_process; - NonnullRefPtr m_fd; + NonnullRefPtr m_description; const size_t m_num_program_headers; }; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 01677c62d0a..23e095d047d 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -553,10 +553,10 @@ bool Process::dump_core() VERIFY(should_generate_coredump()); dbgln("Generating coredump for pid: {}", pid().value()); auto coredump_path = String::formatted("/tmp/coredump/{}_{}_{}", name(), pid().value(), kgettimeofday().to_truncated_seconds()); - auto coredump = Coredump::create(*this, coredump_path); - if (!coredump) + auto coredump_or_error = Coredump::try_create(*this, coredump_path); + if (coredump_or_error.is_error()) return false; - return !coredump->write().is_error(); + return !coredump_or_error.value()->write().is_error(); } bool Process::dump_perfcore()