lib.rs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. pub(crate) mod args;
  2. mod btf_tracepoint;
  3. mod cgroup_device;
  4. mod cgroup_skb;
  5. mod cgroup_sock;
  6. mod cgroup_sock_addr;
  7. mod cgroup_sockopt;
  8. mod cgroup_sysctl;
  9. mod fentry;
  10. mod fexit;
  11. mod kprobe;
  12. mod lsm;
  13. mod map;
  14. mod perf_event;
  15. mod raw_tracepoint;
  16. mod sk_lookup;
  17. mod sk_msg;
  18. mod sk_skb;
  19. mod sock_ops;
  20. mod socket_filter;
  21. mod tc;
  22. mod tracepoint;
  23. mod uprobe;
  24. mod xdp;
  25. use btf_tracepoint::BtfTracePoint;
  26. use cgroup_device::CgroupDevice;
  27. use cgroup_skb::CgroupSkb;
  28. use cgroup_sock::CgroupSock;
  29. use cgroup_sock_addr::CgroupSockAddr;
  30. use cgroup_sockopt::CgroupSockopt;
  31. use cgroup_sysctl::CgroupSysctl;
  32. use fentry::FEntry;
  33. use fexit::FExit;
  34. use kprobe::{KProbe, KProbeKind};
  35. use lsm::Lsm;
  36. use map::Map;
  37. use perf_event::PerfEvent;
  38. use proc_macro::TokenStream;
  39. use proc_macro_error::{abort, proc_macro_error};
  40. use raw_tracepoint::RawTracePoint;
  41. use sk_lookup::SkLookup;
  42. use sk_msg::SkMsg;
  43. use sk_skb::{SkSkb, SkSkbKind};
  44. use sock_ops::SockOps;
  45. use socket_filter::SocketFilter;
  46. use uprobe::{UProbe, UProbeKind};
  47. use tc::SchedClassifier;
  48. use tracepoint::TracePoint;
  49. use xdp::Xdp;
  50. #[proc_macro_error]
  51. #[proc_macro_attribute]
  52. pub fn map(attrs: TokenStream, item: TokenStream) -> TokenStream {
  53. match Map::parse(attrs.into(), item.into()) {
  54. Ok(prog) => prog
  55. .expand()
  56. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  57. .into(),
  58. Err(err) => abort!(err.span(), "{}", err),
  59. }
  60. }
  61. #[proc_macro_error]
  62. #[proc_macro_attribute]
  63. pub fn kprobe(attrs: TokenStream, item: TokenStream) -> TokenStream {
  64. match KProbe::parse(KProbeKind::KProbe, attrs.into(), item.into()) {
  65. Ok(prog) => prog
  66. .expand()
  67. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  68. .into(),
  69. Err(err) => abort!(err.span(), "{}", err),
  70. }
  71. }
  72. #[proc_macro_error]
  73. #[proc_macro_attribute]
  74. pub fn kretprobe(attrs: TokenStream, item: TokenStream) -> TokenStream {
  75. match KProbe::parse(KProbeKind::KRetProbe, attrs.into(), item.into()) {
  76. Ok(prog) => prog
  77. .expand()
  78. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  79. .into(),
  80. Err(err) => abort!(err.span(), "{}", err),
  81. }
  82. }
  83. #[proc_macro_error]
  84. #[proc_macro_attribute]
  85. pub fn uprobe(attrs: TokenStream, item: TokenStream) -> TokenStream {
  86. match UProbe::parse(UProbeKind::UProbe, attrs.into(), item.into()) {
  87. Ok(prog) => prog
  88. .expand()
  89. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  90. .into(),
  91. Err(err) => abort!(err.span(), "{}", err),
  92. }
  93. }
  94. #[proc_macro_error]
  95. #[proc_macro_attribute]
  96. pub fn uretprobe(attrs: TokenStream, item: TokenStream) -> TokenStream {
  97. match UProbe::parse(UProbeKind::URetProbe, attrs.into(), item.into()) {
  98. Ok(prog) => prog
  99. .expand()
  100. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  101. .into(),
  102. Err(err) => abort!(err.span(), "{}", err),
  103. }
  104. }
  105. #[proc_macro_error]
  106. #[proc_macro_attribute]
  107. pub fn sock_ops(attrs: TokenStream, item: TokenStream) -> TokenStream {
  108. match SockOps::parse(attrs.into(), item.into()) {
  109. Ok(prog) => prog
  110. .expand()
  111. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  112. .into(),
  113. Err(err) => abort!(err.span(), "{}", err),
  114. }
  115. }
  116. #[proc_macro_error]
  117. #[proc_macro_attribute]
  118. pub fn sk_msg(attrs: TokenStream, item: TokenStream) -> TokenStream {
  119. match SkMsg::parse(attrs.into(), item.into()) {
  120. Ok(prog) => prog
  121. .expand()
  122. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  123. .into(),
  124. Err(err) => abort!(err.span(), "{}", err),
  125. }
  126. }
  127. /// Marks a function as an eBPF XDP program that can be attached to a network interface.
  128. ///
  129. /// On some NIC drivers, XDP probes are compatible with jumbo frames through the use of
  130. /// multi-buffer packets. Programs can opt-in this support by passing the `frags` argument.
  131. ///
  132. /// XDP programs can also be chained through the use of CPU maps and dev maps, but must opt-in
  133. /// with the `map = "cpumap"` or `map = "devmap"` arguments.
  134. ///
  135. /// # Minimum kernel version
  136. ///
  137. /// The minimum kernel version required to use this feature is 4.8.
  138. ///
  139. /// # Examples
  140. ///
  141. /// ```no_run
  142. /// use aya_bpf::{bindings::xdp_action::XDP_PASS, macros::xdp, programs::XdpContext};
  143. ///
  144. /// #[xdp(frags)]
  145. /// pub fn xdp(ctx: XdpContext) -> u32 {
  146. /// XDP_PASS
  147. /// }
  148. /// ```
  149. #[proc_macro_error]
  150. #[proc_macro_attribute]
  151. pub fn xdp(attrs: TokenStream, item: TokenStream) -> TokenStream {
  152. match Xdp::parse(attrs.into(), item.into()) {
  153. Ok(prog) => prog
  154. .expand()
  155. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  156. .into(),
  157. Err(err) => abort!(err.span(), "{}", err),
  158. }
  159. }
  160. #[proc_macro_error]
  161. #[proc_macro_attribute]
  162. pub fn classifier(attrs: TokenStream, item: TokenStream) -> TokenStream {
  163. match SchedClassifier::parse(attrs.into(), item.into()) {
  164. Ok(prog) => prog
  165. .expand()
  166. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  167. .into(),
  168. Err(err) => abort!(err.span(), "{}", err),
  169. }
  170. }
  171. #[proc_macro_attribute]
  172. pub fn cgroup_sysctl(attrs: TokenStream, item: TokenStream) -> TokenStream {
  173. match CgroupSysctl::parse(attrs.into(), item.into()) {
  174. Ok(prog) => prog
  175. .expand()
  176. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  177. .into(),
  178. Err(err) => abort!(err.span(), "{}", err),
  179. }
  180. }
  181. #[proc_macro_error]
  182. #[proc_macro_attribute]
  183. pub fn cgroup_sockopt(attrs: TokenStream, item: TokenStream) -> TokenStream {
  184. match CgroupSockopt::parse(attrs.into(), item.into()) {
  185. Ok(prog) => prog
  186. .expand()
  187. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  188. .into(),
  189. Err(err) => abort!(err.span(), "{}", err),
  190. }
  191. }
  192. #[proc_macro_error]
  193. #[proc_macro_attribute]
  194. pub fn cgroup_skb(attrs: TokenStream, item: TokenStream) -> TokenStream {
  195. match CgroupSkb::parse(attrs.into(), item.into()) {
  196. Ok(prog) => prog
  197. .expand()
  198. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  199. .into(),
  200. Err(err) => abort!(err.span(), "{}", err),
  201. }
  202. }
  203. /// Marks a function as a [`CgroupSockAddr`] eBPF program.
  204. ///
  205. /// [`CgroupSockAddr`] programs can be used to inspect or modify socket addresses passed to
  206. /// various syscalls within a [cgroup]. The `attach_type` argument specifies a place to attach
  207. /// the eBPF program to. See [`CgroupSockAddrAttachType`] for more details.
  208. ///
  209. /// [cgroup]: https://man7.org/linux/man-pages/man7/cgroups.7.html
  210. /// [`CgroupSockAddrAttachType`]: ../aya/programs/cgroup_sock_addr/enum.CgroupSockAddrAttachType.html
  211. /// [`CgroupSockAddr`]: ../aya/programs/cgroup_sock_addr/struct.CgroupSockAddr.html
  212. ///
  213. /// # Minimum kernel version
  214. ///
  215. /// The minimum kernel version required to use this feature is 4.17.
  216. ///
  217. /// # Examples
  218. ///
  219. /// ```no_run
  220. /// use aya_bpf::{macros::cgroup_sock_addr, programs::SockAddrContext};
  221. ///
  222. /// #[cgroup_sock_addr(connect4)]
  223. /// pub fn connect4(ctx: SockAddrContext) -> i32 {
  224. /// match try_connect4(ctx) {
  225. /// Ok(ret) => ret,
  226. /// Err(ret) => match ret.try_into() {
  227. /// Ok(rt) => rt,
  228. /// Err(_) => 1,
  229. /// },
  230. /// }
  231. /// }
  232. ///
  233. /// fn try_connect4(ctx: SockAddrContext) -> Result<i32, i64> {
  234. /// Ok(0)
  235. /// }
  236. /// ```
  237. #[proc_macro_error]
  238. #[proc_macro_attribute]
  239. pub fn cgroup_sock_addr(attrs: TokenStream, item: TokenStream) -> TokenStream {
  240. match CgroupSockAddr::parse(attrs.into(), item.into()) {
  241. Ok(prog) => prog
  242. .expand()
  243. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  244. .into(),
  245. Err(err) => abort!(err.span(), "{}", err),
  246. }
  247. }
  248. #[proc_macro_error]
  249. #[proc_macro_attribute]
  250. pub fn cgroup_sock(attrs: TokenStream, item: TokenStream) -> TokenStream {
  251. match CgroupSock::parse(attrs.into(), item.into()) {
  252. Ok(prog) => prog
  253. .expand()
  254. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  255. .into(),
  256. Err(err) => abort!(err.span(), "{}", err),
  257. }
  258. }
  259. #[proc_macro_error]
  260. #[proc_macro_attribute]
  261. pub fn tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream {
  262. match TracePoint::parse(attrs.into(), item.into()) {
  263. Ok(prog) => prog
  264. .expand()
  265. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  266. .into(),
  267. Err(err) => abort!(err.span(), "{}", err),
  268. }
  269. }
  270. #[proc_macro_error]
  271. #[proc_macro_attribute]
  272. pub fn perf_event(attrs: TokenStream, item: TokenStream) -> TokenStream {
  273. match PerfEvent::parse(attrs.into(), item.into()) {
  274. Ok(prog) => prog
  275. .expand()
  276. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  277. .into(),
  278. Err(err) => abort!(err.span(), "{}", err),
  279. }
  280. }
  281. /// Marks a function as a raw tracepoint eBPF program that can be attached at a
  282. /// pre-defined kernel trace point.
  283. ///
  284. /// The kernel provides a set of pre-defined trace points that eBPF programs can
  285. /// be attached to. See `/sys/kernel/debug/tracing/events` for a list of which
  286. /// events can be traced.
  287. ///
  288. /// # Minimum kernel version
  289. ///
  290. /// The minimum kernel version required to use this feature is 4.7.
  291. ///
  292. /// # Examples
  293. ///
  294. /// ```no_run
  295. /// use aya_bpf::{macros::raw_tracepoint, programs::RawTracePointContext};
  296. ///
  297. /// #[raw_tracepoint(tracepoint = "sys_enter")]
  298. /// pub fn sys_enter(ctx: RawTracePointContext) -> i32 {
  299. /// match unsafe { try_sys_enter(ctx) } {
  300. /// Ok(ret) => ret,
  301. /// Err(ret) => ret,
  302. /// }
  303. /// }
  304. ///
  305. /// unsafe fn try_sys_enter(_ctx: RawTracePointContext) -> Result<i32, i32> {
  306. /// Ok(0)
  307. /// }
  308. /// ```
  309. #[proc_macro_error]
  310. #[proc_macro_attribute]
  311. pub fn raw_tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream {
  312. match RawTracePoint::parse(attrs.into(), item.into()) {
  313. Ok(prog) => prog
  314. .expand()
  315. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  316. .into(),
  317. Err(err) => abort!(err.span(), "{}", err),
  318. }
  319. }
  320. /// Marks a function as an LSM program that can be attached to Linux LSM hooks.
  321. /// Used to implement security policy and audit logging.
  322. ///
  323. /// The hook name is the first argument to the macro.
  324. /// You may also provide `sleepable` to mark the program as sleepable.
  325. /// Arguments should be comma separated.
  326. ///
  327. /// LSM probes can be attached to the kernel's security hooks to implement mandatory
  328. /// access control policy and security auditing.
  329. ///
  330. /// LSM probes require a kernel compiled with `CONFIG_BPF_LSM=y` and `CONFIG_DEBUG_INFO_BTF=y`.
  331. /// In order for the probes to fire, you also need the BPF LSM to be enabled through your
  332. /// kernel's boot paramters (like `lsm=lockdown,yama,bpf`).
  333. ///
  334. /// # Minimum kernel version
  335. ///
  336. /// The minimum kernel version required to use this feature is 5.7.
  337. ///
  338. /// # Examples
  339. ///
  340. /// ```no_run
  341. /// use aya_bpf::{macros::lsm, programs::LsmContext};
  342. ///
  343. /// #[lsm(hook = "file_open")]
  344. /// pub fn file_open(ctx: LsmContext) -> i32 {
  345. /// match unsafe { try_file_open(ctx) } {
  346. /// Ok(ret) => ret,
  347. /// Err(ret) => ret,
  348. /// }
  349. /// }
  350. ///
  351. /// unsafe fn try_file_open(_ctx: LsmContext) -> Result<i32, i32> {
  352. /// Ok(0)
  353. /// }
  354. /// ```
  355. #[proc_macro_error]
  356. #[proc_macro_attribute]
  357. pub fn lsm(attrs: TokenStream, item: TokenStream) -> TokenStream {
  358. match Lsm::parse(attrs.into(), item.into()) {
  359. Ok(prog) => prog
  360. .expand()
  361. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  362. .into(),
  363. Err(err) => abort!(err.span(), "{}", err),
  364. }
  365. }
  366. /// Marks a function as a [BTF-enabled raw tracepoint][1] eBPF program that can be attached at
  367. /// a pre-defined kernel trace point.
  368. ///
  369. /// The kernel provides a set of pre-defined trace points that eBPF programs can
  370. /// be attached to. See `/sys/kernel/debug/tracing/events` for a list of which
  371. /// events can be traced.
  372. ///
  373. /// # Minimum kernel version
  374. ///
  375. /// The minimum kernel version required to use this feature is 5.5.
  376. ///
  377. /// # Examples
  378. ///
  379. /// ```no_run
  380. /// use aya_bpf::{macros::btf_tracepoint, programs::BtfTracePointContext};
  381. ///
  382. /// #[btf_tracepoint(function = "sched_process_fork")]
  383. /// pub fn sched_process_fork(ctx: BtfTracePointContext) -> u32 {
  384. /// match unsafe { try_sched_process_fork(ctx) } {
  385. /// Ok(ret) => ret,
  386. /// Err(ret) => ret,
  387. /// }
  388. /// }
  389. ///
  390. /// unsafe fn try_sched_process_fork(_ctx: BtfTracePointContext) -> Result<u32, u32> {
  391. /// Ok(0)
  392. /// }
  393. /// ```
  394. ///
  395. /// [1]: https://github.com/torvalds/linux/commit/9e15db66136a14cde3f35691f1d839d950118826
  396. #[proc_macro_error]
  397. #[proc_macro_attribute]
  398. pub fn btf_tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream {
  399. match BtfTracePoint::parse(attrs.into(), item.into()) {
  400. Ok(prog) => prog
  401. .expand()
  402. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  403. .into(),
  404. Err(err) => abort!(err.span(), "{}", err),
  405. }
  406. }
  407. /// Marks a function as a SK_SKB Stream Parser eBPF program that can be attached
  408. /// to a SockMap
  409. ///
  410. /// # Minimum kernel version
  411. ///
  412. /// The minimum kernel version required to use this feature is 4.14
  413. ///
  414. /// # Examples
  415. ///
  416. /// ```no_run
  417. /// use aya_bpf::{macros::stream_parser, programs::SkBuffContext};
  418. ///
  419. ///
  420. ///#[stream_parser]
  421. ///fn stream_parser(ctx: SkBuffContext) -> u32 {
  422. /// match { try_stream_parser(ctx) } {
  423. /// Ok(ret) => ret,
  424. /// Err(ret) => ret,
  425. /// }
  426. ///}
  427. ///
  428. ///fn try_stream_parser(ctx: SkBuffContext) -> Result<u32, u32> {
  429. /// Ok(ctx.len())
  430. ///}
  431. /// ```
  432. #[proc_macro_error]
  433. #[proc_macro_attribute]
  434. pub fn stream_parser(attrs: TokenStream, item: TokenStream) -> TokenStream {
  435. sk_skb(SkSkbKind::StreamParser, attrs, item)
  436. }
  437. /// Marks a function as a SK_SKB Stream Verdict eBPF program that can be attached
  438. /// to a SockMap
  439. ///
  440. /// # Minimum kernel version
  441. ///
  442. /// The minimum kernel version required to use this feature is 4.14
  443. ///
  444. /// # Examples
  445. ///
  446. /// ```no_run
  447. /// use aya_bpf::{macros::stream_verdict, programs::SkBuffContext, bindings::sk_action};
  448. ///
  449. ///
  450. ///#[stream_verdict]
  451. ///fn stream_verdict(ctx: SkBuffContext) -> u32 {
  452. /// match { try_stream_verdict(ctx) } {
  453. /// Ok(ret) => ret,
  454. /// Err(ret) => ret,
  455. /// }
  456. ///}
  457. ///
  458. ///fn try_stream_verdict(_ctx: SkBuffContext) -> Result<u32, u32> {
  459. /// Ok(sk_action::SK_PASS)
  460. ///}
  461. /// ```
  462. #[proc_macro_error]
  463. #[proc_macro_attribute]
  464. pub fn stream_verdict(attrs: TokenStream, item: TokenStream) -> TokenStream {
  465. sk_skb(SkSkbKind::StreamVerdict, attrs, item)
  466. }
  467. fn sk_skb(kind: SkSkbKind, attrs: TokenStream, item: TokenStream) -> TokenStream {
  468. match SkSkb::parse(kind, attrs.into(), item.into()) {
  469. Ok(prog) => prog
  470. .expand()
  471. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  472. .into(),
  473. Err(err) => abort!(err.span(), "{}", err),
  474. }
  475. }
  476. /// Marks a function as a eBPF Socket Filter program that can be attached to
  477. /// a socket.
  478. ///
  479. /// # Minimum kernel version
  480. ///
  481. /// The minimum kernel version required to use this feature is 3.19
  482. ///
  483. /// # Examples
  484. ///
  485. /// ```no_run
  486. /// use aya_bpf::{macros::socket_filter, programs::SkBuffContext};
  487. ///
  488. /// #[socket_filter]
  489. /// pub fn accept_all(_ctx: SkBuffContext) -> i64 {
  490. /// return 0
  491. /// }
  492. /// ```
  493. #[proc_macro_error]
  494. #[proc_macro_attribute]
  495. pub fn socket_filter(attrs: TokenStream, item: TokenStream) -> TokenStream {
  496. match SocketFilter::parse(attrs.into(), item.into()) {
  497. Ok(prog) => prog
  498. .expand()
  499. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  500. .into(),
  501. Err(err) => abort!(err.span(), "{}", err),
  502. }
  503. }
  504. /// Marks a function as a fentry eBPF program that can be attached to almost
  505. /// any function inside the kernel. The difference between fentry and kprobe
  506. /// is that fexit has practically zero overhead to call before kernel function.
  507. /// fentry programs can be also attached to other eBPF programs.
  508. ///
  509. /// # Minimumm kernel version
  510. ///
  511. /// The minimum kernel version required to use this feature is 5.5.
  512. ///
  513. /// # Examples
  514. ///
  515. /// ```no_run
  516. /// # #![allow(non_camel_case_types)]
  517. /// use aya_bpf::{macros::fentry, programs::FEntryContext};
  518. /// # type filename = u32;
  519. /// # type path = u32;
  520. ///
  521. /// #[fentry(function = "filename_lookup")]
  522. /// fn filename_lookup(ctx: FEntryContext) -> i32 {
  523. /// match unsafe { try_filename_lookup(ctx) } {
  524. /// Ok(ret) => ret,
  525. /// Err(ret) => ret,
  526. /// }
  527. /// }
  528. ///
  529. /// unsafe fn try_filename_lookup(ctx: FEntryContext) -> Result<i32, i32> {
  530. /// let _f: *const filename = ctx.arg(1);
  531. /// let _p: *const path = ctx.arg(3);
  532. ///
  533. /// Ok(0)
  534. /// }
  535. /// ```
  536. #[proc_macro_error]
  537. #[proc_macro_attribute]
  538. pub fn fentry(attrs: TokenStream, item: TokenStream) -> TokenStream {
  539. match FEntry::parse(attrs.into(), item.into()) {
  540. Ok(prog) => prog
  541. .expand()
  542. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  543. .into(),
  544. Err(err) => abort!(err.span(), "{}", err),
  545. }
  546. }
  547. /// Marks a function as a fexit eBPF program that can be attached to almost
  548. /// any function inside the kernel. The difference between fexit and kretprobe
  549. /// is that fexit has practically zero overhead to call after kernel function
  550. /// and it focuses on access to arguments rather than the return value. fexit
  551. /// programs can be also attached to other eBPF programs
  552. ///
  553. /// # Minimumm kernel version
  554. ///
  555. /// The minimum kernel version required to use this feature is 5.5.
  556. ///
  557. /// # Examples
  558. ///
  559. /// ```no_run
  560. /// # #![allow(non_camel_case_types)]
  561. /// use aya_bpf::{macros::fexit, programs::FExitContext};
  562. /// # type filename = u32;
  563. /// # type path = u32;
  564. ///
  565. /// #[fexit(function = "filename_lookup")]
  566. /// fn filename_lookup(ctx: FExitContext) -> i32 {
  567. /// match unsafe { try_filename_lookup(ctx) } {
  568. /// Ok(ret) => ret,
  569. /// Err(ret) => ret,
  570. /// }
  571. /// }
  572. ///
  573. /// unsafe fn try_filename_lookup(ctx: FExitContext) -> Result<i32, i32> {
  574. /// let _f: *const filename = ctx.arg(1);
  575. /// let _p: *const path = ctx.arg(3);
  576. ///
  577. /// Ok(0)
  578. /// }
  579. /// ```
  580. #[proc_macro_error]
  581. #[proc_macro_attribute]
  582. pub fn fexit(attrs: TokenStream, item: TokenStream) -> TokenStream {
  583. match FExit::parse(attrs.into(), item.into()) {
  584. Ok(prog) => prog
  585. .expand()
  586. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  587. .into(),
  588. Err(err) => abort!(err.span(), "{}", err),
  589. }
  590. }
  591. /// Marks a function as an eBPF Socket Lookup program that can be attached to
  592. /// a network namespace.
  593. ///
  594. /// # Minimum kernel version
  595. ///
  596. /// The minimum kernel version required to use this feature is 5.9
  597. ///
  598. /// # Examples
  599. ///
  600. /// ```no_run
  601. /// use aya_bpf::{macros::sk_lookup, programs::SkLookupContext};
  602. ///
  603. /// #[sk_lookup]
  604. /// pub fn accept_all(_ctx: SkLookupContext) -> u32 {
  605. /// // use sk_assign to redirect
  606. /// return 0
  607. /// }
  608. /// ```
  609. #[proc_macro_error]
  610. #[proc_macro_attribute]
  611. pub fn sk_lookup(attrs: TokenStream, item: TokenStream) -> TokenStream {
  612. match SkLookup::parse(attrs.into(), item.into()) {
  613. Ok(prog) => prog
  614. .expand()
  615. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  616. .into(),
  617. Err(err) => abort!(err.span(), "{}", err),
  618. }
  619. }
  620. /// Marks a function as a cgroup device eBPF program that can be attached to a
  621. /// cgroup.
  622. ///
  623. /// # Minimum kernel version
  624. ///
  625. /// The minimum kernel version required to use this feature is 4.15.
  626. ///
  627. /// # Examples
  628. ///
  629. /// ```no_run
  630. /// use aya_bpf::{
  631. /// macros::cgroup_device,
  632. /// programs::DeviceContext,
  633. /// };
  634. ///
  635. /// #[cgroup_device]
  636. /// pub fn cgroup_dev(ctx: DeviceContext) -> i32 {
  637. /// // Reject all device access
  638. /// return 0;
  639. /// }
  640. /// ```
  641. #[proc_macro_error]
  642. #[proc_macro_attribute]
  643. pub fn cgroup_device(attrs: TokenStream, item: TokenStream) -> TokenStream {
  644. match CgroupDevice::parse(attrs.into(), item.into()) {
  645. Ok(prog) => prog
  646. .expand()
  647. .unwrap_or_else(|err| abort!(err.span(), "{}", err))
  648. .into(),
  649. Err(err) => abort!(err.span(), "{}", err),
  650. }
  651. }