2#include <clues/format.hxx>
3#include <clues/items/clone.hxx>
4#include <clues/syscalls/process.hxx>
5#include <clues/sysnrs/generic.hxx>
6#include <clues/SystemCall.hxx>
7#include <clues/Tracee.hxx>
9#include <clues/private/utils.hxx>
11namespace clues::item {
15std::string clone_flags_str(
const cosmos::CloneFlags flags,
const std::optional<cosmos::SignalNr> exit_signal = {}) {
16 BITFLAGS_FORMAT_START(flags);
18 BITFLAGS_ADD(CLONE_CHILD_CLEARTID);
19 BITFLAGS_ADD(CLONE_CHILD_SETTID);
20 BITFLAGS_ADD(CLONE_CLEAR_SIGHAND);
21 BITFLAGS_ADD(CLONE_DETACHED);
22 BITFLAGS_ADD(CLONE_FILES);
23 BITFLAGS_ADD(CLONE_FS);
24 BITFLAGS_ADD(CLONE_INTO_CGROUP);
25 BITFLAGS_ADD(CLONE_IO);
26 BITFLAGS_ADD(CLONE_NEWCGROUP);
27 BITFLAGS_ADD(CLONE_NEWIPC);
28 BITFLAGS_ADD(CLONE_NEWNET);
29 BITFLAGS_ADD(CLONE_NEWNS);
30 BITFLAGS_ADD(CLONE_NEWNS);
31 BITFLAGS_ADD(CLONE_NEWPID);
32 BITFLAGS_ADD(CLONE_NEWUSER);
33 BITFLAGS_ADD(CLONE_NEWUTS);
34 BITFLAGS_ADD(CLONE_PARENT);
35 BITFLAGS_ADD(CLONE_PARENT_SETTID);
36 BITFLAGS_ADD(CLONE_PIDFD);
37 BITFLAGS_ADD(CLONE_PTRACE);
38 BITFLAGS_ADD(CLONE_SETTLS);
39 BITFLAGS_ADD(CLONE_SIGHAND);
40 BITFLAGS_ADD(CLONE_SYSVSEM);
41 BITFLAGS_ADD(CLONE_THREAD);
42 BITFLAGS_ADD(CLONE_UNTRACED);
43 BITFLAGS_ADD(CLONE_VFORK);
44 BITFLAGS_ADD(CLONE_VM);
47 BITFLAGS_STREAM() << format::signal(*exit_signal,
false);
50 return BITFLAGS_STR();
60 if (
m_call->callNr() == SystemCallNr::CLONE) {
66 m_flags = cosmos::CloneFlags{
static_cast<uint64_t
>(raw & (~0xFF))};
67 exit_signal.emplace(cosmos::SignalNr{
static_cast<int>(raw) & 0xFF});
74void CloneArgs::resetArgs() {
75 m_pidfd = cosmos::FileNum::INVALID;
76 m_cgroup2_fd = cosmos::FileNum::INVALID;
77 m_child_tid = cosmos::ThreadID::INVALID;
89 m_args.emplace(cosmos::CloneArgs{});
94 if (!proc.
readStruct<cosmos::CloneArgs,
false>(asPtr(), *m_args)) {
99 const auto &
args = *m_args;
100 const auto raw =
args.raw();
101 const auto num_tids = raw->set_tid_size;
104 m_tid_array.resize(num_tids);
107 ForeignPtr{
static_cast<uintptr_t
>(raw->set_tid)},
108 reinterpret_cast<char*
>(m_tid_array.data()), num_tids *
sizeof(cosmos::ThreadID));
109 }
catch (
const std::exception &ex) {
115 if (
args.isSet(cosmos::CloneFlag::INTO_CGROUP)) {
116 m_cgroup2_fd =
args.cgroup().raw();
125 const auto &
args = *m_args;
126 const auto raw =
args.raw();
127 const auto flags =
args.flags();
128 using enum cosmos::CloneFlag;
135 if (flags[PARENT_SETTID]) {
140bool CloneArgs::verifySize()
const {
146 if (info.args()[1] <
sizeof(cosmos::CloneArgs)) {
163 return format::pointer(asPtr()) +
" (size mismatch)";
166 auto uint2ptr = [](uint64_t val) ->
ForeignPtr {
167 return ForeignPtr{
static_cast<uintptr_t
>(val)};
170 std::stringstream ss;
171 const auto &
args = *m_args;
172 const auto flags =
args.flags();
173 const auto raw =
args.raw();
174 using enum cosmos::CloneFlag;
177 ss <<
"flags=" << clone_flags_str(flags);
179 ss <<
", pidfd=" << format::pointer(uint2ptr(raw->pidfd), std::to_string(cosmos::to_integral(m_pidfd)));
181 if (flags[CHILD_CLEARTID] || flags[CHILD_SETTID]) {
182 const auto child_tid_ptr =
ForeignPtr{
reinterpret_cast<uintptr_t
>(
args.childTID())};
183 ss <<
", child_tid=" << format::pointer(child_tid_ptr);
185 if (flags[PARENT_SETTID]) {
186 const auto parent_tid_ptr =
ForeignPtr{
reinterpret_cast<uintptr_t
>(
args.parentTID())};
187 ss <<
", parent_tid=" << format::pointer(parent_tid_ptr,
188 std::to_string(cosmos::to_integral(m_child_tid)));
190 ss <<
", exit_signal=" << format::signal(
args.exitSignal().raw(),
false);
191 const auto stack_ptr =
ForeignPtr{
reinterpret_cast<uintptr_t
>(
args.stack())};
192 ss <<
", stack=" << format::pointer(stack_ptr);
193 ss <<
", stack_size=" <<
args.stackSize();
197 ss <<
", tls=" << format::pointer(uint2ptr(raw->tls));
200 const auto settid_ptr = uint2ptr(raw->set_tid);
201 if (raw->set_tid_size) {
202 std::stringstream ss2;
203 std::string sep =
"";
204 for (
const auto tid: m_tid_array) {
206 ss2 << cosmos::to_integral(
tid);
210 ss <<
", set_tid=" << format::pointer(settid_ptr, ss2.str());
217 ss <<
", set_tid=" << format::pointer(settid_ptr);
219 ss <<
", set_tid_size=" << raw->set_tid_size;
221 if (flags[INTO_CGROUP]) {
222 ss <<
", cgroup=" << cosmos::to_integral(m_cgroup2_fd);
const SystemCall * m_call
The system call context this item part of.
bool isZero() const
Returns whether the parameter is set to 0 / NULL.
OTHER valueAs() const
Helper to cast the strongly typed Word m_val to other strong enum types.
const SystemCallInfo * currentInfo() const
Access the current SystemCallInfo if currently processing syscall entry/exit.
SystemCallNr callNr() const
Returns the system call table number for this system call.
Base class for traced processes.
bool readStruct(const ForeignPtr addr, T &out) const
Reads a system call struct from the tracee's address space into out.
void readBlob(const ForeignPtr addr, char *buffer, const size_t bytes) const
Reads an arbitrary binary blob of fixed length from the tracee.
std::string str() const override
Returns a human readable string representation of the item.
void updateData(const Tracee &proc) override
Called upon exit of the system call to update possible out parameters.
void processValue(const Tracee &) override
Processes the value stored in m_val acc. to the actual item type.
cosmos::ThreadID tid() const
Return the new child's ThreadID stored in parent's memory.
const std::optional< cosmos::CloneArgs > & args() const
Returns an optional containing the cosmos::CloneArgs structure, if available.
std::optional< cosmos::SignalNr > exit_signal
For clone() 1/2 this contains the child exit signal, which is additionally encoded in the flags.
void processValue(const Tracee &) override
Processes the value stored in m_val acc. to the actual item type.
std::string str() const override
Returns a human readable string representation of the item.
ForeignPtr
Strongly typed opaque pointer to tracee memory.