diff --git a/Kernel/Arch/x86/common/Interrupts.cpp b/Kernel/Arch/x86/common/Interrupts.cpp index 0e0caa2a59..d8df04b04d 100644 --- a/Kernel/Arch/x86/common/Interrupts.cpp +++ b/Kernel/Arch/x86/common/Interrupts.cpp @@ -382,14 +382,14 @@ void page_fault_handler(TrapFrame* trap) if (current_thread) { auto& current_process = current_thread->process(); if (current_process.is_user_process()) { - current_process.set_coredump_metadata("fault_address", String::formatted("{:p}", fault_address)); - current_process.set_coredump_metadata("fault_type", fault.type() == PageFault::Type::PageNotPresent ? "NotPresent" : "ProtectionViolation"); + (void)current_process.try_set_coredump_property("fault_address", String::formatted("{:p}", fault_address)); + (void)current_process.try_set_coredump_property("fault_type", fault.type() == PageFault::Type::PageNotPresent ? "NotPresent" : "ProtectionViolation"); String fault_access; if (fault.is_instruction_fetch()) fault_access = "Execute"; else fault_access = fault.access() == PageFault::Access::Read ? "Read" : "Write"; - current_process.set_coredump_metadata("fault_access", fault_access); + (void)current_process.try_set_coredump_property("fault_access", fault_access); } } diff --git a/Kernel/CoreDump.cpp b/Kernel/CoreDump.cpp index 0c9b131903..135579b820 100644 --- a/Kernel/CoreDump.cpp +++ b/Kernel/CoreDump.cpp @@ -291,8 +291,9 @@ ByteBuffer CoreDump::create_notes_metadata_data() const StringBuilder builder; { JsonObjectSerializer metadata_obj { builder }; - for (auto& it : m_process->coredump_metadata()) - metadata_obj.add(it.key, it.value); + m_process->for_each_coredump_property([&](auto& key, auto& value) { + metadata_obj.add(key.view(), value.view()); + }); } builder.append(0); metadata_data.append(builder.string_view().characters_without_null_termination(), builder.length()); diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 64a5e37620..5c5dc8c3c9 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -875,9 +875,26 @@ void Process::set_dumpable(bool dumpable) m_dumpable = dumpable; } -void Process::set_coredump_metadata(const String& key, String value) +KResult Process::set_coredump_property(NonnullOwnPtr key, NonnullOwnPtr value) { - m_coredump_metadata.set(key, move(value)); + // Write it into the first available property slot. + for (auto& slot : m_coredump_properties) { + if (slot.key) + continue; + slot.key = move(key); + slot.value = move(value); + return KSuccess; + } + return ENOBUFS; } +KResult Process::try_set_coredump_property(StringView key, StringView value) +{ + auto key_kstring = KString::try_create(key); + auto value_kstring = KString::try_create(value); + if (key_kstring && value_kstring) + return set_coredump_property(key_kstring.release_nonnull(), value_kstring.release_nonnull()); + return ENOMEM; +}; + } diff --git a/Kernel/Process.h b/Kernel/Process.h index ef9dc2a5d4..c50a714d8b 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -499,9 +499,17 @@ public: void unblock_waiters(Thread::WaitBlocker::UnblockFlags, u8 signal = 0); Thread::WaitBlockCondition& wait_block_condition() { return m_wait_block_condition; } - HashMap& coredump_metadata() { return m_coredump_metadata; } - const HashMap& coredump_metadata() const { return m_coredump_metadata; } - void set_coredump_metadata(const String& key, String value); + template + void for_each_coredump_property(Callback callback) const + { + for (auto& property : m_coredump_properties) { + if (property.key && property.value) + callback(*property.key, *property.value); + } + } + + KResult set_coredump_property(NonnullOwnPtr key, NonnullOwnPtr value); + KResult try_set_coredump_property(StringView key, StringView value); const NonnullRefPtrVector& threads_for_coredump(Badge) const { return m_threads_for_coredump; } @@ -757,7 +765,12 @@ private: Thread::WaitBlockCondition m_wait_block_condition; - HashMap m_coredump_metadata; + struct CoredumpProperty { + OwnPtr key; + OwnPtr value; + }; + + Array m_coredump_properties; NonnullRefPtrVector m_threads_for_coredump; @@ -915,8 +928,8 @@ inline ProcessID Thread::pid() const if (Process::current()->has_promises() \ && !Process::current()->has_promised(Pledge::promise)) { \ dbgln("Has not pledged {}", #promise); \ - Process::current()->coredump_metadata().set( \ - "pledge_violation", #promise); \ + (void)Process::current()->try_set_coredump_property( \ + "pledge_violation"sv, #promise); \ Process::current()->crash(SIGABRT, 0); \ VERIFY_NOT_REACHED(); \ } \ diff --git a/Kernel/Syscalls/execve.cpp b/Kernel/Syscalls/execve.cpp index 6412717a8d..093cdbdee1 100644 --- a/Kernel/Syscalls/execve.cpp +++ b/Kernel/Syscalls/execve.cpp @@ -577,7 +577,8 @@ KResult Process::do_exec(NonnullRefPtr main_program_description m_unveiled_paths.clear(); m_unveiled_paths.set_metadata({ "/", UnveilAccess::None, false }); - m_coredump_metadata.clear(); + for (auto& property : m_coredump_properties) + property = {}; auto current_thread = Thread::current(); current_thread->clear_signals(); diff --git a/Kernel/Syscalls/process.cpp b/Kernel/Syscalls/process.cpp index cfcf1b7317..ac5414d41c 100644 --- a/Kernel/Syscalls/process.cpp +++ b/Kernel/Syscalls/process.cpp @@ -61,16 +61,15 @@ KResultOr Process::sys$set_coredump_metadata(Userspace 16 * KiB) return EINVAL; - auto copied_key = copy_string_from_user(params.key.characters, params.key.length); - if (copied_key.is_null()) - return EFAULT; - auto copied_value = copy_string_from_user(params.value.characters, params.value.length); - if (copied_value.is_null()) - return EFAULT; - if (!m_coredump_metadata.contains(copied_key) && m_coredump_metadata.size() >= 16) - return EFAULT; - m_coredump_metadata.set(move(copied_key), move(copied_value)); - return 0; + auto key_or_error = try_copy_kstring_from_user(params.key); + if (key_or_error.is_error()) + return key_or_error.error(); + auto key = key_or_error.release_value(); + auto value_or_error = try_copy_kstring_from_user(params.value); + if (value_or_error.is_error()) + return value_or_error.error(); + auto value = value_or_error.release_value(); + return set_coredump_property(move(key), move(value)); } }