diff --git a/pkg/ebpf/uprobes/attacher_test.go b/pkg/ebpf/uprobes/attacher_test.go index be848bb5c6afb8..8b9e144d15a804 100644 --- a/pkg/ebpf/uprobes/attacher_test.go +++ b/pkg/ebpf/uprobes/attacher_test.go @@ -985,9 +985,10 @@ func (s *SharedLibrarySuite) TestDetectionWithPIDAndRootNamespace() { t.Cleanup(ua.Stop) time.Sleep(10 * time.Millisecond) - // simulate a slow (1 second) : open, write, close of the file + // simulate a slow (1 second) : open, read, close of the file // in a new pid and mount namespaces - o, err := exec.Command("unshare", "--fork", "--pid", "-R", root, "/ash", "-c", fmt.Sprintf("sleep 1 > %s", libpath)).CombinedOutput() + o, err := exec.Command("unshare", "--fork", "--pid", "-R", root, "/ash", "-c", + fmt.Sprintf("touch foo && mv foo %s && sleep 1 < %s", libpath, libpath)).CombinedOutput() if err != nil { t.Log(err, string(o)) } diff --git a/pkg/network/ebpf/c/shared-libraries/probes.h b/pkg/network/ebpf/c/shared-libraries/probes.h index a45e9d0b494e15..de2db6d9af5f30 100644 --- a/pkg/network/ebpf/c/shared-libraries/probes.h +++ b/pkg/network/ebpf/c/shared-libraries/probes.h @@ -102,9 +102,24 @@ static __always_inline void do_sys_open_helper_exit(exit_sys_ctx *args) { return; } +// This definition is the same for all architectures. +#ifndef O_WRONLY +#define O_WRONLY 00000001 +#endif + +static __always_inline int should_ignore_flags(int flags) +{ + return flags & O_WRONLY; +} + SEC("tracepoint/syscalls/sys_enter_open") int tracepoint__syscalls__sys_enter_open(enter_sys_open_ctx *args) { CHECK_BPF_PROGRAM_BYPASSED() + + if (should_ignore_flags(args->flags)) { + return 0; + } + do_sys_open_helper_enter(args->filename); return 0; } @@ -119,6 +134,11 @@ int tracepoint__syscalls__sys_exit_open(exit_sys_ctx *args) { SEC("tracepoint/syscalls/sys_enter_openat") int tracepoint__syscalls__sys_enter_openat(enter_sys_openat_ctx *args) { CHECK_BPF_PROGRAM_BYPASSED() + + if (should_ignore_flags(args->flags)) { + return 0; + } + do_sys_open_helper_enter(args->filename); return 0; } @@ -133,6 +153,8 @@ int tracepoint__syscalls__sys_exit_openat(exit_sys_ctx *args) { SEC("tracepoint/syscalls/sys_enter_openat2") int tracepoint__syscalls__sys_enter_openat2(enter_sys_openat2_ctx *args) { CHECK_BPF_PROGRAM_BYPASSED() + // Unlike the other variants, openat2(2) has the flags embedded inside the + // how argument; we don't bother trying to accessing it for now. do_sys_open_helper_enter(args->filename); return 0; } diff --git a/pkg/network/usm/sharedlibraries/watcher_test.go b/pkg/network/usm/sharedlibraries/watcher_test.go index 5a0c29e862c10f..d55635fd2ecc7b 100644 --- a/pkg/network/usm/sharedlibraries/watcher_test.go +++ b/pkg/network/usm/sharedlibraries/watcher_test.go @@ -104,6 +104,42 @@ func (s *SharedLibrarySuite) TestSharedLibraryDetection() { }, time.Second*10, 100*time.Millisecond) } +// Test that shared library files opened for writing only are ignored. +func (s *SharedLibrarySuite) TestSharedLibraryIgnoreWrite() { + t := s.T() + + // Since we want to detect that the write _hasn't_ been detected, verify the + // read too to try to ensure that test isn't broken and failing to detect + // the write due to some bug in the test itself. + readPath, readPathID := createTempTestFile(t, "read-foo-libssl.so") + writePath, writePathID := createTempTestFile(t, "write-foo-libssl.so") + + registerRecorder := new(utils.CallbackRecorder) + unregisterRecorder := new(utils.CallbackRecorder) + + watcher, err := NewWatcher(utils.NewUSMEmptyConfig(), LibsetCrypto, + Rule{ + Re: regexp.MustCompile(`foo-libssl.so`), + RegisterCB: registerRecorder.Callback(), + UnregisterCB: unregisterRecorder.Callback(), + }, + ) + require.NoError(t, err) + watcher.Start() + t.Cleanup(watcher.Stop) + + // Use a sleep 1 as in TestSharedLibraryDetectionWithPIDAndRootNamespace + // below to give the watcher a chance to detect the process. + _, err = exec.Command("sh", "-c", + fmt.Sprintf("sleep 1 < %s > %s", readPath, writePath)).CombinedOutput() + require.NoError(t, err) + + require.EventuallyWithT(t, func(c *assert.CollectT) { + assert.Equal(c, 1, registerRecorder.CallsForPathID(readPathID)) + assert.Equal(c, 0, registerRecorder.CallsForPathID(writePathID)) + }, time.Second*5, 10*time.Millisecond) +} + func (s *SharedLibrarySuite) TestLongPath() { t := s.T() @@ -288,9 +324,10 @@ func (s *SharedLibrarySuite) TestSharedLibraryDetectionWithPIDAndRootNamespace() t.Cleanup(watcher.Stop) time.Sleep(10 * time.Millisecond) - // simulate a slow (1 second) : open, write, close of the file + // simulate a slow (1 second) : open, read, close of the file // in a new pid and mount namespaces - o, err := exec.Command("unshare", "--fork", "--pid", "-R", root, "/ash", "-c", fmt.Sprintf("sleep 1 > %s", libpath)).CombinedOutput() + o, err := exec.Command("unshare", "--fork", "--pid", "-R", root, "/ash", "-c", + fmt.Sprintf("touch foo && mv foo %s && sleep 1 < %s", libpath, libpath)).CombinedOutput() if err != nil { t.Log(err, string(o)) }