diff options
-rw-r--r-- | Kernel/API/Syscall.h | 1 | ||||
-rw-r--r-- | Kernel/Process.cpp | 6 | ||||
-rw-r--r-- | Kernel/Process.h | 2 | ||||
-rw-r--r-- | Kernel/Syscalls/profiling.cpp | 33 |
4 files changed, 42 insertions, 0 deletions
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<int> sys$module_unload(Userspace<const char*> name, size_t name_length); KResultOr<int> sys$profiling_enable(pid_t); KResultOr<int> sys$profiling_disable(pid_t); + KResultOr<int> sys$profiling_free_buffer(pid_t); KResultOr<int> sys$futex(Userspace<const Syscall::SC_futex_params*>); KResultOr<int> sys$chroot(Userspace<const char*> path, size_t path_length, int mount_flags); KResultOr<int> sys$pledge(Userspace<const Syscall::SC_pledge_params*>); @@ -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<FileDescription> main_program_description, Vector<String> arguments, Vector<String> environment, RefPtr<FileDescription> interpreter_description, Thread*& new_main_thread, u32& prev_flags, const Elf32_Ehdr& main_program_header); KResultOr<ssize_t> 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<int> Process::sys$profiling_enable(pid_t pid) KResultOr<int> Process::sys$profiling_disable(pid_t pid) { + REQUIRE_NO_PROMISES; + if (pid == -1) { if (!is_superuser()) return EPERM; @@ -87,4 +89,35 @@ KResultOr<int> Process::sys$profiling_disable(pid_t pid) return 0; } +KResultOr<int> Process::sys$profiling_free_buffer(pid_t pid) +{ + REQUIRE_NO_PROMISES; + + if (pid == -1) { + if (!is_superuser()) + return EPERM; + + OwnPtr<PerformanceEventBuffer> 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; +} } |