libclues
Linux C++ Tracing Library
Loading...
Searching...
No Matches
process.cxx
1// clues
2#include <clues/syscalls/process.hxx>
3
4namespace clues {
5
6#ifdef CLUES_HAVE_ARCH_PRCTL
7void ArchPrctlSystemCall::prepareNewSystemCall() {
8 // only keep the `op` parameter
9 m_pars.erase(m_pars.begin() + 1, m_pars.end());
10
11 on_off.reset();
12 set_addr.reset();
13 get_addr.reset();
14
15 on_off_ret.reset();
16 result.emplace(item::SuccessResult{});
17 setReturnItem(*result);
18}
19
20bool ArchPrctlSystemCall::check2ndPass(const Tracee &) {
21
22 using enum item::ArchOpParameter::Operation;
23
24 switch (op.operation()) {
25 case SET_CPUID:
26 on_off.emplace(item::ULongValue{"enable"});
27 addParameters(*on_off);
28 break;
29 case GET_CPUID:
30 result.reset();
31 on_off_ret.emplace(item::IntValue{"enabled?", "", ItemType::RETVAL});
32 setReturnItem(*on_off_ret);
33 break;
34 case SET_FS: [[fallthrough]];
35 case SET_GS:
36 set_addr.emplace(item::GenericPointerValue{"base"});
37 addParameters(*set_addr);
38 break;
39 case GET_FS: [[fallthrough]];
40 case GET_GS:
41 get_addr.emplace(item::PointerToScalar<unsigned long>{"*base"});
42 get_addr->setBase(Base::HEX);
43 addParameters(*get_addr);
44 break;
45 default: /* unknown operation? keep defaults */
46 break;
47 }
48
49 return true;
50}
51#endif
52
54 /* drop all but the fixed initial two parameters */
55 m_pars.erase(m_pars.begin() + 2, m_pars.end());
56
57 /* args */
58 parent_tid.reset();
59 pidfd.reset();
60 child_tid.reset();
61 tls.reset();
62}
63
65 // we need these two sizes to match, since a `pid_t*` is used in
66 // clone() to store either the child pid or a pidfd at.
67 static_assert( sizeof(int) == sizeof(pid_t), "sizeof(int) != sizeof(pid_t)" );
68 using enum cosmos::CloneFlag;
69 const auto clone_flags = this->flags.flags();
70
71 auto maybe_add_unused_par = [this](const size_t need_index) {
72 while (need_index > m_pars.size()) {
73 addParameters(item::unused);
74 }
75 };
76
77 auto maybe_add_settid_par = [this, clone_flags, maybe_add_unused_par](const size_t pos) {
78 if (clone_flags[CHILD_SETTID]) {
79 child_tid.emplace(item::GenericPointerValue{"child_tid", "pointer to child TID in child's memory"});
80 maybe_add_unused_par(pos);
81 addParameters(*child_tid);
82 }
83 };
84
85 auto maybe_add_settls_par = [this, clone_flags, maybe_add_unused_par](const size_t pos) {
86 if (clone_flags[SETTLS]) {
87 tls.emplace(item::GenericPointerValue{"tls", "ABI-specific thread-local-storage data"});
88
89 maybe_add_unused_par(pos);
90 addParameters(*tls);
91 }
92 };
93
94 // these two are mutual-exclusive in the old clone() system call
95 if (clone_flags[PARENT_SETTID]) {
97 "parent_tid", "pointer to child TID in parent's memory"});
98 addParameters(*parent_tid);
99 } else if (clone_flags[PIDFD]) {
101 "pidfd", "pointer to pidfd in parent's memory (alternative use of parent_tid)"});
102 addParameters(*pidfd);
103 }
104
105 /*
106 * Things are messy with clone(), the order of parameters differs
107 * between ABIs and we might need to skip some parameters by adding
108 * item::unused.
109 *
110 * The man page is a bit sketchy on the ABI details. In the kernel
111 * source we have to look for `CONFIG_CLONE_BACKWARDS*`, define in
112 * "arch/.../KConfig" as CLONE_BACKWARDS*.
113 *
114 * The situation for the ABIs we support is as follows:
115 *
116 * X86_32 (I386), ARM, ARM64: CLONE_BACKWARDS
117 * X86_64 (seems to include X32): no define
118 *
119 * CLONE_BACKWARDS means the final two arguments are tls /
120 * child_tidptr.
121 *
122 * no define means the final two arguments are child_tidptr / tls.
123 */
124
125 if (const auto abi = this->abi(); abi == ABI::X86_64 || abi == ABI::X32) {
126 maybe_add_settid_par(3);
127 maybe_add_settls_par(4);
128 } else if (abi == ABI::AARCH64 || abi == ABI::I386) {
129 maybe_add_settls_par(3);
130 maybe_add_settid_par(4);
131 }
132
133 return m_pars.size() > 2;
134}
135
137 const auto args = cl_args.args();
138
139 if (!args) {
140 return;
141 } else if (args->flags()[cosmos::CloneFlag::PIDFD]) {
142 FDInfo info{FDInfo::Type::PID_FD, cl_args.pidfd()};
143 trackFD(proc, std::move(info));
144 }
145}
146
147} // end ns
ABI abi() const
Returns the system call ABi seen during system call entry.
ParameterVector m_pars
The array of system call parameters, if any.
Base class for traced processes.
Definition Tracee.hxx:39
A pointer to an integral data type which will be filled in by the kernel.
Definition items.hxx:209
An always-success return value.
Definition error.hxx:15
@ RETVAL
A system call return value.
@ X32
X86_64 with 32-bit pointers.
Definition types.hxx:66
item::CloneArgs cl_args
Combined clone arguments.
Definition process.hxx:132
void updateFDTracking(const Tracee &proc) override
Update file descriptor tracking.
Definition process.cxx:136
std::optional< item::GenericPointerValue > tls
Thread-local-storage data for the new child.
Definition process.hxx:107
std::optional< item::PointerToScalar< cosmos::FileNum > > pidfd
PID file descriptor referring to the new child.
Definition process.hxx:89
std::optional< item::GenericPointerValue > child_tid
TID of the new child written out to a pid_* in the child.
Definition process.hxx:99
void prepareNewSystemCall() override
Perform any necessary actions before processing a new system call entry event.
Definition process.cxx:53
std::optional< item::PointerToScalar< cosmos::ProcessID > > parent_tid
TID of the new child written out to a pid_t* in the parent.
Definition process.hxx:84
bool check2ndPass(const Tracee &) override
Check whether a second pass needs to be made processing parameters.
Definition process.cxx:64
Contextual information about a file descriptor in a Tracee.
Definition types.hxx:75
@ PID_FD
created by pidfd_open(), clone(), ...
Definition types.hxx:96