diff --git a/kernel/src/syscall/select.rs b/kernel/src/syscall/select.rs index a2cc92eb4..a95e15772 100644 --- a/kernel/src/syscall/select.rs +++ b/kernel/src/syscall/select.rs @@ -19,8 +19,10 @@ pub fn sys_select( let timeout = if timeval_addr == 0 { None } else { - let timeval = ctx.get_user_space().read_val::(timeval_addr)?; - Some(Duration::from(timeval)) + let mut timeval = ctx.get_user_space().read_val::(timeval_addr)?; + timeval.sec += timeval.usec / 1_000_000; + timeval.usec %= 1_000_000; + Some(Duration::try_from(timeval)?) }; do_sys_select( diff --git a/kernel/src/syscall/setitimer.rs b/kernel/src/syscall/setitimer.rs index d572eee08..24b3256fd 100644 --- a/kernel/src/syscall/setitimer.rs +++ b/kernel/src/syscall/setitimer.rs @@ -34,8 +34,8 @@ pub fn sys_setitimer( } let user_space = ctx.get_user_space(); let new_itimerval = user_space.read_val::(new_itimerval_addr)?; - let interval = Duration::from(new_itimerval.it_interval); - let expire_time = Duration::from(new_itimerval.it_value); + let interval = Duration::try_from(new_itimerval.it_interval)?; + let expire_time = Duration::try_from(new_itimerval.it_value)?; let process_timer_manager = ctx.process.timer_manager(); let timer = match ItimerType::try_from(itimer_type)? { diff --git a/kernel/src/time/mod.rs b/kernel/src/time/mod.rs index 647061e73..626a6fd3e 100644 --- a/kernel/src/time/mod.rs +++ b/kernel/src/time/mod.rs @@ -86,9 +86,23 @@ impl From for timeval_t { } } -impl From for Duration { - fn from(timeval: timeval_t) -> Self { - Duration::new(timeval.sec as u64, (timeval.usec * 1000) as u32) +impl TryFrom for Duration { + type Error = crate::Error; + + fn try_from(timeval: timeval_t) -> Result { + if timeval.sec < 0 || timeval.usec < 0 { + return_errno_with_message!(Errno::EINVAL, "timeval_t cannot be negative"); + } + if timeval.usec > 1_000_000 { + // The value of microsecond cannot exceed 10^6, + // otherwise the value for seconds should be set. + return_errno_with_message!(Errno::EINVAL, "nsec is not normalized"); + } + + Ok(Duration::new( + timeval.sec as u64, + (timeval.usec * 1000) as u32, + )) } }