|  |  |  | @ -64,7 +64,6 @@ pub mod uprobe; | 
		
	
		
			
				|  |  |  |  | mod utils; | 
		
	
		
			
				|  |  |  |  | pub mod xdp; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | use crate::util::KernelVersion; | 
		
	
		
			
				|  |  |  |  | use libc::ENOSPC; | 
		
	
		
			
				|  |  |  |  | use std::{ | 
		
	
		
			
				|  |  |  |  |     ffi::CString, | 
		
	
	
		
			
				
					|  |  |  | @ -112,8 +111,9 @@ use crate::{ | 
		
	
		
			
				|  |  |  |  |     sys::{ | 
		
	
		
			
				|  |  |  |  |         bpf_btf_get_fd_by_id, bpf_get_object, bpf_load_program, bpf_pin_object, | 
		
	
		
			
				|  |  |  |  |         bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd, bpf_prog_get_next_id, bpf_prog_query, | 
		
	
		
			
				|  |  |  |  |         retry_with_verifier_logs, BpfLoadProgramAttrs, | 
		
	
		
			
				|  |  |  |  |         retry_with_verifier_logs, BpfLoadProgramAttrs, SyscallError, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |     util::KernelVersion, | 
		
	
		
			
				|  |  |  |  |     VerifierLogLevel, | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -147,14 +147,8 @@ pub enum ProgramError { | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     /// A syscall failed.
 | 
		
	
		
			
				|  |  |  |  |     #[error("`{call}` failed")] | 
		
	
		
			
				|  |  |  |  |     SyscallError { | 
		
	
		
			
				|  |  |  |  |         /// The name of the syscall which failed.
 | 
		
	
		
			
				|  |  |  |  |         call: &'static str, | 
		
	
		
			
				|  |  |  |  |         /// The [`io::Error`] returned by the syscall.
 | 
		
	
		
			
				|  |  |  |  |         #[source] | 
		
	
		
			
				|  |  |  |  |         io_error: io::Error, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |     #[error(transparent)] | 
		
	
		
			
				|  |  |  |  |     SyscallError(#[from] SyscallError), | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     /// The network interface does not exist.
 | 
		
	
		
			
				|  |  |  |  |     #[error("unknown network interface {name}")] | 
		
	
	
		
			
				
					|  |  |  | @ -456,12 +450,11 @@ impl<T: Link> ProgramData<T> { | 
		
	
		
			
				|  |  |  |  |             None | 
		
	
		
			
				|  |  |  |  |         }; | 
		
	
		
			
				|  |  |  |  |         let attach_btf_obj_fd = if info.attach_btf_obj_id > 0 { | 
		
	
		
			
				|  |  |  |  |             let fd = bpf_btf_get_fd_by_id(info.attach_btf_obj_id).map_err(|io_error| { | 
		
	
		
			
				|  |  |  |  |                 ProgramError::SyscallError { | 
		
	
		
			
				|  |  |  |  |             let fd = | 
		
	
		
			
				|  |  |  |  |                 bpf_btf_get_fd_by_id(info.attach_btf_obj_id).map_err(|io_error| SyscallError { | 
		
	
		
			
				|  |  |  |  |                     call: "bpf_btf_get_fd_by_id", | 
		
	
		
			
				|  |  |  |  |                     io_error, | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             })?; | 
		
	
		
			
				|  |  |  |  |                 })?; | 
		
	
		
			
				|  |  |  |  |             Some(fd as u32) | 
		
	
		
			
				|  |  |  |  |         } else { | 
		
	
		
			
				|  |  |  |  |             None | 
		
	
	
		
			
				
					|  |  |  | @ -489,13 +482,12 @@ impl<T: Link> ProgramData<T> { | 
		
	
		
			
				|  |  |  |  |     ) -> Result<ProgramData<T>, ProgramError> { | 
		
	
		
			
				|  |  |  |  |         let path_string = | 
		
	
		
			
				|  |  |  |  |             CString::new(path.as_ref().as_os_str().to_string_lossy().as_bytes()).unwrap(); | 
		
	
		
			
				|  |  |  |  |         let fd = | 
		
	
		
			
				|  |  |  |  |             bpf_get_object(&path_string).map_err(|(_, io_error)| ProgramError::SyscallError { | 
		
	
		
			
				|  |  |  |  |                 call: "bpf_obj_get", | 
		
	
		
			
				|  |  |  |  |                 io_error, | 
		
	
		
			
				|  |  |  |  |             })? as RawFd; | 
		
	
		
			
				|  |  |  |  |         let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError { | 
		
	
		
			
				|  |  |  |  |             call: "bpf_obj_get", | 
		
	
		
			
				|  |  |  |  |             io_error, | 
		
	
		
			
				|  |  |  |  |         })? as RawFd; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| ProgramError::SyscallError { | 
		
	
		
			
				|  |  |  |  |         let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| SyscallError { | 
		
	
		
			
				|  |  |  |  |             call: "bpf_prog_get_info_by_fd", | 
		
	
		
			
				|  |  |  |  |             io_error, | 
		
	
		
			
				|  |  |  |  |         })?; | 
		
	
	
		
			
				
					|  |  |  | @ -537,8 +529,8 @@ fn pin_program<T: Link, P: AsRef<Path>>(data: &ProgramData<T>, path: P) -> Resul | 
		
	
		
			
				|  |  |  |  |             error: e.to_string(), | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     })?; | 
		
	
		
			
				|  |  |  |  |     bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError { | 
		
	
		
			
				|  |  |  |  |         name: "BPF_OBJ_PIN", | 
		
	
		
			
				|  |  |  |  |     bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| SyscallError { | 
		
	
		
			
				|  |  |  |  |         call: "BPF_OBJ_PIN", | 
		
	
		
			
				|  |  |  |  |         io_error, | 
		
	
		
			
				|  |  |  |  |     })?; | 
		
	
		
			
				|  |  |  |  |     Ok(()) | 
		
	
	
		
			
				
					|  |  |  | @ -665,15 +657,17 @@ pub(crate) fn query<T: AsRawFd>( | 
		
	
		
			
				|  |  |  |  |                 prog_ids.resize(prog_cnt as usize, 0); | 
		
	
		
			
				|  |  |  |  |                 return Ok(prog_ids); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             Err((_, io_error)) if retries == 0 && io_error.raw_os_error() == Some(ENOSPC) => { | 
		
	
		
			
				|  |  |  |  |                 prog_ids.resize(prog_cnt as usize, 0); | 
		
	
		
			
				|  |  |  |  |                 retries += 1; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             Err((_, io_error)) => { | 
		
	
		
			
				|  |  |  |  |                 return Err(ProgramError::SyscallError { | 
		
	
		
			
				|  |  |  |  |                     call: "bpf_prog_query", | 
		
	
		
			
				|  |  |  |  |                     io_error, | 
		
	
		
			
				|  |  |  |  |                 }); | 
		
	
		
			
				|  |  |  |  |                 if retries == 0 && io_error.raw_os_error() == Some(ENOSPC) { | 
		
	
		
			
				|  |  |  |  |                     prog_ids.resize(prog_cnt as usize, 0); | 
		
	
		
			
				|  |  |  |  |                     retries += 1; | 
		
	
		
			
				|  |  |  |  |                 } else { | 
		
	
		
			
				|  |  |  |  |                     return Err(SyscallError { | 
		
	
		
			
				|  |  |  |  |                         call: "bpf_prog_query", | 
		
	
		
			
				|  |  |  |  |                         io_error, | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                     .into()); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
	
		
			
				
					|  |  |  | @ -951,24 +945,22 @@ impl ProgramInfo { | 
		
	
		
			
				|  |  |  |  |     ///
 | 
		
	
		
			
				|  |  |  |  |     /// The returned fd must be closed when no longer needed.
 | 
		
	
		
			
				|  |  |  |  |     pub fn fd(&self) -> Result<RawFd, ProgramError> { | 
		
	
		
			
				|  |  |  |  |         let fd = | 
		
	
		
			
				|  |  |  |  |             bpf_prog_get_fd_by_id(self.0.id).map_err(|io_error| ProgramError::SyscallError { | 
		
	
		
			
				|  |  |  |  |                 call: "bpf_prog_get_fd_by_id", | 
		
	
		
			
				|  |  |  |  |                 io_error, | 
		
	
		
			
				|  |  |  |  |             })?; | 
		
	
		
			
				|  |  |  |  |         let fd = bpf_prog_get_fd_by_id(self.0.id).map_err(|io_error| SyscallError { | 
		
	
		
			
				|  |  |  |  |             call: "bpf_prog_get_fd_by_id", | 
		
	
		
			
				|  |  |  |  |             io_error, | 
		
	
		
			
				|  |  |  |  |         })?; | 
		
	
		
			
				|  |  |  |  |         Ok(fd.into_raw_fd()) | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     /// Loads a program from a pinned path in bpffs.
 | 
		
	
		
			
				|  |  |  |  |     pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<ProgramInfo, ProgramError> { | 
		
	
		
			
				|  |  |  |  |         let path_string = CString::new(path.as_ref().to_str().unwrap()).unwrap(); | 
		
	
		
			
				|  |  |  |  |         let fd = | 
		
	
		
			
				|  |  |  |  |             bpf_get_object(&path_string).map_err(|(_, io_error)| ProgramError::SyscallError { | 
		
	
		
			
				|  |  |  |  |                 call: "BPF_OBJ_GET", | 
		
	
		
			
				|  |  |  |  |                 io_error, | 
		
	
		
			
				|  |  |  |  |             })? as RawFd; | 
		
	
		
			
				|  |  |  |  |         let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError { | 
		
	
		
			
				|  |  |  |  |             call: "BPF_OBJ_GET", | 
		
	
		
			
				|  |  |  |  |             io_error, | 
		
	
		
			
				|  |  |  |  |         })? as RawFd; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| ProgramError::SyscallError { | 
		
	
		
			
				|  |  |  |  |         let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| SyscallError { | 
		
	
		
			
				|  |  |  |  |             call: "bpf_prog_get_info_by_fd", | 
		
	
		
			
				|  |  |  |  |             io_error, | 
		
	
		
			
				|  |  |  |  |         })?; | 
		
	
	
		
			
				
					|  |  |  | @ -999,18 +991,19 @@ impl Iterator for ProgramsIter { | 
		
	
		
			
				|  |  |  |  |                 self.current = next; | 
		
	
		
			
				|  |  |  |  |                 Some( | 
		
	
		
			
				|  |  |  |  |                     bpf_prog_get_fd_by_id(next) | 
		
	
		
			
				|  |  |  |  |                         .map_err(|io_error| ProgramError::SyscallError { | 
		
	
		
			
				|  |  |  |  |                         .map_err(|io_error| SyscallError { | 
		
	
		
			
				|  |  |  |  |                             call: "bpf_prog_get_fd_by_id", | 
		
	
		
			
				|  |  |  |  |                             io_error, | 
		
	
		
			
				|  |  |  |  |                         }) | 
		
	
		
			
				|  |  |  |  |                         .and_then(|fd| { | 
		
	
		
			
				|  |  |  |  |                             bpf_prog_get_info_by_fd(fd.as_raw_fd()) | 
		
	
		
			
				|  |  |  |  |                                 .map_err(|io_error| ProgramError::SyscallError { | 
		
	
		
			
				|  |  |  |  |                                 .map_err(|io_error| SyscallError { | 
		
	
		
			
				|  |  |  |  |                                     call: "bpf_prog_get_info_by_fd", | 
		
	
		
			
				|  |  |  |  |                                     io_error, | 
		
	
		
			
				|  |  |  |  |                                 }) | 
		
	
		
			
				|  |  |  |  |                                 .map(ProgramInfo) | 
		
	
		
			
				|  |  |  |  |                         }), | 
		
	
		
			
				|  |  |  |  |                         }) | 
		
	
		
			
				|  |  |  |  |                         .map_err(Into::into), | 
		
	
		
			
				|  |  |  |  |                 ) | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             Ok(None) => None, | 
		
	
	
		
			
				
					|  |  |  | @ -1018,10 +1011,11 @@ impl Iterator for ProgramsIter { | 
		
	
		
			
				|  |  |  |  |                 // If getting the next program failed, we have to yield None in our next
 | 
		
	
		
			
				|  |  |  |  |                 // iteration to avoid an infinite loop.
 | 
		
	
		
			
				|  |  |  |  |                 self.error = true; | 
		
	
		
			
				|  |  |  |  |                 Some(Err(ProgramError::SyscallError { | 
		
	
		
			
				|  |  |  |  |                 Some(Err(SyscallError { | 
		
	
		
			
				|  |  |  |  |                     call: "bpf_prog_get_fd_by_id", | 
		
	
		
			
				|  |  |  |  |                     io_error, | 
		
	
		
			
				|  |  |  |  |                 })) | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 .into())) | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
	
		
			
				
					|  |  |  | 
 |