diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index 11d6807302..db876d786d 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -171,6 +171,7 @@ namespace Kernel { S(purge) \ S(profiling_enable) \ S(profiling_disable) \ + S(profiling_free_buffer) \ S(futex) \ S(chroot) \ S(pledge) \ diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index fb18f73796..c3eba414ff 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -700,6 +700,12 @@ bool Process::create_perf_events_buffer_if_needed() return !!m_perf_event_buffer; } +void Process::delete_perf_events_buffer() +{ + if (m_perf_event_buffer) + m_perf_event_buffer = nullptr; +} + bool Process::remove_thread(Thread& thread) { ProtectedDataMutationScope scope { *this }; diff --git a/Kernel/Process.h b/Kernel/Process.h index 8a4f4f7653..7f2d64d458 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -394,6 +394,7 @@ public: KResultOr sys$module_unload(Userspace name, size_t name_length); KResultOr sys$profiling_enable(pid_t); KResultOr sys$profiling_disable(pid_t); + KResultOr sys$profiling_free_buffer(pid_t); KResultOr sys$futex(Userspace); KResultOr sys$chroot(Userspace path, size_t path_length, int mount_flags); KResultOr sys$pledge(Userspace); @@ -520,6 +521,7 @@ private: bool dump_core(); bool dump_perfcore(); bool create_perf_events_buffer_if_needed(); + void delete_perf_events_buffer(); KResult do_exec(NonnullRefPtr main_program_description, Vector arguments, Vector environment, RefPtr interpreter_description, Thread*& new_main_thread, u32& prev_flags, const Elf32_Ehdr& main_program_header); KResultOr do_write(FileDescription&, const UserOrKernelBuffer&, size_t); diff --git a/Kernel/Syscalls/profiling.cpp b/Kernel/Syscalls/profiling.cpp index 62aa46a443..182fa09285 100644 --- a/Kernel/Syscalls/profiling.cpp +++ b/Kernel/Syscalls/profiling.cpp @@ -67,6 +67,8 @@ KResultOr Process::sys$profiling_enable(pid_t pid) KResultOr Process::sys$profiling_disable(pid_t pid) { + REQUIRE_NO_PROMISES; + if (pid == -1) { if (!is_superuser()) return EPERM; @@ -87,4 +89,35 @@ KResultOr Process::sys$profiling_disable(pid_t pid) return 0; } +KResultOr Process::sys$profiling_free_buffer(pid_t pid) +{ + REQUIRE_NO_PROMISES; + + if (pid == -1) { + if (!is_superuser()) + return EPERM; + + OwnPtr perf_events; + + { + ScopedCritical critical; + + perf_events = g_global_perf_events; + g_global_perf_events = nullptr; + } + + return 0; + } + + ScopedSpinLock lock(g_processes_lock); + auto process = Process::from_pid(pid); + if (!process) + return ESRCH; + if (!is_superuser() && process->uid() != euid()) + return EPERM; + if (process->is_profiling()) + return EINVAL; + process->delete_perf_events_buffer(); + return 0; +} }