|  |  | @ -10,47 +10,47 @@ use aya_bpf::{ | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | const RESULT_BUF_LEN: usize = 1024; |  |  |  | const RESULT_BUF_LEN: usize = 1024; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | macro_rules! read_str_bytes { |  |  |  | fn read_str_bytes( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     ($fun:ident, $ptr:expr, $len:expr $(,)?) => { |  |  |  |     fun: unsafe fn(*const u8, &mut [u8]) -> Result<&[u8], i64>, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         let Some(ptr) = RESULT.get_ptr_mut(0) else { |  |  |  |     iptr: Option<*const u8>, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             return; |  |  |  |     ilen: Option<usize>, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         }; |  |  |  | ) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         let TestResult { |  |  |  |     let Some(iptr) = iptr else { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             did_error, |  |  |  |         return; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             len, |  |  |  |     }; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             buf, |  |  |  |     let Some(ilen) = ilen else { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         } = unsafe { &mut *ptr }; |  |  |  |         return; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |     }; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         // $len comes from ctx.arg(1) so it's dynamic and the verifier
 |  |  |  |     let Some(ptr) = RESULT.get_ptr_mut(0) else { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         // doesn't see any bounds. We do $len.min(RESULT_BUF_LEN) here to
 |  |  |  |         return; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         // ensure that the verifier can see the upper bound, or you get:
 |  |  |  |     }; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         //
 |  |  |  |     let dst = unsafe { ptr.as_mut() }; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         // 18: (79) r7 = *(u64 *)(r7 +8)         ; R7_w=scalar()
 |  |  |  |     let Some(TestResult { buf, len }) = dst else { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         // [snip]
 |  |  |  |         return; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         // 27: (bf) r2 = r7                      ;
 |  |  |  |     }; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         // R2_w=scalar(id=2,umax=9223372036854775807,var_off=(0x0; 0x7fffffffffffffff)) [snip]
 |  |  |  |     *len = None; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         // 28: (85) call bpf_probe_read_user_str#114
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         // R2 unbounded memory access, use 'var &= const' or 'if (var < const)'
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         let Some(buf) = buf.get_mut(..$len) else { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             return; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         }; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         match unsafe { $fun($ptr, buf) } { |  |  |  |     // len comes from ctx.arg(1) so it's dynamic and the verifier
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             Ok(s) => { |  |  |  |     // doesn't see any bounds. We do len.min(RESULT_BUF_LEN) here to
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 *len = s.len(); |  |  |  |     // ensure that the verifier can see the upper bound, or you get:
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |     //
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             Err(_) => { |  |  |  |     // 18: (79) r7 = *(u64 *)(r7 +8)         ; R7_w=scalar()
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 *did_error = 1; |  |  |  |     // [snip]
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |     // 27: (bf) r2 = r7                      ;
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |     // R2_w=scalar(id=2,umax=9223372036854775807,var_off=(0x0; 0x7fffffffffffffff)) [snip]
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // 28: (85) call bpf_probe_read_user_str#114
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // R2 unbounded memory access, use 'var &= const' or 'if (var < const)'
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     let Some(buf) = buf.get_mut(..ilen) else { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return; | 
			
		
	
		
		
			
				
					
					|  |  |  |     }; |  |  |  |     }; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     *len = Some(unsafe { fun(iptr, buf) }.map(<[_]>::len)); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #[repr(C)] |  |  |  | #[repr(C)] | 
			
		
	
		
		
			
				
					
					|  |  |  | struct TestResult { |  |  |  | struct TestResult { | 
			
		
	
		
		
			
				
					
					|  |  |  |     did_error: u64, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     len: usize, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     buf: [u8; RESULT_BUF_LEN], |  |  |  |     buf: [u8; RESULT_BUF_LEN], | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     len: Option<Result<usize, i64>>, | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #[map] |  |  |  | #[map] | 
			
		
	
	
		
		
			
				
					|  |  | @ -61,31 +61,22 @@ static KERNEL_BUFFER: Array<[u8; RESULT_BUF_LEN]> = Array::with_max_entries(1, 0 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #[uprobe] |  |  |  | #[uprobe] | 
			
		
	
		
		
			
				
					
					|  |  |  | pub fn test_bpf_probe_read_user_str_bytes(ctx: ProbeContext) { |  |  |  | pub fn test_bpf_probe_read_user_str_bytes(ctx: ProbeContext) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     read_str_bytes!( |  |  |  |     read_str_bytes( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         bpf_probe_read_user_str_bytes, |  |  |  |         bpf_probe_read_user_str_bytes, | 
			
		
	
		
		
			
				
					
					|  |  |  |         match ctx.arg::<*const u8>(0) { |  |  |  |         ctx.arg::<*const u8>(0), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             Some(p) => p, |  |  |  |         ctx.arg::<usize>(1), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             _ => return, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         }, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         match ctx.arg::<usize>(1) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             Some(p) => p, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             _ => return, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         }, |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     ); |  |  |  |     ); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #[uprobe] |  |  |  | #[uprobe] | 
			
		
	
		
		
			
				
					
					|  |  |  | pub fn test_bpf_probe_read_kernel_str_bytes(ctx: ProbeContext) { |  |  |  | pub fn test_bpf_probe_read_kernel_str_bytes(ctx: ProbeContext) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     read_str_bytes!( |  |  |  |     read_str_bytes( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         bpf_probe_read_kernel_str_bytes, |  |  |  |         bpf_probe_read_kernel_str_bytes, | 
			
		
	
		
		
			
				
					
					|  |  |  |         match KERNEL_BUFFER.get_ptr(0) { |  |  |  |         KERNEL_BUFFER | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             Some(p) => p as *const u8, |  |  |  |             .get_ptr(0) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             _ => return, |  |  |  |             .and_then(|ptr| unsafe { ptr.as_ref() }) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         }, |  |  |  |             .map(|buf| buf.as_ptr()), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         match ctx.arg::<usize>(0) { |  |  |  |         ctx.arg::<usize>(0), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             Some(p) => p, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             _ => return, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         }, |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     ); |  |  |  |     ); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | 
 |