From 0688e0233941e97ec6ab3eb1904d02c8f293f3a4 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sun, 23 May 2021 22:16:30 +0200 Subject: [PATCH] Kernel: Make sure we only log profiling events when m_profiling is true Previously the process' m_profiling flag was ignored for all event types other than CPU samples. The kfree tracing code relies on temporarily disabling tracing during exec. This didn't work for per-process profiles and would instead panic. This updates the profiling code so that the m_profiling flag isn't ignored. --- Kernel/PerformanceManager.h | 14 ++------------ Kernel/Process.h | 7 ++++++- Kernel/Syscalls/execve.cpp | 6 +++++- Kernel/Syscalls/profiling.cpp | 4 ++-- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/Kernel/PerformanceManager.h b/Kernel/PerformanceManager.h index f00c4db797..6ef78ab7fe 100644 --- a/Kernel/PerformanceManager.h +++ b/Kernel/PerformanceManager.h @@ -54,18 +54,8 @@ public: inline static void add_cpu_sample_event(Thread& current_thread, const RegisterState& regs, u32 lost_time) { - PerformanceEventBuffer* perf_events = nullptr; - - if (g_profiling_all_threads) { - VERIFY(g_global_perf_events); - perf_events = g_global_perf_events; - } else if (current_thread.process().is_profiling()) { - VERIFY(current_thread.process().perf_events()); - perf_events = current_thread.process().perf_events(); - } - - if (perf_events) { - [[maybe_unused]] auto rc = perf_events->append_with_eip_and_ebp( + if (auto* event_buffer = current_thread.process().current_perf_events_buffer()) { + [[maybe_unused]] auto rc = event_buffer->append_with_eip_and_ebp( current_thread.pid(), current_thread.tid(), regs.eip, regs.ebp, PERF_EVENT_SAMPLE, lost_time, 0, 0, nullptr); } diff --git a/Kernel/Process.h b/Kernel/Process.h index 0867ddac37..526a5c7f8e 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -559,7 +559,12 @@ private: inline PerformanceEventBuffer* current_perf_events_buffer() { - return g_profiling_all_threads ? g_global_perf_events : m_perf_event_buffer.ptr(); + if (g_profiling_all_threads) + return g_global_perf_events; + else if (m_profiling) + return m_perf_event_buffer.ptr(); + else + return nullptr; } Process* m_prev { nullptr }; diff --git a/Kernel/Syscalls/execve.cpp b/Kernel/Syscalls/execve.cpp index 25ca3f8dfc..842202b889 100644 --- a/Kernel/Syscalls/execve.cpp +++ b/Kernel/Syscalls/execve.cpp @@ -506,6 +506,7 @@ KResult Process::do_exec(NonnullRefPtr main_program_description Locker ptrace_locker(ptrace_lock()); // Disable profiling temporarily in case it's running on this process. + auto was_profiling = m_profiling; TemporaryChange profiling_disabler(m_profiling, false); kill_threads_except_self(); @@ -645,7 +646,10 @@ KResult Process::do_exec(NonnullRefPtr main_program_description tss.cr3 = space().page_directory().cr3(); tss.ss2 = pid().value(); - PerformanceManager::add_process_exec_event(*this); + { + TemporaryChange profiling_disabler(m_profiling, was_profiling); + PerformanceManager::add_process_exec_event(*this); + } { ScopedSpinLock lock(g_scheduler_lock); diff --git a/Kernel/Syscalls/profiling.cpp b/Kernel/Syscalls/profiling.cpp index 76a6ad92fd..d727195a72 100644 --- a/Kernel/Syscalls/profiling.cpp +++ b/Kernel/Syscalls/profiling.cpp @@ -51,12 +51,12 @@ KResultOr Process::sys$profiling_enable(pid_t pid, u64 event_mask) return ESRCH; if (!is_superuser() && process->uid() != euid()) return EPERM; + g_profiling_event_mask = event_mask; + process->set_profiling(true); if (!process->create_perf_events_buffer_if_needed()) return ENOMEM; if (!TimeManagement::the().enable_profile_timer()) return ENOTSUP; - g_profiling_event_mask = event_mask; - process->set_profiling(true); return 0; }