Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions pinchy-common/src/kernel_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ pub struct Timespec {
pub nanos: i64,
}

/// Structure for utime syscall
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct Utimbuf {
pub actime: i64, // Access time
pub modtime: i64, // Modification time
}

/// Structure for openat2 syscall, matching the kernel's struct open_how
/// See: https://man7.org/linux/man-pages/man2/openat2.2.html
#[repr(C)]
Expand Down
27 changes: 27 additions & 0 deletions pinchy-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,9 @@ pub union SyscallEventData {
pub remap_file_pages: RemapFilePagesData,
pub restart_syscall: RestartSyscallData,
pub kexec_load: KexecLoadData,
pub lookup_dcookie: LookupDcookieData,
pub nfsservctl: NfsservctlData,
pub utime: UtimeData,
}

#[repr(C)]
Expand Down Expand Up @@ -3424,3 +3427,27 @@ pub struct KexecLoadData {
pub segments_read: u64,
pub parsed_segments: [kernel_types::KexecSegment; kernel_types::KEXEC_SEGMENT_ARRAY_CAP],
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct LookupDcookieData {
pub cookie: u64,
pub buffer: [u8; MEDIUM_READ_SIZE],
pub size: u64,
}

#[repr(C)]
#[derive(Clone, Copy, Default)]
pub struct NfsservctlData {
pub cmd: i32,
pub argp: u64,
pub resp: u64,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct UtimeData {
pub filename: [u8; DATA_READ_SIZE],
pub times: kernel_types::Utimbuf,
pub times_is_null: u8,
}
44 changes: 44 additions & 0 deletions pinchy-ebpf/src/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,50 @@ pub fn syscall_exit_filesystem(ctx: TracePointContext) -> u32 {
data.id = args[2] as i32;
data.addr = args[3] as u64;
}
syscalls::SYS_lookup_dcookie => {
let data = data_mut!(entry, lookup_dcookie);
data.cookie = args[0] as u64;
data.size = args[2] as u64;

let buffer_ptr = args[1] as *const u8;

if !buffer_ptr.is_null() && return_value > 0 {
unsafe {
let _ = bpf_probe_read_buf(buffer_ptr, &mut data.buffer);
}
}
}
syscalls::SYS_nfsservctl => {
let data = data_mut!(entry, nfsservctl);
data.cmd = args[0] as i32;
data.argp = args[1] as u64;
data.resp = args[2] as u64;
}
#[cfg(target_arch = "x86_64")]
syscalls::SYS_utime => {
let data = data_mut!(entry, utime);

let filename_ptr = args[0] as *const u8;
let times_ptr = args[1] as *const pinchy_common::kernel_types::Utimbuf;

if !filename_ptr.is_null() {
unsafe {
let _ = bpf_probe_read_buf(filename_ptr, &mut data.filename);
}
}

if times_ptr.is_null() {
data.times_is_null = 1;
} else {
data.times_is_null = 0;

unsafe {
if let Ok(times) = bpf_probe_read_user(times_ptr) {
data.times = times;
}
}
}
}
_ => {
entry.discard();
return Ok(());
Expand Down
42 changes: 42 additions & 0 deletions pinchy/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4661,6 +4661,48 @@ pub async fn handle_event(event: &SyscallEvent, formatter: Formatter<'_>) -> any

finish!(sf, event.return_value);
}
syscalls::SYS_lookup_dcookie => {
let data = unsafe { event.data.lookup_dcookie };

argf!(sf, "cookie: {}", data.cookie);

let buffer = format_path(&data.buffer, false);

argf!(sf, "buffer: {}", buffer);
argf!(sf, "size: {}", data.size);

finish!(sf, event.return_value);
}
syscalls::SYS_nfsservctl => {
let data = unsafe { event.data.nfsservctl };

argf!(sf, "cmd: {}", data.cmd);
argf!(sf, "argp: 0x{:x}", data.argp);
argf!(sf, "resp: 0x{:x}", data.resp);

finish!(sf, event.return_value);
}
#[cfg(target_arch = "x86_64")]
syscalls::SYS_utime => {
let data = unsafe { event.data.utime };

let filename = format_path(&data.filename, false);

argf!(sf, "filename: {}", filename);

if data.times_is_null != 0 {
argf!(sf, "times: NULL");
} else {
argf!(
sf,
"times: {{actime: {}, modtime: {}}}",
data.times.actime,
data.times.modtime
);
}

finish!(sf, event.return_value);
}
_ => {
let data = unsafe { event.data.generic };

Expand Down
9 changes: 6 additions & 3 deletions pinchy/src/format_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2327,7 +2327,8 @@ pub fn format_return_value(syscall_nr: i64, return_value: i64) -> std::borrow::C
| syscalls::SYS_process_vm_readv
| syscalls::SYS_process_vm_writev
| syscalls::SYS_sched_getaffinity
| syscalls::SYS_copy_file_range => {
| syscalls::SYS_copy_file_range
| syscalls::SYS_lookup_dcookie => {
if return_value >= 0 {
std::borrow::Cow::Owned(format!("{return_value} (bytes)"))
} else {
Expand Down Expand Up @@ -2492,7 +2493,8 @@ pub fn format_return_value(syscall_nr: i64, return_value: i64) -> std::borrow::C
| syscalls::SYS_getresuid
| syscalls::SYS_getresgid
| syscalls::SYS_restart_syscall
| syscalls::SYS_kexec_load => match return_value {
| syscalls::SYS_kexec_load
| syscalls::SYS_nfsservctl => match return_value {
0 => std::borrow::Cow::Borrowed("0 (success)"),
_ => std::borrow::Cow::Owned(format!("{return_value} (error)")),
},
Expand Down Expand Up @@ -2532,7 +2534,8 @@ pub fn format_return_value(syscall_nr: i64, return_value: i64) -> std::borrow::C
| syscalls::SYS_rename
| syscalls::SYS_mknod
| syscalls::SYS_stat
| syscalls::SYS_lstat => match return_value {
| syscalls::SYS_lstat
| syscalls::SYS_utime => match return_value {
0 => std::borrow::Cow::Borrowed("0 (success)"),
_ => std::borrow::Cow::Owned(format!("{return_value} (error)")),
},
Expand Down
4 changes: 4 additions & 0 deletions pinchy/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,10 @@ fn load_tailcalls(ebpf: &mut Ebpf) -> anyhow::Result<()> {
syscalls::SYS_utimensat,
syscalls::SYS_quotactl,
syscalls::SYS_quotactl_fd,
syscalls::SYS_lookup_dcookie,
syscalls::SYS_nfsservctl,
#[cfg(target_arch = "x86_64")]
syscalls::SYS_utime,
];
let filesystem_prog: &mut aya::programs::TracePoint = ebpf
.program_mut("syscall_exit_filesystem")
Expand Down
139 changes: 131 additions & 8 deletions pinchy/src/tests/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,20 @@ use pinchy_common::{
self, SYS_acct, SYS_chdir, SYS_copy_file_range, SYS_faccessat, SYS_fallocate,
SYS_fanotify_init, SYS_fanotify_mark, SYS_fchmod, SYS_fchmodat, SYS_fchown, SYS_fchownat,
SYS_fdatasync, SYS_fstat, SYS_fsync, SYS_ftruncate, SYS_getcwd, SYS_getdents64,
SYS_inotify_add_watch, SYS_inotify_init1, SYS_inotify_rm_watch, SYS_linkat, SYS_mkdirat,
SYS_name_to_handle_at, SYS_newfstatat, SYS_open_by_handle_at, SYS_quotactl,
SYS_quotactl_fd, SYS_readlinkat, SYS_renameat, SYS_renameat2, SYS_statfs,
SYS_sync_file_range, SYS_syncfs, SYS_truncate, SYS_utimensat,
SYS_inotify_add_watch, SYS_inotify_init1, SYS_inotify_rm_watch, SYS_linkat,
SYS_lookup_dcookie, SYS_mkdirat, SYS_name_to_handle_at, SYS_newfstatat, SYS_nfsservctl,
SYS_open_by_handle_at, SYS_quotactl, SYS_quotactl_fd, SYS_readlinkat, SYS_renameat,
SYS_renameat2, SYS_statfs, SYS_sync_file_range, SYS_syncfs, SYS_truncate, SYS_utimensat,
},
AcctData, CopyFileRangeData, FaccessatData, FallocateData, FanotifyInitData, FanotifyMarkData,
FchmodData, FchmodatData, FchownData, FchownatData, FdatasyncData, FsyncData, FtruncateData,
InotifyAddWatchData, InotifyInit1Data, InotifyRmWatchData, LinkatData, MkdiratData,
MknodatData, NameToHandleAtData, OpenByHandleAtData, QuotactlFdData, Renameat2Data,
RenameatData, SyncFileRangeData, SyncfsData, SyscallEvent, SyscallEventData, UtimensatData,
DATA_READ_SIZE, MEDIUM_READ_SIZE, SMALLISH_READ_SIZE,
InotifyAddWatchData, InotifyInit1Data, InotifyRmWatchData, LinkatData, LookupDcookieData,
MkdiratData, MknodatData, NameToHandleAtData, NfsservctlData, OpenByHandleAtData,
QuotactlFdData, Renameat2Data, RenameatData, SyncFileRangeData, SyncfsData, SyscallEvent,
SyscallEventData, UtimensatData, DATA_READ_SIZE, MEDIUM_READ_SIZE, SMALLISH_READ_SIZE,
};
#[cfg(target_arch = "x86_64")]
use pinchy_common::{syscalls::SYS_utime, UtimeData};

use crate::syscall_test;

Expand Down Expand Up @@ -3395,3 +3397,124 @@ syscall_test!(
},
"10008 quotactl(op: 0x80000802 (QCMD(Q_SETQUOTA, PRJQUOTA)), special: \"/dev/sdc1\", id: 1001, addr: 0x7fff22222222) = 0 (success)\n"
);

syscall_test!(
parse_lookup_dcookie_success,
{
SyscallEvent {
syscall_nr: SYS_lookup_dcookie,
pid: 123,
tid: 123,
return_value: 10,
data: SyscallEventData {
lookup_dcookie: LookupDcookieData {
cookie: 0x123456789abcdef0,
buffer: *b"/proc/sys\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
size: 64,
},
},
}
},
"123 lookup_dcookie(cookie: 1311768467463790320, buffer: \"/proc/sys\", size: 64) = 10 (bytes)\n"
);

syscall_test!(
parse_lookup_dcookie_error,
{
SyscallEvent {
syscall_nr: SYS_lookup_dcookie,
pid: 123,
tid: 123,
return_value: -1,
data: SyscallEventData {
lookup_dcookie: LookupDcookieData {
cookie: 0x123456789abcdef0,
buffer: [0; MEDIUM_READ_SIZE],
size: 64,
},
},
}
},
"123 lookup_dcookie(cookie: 1311768467463790320, buffer: \"\", size: 64) = -1 (error)\n"
);

syscall_test!(
parse_nfsservctl_success,
{
SyscallEvent {
syscall_nr: SYS_nfsservctl,
pid: 123,
tid: 123,
return_value: 0,
data: SyscallEventData {
nfsservctl: NfsservctlData {
cmd: 1,
argp: 0x7fff1000,
resp: 0x7fff2000,
},
},
}
},
"123 nfsservctl(cmd: 1, argp: 0x7fff1000, resp: 0x7fff2000) = 0 (success)\n"
);

#[cfg(target_arch = "x86_64")]
syscall_test!(
parse_utime_with_times,
{
use pinchy_common::kernel_types::Utimbuf;

SyscallEvent {
syscall_nr: SYS_utime,
pid: 123,
tid: 123,
return_value: 0,
data: SyscallEventData {
utime: UtimeData {
filename: {
let mut filename = [0u8; DATA_READ_SIZE];
let name = b"/tmp/foo";
filename[..name.len()].copy_from_slice(name);

filename
},
times: Utimbuf {
actime: 1234567890,
modtime: 1234567900,
},
times_is_null: 0,
},
},
}
},
"123 utime(filename: \"/tmp/foo\", times: {actime: 1234567890, modtime: 1234567900}) = 0 (success)\n"
);

#[cfg(target_arch = "x86_64")]
syscall_test!(
parse_utime_null_times,
{
use pinchy_common::kernel_types::Utimbuf;

SyscallEvent {
syscall_nr: SYS_utime,
pid: 123,
tid: 123,
return_value: 0,
data: SyscallEventData {
utime: UtimeData {
filename: {
let mut filename = [0u8; DATA_READ_SIZE];
let name = b"/tmp/bar";
filename[..name.len()].copy_from_slice(name);

filename
},
times: Utimbuf::default(),
times_is_null: 1,
},
},
}
},
"123 utime(filename: \"/tmp/bar\", times: NULL) = 0 (success)\n"
);