implement fanotify event info

This commit is contained in:
guochao 2025-04-05 06:00:46 +00:00
parent 4ea80a819b
commit bab60681b3
3 changed files with 190 additions and 107 deletions

View File

@ -161,6 +161,8 @@ fn main() -> Result<(), Error> {
continue; continue;
} }
for event in events.iter_mut() { for event in events.iter_mut() {
if event.mask().is_permission_event() {
// permission event
let Some(fd) = event.fd() else { let Some(fd) = event.fd() else {
if init_flags & (InitFlags::FAN_REPORT_FID | InitFlags::FAN_REPORT_DIR_FID) if init_flags & (InitFlags::FAN_REPORT_FID | InitFlags::FAN_REPORT_DIR_FID)
!= InitFlags::empty() != InitFlags::empty()
@ -206,10 +208,10 @@ fn main() -> Result<(), Error> {
}; };
trace!( trace!(
"++++++++= {:?} {} {:?} {:?}", "++++++++ permission event:{} {:?} {:?} {:?}",
fd,
event.pid(), event.pid(),
event.mask(), event.mask(),
fd,
path path
); );
let arg0 = if let Some(cmdline) = cmdline.as_ref() { let arg0 = if let Some(cmdline) = cmdline.as_ref() {
@ -238,7 +240,8 @@ fn main() -> Result<(), Error> {
} }
Err(error) => error.kind() == std::io::ErrorKind::NotFound, Err(error) => error.kind() == std::io::ErrorKind::NotFound,
}; };
if allowed || whitelist.contains(&arg0) || storage_provider.contains(&arg0) { if allowed || whitelist.contains(&arg0) || storage_provider.contains(&arg0)
{
info!("<<<<< {} allowed", fd.as_raw_fd()); info!("<<<<< {} allowed", fd.as_raw_fd());
if let Err(err) = if let Err(err) =
fan.write_response(FanotifyResponse::new(fd, Response::FAN_ALLOW)) fan.write_response(FanotifyResponse::new(fd, Response::FAN_ALLOW))
@ -264,7 +267,11 @@ fn main() -> Result<(), Error> {
fd.as_fd(), fd.as_fd(),
Response::FAN_ALLOW, Response::FAN_ALLOW,
)) { )) {
warn!("write response for {} failed: {}", fd.as_raw_fd(), err); warn!(
"write response for {} failed: {}",
fd.as_raw_fd(),
err
);
} }
info!(">>>>> {} allowed(defer)", fd.as_raw_fd()); info!(">>>>> {} allowed(defer)", fd.as_raw_fd());
} }
@ -273,6 +280,14 @@ fn main() -> Result<(), Error> {
} }
_ => {} _ => {}
} }
} else {
trace!(
"++++++++ notification event: {} {:?} {:?}",
event.pid(),
event.mask(),
event.event_info,
);
}
} }
} }
} }

View File

@ -114,3 +114,12 @@ fa_bitflags! {
FAN_EVENT_ON_CHILD; // enable events on direct FAN_EVENT_ON_CHILD; // enable events on direct
} }
} }
impl MaskFlags {
pub fn is_permission_event(&self) -> bool {
match self.bits() {
FAN_OPEN_PERM | FAN_ACCESS | FAN_OPEN_EXEC_PERM => true,
_ => false,
}
}
}

View File

@ -105,6 +105,53 @@ impl Fanotify {
); );
let event = uninited.assume_init(); let event = uninited.assume_init();
#[repr(C)]
union fanotify_event_info {
header: libc::fanotify_event_info_header,
fid: libc::fanotify_event_info_fid,
pidfd: libc::fanotify_event_info_pidfd,
error: libc::fanotify_event_info_error,
}
let mut event_info = Vec::new();
const HEADER_SIZE: usize = std::mem::size_of::<libc::fanotify_event_info_header>();
let mut header_offset = EVENT_SIZE;
while header_offset + HEADER_SIZE < event.event_len as usize {
// pre-check
let mut uninited: MaybeUninit<fanotify_event_info> = MaybeUninit::uninit();
std::ptr::copy(
buffer.as_ptr().add(offset+EVENT_SIZE),
uninited.as_mut_ptr().cast(),
EVENT_SIZE,
);
std::ptr::copy(
buffer.as_ptr().add(offset + header_offset),
uninited.as_mut_ptr().add(header_offset).cast(),
(*uninited.as_ptr()).header.len as usize - HEADER_SIZE,
);
let event_info_len = (*uninited.as_ptr()).header.len as usize;
let event_info_type = (*uninited.as_ptr()).header.info_type;
match event_info_type {
libc::FAN_EVENT_INFO_TYPE_FID | libc::FAN_EVENT_INFO_TYPE_DFID_NAME | libc::FAN_EVENT_INFO_TYPE_DFID=> {
event_info.push(EventInfo::Fid(uninited.assume_init().fid));
}
libc::FAN_EVENT_INFO_TYPE_PIDFD => {
event_info.push(EventInfo::PidFd(uninited.assume_init().pidfd));
}
libc::FAN_EVENT_INFO_TYPE_ERROR => {
event_info.push(EventInfo::PidFd(uninited.assume_init().pidfd));
}
_ => {
panic!("unknown fan_event_info_header.type={event_info_type}")
}
}
header_offset += event_info_len;
}
// #define FAN_EVENT_NEXT(meta, len) ((len) -= (meta)->event_len, (struct fanotify_event_metadata*)(((char*)(meta)) + (meta) -> event_len) // #define FAN_EVENT_NEXT(meta, len) ((len) -= (meta)->event_len, (struct fanotify_event_metadata*)(((char*)(meta)) + (meta) -> event_len)
// meta = FAN_EVENT_NEXT(meta, len) translate to: // meta = FAN_EVENT_NEXT(meta, len) translate to:
// len -= meta->event_len; // shrink rest length // len -= meta->event_len; // shrink rest length
@ -115,7 +162,7 @@ impl Fanotify {
// + (meta) -> event_len // add event_len to move to next // + (meta) -> event_len // add event_len to move to next
// ); // );
offset += event.event_len as usize; offset += event.event_len as usize;
result.push(Event::new(event)); result.push(Event::new(event, event_info));
} }
} }
@ -139,12 +186,17 @@ impl Fanotify {
pub struct Event { pub struct Event {
pub fanotify_event_metadata: libc::fanotify_event_metadata, pub fanotify_event_metadata: libc::fanotify_event_metadata,
pub event_info: Vec<EventInfo>,
} }
impl Event { impl Event {
fn new(fanotify_event_metadata: libc::fanotify_event_metadata) -> Self { fn new(
fanotify_event_metadata: libc::fanotify_event_metadata,
event_info: Vec<EventInfo>,
) -> Self {
Self { Self {
fanotify_event_metadata, fanotify_event_metadata,
event_info,
} }
} }
// compatible to nix::sys::fanotify::FanotifyEvent // compatible to nix::sys::fanotify::FanotifyEvent
@ -191,6 +243,13 @@ impl Drop for Event {
} }
} }
#[derive(Debug)]
pub enum EventInfo {
Fid(libc::fanotify_event_info_fid),
PidFd(libc::fanotify_event_info_pidfd),
Error(libc::fanotify_event_info_error),
}
pub struct Response { pub struct Response {
inner: libc::fanotify_response, inner: libc::fanotify_response,
} }