ebpf.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. package pod
  2. /*import (
  3. "fmt"
  4. "github.com/cilium/ebpf"
  5. "github.com/cilium/ebpf/asm"
  6. "github.com/cilium/ebpf/link"
  7. "github.com/opencontainers/runtime-spec/specs-go"
  8. "golang.org/x/sys/unix"
  9. )
  10. // LoadAttachCgroupDeviceFilter installs eBPF device filter program to /sys/fs/cgroup/<foo> directory.
  11. //
  12. // Requires the system to be running in cgroup2 unified-mode with kernel >= 4.15 .
  13. //
  14. // https://github.com/torvalds/linux/commit/ebc614f687369f9df99828572b1d85a7c2de3d92
  15. func LoadAttachCgroupDeviceFilter(insts asm.Instructions, license string, dirFD int) (func() error, error) {
  16. nilCloser := func() error {
  17. return nil
  18. }
  19. spec := &ebpf.ProgramSpec{
  20. Type: ebpf.CGroupDevice,
  21. Instructions: insts,
  22. License: license,
  23. }
  24. prog, err := ebpf.NewProgram(spec)
  25. if err != nil {
  26. return nilCloser, err
  27. }
  28. err = link.RawAttachProgram(link.RawAttachProgramOptions{
  29. Target: dirFD,
  30. Program: prog,
  31. Attach: ebpf.AttachCGroupDevice,
  32. Flags: unix.BPF_F_ALLOW_MULTI,
  33. })
  34. if err != nil {
  35. return nilCloser, fmt.Errorf("failed to call BPF_PROG_ATTACH (BPF_CGROUP_DEVICE, BPF_F_ALLOW_MULTI): %w", err)
  36. }
  37. closer := func() error {
  38. err = link.RawDetachProgram(link.RawDetachProgramOptions{
  39. Target: dirFD,
  40. Program: prog,
  41. Attach: ebpf.AttachCGroupDevice,
  42. })
  43. if err != nil {
  44. return fmt.Errorf("failed to call BPF_PROG_DETACH (BPF_CGROUP_DEVICE): %w", err)
  45. }
  46. return nil
  47. }
  48. return closer, nil
  49. }
  50. func isRWM(cgroupPermissions string) bool {
  51. r := false
  52. w := false
  53. m := false
  54. for _, rn := range cgroupPermissions {
  55. switch rn {
  56. case 'r':
  57. r = true
  58. case 'w':
  59. w = true
  60. case 'm':
  61. m = true
  62. }
  63. }
  64. return r && w && m
  65. }
  66. // the logic is from runc
  67. // https://github.com/opencontainers/runc/blob/master/libcontainer/cgroups/fs/devices_v2.go#L44
  68. func canSkipEBPFError(devices []specs.LinuxDeviceCgroup) bool {
  69. for _, dev := range devices {
  70. if dev.Allow || !isRWM(dev.Access) {
  71. return false
  72. }
  73. }
  74. return true
  75. }
  76. */