bpf_probe_read.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. use aya::{maps::Array, programs::UProbe, Bpf};
  2. const RESULT_BUF_LEN: usize = 1024;
  3. #[derive(Copy, Clone)]
  4. #[repr(C)]
  5. struct TestResult {
  6. did_error: u64,
  7. len: usize,
  8. buf: [u8; RESULT_BUF_LEN],
  9. }
  10. unsafe impl aya::Pod for TestResult {}
  11. #[test]
  12. fn bpf_probe_read_user_str_bytes() {
  13. let bpf = set_user_buffer(b"foo\0", RESULT_BUF_LEN);
  14. assert_eq!(result_bytes(&bpf), b"foo");
  15. }
  16. #[test]
  17. fn bpf_probe_read_user_str_bytes_truncate() {
  18. let s = vec![b'a'; RESULT_BUF_LEN];
  19. let bpf = set_user_buffer(&s, RESULT_BUF_LEN);
  20. // The kernel truncates the string and the last byte is the null terminator
  21. assert_eq!(result_bytes(&bpf), &s[..RESULT_BUF_LEN - 1]);
  22. }
  23. #[test]
  24. fn bpf_probe_read_user_str_bytes_empty_string() {
  25. let bpf = set_user_buffer(b"\0", RESULT_BUF_LEN);
  26. assert_eq!(result_bytes(&bpf), b"");
  27. }
  28. #[test]
  29. fn bpf_probe_read_user_str_bytes_empty_dest() {
  30. let bpf = set_user_buffer(b"foo\0", 0);
  31. assert_eq!(result_bytes(&bpf), b"");
  32. }
  33. #[test]
  34. fn bpf_probe_read_kernel_str_bytes() {
  35. let bpf = set_kernel_buffer(b"foo\0", RESULT_BUF_LEN);
  36. assert_eq!(result_bytes(&bpf), b"foo");
  37. }
  38. #[test]
  39. fn bpf_probe_read_kernel_str_bytes_truncate() {
  40. let s = vec![b'a'; RESULT_BUF_LEN];
  41. let bpf = set_kernel_buffer(&s, RESULT_BUF_LEN);
  42. // The kernel truncates the string and the last byte is the null terminator
  43. assert_eq!(result_bytes(&bpf), &s[..RESULT_BUF_LEN - 1]);
  44. }
  45. #[test]
  46. fn bpf_probe_read_kernel_str_bytes_empty_string() {
  47. let bpf = set_kernel_buffer(b"\0", RESULT_BUF_LEN);
  48. assert_eq!(result_bytes(&bpf), b"");
  49. }
  50. #[test]
  51. fn bpf_probe_read_kernel_str_bytes_empty_dest() {
  52. let bpf = set_kernel_buffer(b"foo\0", 0);
  53. assert_eq!(result_bytes(&bpf), b"");
  54. }
  55. fn set_user_buffer(bytes: &[u8], dest_len: usize) -> Bpf {
  56. let bpf = load_and_attach_uprobe(
  57. "test_bpf_probe_read_user_str_bytes",
  58. "trigger_bpf_probe_read_user",
  59. integration_test::BPF_PROBE_READ,
  60. );
  61. trigger_bpf_probe_read_user(bytes.as_ptr(), dest_len);
  62. bpf
  63. }
  64. fn set_kernel_buffer(bytes: &[u8], dest_len: usize) -> Bpf {
  65. let mut bpf = load_and_attach_uprobe(
  66. "test_bpf_probe_read_kernel_str_bytes",
  67. "trigger_bpf_probe_read_kernel",
  68. integration_test::BPF_PROBE_READ,
  69. );
  70. set_kernel_buffer_element(&mut bpf, bytes);
  71. trigger_bpf_probe_read_kernel(dest_len);
  72. bpf
  73. }
  74. fn set_kernel_buffer_element(bpf: &mut Bpf, bytes: &[u8]) {
  75. let mut bytes = bytes.to_vec();
  76. bytes.resize(1024, 0xFF);
  77. let bytes: [u8; 1024] = bytes.try_into().unwrap();
  78. let mut m = Array::<_, [u8; 1024]>::try_from(bpf.map_mut("KERNEL_BUFFER").unwrap()).unwrap();
  79. m.set(0, bytes, 0).unwrap();
  80. }
  81. fn result_bytes(bpf: &Bpf) -> Vec<u8> {
  82. let m = Array::<_, TestResult>::try_from(bpf.map("RESULT").unwrap()).unwrap();
  83. let result = m.get(&0, 0).unwrap();
  84. assert!(result.did_error == 0);
  85. // assert that the buffer is always null terminated
  86. assert_eq!(result.buf[result.len], 0);
  87. result.buf[..result.len].to_vec()
  88. }
  89. fn load_and_attach_uprobe(prog_name: &str, func_name: &str, bytes: &[u8]) -> Bpf {
  90. let mut bpf = Bpf::load(bytes).unwrap();
  91. let prog: &mut UProbe = bpf.program_mut(prog_name).unwrap().try_into().unwrap();
  92. prog.load().unwrap();
  93. prog.attach(Some(func_name), 0, "/proc/self/exe", None)
  94. .unwrap();
  95. bpf
  96. }
  97. #[no_mangle]
  98. #[inline(never)]
  99. pub extern "C" fn trigger_bpf_probe_read_user(_string: *const u8, _len: usize) {}
  100. #[no_mangle]
  101. #[inline(never)]
  102. pub extern "C" fn trigger_bpf_probe_read_kernel(_len: usize) {}