-
Notifications
You must be signed in to change notification settings - Fork 432
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: filldir64 event #4588
base: main
Are you sure you want to change the base?
fix: filldir64 event #4588
Conversation
@OriGlassman FYI |
The second parameter (`name`) of filldir64 is currently being interpreted as the `process name`, whereas it should be interpreted as the directory entry name (`dirent`).
6482680
to
b830f86
Compare
@@ -1674,8 +1674,8 @@ SEC("kprobe/filldir64") | |||
int BPF_KPROBE(trace_filldir64) | |||
{ | |||
// only inode=0 is relevant, simple filter prior to program run | |||
unsigned long process_inode_number = (unsigned long) PT_REGS_PARM5(ctx); | |||
if (process_inode_number != 0) | |||
unsigned long dirent_inode_number = (unsigned long) PT_REGS_PARM5(ctx); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes align with the probed function, but I suspect the probe name is misleading. It only submits events related to zeroed inodes (a corner case), which, in the case of procfs, would suppress output for the associated processes. To avoid confusion for those encountering this probe, renaming the probe appropriately would be great too.
@@ -11900,7 +11900,7 @@ var CoreEvents = map[ID]Definition{ | |||
}, | |||
sets: []string{}, | |||
fields: []trace.ArgMeta{ | |||
{Type: "char*", Name: "hidden_process"}, | |||
{Type: "char*", Name: "hidden_dirent"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{Type: "char*", Name: "hidden_dirent"}, | |
{Type: "char*", Name: "dirent_name"}, |
Although the event is used to catch hidden processes, the arg field is the name of the dirent with zeroed inode.
The event, in my opinion, should be called ZeroedInodes
, since whoever indirectly calls filldir64 may pass a zeroed inode. @NDStrahilevitz WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if research uses this event "raw" or passes it to a signature for further inspection. So their input is the relevant one. @OriGlassman @oshaked1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's used as data filter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As pointed out by @geyslan in this reference, always assuming that inode=0 is explicitly used by an attacker to hide an inode may lead to a false positive... if unused dir uses inode=0
as described:
The end of the entire directory is of course signified by reaching the end of the file. Unused directory entries are signified by inode = 0.
Maybe one possibility is changing the name as Geyslan suggested.
There is one helper from research which is using the field interpreting as hidden process
whereas should be hidden dirent
or unused dirent
or something similar.
Postponing this, since we need to release v0.23.0 asap. @rscampos |
1. Explain what the PR does
6482680 fix: filldir64 event
2. Explain how to test it
In order to generate the event
hidden_inodes
its necessary to triggerfilldir64
.filldir64
is triggered bygetdents64
(library function readdir). Flow: readdir -> getdents64 -> filldir64readdir source code:
Source code
3. Other comments
Notes: this C example is a partial PoC because don't trigger the event unless we comment out the lines:
For a fully PoC would be necessary to trigger the event and some how set the
inode=0
before callingfilldir64
. Maybe using a LKM to hookfilldir64
and set to 0 before passing to the original function.