4
0

helpers.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. //! This module contains kernel helper functions that may be exposed to specific BPF
  2. //! program types. These helpers can be used to perform common tasks, query and operate on
  3. //! data exposed by the kernel, and perform some operations that would normally be denied
  4. //! by the BPF verifier.
  5. //!
  6. //! Here, we provide some higher-level wrappers around the underlying kernel helpers, but
  7. //! also expose bindings to the underlying helpers as a fall-back in case of a missing
  8. //! implementation.
  9. use core::mem::{self, MaybeUninit};
  10. pub use aya_bpf_bindings::helpers as gen;
  11. pub use gen::*;
  12. use crate::cty::{c_char, c_long, c_void};
  13. /// Read bytes stored at `src` and store them as a `T`.
  14. ///
  15. /// Generally speaking, the more specific [`bpf_probe_read_user`] and
  16. /// [`bpf_probe_read_kernel`] should be preferred over this function.
  17. ///
  18. /// Returns a bitwise copy of `mem::size_of::<T>()` bytes stored at the user space address
  19. /// `src`. See `bpf_probe_read_kernel` for reading kernel space memory.
  20. ///
  21. /// # Examples
  22. ///
  23. /// ```no_run
  24. /// # #![allow(dead_code)]
  25. /// # use aya_bpf::{cty::{c_int, c_long}, helpers::bpf_probe_read};
  26. /// # fn try_test() -> Result<(), c_long> {
  27. /// # let kernel_ptr: *const c_int = 0 as _;
  28. /// let my_int: c_int = unsafe { bpf_probe_read(kernel_ptr)? };
  29. ///
  30. /// // Do something with my_int
  31. /// # Ok::<(), c_long>(())
  32. /// # }
  33. /// ```
  34. ///
  35. /// # Errors
  36. ///
  37. /// On failure, this function returns a negative value wrapped in an `Err`.
  38. #[inline]
  39. pub unsafe fn bpf_probe_read<T>(src: *const T) -> Result<T, c_long> {
  40. let mut v: MaybeUninit<T> = MaybeUninit::uninit();
  41. let ret = gen::bpf_probe_read(
  42. v.as_mut_ptr() as *mut c_void,
  43. mem::size_of::<T>() as u32,
  44. src as *const c_void,
  45. );
  46. if ret < 0 {
  47. return Err(ret);
  48. }
  49. Ok(v.assume_init())
  50. }
  51. /// Read bytes from the pointer `src` into the provided destination buffer.
  52. ///
  53. /// Generally speaking, the more specific [`bpf_probe_read_user_buf`] and
  54. /// [`bpf_probe_read_kernel_buf`] should be preferred over this function.
  55. ///
  56. /// # Examples
  57. ///
  58. /// ```no_run
  59. /// # #![allow(dead_code)]
  60. /// # use aya_bpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_buf};
  61. /// # fn try_test() -> Result<(), c_long> {
  62. /// # let ptr: *const u8 = 0 as _;
  63. /// let mut buf = [0u8; 16];
  64. /// unsafe { bpf_probe_read_buf(ptr, &mut buf)? };
  65. ///
  66. /// # Ok::<(), c_long>(())
  67. /// # }
  68. /// ```
  69. ///
  70. /// # Errors
  71. ///
  72. /// On failure, this function returns a negative value wrapped in an `Err`.
  73. #[inline]
  74. pub unsafe fn bpf_probe_read_buf(src: *const u8, dst: &mut [u8]) -> Result<(), c_long> {
  75. let ret = gen::bpf_probe_read(
  76. dst.as_mut_ptr() as *mut c_void,
  77. dst.len() as u32,
  78. src as *const c_void,
  79. );
  80. if ret < 0 {
  81. return Err(ret);
  82. }
  83. Ok(())
  84. }
  85. /// Read bytes stored at the _user space_ pointer `src` and store them as a `T`.
  86. ///
  87. /// Returns a bitwise copy of `mem::size_of::<T>()` bytes stored at the user space address
  88. /// `src`. See `bpf_probe_read_kernel` for reading kernel space memory.
  89. ///
  90. /// # Examples
  91. ///
  92. /// ```no_run
  93. /// # #![allow(dead_code)]
  94. /// # use aya_bpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_user};
  95. /// # fn try_test() -> Result<(), c_long> {
  96. /// # let user_ptr: *const c_int = 0 as _;
  97. /// let my_int: c_int = unsafe { bpf_probe_read_user(user_ptr)? };
  98. ///
  99. /// // Do something with my_int
  100. /// # Ok::<(), c_long>(())
  101. /// # }
  102. /// ```
  103. ///
  104. /// # Errors
  105. ///
  106. /// On failure, this function returns a negative value wrapped in an `Err`.
  107. #[inline]
  108. pub unsafe fn bpf_probe_read_user<T>(src: *const T) -> Result<T, c_long> {
  109. let mut v: MaybeUninit<T> = MaybeUninit::uninit();
  110. let ret = gen::bpf_probe_read_user(
  111. v.as_mut_ptr() as *mut c_void,
  112. mem::size_of::<T>() as u32,
  113. src as *const c_void,
  114. );
  115. if ret < 0 {
  116. return Err(ret);
  117. }
  118. Ok(v.assume_init())
  119. }
  120. /// Read bytes from the _user space_ pointer `src` into the provided destination
  121. /// buffer.
  122. ///
  123. /// # Examples
  124. ///
  125. /// ```no_run
  126. /// # #![allow(dead_code)]
  127. /// # use aya_bpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_user_buf};
  128. /// # fn try_test() -> Result<(), c_long> {
  129. /// # let user_ptr: *const u8 = 0 as _;
  130. /// let mut buf = [0u8; 16];
  131. /// unsafe { bpf_probe_read_user_buf(user_ptr, &mut buf)? };
  132. ///
  133. /// # Ok::<(), c_long>(())
  134. /// # }
  135. /// ```
  136. ///
  137. /// # Errors
  138. ///
  139. /// On failure, this function returns a negative value wrapped in an `Err`.
  140. #[inline]
  141. pub unsafe fn bpf_probe_read_user_buf(src: *const u8, dst: &mut [u8]) -> Result<(), c_long> {
  142. let ret = gen::bpf_probe_read_user(
  143. dst.as_mut_ptr() as *mut c_void,
  144. dst.len() as u32,
  145. src as *const c_void,
  146. );
  147. if ret < 0 {
  148. return Err(ret);
  149. }
  150. Ok(())
  151. }
  152. /// Read bytes stored at the _kernel space_ pointer `src` and store them as a `T`.
  153. ///
  154. /// Returns a bitwise copy of `mem::size_of::<T>()` bytes stored at the kernel space address
  155. /// `src`. See `bpf_probe_read_user` for reading user space memory.
  156. ///
  157. /// # Examples
  158. ///
  159. /// ```no_run
  160. /// # #![allow(dead_code)]
  161. /// # use aya_bpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_kernel};
  162. /// # fn try_test() -> Result<(), c_long> {
  163. /// # let kernel_ptr: *const c_int = 0 as _;
  164. /// let my_int: c_int = unsafe { bpf_probe_read_kernel(kernel_ptr)? };
  165. ///
  166. /// // Do something with my_int
  167. /// # Ok::<(), c_long>(())
  168. /// # }
  169. /// ```
  170. ///
  171. /// # Errors
  172. ///
  173. /// On failure, this function returns a negative value wrapped in an `Err`.
  174. #[inline]
  175. pub unsafe fn bpf_probe_read_kernel<T>(src: *const T) -> Result<T, c_long> {
  176. let mut v: MaybeUninit<T> = MaybeUninit::uninit();
  177. let ret = gen::bpf_probe_read_kernel(
  178. v.as_mut_ptr() as *mut c_void,
  179. mem::size_of::<T>() as u32,
  180. src as *const c_void,
  181. );
  182. if ret < 0 {
  183. return Err(ret);
  184. }
  185. Ok(v.assume_init())
  186. }
  187. /// Read bytes from the _kernel space_ pointer `src` into the provided destination
  188. /// buffer.
  189. ///
  190. /// # Examples
  191. ///
  192. /// ```no_run
  193. /// # #![allow(dead_code)]
  194. /// # use aya_bpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_kernel_buf};
  195. /// # fn try_test() -> Result<(), c_long> {
  196. /// # let kernel_ptr: *const u8 = 0 as _;
  197. /// let mut buf = [0u8; 16];
  198. /// unsafe { bpf_probe_read_kernel_buf(kernel_ptr, &mut buf)? };
  199. ///
  200. /// # Ok::<(), c_long>(())
  201. /// # }
  202. /// ```
  203. ///
  204. /// # Errors
  205. ///
  206. /// On failure, this function returns a negative value wrapped in an `Err`.
  207. #[inline]
  208. pub unsafe fn bpf_probe_read_kernel_buf(src: *const u8, dst: &mut [u8]) -> Result<(), c_long> {
  209. let ret = gen::bpf_probe_read_kernel(
  210. dst.as_mut_ptr() as *mut c_void,
  211. dst.len() as u32,
  212. src as *const c_void,
  213. );
  214. if ret < 0 {
  215. return Err(ret);
  216. }
  217. Ok(())
  218. }
  219. /// Read a null-terminated string stored at `src` into `dest`.
  220. ///
  221. /// Generally speaking, the more specific [`bpf_probe_read_user_str`] and
  222. /// [`bpf_probe_read_kernel_str`] should be preferred over this function.
  223. ///
  224. /// In case the length of `dest` is smaller then the length of `src`, the read bytes will
  225. /// be truncated to the size of `dest`.
  226. ///
  227. /// # Examples
  228. ///
  229. /// ```no_run
  230. /// # #![allow(dead_code)]
  231. /// # use aya_bpf::{cty::c_long, helpers::bpf_probe_read_str};
  232. /// # fn try_test() -> Result<(), c_long> {
  233. /// # let kernel_ptr: *const u8 = 0 as _;
  234. /// let mut my_str = [0u8; 16];
  235. /// let num_read = unsafe { bpf_probe_read_str(kernel_ptr, &mut my_str)? };
  236. ///
  237. /// // Do something with num_read and my_str
  238. /// # Ok::<(), c_long>(())
  239. /// # }
  240. /// ```
  241. ///
  242. /// # Errors
  243. ///
  244. /// On failure, this function returns Err(-1).
  245. #[inline]
  246. pub unsafe fn bpf_probe_read_str(src: *const u8, dest: &mut [u8]) -> Result<usize, c_long> {
  247. let len = gen::bpf_probe_read_str(
  248. dest.as_mut_ptr() as *mut c_void,
  249. dest.len() as u32,
  250. src as *const c_void,
  251. );
  252. if len < 0 {
  253. return Err(-1);
  254. }
  255. let mut len = len as usize;
  256. if len > dest.len() {
  257. // this can never happen, it's needed to tell the verifier that len is
  258. // bounded
  259. len = dest.len();
  260. }
  261. Ok(len as usize)
  262. }
  263. /// Read a null-terminated string from _user space_ stored at `src` into `dest`.
  264. ///
  265. /// In case the length of `dest` is smaller then the length of `src`, the read bytes will
  266. /// be truncated to the size of `dest`.
  267. ///
  268. /// # Examples
  269. ///
  270. /// ```no_run
  271. /// # #![allow(dead_code)]
  272. /// # use aya_bpf::{cty::c_long, helpers::bpf_probe_read_user_str};
  273. /// # fn try_test() -> Result<(), c_long> {
  274. /// # let user_ptr: *const u8 = 0 as _;
  275. /// let mut my_str = [0u8; 16];
  276. /// let num_read = unsafe { bpf_probe_read_user_str(user_ptr, &mut my_str)? };
  277. ///
  278. /// // Do something with num_read and my_str
  279. /// # Ok::<(), c_long>(())
  280. /// # }
  281. /// ```
  282. ///
  283. /// # Errors
  284. ///
  285. /// On failure, this function returns Err(-1).
  286. #[inline]
  287. pub unsafe fn bpf_probe_read_user_str(src: *const u8, dest: &mut [u8]) -> Result<usize, c_long> {
  288. let len = gen::bpf_probe_read_user_str(
  289. dest.as_mut_ptr() as *mut c_void,
  290. dest.len() as u32,
  291. src as *const c_void,
  292. );
  293. if len < 0 {
  294. return Err(-1);
  295. }
  296. let mut len = len as usize;
  297. if len > dest.len() {
  298. // this can never happen, it's needed to tell the verifier that len is
  299. // bounded
  300. len = dest.len();
  301. }
  302. Ok(len as usize)
  303. }
  304. /// Read a null-terminated string from _kernel space_ stored at `src` into `dest`.
  305. ///
  306. /// In case the length of `dest` is smaller then the length of `src`, the read bytes will
  307. /// be truncated to the size of `dest`.
  308. ///
  309. /// # Examples
  310. ///
  311. /// ```no_run
  312. /// # #![allow(dead_code)]
  313. /// # use aya_bpf::{cty::c_long, helpers::bpf_probe_read_kernel_str};
  314. /// # fn try_test() -> Result<(), c_long> {
  315. /// # let kernel_ptr: *const u8 = 0 as _;
  316. /// let mut my_str = [0u8; 16];
  317. /// let num_read = unsafe { bpf_probe_read_kernel_str(kernel_ptr, &mut my_str)? };
  318. ///
  319. /// // Do something with num_read and my_str
  320. /// # Ok::<(), c_long>(())
  321. /// # }
  322. /// ```
  323. ///
  324. /// # Errors
  325. ///
  326. /// On failure, this function returns Err(-1).
  327. #[inline]
  328. pub unsafe fn bpf_probe_read_kernel_str(src: *const u8, dest: &mut [u8]) -> Result<usize, c_long> {
  329. let len = gen::bpf_probe_read_kernel_str(
  330. dest.as_mut_ptr() as *mut c_void,
  331. dest.len() as u32,
  332. src as *const c_void,
  333. );
  334. if len < 0 {
  335. return Err(-1);
  336. }
  337. let mut len = len as usize;
  338. if len > dest.len() {
  339. // this can never happen, it's needed to tell the verifier that len is
  340. // bounded
  341. len = dest.len();
  342. }
  343. Ok(len as usize)
  344. }
  345. /// Read the `comm` field associated with the current task struct
  346. /// as a `[c_char; 16]`.
  347. ///
  348. /// # Examples
  349. ///
  350. /// ```no_run
  351. /// # #![allow(dead_code)]
  352. /// # use aya_bpf:: helpers::bpf_get_current_comm;
  353. /// let comm = bpf_get_current_comm();
  354. ///
  355. /// // Do something with comm
  356. /// ```
  357. ///
  358. /// # Errors
  359. ///
  360. /// On failure, this function returns a negative value wrapped in an `Err`.
  361. #[inline]
  362. pub fn bpf_get_current_comm() -> Result<[c_char; 16], c_long> {
  363. let mut comm: [c_char; 16usize] = [0; 16];
  364. let ret = unsafe { gen::bpf_get_current_comm(&mut comm as *mut _ as *mut c_void, 16u32) };
  365. if ret == 0 {
  366. Ok(comm)
  367. } else {
  368. Err(ret)
  369. }
  370. }
  371. /// Read the process id and thread group id associated with the current task struct as
  372. /// a `u64`.
  373. ///
  374. /// In the return value, the upper 32 bits are the `tgid`, and the lower 32 bits are the
  375. /// `pid`. That is, the returned value is equal to: `(tgid << 32) | pid`. A caller may
  376. /// access the individual fields by either casting to a `u32` or performing a `>> 32` bit
  377. /// shift and casting to a `u32`.
  378. ///
  379. /// Note that the naming conventions used in the kernel differ from user space. From the
  380. /// perspective of user space, `pid` may be thought of as the thread id, and `tgid` may be
  381. /// thought of as the process id. For single-threaded processes, these values are
  382. /// typically the same.
  383. ///
  384. /// # Examples
  385. ///
  386. /// ```no_run
  387. /// # #![allow(dead_code)]
  388. /// # use aya_bpf:: helpers::bpf_get_current_pid_tgid;
  389. /// let tgid = (bpf_get_current_pid_tgid() >> 32) as u32;
  390. /// let pid = bpf_get_current_pid_tgid() as u32;
  391. ///
  392. /// // Do something with pid and tgid
  393. /// ```
  394. #[inline]
  395. pub fn bpf_get_current_pid_tgid() -> u64 {
  396. unsafe { gen::bpf_get_current_pid_tgid() }
  397. }
  398. /// Read the user id and group id associated with the current task struct as
  399. /// a `u64`.
  400. ///
  401. /// In the return value, the upper 32 bits are the `gid`, and the lower 32 bits are the
  402. /// `uid`. That is, the returned value is equal to: `(gid << 32) | uid`. A caller may
  403. /// access the individual fields by either casting to a `u32` or performing a `>> 32` bit
  404. /// shift and casting to a `u32`.
  405. ///
  406. /// # Examples
  407. ///
  408. /// ```no_run
  409. /// # #![allow(dead_code)]
  410. /// # use aya_bpf::helpers::bpf_get_current_uid_gid;
  411. /// let gid = (bpf_get_current_uid_gid() >> 32) as u32;
  412. /// let uid = bpf_get_current_uid_gid() as u32;
  413. ///
  414. /// // Do something with uid and gid
  415. /// ```
  416. #[inline]
  417. pub fn bpf_get_current_uid_gid() -> u64 {
  418. unsafe { gen::bpf_get_current_uid_gid() }
  419. }