libclues
Linux C++ Tracing Library
Loading...
Searching...
No Matches
AutoAttachedTracee.cxx
1// cosmos
2#include <cosmos/error/ApiError.hxx>
3#include <cosmos/io/ILogger.hxx>
4#include <cosmos/proc/process.hxx>
5
6// clues
7#include <clues/AutoAttachedTracee.hxx>
8#include <clues/logger.hxx>
9#include <clues/syscalls/process.hxx>
10#include <clues/sysnrs/generic.hxx>
11
12namespace clues {
13
14namespace {
15
16bool shares_file_descriptors_with_parent(const SystemCall &sc) {
17
18 /*
19 * In case of clone() with CLONE_FILES we need to share process data
20 * with the parent.
21 *
22 * In all other cases we need a deep-copy of process data (sharing of
23 * the file descriptor table ends).
24 *
25 * Note: clone() calls with SIGCHILD as exit signal can appear as
26 * regular fork events, clone() calls with CLONE_VFORK will appear as
27 * regular vfork events. This is the case even if SHARE_FILES is
28 * passed to clone(), which doesn't match the fork() semantics.
29 *
30 * For this reason we cannot rely on the ptrace event for this, but
31 * need to inspect the active system call exclusively.
32 */
33
34 switch (sc.callNr()) {
35 case SystemCallNr::CLONE3: {
36 auto &clone3_sc = dynamic_cast<const Clone3SystemCall&>(sc);
37 const auto args = clone3_sc.cl_args.args();
38
39 if (args) {
40 return args->flags()[cosmos::CloneFlag::SHARE_FILES];
41 } else {
42 // failes to parse cl_args, what now?
43 return false;
44 }
45 }
46 case SystemCallNr::CLONE: {
47 // this throws if the cast fails, but this should never happen
48 auto &clone_sc = dynamic_cast<const CloneSystemCall&>(sc);
49 const auto flags = clone_sc.flags.flags();
50
51 return flags[cosmos::CloneFlag::SHARE_FILES];
52 }
53 case SystemCallNr::FORK: /* fallthrough */
54 case SystemCallNr::VFORK: return false;
55 default:
56 LOG_ERROR("PTRACE auto-attach event but last system call is not recognized?!");
57 // we don't know what to do in this case, further tracing is
58 // undefined, might be best to detach?
59 return false;
60 }
61}
62
63} // end anon ns
64
65AutoAttachedTracee::AutoAttachedTracee(Engine &engine, EventConsumer &consumer, TraceePtr parent) :
66 Tracee{engine, consumer, parent} {
67}
68
69void AutoAttachedTracee::configure(const cosmos::ProcessID pid, const cosmos::ptrace::Event event,
70 const SystemCall &sc) {
71 (void)event;
72 setPID(pid);
74
75 if (!shares_file_descriptors_with_parent(sc)) {
76 unshareProcessData();
77 }
78}
79
80AutoAttachedTracee::~AutoAttachedTracee() {
81 try {
82 detach();
83 } catch (const cosmos::CosmosError &ce) {
84 LOG_DEBUG("Couldn't detach from PID " << cosmos::to_integral(m_ptrace.pid()) << ":\n\n" << ce.what());
85 }
86}
87
88} // end ns
AutoAttachedTracee(Engine &engine, EventConsumer &consumer, TraceePtr parent)
Create a traced process object by attaching to the given process ID.
void configure(const cosmos::ProcessID pid, const cosmos::ptrace::Event event, const SystemCall &sc)
Sets the given process ID as the process to be traced.
Callback interface for consumers of tracing events.
Access to System Call Data.
SystemCallNr callNr() const
Returns the system call table number for this system call.
void setPID(const cosmos::ProcessID tracee)
Sets the tracee PID.
Definition Tracee.cxx:129
@ WAIT_FOR_ATTACH_STOP
we're still waiting for the PTRACE_INTERRUPT event stop.
Definition Tracee.hxx:62
bool detach()
Attempt to detach the Tracee.
Definition Tracee.cxx:177
Tracee(Engine &engine, EventConsumer &consumer, TraceePtr sibling=nullptr)
Definition Tracee.cxx:100
Flags m_flags
These keep track of various state on the tracer side.
Definition Tracee.hxx:442
cosmos::Tracee m_ptrace
libcosmos API for the Tracee.
Definition Tracee.hxx:444
const std::optional< cosmos::CloneArgs > & args() const
Returns an optional containing the cosmos::CloneArgs structure, if available.
Definition clone.hxx:60
item::CloneArgs cl_args
Combined clone arguments.
Definition process.hxx:132
Wrapper for the clone() and clone2() system calls.
Definition process.hxx:62