Skip to content

Commit

Permalink
Add check to ensure we attach to shared libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
gjulianm committed Jan 31, 2025
1 parent c68ee8d commit 56ff278
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 9 deletions.
11 changes: 4 additions & 7 deletions pkg/ebpf/uprobes/attacher.go
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ func (ua *UprobeAttacher) AttachPIDWithOptions(pid uint32, attachToLibs bool) er
procInfo := NewProcInfo(ua.config.ProcRoot, pid)

// Only compute the binary path if we are going to need it. It's better to do these two checks
// (which are cheak, the handlesExecutables function is cached) than to do the syscall
// (which are cheap, the handlesExecutables function is cached) than to do the syscall
// every time
var binPath string
var err error
Expand All @@ -679,21 +679,18 @@ func (ua *UprobeAttacher) AttachPIDWithOptions(pid uint32, attachToLibs bool) er

if ua.handlesExecutables() {
matchingRules := ua.getRulesForExecutable(binPath, procInfo)

if len(matchingRules) != 0 {
registerCB, unregisterCB := ua.buildRegisterCallbacks(matchingRules, procInfo)
err = ua.fileRegistry.Register(binPath, pid, registerCB, unregisterCB, utils.IgnoreCB)
if err != nil {
return err
}
// Do not return in case of error, as we still might want to attach to libraries
}
}

if attachToLibs && ua.handlesLibraries() {
return ua.attachToLibrariesOfPID(pid)
err = errors.Join(err, ua.attachToLibrariesOfPID(pid))
}

return nil
return err
}

// DetachPID detaches the uprobes attached to a PID
Expand Down
40 changes: 40 additions & 0 deletions pkg/ebpf/uprobes/attacher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package uprobes

import (
"errors"
"fmt"
"os"
"os/exec"
Expand Down Expand Up @@ -63,6 +64,45 @@ func TestAttachPidExcludesInternal(t *testing.T) {
require.ErrorIs(t, err, ErrInternalDDogProcessRejected)
}

func TestAttachPidReadsSharedLibraries(t *testing.T) {
exe := "foobar"
pid := uint32(1)
libname := "/target/libssl.so"
maps := fmt.Sprintf("08048000-08049000 r-xp 00000000 03:00 8312 %s", libname)
procRoot := CreateFakeProcFS(t, []FakeProcFSEntry{{Pid: pid, Cmdline: exe, Command: exe, Exe: exe, Maps: maps}})
config := AttacherConfig{
ProcRoot: procRoot,
Rules: []*AttachRule{
{LibraryNameRegex: regexp.MustCompile(`libssl\.so`), Targets: AttachToSharedLibraries},
{Targets: AttachToExecutable},
},
SharedLibsLibset: sharedlibraries.LibsetCrypto,
EnableDetailedLogging: true,
}

registry := &MockFileRegistry{}
// Force a failure on the Register call for the executable, to simulate a
// binary that doesn't have our desired functions to attach
registry.On("Register", exe, pid, mock.Anything, mock.Anything, mock.Anything).Return(errors.New("cannot attach"))

// Expect a call to Register for the library
registry.On("Register", libname, pid, mock.Anything, mock.Anything, mock.Anything).Return(nil)

ua, err := NewUprobeAttacher(testModuleName, testAttacherName, config, &MockManager{}, nil, nil, newMockProcessMonitor())
require.NoError(t, err)
require.NotNil(t, ua)
require.True(t, ua.handlesExecutables())
require.True(t, ua.handlesLibraries())
ua.fileRegistry = registry

err = ua.AttachPIDWithOptions(pid, true)
require.Error(t, err)

// We should get calls to Register both with the executable and the library
// name, even though the executable returns an error
registry.AssertExpectations(t)
}

func TestAttachPidExcludesSelf(t *testing.T) {
config := AttacherConfig{
ExcludeTargets: ExcludeSelf,
Expand Down
4 changes: 2 additions & 2 deletions pkg/ebpf/uprobes/testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ type MockFileRegistry struct {
}

// Register is a mock implementation of the FileRegistry.Register method.
func (m *MockFileRegistry) Register(namespacedPath string, pid uint32, activationCB, deactivationCB, _ utils.Callback) error {
args := m.Called(namespacedPath, pid, activationCB, deactivationCB)
func (m *MockFileRegistry) Register(namespacedPath string, pid uint32, activationCB, deactivationCB, ignoreCB utils.Callback) error {
args := m.Called(namespacedPath, pid, activationCB, deactivationCB, ignoreCB)
return args.Error(0)
}

Expand Down

0 comments on commit 56ff278

Please sign in to comment.