use ax_errno::AxError;
use ax_task::current;
use starry_vm::VmPtr;
use crate::task::AsThread;
fn validate_rseq_addr(addr: *mut u8, len: usize) -> Result<Option<usize>, AxError> {
if addr.is_null() {
if len != 0 {
return Err(AxError::InvalidInput);
}
return Ok(None);
}
if len == 0 {
return Err(AxError::InvalidInput);
}
Ok(Some(addr.addr()))
}
pub fn sys_rseq(addr: *mut u8, len: usize, flags: u32, sig: u32) -> Result<isize, AxError> {
debug!(
"sys_rseq <= addr: {:?}, len: {}, flags: {}, sig: {}",
addr, len, flags, sig
);
let Some(addr) = validate_rseq_addr(addr, len)? else {
current().as_thread().set_rseq_area(0);
return Ok(0);
};
if (addr as *mut u8).vm_read().is_err() {
return Err(AxError::InvalidInput);
}
current().as_thread().set_rseq_area(addr);
Ok(0)
}
#[cfg(test)]
mod tests {
use ax_errno::AxError;
use super::validate_rseq_addr;
#[test]
fn validate_rseq_addr_allows_unregister() {
assert_eq!(validate_rseq_addr(core::ptr::null_mut(), 0).unwrap(), None);
}
#[test]
fn validate_rseq_addr_rejects_null_addr_with_nonzero_len() {
assert_eq!(
validate_rseq_addr(core::ptr::null_mut(), 8).unwrap_err(),
AxError::InvalidInput
);
}
#[test]
fn validate_rseq_addr_rejects_nonnull_addr_with_zero_len() {
assert_eq!(
validate_rseq_addr(1usize as *mut u8, 0).unwrap_err(),
AxError::InvalidInput
);
}
}