Kernel: Store coredump metadata properties as KStrings

This patch also replaces the HashMap previously used to store coredump
properties with a plain AK::Array.
This commit is contained in:
Andreas Kling 2021-08-05 23:43:10 +02:00
parent 95669fa861
commit 33adc3a42d
Notes: sideshowbarker 2024-07-18 07:25:41 +09:00
6 changed files with 55 additions and 24 deletions

View File

@ -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);
}
}

View File

@ -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());

View File

@ -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<KString> key, NonnullOwnPtr<KString> 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;
};
}

View File

@ -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<String, String>& coredump_metadata() { return m_coredump_metadata; }
const HashMap<String, String>& coredump_metadata() const { return m_coredump_metadata; }
void set_coredump_metadata(const String& key, String value);
template<typename Callback>
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<KString> key, NonnullOwnPtr<KString> value);
KResult try_set_coredump_property(StringView key, StringView value);
const NonnullRefPtrVector<Thread>& threads_for_coredump(Badge<CoreDump>) const { return m_threads_for_coredump; }
@ -757,7 +765,12 @@ private:
Thread::WaitBlockCondition m_wait_block_condition;
HashMap<String, String> m_coredump_metadata;
struct CoredumpProperty {
OwnPtr<KString> key;
OwnPtr<KString> value;
};
Array<CoredumpProperty, 4> m_coredump_properties;
NonnullRefPtrVector<Thread> 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(); \
} \

View File

@ -577,7 +577,8 @@ KResult Process::do_exec(NonnullRefPtr<FileDescription> 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();

View File

@ -61,16 +61,15 @@ KResultOr<FlatPtr> Process::sys$set_coredump_metadata(Userspace<const Syscall::S
return EINVAL;
if (params.value.length > 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));
}
}