Skip to content

Commit b0bf99b

Browse files
Merge pull request #91 from asparsa/exclusion_check_create
Probe exclusion creation and checks
2 parents 932cc13 + d0fbf07 commit b0bf99b

3 files changed

Lines changed: 109 additions & 21 deletions

File tree

src/datacrumbs/common/data_structures.h

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ struct EventWithId {
5959
// Base class representing a generic probe
6060
class Probe {
6161
public:
62+
// Default constructor
6263
Probe() {}
6364
// Copy constructor
6465
Probe(const Probe& other) : type(other.type), name(other.name), functions(other.functions) {
@@ -92,16 +93,21 @@ class Probe {
9293
}
9394

9495
// Serializes the probe to a JSON object
95-
virtual json_object* toJson() const {
96+
virtual json_object* toJson(bool include_functions=true) const {
9697
DC_LOG_TRACE("Probe::toJson called");
9798
json_object* j = json_object_new_object();
9899
json_object_object_add(j, "type", json_object_new_int(static_cast<int>(type)));
99100
json_object_object_add(j, "name", json_object_new_string(name.c_str()));
100-
101+
101102
json_object* funcs = json_object_new_array();
103+
if(include_functions){
102104
for (const auto& func : functions) {
103105
json_object_array_add(funcs, json_object_new_string(func.c_str()));
106+
}}
107+
else{
108+
json_object_array_add(funcs, json_object_new_string(""));
104109
}
110+
105111
json_object_object_add(j, "functions", funcs);
106112

107113
return j;
@@ -140,10 +146,10 @@ struct SysCallProbe : public Probe {
140146
}
141147

142148
// Serializes the syscall probe to a JSON object
143-
json_object* toJson() const override {
149+
json_object* toJson(bool include_functions=true) const override {
144150
DC_LOG_TRACE("SysCallProbe::toJson called");
145151
// No extra fields, just use base
146-
return Probe::toJson();
152+
return Probe::toJson(include_functions);
147153
}
148154

149155
// Deserializes a syscall probe from a JSON object
@@ -172,10 +178,10 @@ struct KProbe : public Probe {
172178
}
173179

174180
// Serializes the kprobe to a JSON object
175-
json_object* toJson() const override {
181+
json_object* toJson(bool include_functions=true) const override {
176182
DC_LOG_TRACE("KProbe::toJson called");
177183
// No extra fields, just use base
178-
return Probe::toJson();
184+
return Probe::toJson(include_functions);
179185
}
180186

181187
// Deserializes a kprobe from a JSON object
@@ -214,9 +220,9 @@ struct UProbe : public Probe {
214220
}
215221

216222
// Serializes the uprobe to a JSON object
217-
json_object* toJson() const override {
223+
json_object* toJson(bool include_functions=true) const override {
218224
DC_LOG_TRACE("UProbe::toJson called");
219-
json_object* j = Probe::toJson();
225+
json_object* j = Probe::toJson(include_functions);
220226
json_object_object_add(j, "binary_path", json_object_new_string(binary_path.c_str()));
221227
json_object_object_add(j, "include_offsets", json_object_new_boolean(include_offsets));
222228
return j;
@@ -269,9 +275,9 @@ struct USDTProbe : public Probe {
269275
}
270276

271277
// Serializes the USDT probe to a JSON object
272-
json_object* toJson() const override {
278+
json_object* toJson(bool include_functions=true) const override {
273279
DC_LOG_TRACE("USDTProbe::toJson called");
274-
json_object* j = Probe::toJson();
280+
json_object* j = Probe::toJson(include_functions);
275281
json_object_object_add(j, "binary_path", json_object_new_string(binary_path.c_str()));
276282
json_object_object_add(j, "provider", json_object_new_string(provider.c_str()));
277283
return j;
@@ -341,9 +347,9 @@ struct CustomProbe : public Probe {
341347
}
342348

343349
// Serializes the USDT probe to a JSON object
344-
json_object* toJson() const override {
350+
json_object* toJson(bool include_functions=true) const override {
345351
DC_LOG_TRACE("CustomProbe::toJson called");
346-
json_object* j = Probe::toJson();
352+
json_object* j = Probe::toJson(include_functions);
347353
json_object_object_add(j, "bpf_path", json_object_new_string(bpf_path.c_str()));
348354
json_object_object_add(j, "start_event_id", json_object_new_int64(start_event_id));
349355
json_object_object_add(j, "process_header", json_object_new_string(process_header.c_str()));

src/datacrumbs/explorer/probe_explorer.cpp

Lines changed: 86 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,9 @@ ProbeExplorer::ProbeExplorer(int argc, char** argv) {
1010
has_invalid_probes_ = false;
1111
DC_LOG_TRACE("ProbeExplorer::ProbeExplorer - end");
1212
}
13-
14-
// Extracts probes based on configuration and exclusion file
15-
std::vector<std::shared_ptr<Probe>> ProbeExplorer::extractProbes() {
16-
DC_LOG_TRACE("ProbeExplorer::extractProbes - start");
13+
std::unordered_map<std::string, std::unordered_set<std::string>> ProbeExplorer::Extract_Exclusions() {
14+
DC_LOG_TRACE("ProbeExplorer::validate_exclusion_file - start");
1715
std::unordered_map<std::string, std::unordered_set<std::string>> exclusionMap;
18-
19-
// Load exclusion map from file if specified
2016
if (!configManager_->probe_exclusion_file_path.empty() &&
2117
std::filesystem::exists(configManager_->probe_exclusion_file_path)) {
2218
std::ifstream ifs(configManager_->probe_exclusion_file_path);
@@ -27,7 +23,14 @@ std::vector<std::shared_ptr<Probe>> ProbeExplorer::extractProbes() {
2723
int arr_len = json_object_array_length(jobj);
2824
for (int i = 0; i < arr_len; ++i) {
2925
json_object* probe_obj = json_object_array_get_idx(jobj, i);
30-
if (!probe_obj) continue;
26+
if (!probe_obj) {
27+
DC_LOG_WARN("the %dth element of exclusion file is missing (null pointer returned).", i);
28+
continue;
29+
}
30+
if (json_object_get_type(probe_obj) == json_type_null) {
31+
DC_LOG_WARN("exclusion file contains explicit JSON null at %dth element.", i);
32+
continue;
33+
}
3134
json_object* name_obj = nullptr;
3235
json_object* funcs_obj = nullptr;
3336
if (json_object_object_get_ex(probe_obj, "name", &name_obj) &&
@@ -39,20 +42,40 @@ std::vector<std::shared_ptr<Probe>> ProbeExplorer::extractProbes() {
3942
int func_len = json_object_array_length(funcs_obj);
4043
for (int j = 0; j < func_len; ++j) {
4144
json_object* func_obj = json_object_array_get_idx(funcs_obj, j);
45+
4246
if (func_obj && json_object_get_type(func_obj) == json_type_string) {
47+
//check the function name
48+
std::string func_name = json_object_get_string(func_obj);
49+
if(func_name.find('/')!= std::string::npos || func_name.find('\\') != std::string::npos || func_name.find(' ') != std::string::npos){
50+
DC_LOG_WARN("Exclusion file contains invalid function name '%s' for probe '%s'. Skipping this function.",
51+
func_name.c_str(), probe_name.c_str());
52+
continue;
53+
}
4354
func_set.insert(json_object_get_string(func_obj));
4455
}
4556
}
4657
exclusionMap[probe_name] = std::move(func_set);
58+
}else{
59+
DC_LOG_WARN("Exclusion file entry at index %d is missing 'name' or 'functions' field, or they are of incorrect type.", i);
4760
}
4861
}
62+
}else{
63+
DC_LOG_WARN("Exclusion file is not a valid JSON array.");
4964
}
5065
if (jobj) json_object_put(jobj);
5166
} else {
5267
DC_LOG_ERROR("Failed to open exclusion probes file: %s",
5368
configManager_->probe_exclusion_file_path.string().c_str());
5469
}
5570
}
71+
return exclusionMap;
72+
73+
DC_LOG_TRACE("ProbeExplorer::validate_exclusion_file - end");
74+
}
75+
// Extracts probes based on configuration and exclusion file
76+
std::vector<std::shared_ptr<Probe>> ProbeExplorer::extractProbes() {
77+
DC_LOG_TRACE("ProbeExplorer::extractProbes - start");
78+
auto exclusionMap = Extract_Exclusions();
5679

5780
// Log the contents of the exclusion map for debugging
5881
DC_LOG_DEBUG("Exclusion Map Contents:");
@@ -417,11 +440,67 @@ std::vector<std::shared_ptr<Probe>> ProbeExplorer::extractProbes() {
417440
DC_LOG_TRACE("ProbeExplorer::extractProbes - end");
418441
return probes;
419442
}
443+
void ProbeExplorer::create_exclusion_file(std::vector<std::shared_ptr<Probe>> probes) {
444+
DC_LOG_TRACE("ProbeExplorer::create_exclusion_file - start");
445+
json_object* jexarray = json_object_new_array();
446+
// Serialize each probe to JSON without functions
447+
for (const auto& probe : probes) {
448+
json_object* jexclude = nullptr;
449+
switch (probe->type) {
450+
case ProbeType::SYSCALLS:
451+
jexclude = std::dynamic_pointer_cast<SysCallProbe>(probe)->toJson(false);
452+
break;
453+
case ProbeType::KPROBE:
454+
jexclude = std::dynamic_pointer_cast<KProbe>(probe)->toJson(false);
455+
break;
456+
case ProbeType::UPROBE:
457+
jexclude = std::dynamic_pointer_cast<UProbe>(probe)->toJson(false);
458+
break;
459+
case ProbeType::USDT:
460+
jexclude = std::dynamic_pointer_cast<USDTProbe>(probe)->toJson(false);
461+
break;
462+
case ProbeType::CUSTOM:
463+
jexclude = std::dynamic_pointer_cast<CustomProbe>(probe)->toJson(false);
464+
break;
465+
default:
466+
DC_LOG_ERROR("Unknown probe type encountered.");
467+
continue; // Skip unknown types
468+
}
469+
if (!jexclude) {
470+
DC_LOG_ERROR("Failed to serialize probe for exclusion: %s", probe->name.c_str());
471+
continue; // Skip serialization failure
472+
}
473+
json_object_array_add(jexarray, jexclude);
474+
}
475+
if(!configManager_->probe_exclusion_file_path.empty() &&
476+
!std::filesystem::exists(configManager_->probe_exclusion_file_path)) {
477+
const char* exclude_json_str = json_object_to_json_string_ext(jexarray, JSON_C_TO_STRING_PRETTY);
478+
std::ofstream ofs(configManager_->probe_exclusion_file_path);
479+
if (ofs.is_open()) {
480+
ofs << exclude_json_str;
481+
ofs.close();
482+
} else {
483+
DC_LOG_ERROR("Failed to open file: %s", configManager_->probe_exclusion_file_path.c_str());
484+
}
485+
}
486+
487+
DC_LOG_TRACE("ProbeExplorer::create_exclusion_file - end");
488+
}
489+
490+
420491

421492
// Writes extracted probes to a JSON file and returns the probe list
422493
std::vector<std::shared_ptr<Probe>> ProbeExplorer::writeProbesToJson() {
423494
DC_LOG_TRACE("ProbeExplorer::writeProbesToJson - start");
424495
auto probes = extractProbes();
496+
if(probes.empty()) {
497+
DC_LOG_WARN("No valid probes extracted. Skipping JSON write.");
498+
return probes;
499+
}
500+
if(!configManager_->probe_exclusion_file_path.empty() &&
501+
!std::filesystem::exists(configManager_->probe_exclusion_file_path)) {
502+
create_exclusion_file(probes);
503+
}
425504
json_object* jarray = json_object_new_array();
426505

427506
// Serialize each probe to JSON

src/datacrumbs/explorer/probe_explorer.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,14 @@ class ProbeExplorer {
2929
public:
3030
// Constructor: Initializes ProbeExplorer with command-line arguments
3131
ProbeExplorer(int argc, char** argv);
32-
32+
// Extracts exclusion mappings and check for invalid entries
33+
// Returns a map of probe names to sets of function names to be excluded
34+
std::unordered_map<std::string, std::unordered_set<std::string>> Extract_Exclusions();
3335
// Extracts probes from a given data source (dummy implementation)
3436
// Returns a vector of shared pointers to Probe objects
3537
std::vector<std::shared_ptr<Probe>> extractProbes();
36-
38+
// Creates an exclusion file from the provided probes if the file does not exist
39+
void create_exclusion_file(std::vector<std::shared_ptr<Probe>> probes);
3740
// Writes extracted probes to a JSON file
3841
// Returns a vector of shared pointers to Probe objects
3942
std::vector<std::shared_ptr<Probe>> writeProbesToJson();

0 commit comments

Comments
 (0)