Closed mstemm closed 2 years ago
I'd like to understand why we have no routing table entry for execve
and umount
; moreover, there is even no PPM_SC_EXECVE.
Btw thanks for catching this! Another solution would be to let sinsp::fill_syscalls_of_interest()
set NULL oargs->ppm_sc_of_interest
pointer when no m_simpleconsumer
is set; i think this is cleaner;
but, again, i'd like to understand why those syscalls are missing from routing table in the first place.
@mstemm @ldegio any idea why the routing table is missing entries for execve
and umount
?
driver/syscall_table.c:
[__NR_umount - SYSCALL_TABLE_ID0] = PPM_SC_UMOUNT,
...
userspace/libscap/syscall_info_table.c
/*PPM_SC_UMOUNT*/ { EC_FILE, (enum ppm_event_flags)(EF_NONE), "umount" },
I think we'd expect the routing table to have the PPM_SC_UMOUNT<->syscall mapping.
Instead, PPM_SC_EXECVE does not exist.
A fix is proposed in #177 .
I fixed it using the cleanest solution, ie: by adding the proper routing table values.
I think there is a bug, or at least some unintended behavior, associated with those changes. The bug is that certain code paths which are trying to get the previous/default behavior (track all system calls), fail to do so.
The source of the bug involves three sections of code:
1) scap.c, function scap_open_live_int()
Look at this code, which populates the handle->syscalls_of_interest[] table:
If the caller specifies a NULL pointer for ppm_sc_of_interest, then the code sets ALL elements of handle->syscalls_of_interest[] to TRUE (lines 365-369), thus preserving the original default behavior of tracking all system calls.
But, if the caller specifies a non-NULL pointer, then code examines ppm_sc_of_interest AND the g_syscall_code_routing_table[] (lines 345-361) to figure out which elements of handle->syscalls_of_interest[] to populate.
2) syscall_table.c, syscall_code_routing_table[] definition
The g_syscall_code_routing_table[] DOES NOT contain any entry for the execve or umount2 system calls. So, anytime scap_open_live_int() lines 345-361 runs, to build the handle->syscalls_of_interest[] based on the caller-specified ppm_sc_of_interest, it NEVER sets syscalls_of_interest entry for those system calls.
3) sinsp.cpp, function fill_syscalls_of_interest()
If no specific set of system calls is specified, the logic wants to request the default behavior -- tracking all system calls. It TRIES to achieve this by populating oargs->ppm_sc_of_interest with all 1s:
But, as described under above, what ends up happening is, execve and umount ARE not set in the handle's syscalls_of_interest[], and thus are not captured.
Here's a localized workaround that I implemented, in scap_open_live_int(), to work around this issue:
Force the use of the 2nd code path (lines 365-369 above) in this case.
NEW // Special case -- force fallback path if all syscalls are enabled. NEW // This works around the following situation: NEW // - g_syscall_code_routing_table[] is incomplete NEW // - It does not contain an entry for execve or umount2 (and possibly others) NEW // - so, syscalls_of_interest builder below fails to enable those system calls NEW if (ppm_sc_of_interest) NEW { NEW bool all_set = true; NEW for (int i = 0; i < PPM_SC_MAX; i++) NEW { NEW if (!ppm_sc_of_interest->ppm_sc[i]) NEW { NEW all_set = false; NEW break; NEW } NEW } NEW NEW if (all_set) NEW { NEW ppm_sc_of_interest = NULL; NEW } NEW } NEW
343 if (ppm_sc_of_interest) 344 { 345 for (int i = 0; i < PPM_SC_MAX; i++) ... 362 } 363 else 364 { 365 // fallback to trace all syscalls 366 for (int i = 0; i < SYSCALL_TABLE_SIZE; i++) 367 { 368 handle->syscalls_of_interest[i] = true; 369 } 370 }