cilium / tetragon

eBPF-based Security Observability and Runtime Enforcement

Home Page:https://tetragon.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

LSM `security_path_*` deletion kprobes can't resolve target dentry name

crabique opened this issue · comments

What happened?

On latest Tetragon release, the behavior of security hooks related to deletion seems to have changed compared to 1.0.0.

Previously (before 1.0.1), for these hooks it would not even prepend the root path before the mount point, but the file_arg was always the correct operation subject:

$ rmdir -- /mnt/ext4/test/emptydir # security_path_rmdir
[{"file_arg":{"path":"/ (deleted)"}},{"file_arg":{"path":"/test/emptydir"}}]

In 1.0.1 this got changed, and the correct path is now available in path_arg. However, there is nothing in the file_arg for deletion operations anymore, so the file/directory name can't be tracked:

$ rmdir -- /mnt/ext4/test/emptydir # security_path_rmdir
[{"path_arg":{"path":"/mnt/ext4/test"}},{"file_arg"{"flags":"unresolvedPathComponents"}}]}

$ rm -f -- /mnt/ext4/test/file # security_path_unlink
[{"path_arg":{"path":"/mnt/ext4/test"}}, {"file_arg":{"flags":"unresolvedPathComponents"}}]

This may also affect other hooks, these are just the ones I stumbled upon.

Tetragon Version

1.1.0

Kernel Version

5.15.0-91-generic

Kubernetes Version

1.26

Bugtool

No response

Relevant log output

No response

Anything else?

No response

Thanks for reporting this issue in Tetragon!

The prototype for security_path_rename function is int security_path_rmdir(const struct path *dir, struct dentry *dentry).

In the first case, you report:

$ rmdir -- /mnt/ext4/test/emptydir # security_path_rmdir
[{"file_arg":{"path":"/ (deleted)"}},{"file_arg":{"path":"/test/emptydir"}}]

Based on these it seems that the tracing policy that you used is something like:

  kprobes:
  - call: "security_path_rmdir"
    syscall: false
    args:
    - index: 0
      type: "file"
    - index: 1
      type: "file"

Which is not correct as none of the function args is struct file *. The first is struct path * and the second struct dentry *.

In the second case, you report:

$ rmdir -- /mnt/ext4/test/emptydir # security_path_rmdir
[{"path_arg":{"path":"/mnt/ext4/test"}},{"file_arg"{"flags":"unresolvedPathComponents"}}]}

Based on these it seems that the tracing policy that you used is something like:

  kprobes:
  - call: "security_path_rmdir"
    syscall: false
    args:
    - index: 0
      type: "path"
    - index: 1
      type: "file"

Which is not correct as the second argument of the function args is not struct file * but struct dentry *.

Based on this, Tetragonal has support for struct path * but not for struct dentry *.

So a correct tracing policy (based on what Tetragonal supports) would be:

  kprobes:
  - call: "security_path_rmdir"
    syscall: false
    args:
    - index: 0
      type: "path"
    - index: 1
      type: "nop"

Which I tested on both v1.0 and v1.1 and seems to return the directory where the rmdir happens. As Tetragon does not have support for struct dentry *, we cannot see the name of the directory that is going to be deleted.

Let me know if any of these does not make sense!

Thanks @tpapagian! I'm closing the issue.