lsm.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. use std::borrow::Cow;
  2. use proc_macro2::TokenStream;
  3. use quote::quote;
  4. use syn::{ItemFn, Result};
  5. use crate::args::{err_on_unknown_args, pop_bool_arg, pop_string_arg};
  6. pub(crate) struct Lsm {
  7. item: ItemFn,
  8. hook: Option<String>,
  9. sleepable: bool,
  10. }
  11. impl Lsm {
  12. pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Lsm> {
  13. let item = syn::parse2(item)?;
  14. let mut args = syn::parse2(attrs)?;
  15. let hook = pop_string_arg(&mut args, "hook");
  16. let sleepable = pop_bool_arg(&mut args, "sleepable");
  17. err_on_unknown_args(&args)?;
  18. Ok(Lsm {
  19. item,
  20. hook,
  21. sleepable,
  22. })
  23. }
  24. pub(crate) fn expand(&self) -> Result<TokenStream> {
  25. let section_prefix = if self.sleepable { "lsm.s" } else { "lsm" };
  26. let section_name: Cow<'_, _> = if let Some(hook) = &self.hook {
  27. format!("{}/{}", section_prefix, hook).into()
  28. } else {
  29. section_prefix.into()
  30. };
  31. let fn_vis = &self.item.vis;
  32. let fn_name = self.item.sig.ident.clone();
  33. let item = &self.item;
  34. // LSM probes need to return an integer corresponding to the correct
  35. // policy decision. Therefore we do not simply default to a return value
  36. // of 0 as in other program types.
  37. Ok(quote! {
  38. #[no_mangle]
  39. #[link_section = #section_name]
  40. #fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
  41. return #fn_name(::aya_bpf::programs::LsmContext::new(ctx));
  42. #item
  43. }
  44. })
  45. }
  46. }
  47. #[cfg(test)]
  48. mod tests {
  49. use syn::parse_quote;
  50. use super::*;
  51. #[test]
  52. fn test_lsm_sleepable() {
  53. let prog = Lsm::parse(
  54. parse_quote! {
  55. sleepable,
  56. hook = "bprm_committed_creds"
  57. },
  58. parse_quote! {
  59. fn bprm_committed_creds(ctx: &mut ::aya_bpf::programs::LsmContext) -> i32 {
  60. 0
  61. }
  62. },
  63. )
  64. .unwrap();
  65. let expanded = prog.expand().unwrap();
  66. let expected = quote! {
  67. #[no_mangle]
  68. #[link_section = "lsm.s/bprm_committed_creds"]
  69. fn bprm_committed_creds(ctx: *mut ::core::ffi::c_void) -> i32 {
  70. return bprm_committed_creds(::aya_bpf::programs::LsmContext::new(ctx));
  71. fn bprm_committed_creds(ctx: &mut ::aya_bpf::programs::LsmContext) -> i32 {
  72. 0
  73. }
  74. }
  75. };
  76. assert_eq!(expected.to_string(), expanded.to_string());
  77. }
  78. #[test]
  79. fn test_lsm() {
  80. let prog = Lsm::parse(
  81. parse_quote! {
  82. hook = "bprm_committed_creds"
  83. },
  84. parse_quote! {
  85. fn bprm_committed_creds(ctx: &mut ::aya_bpf::programs::LsmContext) -> i32 {
  86. 0
  87. }
  88. },
  89. )
  90. .unwrap();
  91. let expanded = prog.expand().unwrap();
  92. let expected = quote! {
  93. #[no_mangle]
  94. #[link_section = "lsm/bprm_committed_creds"]
  95. fn bprm_committed_creds(ctx: *mut ::core::ffi::c_void) -> i32 {
  96. return bprm_committed_creds(::aya_bpf::programs::LsmContext::new(ctx));
  97. fn bprm_committed_creds(ctx: &mut ::aya_bpf::programs::LsmContext) -> i32 {
  98. 0
  99. }
  100. }
  101. };
  102. assert_eq!(expected.to_string(), expanded.to_string());
  103. }
  104. }