bpf_probe_read.rs 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #![no_std]
  2. #![no_main]
  3. use aya_bpf::{
  4. helpers::{bpf_probe_read_kernel_str_bytes, bpf_probe_read_user_str_bytes},
  5. macros::{map, uprobe},
  6. maps::Array,
  7. programs::ProbeContext,
  8. };
  9. const RESULT_BUF_LEN: usize = 1024;
  10. macro_rules! read_str_bytes {
  11. ($fun:ident, $ptr:expr, $len:expr $(,)?) => {
  12. let r = unsafe {
  13. let Some(ptr) = RESULT.get_ptr_mut(0) else {
  14. return;
  15. };
  16. &mut *ptr
  17. };
  18. let s = unsafe {
  19. // $len comes from ctx.arg(1) so it's dynamic and the verifier
  20. // doesn't see any bounds. We do $len.min(RESULT_BUF_LEN) here to
  21. // ensure that the verifier can see the upper bound, or you get:
  22. //
  23. // 18: (79) r7 = *(u64 *)(r7 +8) ; R7_w=scalar()
  24. // [snip]
  25. // 27: (bf) r2 = r7 ;
  26. // R2_w=scalar(id=2,umax=9223372036854775807,var_off=(0x0; 0x7fffffffffffffff)) [snip]
  27. // 28: (85) call bpf_probe_read_user_str#114
  28. // R2 unbounded memory access, use 'var &= const' or 'if (var < const)'
  29. match $fun($ptr, &mut r.buf[..$len.min(RESULT_BUF_LEN)]) {
  30. Ok(s) => s,
  31. Err(_) => {
  32. r.did_error = 1;
  33. return;
  34. }
  35. }
  36. };
  37. r.len = s.len();
  38. };
  39. }
  40. #[repr(C)]
  41. struct TestResult {
  42. did_error: u64,
  43. len: usize,
  44. buf: [u8; RESULT_BUF_LEN],
  45. }
  46. #[map]
  47. static RESULT: Array<TestResult> = Array::with_max_entries(1, 0);
  48. #[map]
  49. static KERNEL_BUFFER: Array<[u8; 1024]> = Array::with_max_entries(1, 0);
  50. #[uprobe]
  51. pub fn test_bpf_probe_read_user_str_bytes(ctx: ProbeContext) {
  52. read_str_bytes!(
  53. bpf_probe_read_user_str_bytes,
  54. match ctx.arg::<*const u8>(0) {
  55. Some(p) => p,
  56. _ => return,
  57. },
  58. match ctx.arg::<usize>(1) {
  59. Some(p) => p,
  60. _ => return,
  61. },
  62. );
  63. }
  64. #[uprobe]
  65. pub fn test_bpf_probe_read_kernel_str_bytes(ctx: ProbeContext) {
  66. read_str_bytes!(
  67. bpf_probe_read_kernel_str_bytes,
  68. match KERNEL_BUFFER.get_ptr(0) {
  69. Some(p) => p as *const u8,
  70. _ => return,
  71. },
  72. match ctx.arg::<usize>(0) {
  73. Some(p) => p,
  74. _ => return,
  75. },
  76. );
  77. }
  78. #[panic_handler]
  79. fn panic(_info: &core::panic::PanicInfo) -> ! {
  80. unsafe { core::hint::unreachable_unchecked() }
  81. }