The Pedigree Project 0.1
trace-syscall-state.cc
1/* Copyright (c) 2026, Pedigree Developers. */
2#include "pedigree/kernel/process/Scheduler.h"
3#include "pedigree/kernel/process/Thread.h"
4#include "pedigree/kernel/process/Uninterruptible.h"
5#include "pedigree/kernel/processor/Processor.h"
6#include "pedigree/kernel/processor/ProcessorInformation.h"
7#include "pedigree/kernel/utilities/assert.h"
8#include "pedigree/kernel/utilities/utility.h"
9
10#include "PosixProcess.h"
11#include "PosixSubsystem.h"
13#include "trace-context.h"
14
15namespace {
16bool permitted(PosixProcess& source, PosixProcess& destination) {
17 if (&source == &destination)
18 return true;
19 const auto caller = source.snapshotCredentials();
20 const auto target = destination.snapshotCredentials();
21 return target.dumpable && caller.ruid == target.ruid && caller.ruid == target.euid &&
22 caller.ruid == target.suid && caller.rgid == target.rgid && caller.rgid == target.egid &&
23 caller.rgid == target.sgid;
24}
25} // namespace
26TraceStatus posix_trace_traceme() {
27#if !X64
28 return TraceStatus::Unsupported;
29#else
30 Thread* current = Processor::information().getCurrentThread();
31 auto* process = static_cast<PosixProcess*>(current->getParent());
32 auto* subsystem = static_cast<PosixSubsystem*>(process->getSubsystem());
33 Uninterruptible enrollmentWindow;
35 auto status = subsystem->traceContext().reserveEnrollment(*current, admission);
36 if (status != TraceStatus::Success)
37 return status;
39 {
41 status = posix_trace_acquire_task(admission.tracer(), task);
42 if (status != TraceStatus::Success ||
43 !Scheduler::instance().acquireProcess(creator, task->getParent()))
44 return TraceStatus::Missing;
45 }
48 if (!subsystem->snapshotUserImage(image))
49 return TraceStatus::Missing;
50 if (!subsystem->tracePolicyAllowed())
51 return TraceStatus::Unsupported;
52 if (process->getParent() != creator.get() || creator->getType() != Process::Posix)
53 return TraceStatus::Missing;
54 if (!permitted(*static_cast<PosixProcess*>(creator.get()), *process))
55 return TraceStatus::Denied;
56 auto* tracerSubsystem = static_cast<PosixSubsystem*>(creator->getSubsystem());
57 auto relation = TraceRelationRef::tryAllocate(admission.tracer(), admission.tracee());
58 if (!relation || !relation->valid())
59 return TraceStatus::NoMemory;
60 status = tracerSubsystem->traceContext().registerTracee(admission.tracer(), relation);
61 if (status != TraceStatus::Success)
62 return status;
63 if (!current->tryRequireSignalFrames()) {
64 tracerSubsystem->traceContext().unregisterTracee(relation.get());
65 return TraceStatus::Unsupported;
66 }
67 status = subsystem->traceContext().commitEnrollment(admission, relation);
68 if (status != TraceStatus::Success) {
69 current->clearSignalFrameRequirement();
70 tracerSubsystem->traceContext().unregisterTracee(relation.get());
71 }
72 return status;
73#endif
74}
75TraceStatus posix_trace_lookup(int32_t tid, TraceRelationRef& result) {
76 assert(!result);
77 if (tid <= 0)
78 return TraceStatus::Missing;
79 Thread* current = Processor::information().getCurrentThread();
80 auto* caller = static_cast<PosixProcess*>(current->getParent());
81 auto* callerSubsystem = static_cast<PosixSubsystem*>(caller->getSubsystem());
82 TraceTaskRef owner;
83 if (!callerSubsystem->traceContext().taskToken(*current, owner))
84 return TraceStatus::Missing;
86 TraceTaskRef selected;
87 {
89 if (!Scheduler::instance().acquireThreadByUserspaceId(task, static_cast<size_t>(tid)) ||
90 task->getParent()->getType() != Process::Posix || !task->acceptingEvents() ||
92 return TraceStatus::Missing;
93 }
94 auto* subsystem = static_cast<PosixSubsystem*>(task->getParent()->getSubsystem());
95 if (!subsystem || !subsystem->traceContext().taskToken(*task.get(), selected) ||
96 !Scheduler::instance().acquireProcess(process, task->getParent()))
97 return TraceStatus::Missing;
98 }
99 TraceRelationRef relation;
100 {
102 auto* subsystem = static_cast<PosixSubsystem*>(process->getSubsystem());
104 if (!subsystem || !subsystem->snapshotUserImage(image) || !selected->live() ||
105 !subsystem->traceContext().acquireIncoming(relation) || relation->tracer() != owner ||
106 relation->tracee() != selected)
107 return TraceStatus::Missing;
108 if (!permitted(*caller, *static_cast<PosixProcess*>(process.get())))
109 return TraceStatus::Denied;
110 if (!relation->stopped())
111 return TraceStatus::NotStopped;
112 }
113 result = pedigree_std::move(relation);
114 return TraceStatus::Success;
115}
116
117TraceStatus posix_trace_prepare_resume(const TraceTaskRef& target, int signal,
118 bool inheritReservation, int32_t pid, uint32_t uid,
120 assert(!result);
121 const auto identity = target->snapshot();
122 if (identity.state != TraceTaskToken::State::Live)
123 return TraceStatus::Missing;
125 if (!Scheduler::instance().acquireProcessById(process, identity.processId) ||
126 process->getType() != Process::Posix)
127 return TraceStatus::Missing;
129 auto* caller =
130 static_cast<PosixProcess*>(Processor::information().getCurrentThread()->getParent());
131 auto* subsystem = static_cast<PosixSubsystem*>(process->getSubsystem());
133 if (!subsystem || !subsystem->snapshotUserImage(image))
134 return TraceStatus::Missing;
135 if (!permitted(*caller, *static_cast<PosixProcess*>(process.get())))
136 return TraceStatus::Denied;
137 // Acquire only after the possibly blocking authority gate, and release
138 // before that gate. A tracee exec never waits for a lease held behind it.
140 if (posix_trace_acquire_task(target, task) != TraceStatus::Success)
141 return TraceStatus::Missing;
142 return subsystem->prepareTraceSignal(*task.get(), signal, pid, uid, inheritReservation, result);
143}
Memory-mapped file interface.
static MemoryMapManager & instance()
Process * getParent()
Definition Process.h:620
static ProcessorInformation & information()
static Scheduler & instance()
Definition Scheduler.h:96
MUST_USE_RESULT bool acquireProcess(ProcessLease &lease, size_t n)
Definition Scheduler.cc:275
static SharedPointer< PosixTraceRelation > tryAllocate(Args...)
@ Continue
No unwind necessary, carry on as normal.
Definition Thread.h:517
UnwindType getUnwindState()
Definition Thread.h:535
Process * getParent() const
Definition Thread.h:340