summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/API/Syscall.h1
-rw-r--r--Kernel/Process.cpp6
-rw-r--r--Kernel/Process.h2
-rw-r--r--Kernel/Syscalls/profiling.cpp33
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;
+}
}