@@ -138,8 +138,8 @@ falcosecurity::init_schema my_plugin::get_init_schema()
138
138
},
139
139
"hostProc": {
140
140
"type": "string",
141
- "title": "Path to reach the '/proc' folder we want to scan.",
142
- "description": "The plugin needs to scan the '/proc' of the host on which is running. In Falco usually we put the host '/proc' folder under '/host/proc' so the the default for this config is '/host'. The path used here must not have a final '/'."
141
+ "title": "[DEPRECATED] Path to reach the '/proc' folder we want to scan.",
142
+ "description": "[DEPRECATED] The plugin needs to scan the '/proc' of the host on which is running. In Falco usually we put the host '/proc' folder under '/host/proc' so the the default for this config is '/host'. The path used here must not have a final '/'."
143
143
}
144
144
},
145
145
"additionalProperties": false,
@@ -256,139 +256,6 @@ void my_plugin::parse_init_config(nlohmann::json& config_json)
256
256
}
257
257
}
258
258
}
259
-
260
- if (config_json.contains (nlohmann::json::json_pointer (HOST_PROC_PATH)))
261
- {
262
- config_json.at (nlohmann::json::json_pointer (HOST_PROC_PATH))
263
- .get_to (m_host_proc);
264
- }
265
- else
266
- {
267
- // Default value
268
- m_host_proc = " /host" ;
269
- }
270
- }
271
-
272
- void my_plugin::do_initial_proc_scan ()
273
- {
274
- std::filesystem::directory_iterator dir_iter;
275
- std::string proc_root = m_host_proc + " /proc" ;
276
- try
277
- {
278
- SPDLOG_INFO (" Start the process scan under: '{}'" , proc_root);
279
- dir_iter = std::filesystem::directory_iterator (proc_root);
280
- }
281
- catch (std::filesystem::filesystem_error& err)
282
- {
283
- SPDLOG_ERROR (" cannot iter over '{}' for initial proc scan: {}" ,
284
- proc_root, err.what ());
285
- return ;
286
- }
287
-
288
- int64_t tid = 0 ;
289
- std::string proc_path = " " ;
290
- std::string cgroup_line = " " ;
291
- for (const auto & entry : dir_iter)
292
- {
293
- auto file_name = entry.path ().filename ();
294
- // The file_name here should be `1`,`2` so the thread id, not the
295
- // process id. We should exclude other directories or files like
296
- // `bootconfig`,`vmstat`, ...
297
-
298
- if (!entry.is_directory () ||
299
- (tid = strtol (file_name.c_str (), NULL , 10 )) == 0 )
300
- {
301
- // skip if not a tid directory.
302
- continue ;
303
- }
304
-
305
- // Now scan /proc/pid/task for threads
306
- std::string task_dir = proc_root + " /" + file_name.c_str () + " /task" ;
307
-
308
- try
309
- {
310
- for (const auto & task_entry :
311
- std::filesystem::directory_iterator (task_dir))
312
- {
313
- try
314
- {
315
- auto task_file_name = task_entry.path ().filename ();
316
- tid = strtol (task_file_name.c_str (), NULL , 10 );
317
-
318
- if (tid == 0 || !task_entry.is_directory ())
319
- {
320
- SPDLOG_WARN (" Found task entry `{}` in process `{}` "
321
- " that is not "
322
- " a number" ,
323
- task_file_name.c_str (), file_name.c_str ());
324
- continue ; // skip if not a thread id directory
325
- }
326
- // Example of the path: `/proc/1/task/200/cgroup`
327
- proc_path = std::string (proc_root)
328
- .append (" /" )
329
- .append (file_name.c_str ())
330
- .append (" /task/" )
331
- .append (task_file_name.c_str ())
332
- .append (" /cgroup" );
333
-
334
- std::ifstream file (proc_path);
335
-
336
- if (file.is_open ())
337
- {
338
- // Read the first line from the file
339
- if (std::getline (file, cgroup_line))
340
- {
341
- std::string pod_uid =
342
- get_pod_uid_from_cgroup_string (cgroup_line);
343
- if (!pod_uid.empty ())
344
- {
345
- m_thread_id_pod_uid_map[tid] = pod_uid;
346
- SPDLOG_TRACE (" Found thread with tid '{}' and "
347
- " pod uid '{}'" ,
348
- tid, pod_uid);
349
- }
350
- }
351
- else
352
- {
353
- SPDLOG_WARN (" Cannot retrieve the cgroup first line "
354
- " for '{}'. "
355
- " Error: {}. Skip it" ,
356
- proc_path,
357
- file.eof () ? " Empty file"
358
- : strerror (errno));
359
- }
360
- file.close ();
361
- }
362
- else
363
- {
364
- SPDLOG_WARN (" Cannot open '{}'. Error: {}. Skip it." ,
365
- proc_path, strerror (errno));
366
- }
367
-
368
- SPDLOG_DEBUG (
369
- " Thread scan correctly completed for process `{}`" ,
370
- file_name.c_str ());
371
- }
372
- catch (const std::filesystem::filesystem_error& err)
373
- {
374
- SPDLOG_WARN (" cannot iter over '{}' for initial proc scan: "
375
- " {}. It could happen that some process "
376
- " entries disappear between iterations" ,
377
- task_dir, err.what ());
378
- }
379
- }
380
- }
381
- catch (const std::filesystem::filesystem_error& err)
382
- {
383
- SPDLOG_WARN (" cannot iter over '{}' for initial proc scan: {}. It "
384
- " could happen that some process entries disappear "
385
- " between iterations" ,
386
- task_dir, err.what ());
387
- }
388
- }
389
- SPDLOG_INFO (
390
- " Process scan correctly completed. Found '{}' threads inside pods." ,
391
- m_thread_id_pod_uid_map.size ());
392
259
}
393
260
394
261
bool my_plugin::init (falcosecurity::init_input& in)
@@ -428,11 +295,20 @@ bool my_plugin::init(falcosecurity::init_input& in)
428
295
try
429
296
{
430
297
m_thread_table = t.get_table (THREAD_TABLE_NAME, st::SS_PLUGIN_ST_INT64);
298
+
299
+ // get the 'cgroups' field accessor from the thread table
300
+ m_thread_field_cgroups = m_thread_table.get_field (
301
+ t.fields (), CGROUPS_TABLE_NAME, st::SS_PLUGIN_ST_TABLE);
302
+ // get the 'second' field accessor from the cgroups table
303
+ m_cgroups_field_second = t.get_subtable_field (
304
+ m_thread_table, m_thread_field_cgroups, " second" ,
305
+ st::SS_PLUGIN_ST_STRING);
306
+
431
307
// Add the pod_uid field into thread table
432
308
m_pod_uid_field = m_thread_table.add_field (
433
309
t.fields (), POD_UID_FIELD_NAME, st::SS_PLUGIN_ST_STRING);
434
310
}
435
- catch (falcosecurity::plugin_exception e)
311
+ catch (falcosecurity::plugin_exception& e)
436
312
{
437
313
m_lasterr = " cannot add the '" + std::string (POD_UID_FIELD_NAME) +
438
314
" ' field into the '" + std::string (THREAD_TABLE_NAME) +
@@ -441,11 +317,53 @@ bool my_plugin::init(falcosecurity::init_input& in)
441
317
return false ;
442
318
}
443
319
444
- // Here we do /proc scan to catch the pod_uid from already running
445
- // processes.
446
- // We cannot populate the sinsp thread table because when we call `init` it
447
- // is still empty. The /proc scan in sinsp is done after the plugin init.
448
- do_initial_proc_scan ();
320
+ return true ;
321
+ }
322
+
323
+ // ////////////////////////
324
+ // Listen capability
325
+ // ////////////////////////
326
+
327
+ bool my_plugin::capture_open (const falcosecurity::capture_listen_input& in) {
328
+ using st = falcosecurity::state_value_type;
329
+
330
+ SPDLOG_DEBUG (" enriching initial thread table entries" );
331
+ auto & tr = in.get_table_reader ();
332
+ auto & tw = in.get_table_writer ();
333
+ m_thread_table.iterate_entries (
334
+ tr,
335
+ [this , tr, tw](const falcosecurity::table_entry& e)
336
+ {
337
+ try {
338
+ auto cgroups_table = m_thread_table.get_subtable (tr,
339
+ m_thread_field_cgroups, e, st::SS_PLUGIN_ST_UINT64);
340
+ cgroups_table.iterate_entries (tr, [&](const falcosecurity::table_entry& e){
341
+ // read the "second" field (aka: the cgroup path)
342
+ // from the current entry of the cgroups table
343
+ std::string cgroup;
344
+ m_cgroups_field_second.read_value (tr, e, cgroup);
345
+ if (!cgroup.empty ()) {
346
+ const std::string pod_uid = get_pod_uid_from_cgroup_string (cgroup);
347
+ if (!pod_uid.empty ())
348
+ {
349
+ m_pod_uid_field.write_value (tw, e, pod_uid.c_str ());
350
+ // break the loop
351
+ return false ;
352
+ }
353
+ }
354
+ return true ;
355
+ });
356
+ return true ;
357
+ } catch (falcosecurity::plugin_exception &e) {
358
+ SPDLOG_ERROR (" cannot attach pod_uid to process: {}" , e.what ());
359
+ // break the loop
360
+ return false ;
361
+ }
362
+ });
363
+ return true ;
364
+ }
365
+
366
+ bool my_plugin::capture_close (const falcosecurity::capture_listen_input& in) {
449
367
return true ;
450
368
}
451
369
@@ -520,7 +438,7 @@ std::vector<falcosecurity::field_info> my_plugin::get_fields()
520
438
// Use an array to perform a static_assert one the size.
521
439
const falcosecurity::field_info fields[] = {
522
440
{ft::FTYPE_STRING, " k8smeta.pod.name" , " Pod Name" ,
523
- " Kubernetes pod name." },
441
+ " Kubernetes pod name." , {}, false , {}, true }, // use as suggested output format
524
442
{ft::FTYPE_STRING, " k8smeta.pod.uid" , " Pod UID" ,
525
443
" Kubernetes pod UID." },
526
444
{ft::FTYPE_STRING,
@@ -535,7 +453,7 @@ std::vector<falcosecurity::field_info> my_plugin::get_fields()
535
453
{ft::FTYPE_STRING, " k8smeta.pod.ip" , " Pod Ip" , " Kubernetes pod ip" },
536
454
537
455
{ft::FTYPE_STRING, " k8smeta.ns.name" , " Namespace Name" ,
538
- " Kubernetes namespace name." },
456
+ " Kubernetes namespace name." , {}, false , {}, true }, // use as suggested output format
539
457
{ft::FTYPE_STRING, " k8smeta.ns.uid" , " Namespace UID" ,
540
458
" Kubernetes namespace UID." },
541
459
{ft::FTYPE_STRING,
@@ -1112,27 +1030,9 @@ bool my_plugin::extract(const falcosecurity::extract_fields_input& in)
1112
1030
// The process is not into a pod, stop here.
1113
1031
if (pod_uid.empty ())
1114
1032
{
1115
- // If we fall here and our cache is empty, it means that probably we are
1116
- // not in a pod.
1117
- if (m_thread_id_pod_uid_map.empty ())
1118
- {
1119
- SPDLOG_TRACE (" no pod uid in the framework table for thread id '{}'" ,
1120
- thread_id);
1121
- return false ;
1122
- }
1123
-
1124
- // If the cache is not empty we try to search the pod_uid in the cache.
1125
- // There could be cases in which we first call an extract and then a
1126
- // parse so the sinsp table is not yet populated with the content of our
1127
- // cache and so we need to use it here.
1128
- auto it = m_thread_id_pod_uid_map.find (thread_id);
1129
- if (it == m_thread_id_pod_uid_map.end ())
1130
- {
1131
- SPDLOG_TRACE (" no pod uid in the plugin cache for thread id '{}'" ,
1132
- thread_id);
1133
- return false ;
1134
- }
1135
- pod_uid = it->second ;
1033
+ SPDLOG_TRACE (" no pod uid in the framework table for thread id '{}'" ,
1034
+ thread_id);
1035
+ return false ;
1136
1036
}
1137
1037
1138
1038
// Try to find the entry associated with the pod_uid
@@ -1468,7 +1368,7 @@ bool inline my_plugin::parse_process_events(
1468
1368
std::string pod_uid = get_pod_uid_from_cgroup_string (cgroup_first_charbuf);
1469
1369
1470
1370
// If we don't have a pod_uid we don't need to populate the table
1471
- if (pod_uid != " " )
1371
+ if (!pod_uid. empty () )
1472
1372
{
1473
1373
// retrieve thread entry associated with the event tid
1474
1374
auto & tr = in.get_table_reader ();
@@ -1494,40 +1394,6 @@ bool my_plugin::parse_event(const falcosecurity::parse_event_input& in)
1494
1394
{
1495
1395
// NOTE: today in the libs framework, parsing errors are not logged
1496
1396
1497
- // Workaround: the parsing is the unique place where we can populate the
1498
- // sinsp thread table. The first time we call parse we populate the sinsp
1499
- // table and we clear our internal cache.
1500
- if (!m_sinsp_proc_populated)
1501
- {
1502
- auto & tr = in.get_table_reader ();
1503
- auto & tw = in.get_table_writer ();
1504
- falcosecurity::table_entry thread_entry;
1505
-
1506
- SPDLOG_INFO (" Update the framework state with the plugin cache. The "
1507
- " cache has '{}' "
1508
- " elements" ,
1509
- m_thread_id_pod_uid_map.size ());
1510
-
1511
- for (auto it = m_thread_id_pod_uid_map.begin ();
1512
- it != m_thread_id_pod_uid_map.end (); it++)
1513
- {
1514
- try
1515
- {
1516
- thread_entry = m_thread_table.get_entry (tr, (int64_t )it->first );
1517
- m_pod_uid_field.write_value (tw, thread_entry,
1518
- (const char *)it->second .c_str ());
1519
- }
1520
- catch (falcosecurity::plugin_exception e)
1521
- {
1522
- SPDLOG_WARN (" Thead id '{}' with pod_uid '{}' is not found "
1523
- " inside the framework table. Skip it." ,
1524
- it->first , it->second );
1525
- }
1526
- }
1527
- m_thread_id_pod_uid_map.clear ();
1528
- m_sinsp_proc_populated = true ;
1529
- }
1530
-
1531
1397
uint16_t evt_type = in.get_event_reader ().get_type ();
1532
1398
switch (evt_type)
1533
1399
{
0 commit comments