-
Notifications
You must be signed in to change notification settings - Fork 393
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
tetragon: Add support to use security_ functions in killer #2002
Conversation
87558af
to
0452e39
Compare
✅ Deploy Preview for tetragon ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
ed095f2
to
44502b5
Compare
44502b5
to
a53fa6c
Compare
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.
Thanks :)
Had a quick look and added some first comments.
pkg/sensors/tracing/generickprobe.go
Outdated
@@ -355,6 +355,9 @@ func createMultiKprobeSensor(sensorPath string, multiIDs []idtable.EntryID) ([]* | |||
maps = append(maps, socktrack) | |||
} | |||
|
|||
killerDataMap := program.MapBuilderPin("killer_data", "killer_data", load) |
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.
Let's use
tetragon/pkg/sensors/tracing/killer.go
Line 24 in 506677d
killerDataMapName = "killer_data" |
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.
nice, did not see that, thanks
Just curious, how is this different from killing a process inline by overriding the return value of one of the LSM calls to be non-zero? |
not too much different, this way we get invoked earlier directly from security_* function call, lsm hook would get invoked later on, but that would not really matter, it'd work the same I think.. another thing is we don't need to depend on lsm being enabled |
ee0866a
to
2fdef39
Compare
Also its non-obvious that all syscalls map to a security hook. Many will but not sure its 1:1 without auditing. |
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.
Thanks!
if hasSyscall && !bpf.HasModifyReturnSyscall() { | ||
return OverrideMethodInvalid, fmt.Errorf("option fmod_ret on syscall set, but it is not supported") | ||
} | ||
if hasNormal && !bpf.HasModifyReturn() { | ||
return OverrideMethodInvalid, fmt.Errorf("option fmod_ret set, but it is not supported") |
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 don't think the hasNormal
check is needed.
AFIACT, if HadModifyReturnSyscall()
is true , HasModifyReturn()
is (always) true.
So I think the following check:
if !bpf.HasModifyReturn() || (hasSyscall && !bpf.HasModifyReturnSyscall()) {
return err
}
catches all the cases we care about, without the extra argument.
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.
right, I guess I wanted it to be more explicit.. I'll change that
I didn't follow it closely but I have one question: would it be possible to just fmod_ret the security_ hook without killing the process? is the old behavior still supported? cause there is valid software there that is happy with -EPERM and continues to work as expected, delivering sigkill for such cases is too much and could break. Also extra note didn't check code but as John noted is this planning a 1:1 mapping? the security hooks don't really map to syscalls, there are syscalls->operations (different context)-> lead to same security hook, and other cases where one syscall is handled through multiple security hooks according to context. The security hooks are more about the context of the process, actually constructing the context if we check that in details, then acting when necessary, where in syscall you may act in advance without context at all... The mapping could work for some read/write fs operation but for other cases where example the kernel acts on behalf is different story |
To get error value for wrong pattern. Signed-off-by: Jiri Olsa <[email protected]>
Adding extra Attach field to the loading log message, from: logcapture.go:25: time="2024-01-22T08:53:45Z" level=info msg="Loading BPF program" Program=/home/jolsa/tetragon/bpf/objs/bpf_exit.o Type=kprobe logcapture.go:25: time="2024-01-22T08:53:45Z" level=info msg="Loading BPF program" Program=/home/jolsa/tetragon/bpf/objs/bpf_fork.o Type=kprobe time="2024-01-22T08:55:09Z" level=info msg="tetragon, map loaded." map=killer_data path=/sys/fs/bpf/tetragon/killer_data sensor=__killer__ time="2024-01-22T08:55:09Z" level=info msg="Loading registered BPF probe" Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:55:09Z" level=info msg="Loading registered BPF probe" Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:55:09Z" level=info msg="Loading registered BPF probe" Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:55:09Z" level=info msg="Loading registered BPF probe" Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:55:09Z" level=info msg="Loading registered BPF probe" Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:55:09Z" level=info msg="Loading registered BPF probe" Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:55:09Z" level=info msg="Loading registered BPF probe" Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:55:09Z" level=info msg="Loading registered BPF probe" Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:55:09Z" level=info msg="Loading registered BPF probe" Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:55:09Z" level=info msg="Loading registered BPF probe" Program=bpf/objs/bpf_fmodret_killer.o Type=killer to following: logcapture.go:25: time="2024-01-22T08:51:37Z" level=info msg="Loading BPF program" Attach=acct_process Program=/home/jolsa/tetragon/bpf/objs/bpf_exit.o Type=kprobe logcapture.go:25: time="2024-01-22T08:51:37Z" level=info msg="Loading BPF program" Attach=wake_up_new_task Program=/home/jolsa/tetragon/bpf/objs/bpf_fork.o Type=kprobe time="2024-01-22T08:57:12Z" level=info msg="tetragon, map loaded." map=killer_data path=/sys/fs/bpf/tetragon/killer_data sensor=__killer__ time="2024-01-22T08:57:12Z" level=info msg="Loading registered BPF probe" Attach=security_audit_rule_free Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:57:12Z" level=info msg="Loading registered BPF probe" Attach=security_audit_rule_init Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:57:12Z" level=info msg="Loading registered BPF probe" Attach=security_audit_rule_known Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:57:12Z" level=info msg="Loading registered BPF probe" Attach=security_audit_rule_match Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:57:12Z" level=info msg="Loading registered BPF probe" Attach=security_binder_set_context_mgr Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:57:12Z" level=info msg="Loading registered BPF probe" Attach=security_binder_transaction Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:57:12Z" level=info msg="Loading registered BPF probe" Attach=security_binder_transfer_binder Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:57:12Z" level=info msg="Loading registered BPF probe" Attach=security_binder_transfer_file Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:57:12Z" level=info msg="Loading registered BPF probe" Attach=security_bounded_transition Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:57:12Z" level=info msg="Loading registered BPF probe" Attach=security_bpf Program=bpf/objs/bpf_fmodret_killer.o Type=killer time="2024-01-22T08:57:12Z" level=info msg="Loading registered BPF probe" Attach=security_bpf_map Program=bpf/objs/bpf_fmodret_killer.o Type=killer Signed-off-by: Jiri Olsa <[email protected]>
We are about to allow security_* functions in killer, so let's rename killer's syscalls field to calls. Signed-off-by: Jiri Olsa <[email protected]>
Adding support to use NotifyKiller action from kprobes, which means we need to add the do_action_notify_killer to the kprobe ebpf program and share the killer_data map with the kprobe sensor. Signed-off-by: Jiri Olsa <[email protected]>
Adding support to use security_* functions in killer in addition to syscalls. It's possible now to use spec like: killers: - syscalls: - "security_file_permission" Signed-off-by: Jiri Olsa <[email protected]>
yes, this change just adds functionality, does not remove any, it adds the possibility to attach killer to security_* functions
the idea behind this change is to be able to kill process that's about to execute a syscall and make sure the syscall is not executed by attaching extra killer probe to security function (because there could be kernel configs where you can't override syscall directly) ... it's up to the user to pick up which security function to hook for which syscall, there's nothing hardcoded |
Checking fmodret support based on the symbol types used in killer, so the detected support can properly evaluate the need to fail. Signed-off-by: Jiri Olsa <[email protected]>
Adding direct-write-tester tester prog to test the bypass of sigkill action in pwrite. It's originally written by Anastasios. Signed-off-by: Jiri Olsa <[email protected]>
Testing the ability to kill the process before it executes the syscall, in this case direct pwrite syscall. Standard Sigkill action kills executed from sys_pwrite probe kills the process, but only after the pwrite syscall is executed. Now we can mitigate that by attaching killer to security_file_permission function and override its return value to prevent the pwrite syscall execution. Signed-off-by: Jiri Olsa <[email protected]>
2fdef39
to
42fc929
Compare
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.
thanks looks good! :)
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.
Thanks!
Adding support to attach killer to security_ functions and use NotifyKiller from kprobe. It's used to override specific security_* function in case we want to ensure we bypass syscall processing before sigkill is delivered.