#![forbid(unsafe_code)]
#[cfg(feature = "log")]
use libseccomp::ScmpNotifResp;
#[cfg(feature = "log")]
use nix::errno::Errno;
#[cfg(feature = "log")]
use crate::{
req::UNotifyEventRequest,
syslog::{SYSLOG_ACTION_READ, SYSLOG_ACTION_READ_ALL, SYSLOG_ACTION_READ_CLEAR},
};
#[cfg(feature = "log")]
pub(crate) fn sys_syslog(request: UNotifyEventRequest) -> ScmpNotifResp {
syscall_handler!(request, |request: UNotifyEventRequest| {
let req = request.scmpreq;
let sandbox = request.get_sandbox();
if !sandbox.options.allow_safe_syslog() && sandbox.locked_for(req.pid()) {
return Err(Errno::EPERM);
}
drop(sandbox);
let syslog = if let Some(syslog) = crate::syslog::global_syslog() {
syslog
} else {
return Err(Errno::EPERM);
};
#[expect(clippy::cast_possible_truncation)]
let action = req.data.args[0] as libc::c_int;
let is_read_action = matches!(
action,
SYSLOG_ACTION_READ | SYSLOG_ACTION_READ_ALL | SYSLOG_ACTION_READ_CLEAR,
);
if is_read_action && req.data.args[1] == 0 {
return Err(Errno::EINVAL);
}
#[expect(clippy::cast_possible_truncation)]
let len = match usize::try_from(req.data.args[2] as libc::c_int) {
Ok(len) => len,
Err(_) if is_read_action => return Err(Errno::EINVAL),
Err(_) => 0,
};
let (count, buf) = syslog.syslog(action, len)?;
if let Some(buf) = buf {
request.write_mem_all(&buf, req.data.args[1])?;
}
#[expect(clippy::cast_possible_wrap)]
Ok(request.return_syscall(count as i64))
})
}