mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 00:37:35 +00:00
Kernel: Lock target process when generating core dump
Dumping core can happen at the end of a profiling run, and in that case we have to protect the target process and take the lock while iterating over its region map. Fixes #4509.
This commit is contained in:
parent
4395e1b240
commit
87492e723b
2 changed files with 17 additions and 17 deletions
|
@ -40,23 +40,23 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
OwnPtr<CoreDump> CoreDump::create(Process& process, const String& output_path)
|
OwnPtr<CoreDump> CoreDump::create(NonnullRefPtr<Process> process, const String& output_path)
|
||||||
{
|
{
|
||||||
if (!process.is_dumpable()) {
|
if (!process->is_dumpable()) {
|
||||||
dbgln("Refusing to generate CoreDump for non-dumpable process {}", process.pid().value());
|
dbgln("Refusing to generate CoreDump for non-dumpable process {}", process->pid().value());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fd = create_target_file(process, output_path);
|
auto fd = create_target_file(process, output_path);
|
||||||
if (!fd)
|
if (!fd)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return adopt_own(*new CoreDump(process, fd.release_nonnull()));
|
return adopt_own(*new CoreDump(move(process), fd.release_nonnull()));
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreDump::CoreDump(Process& process, NonnullRefPtr<FileDescription>&& fd)
|
CoreDump::CoreDump(NonnullRefPtr<Process> process, NonnullRefPtr<FileDescription>&& fd)
|
||||||
: m_process(process)
|
: m_process(move(process))
|
||||||
, m_fd(move(fd))
|
, m_fd(move(fd))
|
||||||
, m_num_program_headers(process.m_regions.size() + 1) // +1 for NOTE segment
|
, m_num_program_headers(m_process->m_regions.size() + 1) // +1 for NOTE segment
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ KResult CoreDump::write_elf_header()
|
||||||
KResult CoreDump::write_program_headers(size_t notes_size)
|
KResult CoreDump::write_program_headers(size_t notes_size)
|
||||||
{
|
{
|
||||||
size_t offset = sizeof(Elf32_Ehdr) + m_num_program_headers * sizeof(Elf32_Phdr);
|
size_t offset = sizeof(Elf32_Ehdr) + m_num_program_headers * sizeof(Elf32_Phdr);
|
||||||
for (auto& region : m_process.m_regions) {
|
for (auto& region : m_process->m_regions) {
|
||||||
Elf32_Phdr phdr {};
|
Elf32_Phdr phdr {};
|
||||||
|
|
||||||
phdr.p_type = PT_LOAD;
|
phdr.p_type = PT_LOAD;
|
||||||
|
@ -171,16 +171,15 @@ KResult CoreDump::write_program_headers(size_t notes_size)
|
||||||
|
|
||||||
KResult CoreDump::write_regions()
|
KResult CoreDump::write_regions()
|
||||||
{
|
{
|
||||||
for (auto& region : m_process.m_regions) {
|
for (auto& region : m_process->m_regions) {
|
||||||
if (region.is_kernel())
|
if (region.is_kernel())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
region.set_readable(true);
|
region.set_readable(true);
|
||||||
region.remap();
|
region.remap();
|
||||||
|
|
||||||
auto& vmobj = region.vmobject();
|
|
||||||
for (size_t i = 0; i < region.page_count(); i++) {
|
for (size_t i = 0; i < region.page_count(); i++) {
|
||||||
PhysicalPage* page = vmobj.physical_pages()[region.first_page_index() + i];
|
auto* page = region.physical_page(i);
|
||||||
|
|
||||||
uint8_t zero_buffer[PAGE_SIZE] = {};
|
uint8_t zero_buffer[PAGE_SIZE] = {};
|
||||||
Optional<UserOrKernelBuffer> src_buffer;
|
Optional<UserOrKernelBuffer> src_buffer;
|
||||||
|
@ -213,7 +212,7 @@ ByteBuffer CoreDump::create_notes_threads_data() const
|
||||||
{
|
{
|
||||||
ByteBuffer threads_data;
|
ByteBuffer threads_data;
|
||||||
|
|
||||||
m_process.for_each_thread([&](Thread& thread) {
|
m_process->for_each_thread([&](Thread& thread) {
|
||||||
ByteBuffer entry_buff;
|
ByteBuffer entry_buff;
|
||||||
|
|
||||||
ELF::Core::ThreadInfo info {};
|
ELF::Core::ThreadInfo info {};
|
||||||
|
@ -233,13 +232,13 @@ ByteBuffer CoreDump::create_notes_threads_data() const
|
||||||
ByteBuffer CoreDump::create_notes_regions_data() const
|
ByteBuffer CoreDump::create_notes_regions_data() const
|
||||||
{
|
{
|
||||||
ByteBuffer regions_data;
|
ByteBuffer regions_data;
|
||||||
for (size_t region_index = 0; region_index < m_process.m_regions.size(); ++region_index) {
|
for (size_t region_index = 0; region_index < m_process->m_regions.size(); ++region_index) {
|
||||||
|
|
||||||
ByteBuffer memory_region_info_buffer;
|
ByteBuffer memory_region_info_buffer;
|
||||||
ELF::Core::MemoryRegionInfo info {};
|
ELF::Core::MemoryRegionInfo info {};
|
||||||
info.header.type = ELF::Core::NotesEntryHeader::Type::MemoryRegionInfo;
|
info.header.type = ELF::Core::NotesEntryHeader::Type::MemoryRegionInfo;
|
||||||
|
|
||||||
auto& region = m_process.m_regions[region_index];
|
auto& region = m_process->m_regions[region_index];
|
||||||
info.region_start = reinterpret_cast<uint32_t>(region.vaddr().as_ptr());
|
info.region_start = reinterpret_cast<uint32_t>(region.vaddr().as_ptr());
|
||||||
info.region_end = reinterpret_cast<uint32_t>(region.vaddr().as_ptr() + region.size());
|
info.region_end = reinterpret_cast<uint32_t>(region.vaddr().as_ptr() + region.size());
|
||||||
info.program_header_index = region_index;
|
info.program_header_index = region_index;
|
||||||
|
@ -272,6 +271,7 @@ ByteBuffer CoreDump::create_notes_segment_data() const
|
||||||
|
|
||||||
KResult CoreDump::write()
|
KResult CoreDump::write()
|
||||||
{
|
{
|
||||||
|
ScopedSpinLock lock(m_process->get_lock());
|
||||||
ProcessPagingScope scope(m_process);
|
ProcessPagingScope scope(m_process);
|
||||||
|
|
||||||
ByteBuffer notes_segment = create_notes_segment_data();
|
ByteBuffer notes_segment = create_notes_segment_data();
|
||||||
|
|
|
@ -39,13 +39,13 @@ class Process;
|
||||||
|
|
||||||
class CoreDump {
|
class CoreDump {
|
||||||
public:
|
public:
|
||||||
static OwnPtr<CoreDump> create(Process&, const String& output_path);
|
static OwnPtr<CoreDump> create(NonnullRefPtr<Process>, const String& output_path);
|
||||||
|
|
||||||
~CoreDump();
|
~CoreDump();
|
||||||
[[nodiscard]] KResult write();
|
[[nodiscard]] KResult write();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CoreDump(Process&, NonnullRefPtr<FileDescription>&&);
|
CoreDump(NonnullRefPtr<Process>, NonnullRefPtr<FileDescription>&&);
|
||||||
static RefPtr<FileDescription> create_target_file(const Process&, const String& output_path);
|
static RefPtr<FileDescription> create_target_file(const Process&, const String& output_path);
|
||||||
|
|
||||||
[[nodiscard]] KResult write_elf_header();
|
[[nodiscard]] KResult write_elf_header();
|
||||||
|
@ -57,7 +57,7 @@ private:
|
||||||
ByteBuffer create_notes_threads_data() const;
|
ByteBuffer create_notes_threads_data() const;
|
||||||
ByteBuffer create_notes_regions_data() const;
|
ByteBuffer create_notes_regions_data() const;
|
||||||
|
|
||||||
Process& m_process;
|
NonnullRefPtr<Process> m_process;
|
||||||
NonnullRefPtr<FileDescription> m_fd;
|
NonnullRefPtr<FileDescription> m_fd;
|
||||||
const size_t m_num_program_headers;
|
const size_t m_num_program_headers;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue