1use std::time::Duration;
11
12use nix::sys::signal::Signal;
13use reverie::Error;
14use reverie::Guest;
15use reverie::Stack;
16use reverie::syscalls;
17use reverie::syscalls::AddrMut;
18use reverie::syscalls::ClockId;
19use reverie::syscalls::Errno;
20use reverie::syscalls::MemoryAccess;
21use reverie::syscalls::Syscall;
22use reverie::syscalls::Timespec;
23use reverie::syscalls::Timeval;
24use reverie::syscalls::family::NanosleepFamily;
25use tracing::error;
26use tracing::info;
27use tracing::trace;
28
29use crate::detlog;
30use crate::procmaps;
31use crate::record_or_replay::RecordOrReplay;
32use crate::resources::Permission;
33use crate::resources::ResourceID;
34use crate::resources::Resources;
35use crate::scheduler::Priority;
36use crate::scheduler::entropy_to_priority;
37use crate::tool_global::ResumeStatus;
38use crate::tool_global::register_posix_timer;
39use crate::tool_global::thread_observe_time;
40use crate::tool_local::Detcore;
41use crate::types::LogicalTime;
42
43fn time_from_resources(rsrcs: &Resources) -> Option<LogicalTime> {
44 if rsrcs.resources.len() > 1 {
45 panic!(
46 "time_from_resources: multiple resource ids in resource request: {:?}",
47 rsrcs
48 );
49 }
50 for rs in rsrcs.resources.iter() {
51 if let (ResourceID::SleepUntil(tm), _) = rs {
52 return Some(*tm);
53 }
54 }
55 None
56}
57
58fn timespec_to_ns(ts: libc::timespec) -> u64 {
61 let secs = ts.tv_sec.max(0) as u64;
62 let nsec = ts.tv_nsec.max(0) as u64;
63 secs.saturating_mul(1_000_000_000).saturating_add(nsec)
64}
65
66fn ns_to_timespec(ns: u64) -> libc::timespec {
68 libc::timespec {
69 tv_sec: (ns / 1_000_000_000) as libc::time_t,
70 tv_nsec: (ns % 1_000_000_000) as libc::c_long,
71 }
72}
73
74fn timex_mode_is_query(modes: libc::c_uint) -> bool {
77 modes == 0 || modes == libc::ADJ_OFFSET_SS_READ
78}
79
80fn deterministic_timex(now: Timespec) -> libc::timex {
83 let mut tx: libc::timex = unsafe { std::mem::zeroed() };
86 tx.status = libc::STA_UNSYNC;
87 tx.tick = 10_000;
88 tx.time = libc::timeval {
89 tv_sec: now.tv_sec,
90 tv_usec: now.tv_nsec / 1_000,
91 };
92 tx
93}
94
95pub(crate) async fn guest_clock_time<G, T>(guest: &mut G) -> LogicalTime
98where
99 G: Guest<Detcore<T>>,
100 T: RecordOrReplay,
101{
102 let raw = thread_observe_time(guest).await;
103 guest.thread_state().observe_guest_clock(raw)
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq)]
110struct TvRepairFailure {
111 field: &'static str,
113 kind: TvRepairFailureKind,
114}
115
116#[derive(Debug, Clone, Copy, PartialEq, Eq)]
117enum TvRepairFailureKind {
118 ProbeFailed(Errno),
121 ControlProbeFailed(Errno),
125 StoppedWordChanged,
129 StoppedWordUnreadable,
134 MapsUnavailable,
137 OverwriteFailed(Errno),
140 OverwriteCount { expected: usize, reported: usize },
142 AddressOverflow,
144 ReplayMode,
147}
148
149impl std::fmt::Display for TvRepairFailure {
150 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
151 write!(
152 f,
153 "replacing host time in the {} of a failed gettimeofday: ",
154 self.field
155 )?;
156 match self.kind {
157 TvRepairFailureKind::ProbeFailed(errno) => {
158 write!(f, "time(2) store probe failed: {errno}")
159 }
160 TvRepairFailureKind::ControlProbeFailed(errno) => write!(
161 f,
162 "time(NULL) control probe failed: {errno}, so the store probe's EFAULT was not a store fault"
163 ),
164 TvRepairFailureKind::StoppedWordChanged => f.write_str(
165 "the word changed during the call although its store probe returned EFAULT",
166 ),
167 TvRepairFailureKind::StoppedWordUnreadable => f.write_str(
168 "the word is mapped but could not be read, so its store probe's EFAULT is unconfirmed",
169 ),
170 TvRepairFailureKind::MapsUnavailable => {
171 f.write_str("the guest's memory map could not be read")
172 }
173 TvRepairFailureKind::OverwriteFailed(errno) => {
174 write!(f, "virtual-time overwrite failed: {errno}")
175 }
176 TvRepairFailureKind::OverwriteCount { expected, reported } => write!(
177 f,
178 "virtual-time overwrite reported {reported} of {expected} bytes"
179 ),
180 TvRepairFailureKind::AddressOverflow => f.write_str("field address overflowed"),
181 TvRepairFailureKind::ReplayMode => {
182 f.write_str("cannot probe a recorded or replayed EFAULT")
183 }
184 }
185 }
186}
187
188impl std::error::Error for TvRepairFailure {}
189
190fn tv_repair_error(field: &'static str, kind: TvRepairFailureKind) -> Error {
191 Error::Tool(anyhow::Error::new(TvRepairFailure { field, kind }))
192}
193
194#[derive(Debug, Clone, Copy, PartialEq, Eq)]
195enum TimeStoreProbe {
196 Stored,
197 Stopped,
198}
199
200fn classify_time_store_probe(
201 field: &'static str,
202 result: Result<i64, Errno>,
203) -> Result<TimeStoreProbe, Error> {
204 match result {
205 Ok(_) => Ok(TimeStoreProbe::Stored),
206 Err(Errno::EFAULT) => Ok(TimeStoreProbe::Stopped),
207 Err(errno) => Err(tv_repair_error(
208 field,
209 TvRepairFailureKind::ProbeFailed(errno),
210 )),
211 }
212}
213
214fn require_native_time_control_probe(
217 field: &'static str,
218 result: Result<i64, Errno>,
219) -> Result<(), Error> {
220 match result {
221 Ok(_) => Ok(()),
222 Err(errno) => Err(tv_repair_error(
223 field,
224 TvRepairFailureKind::ControlProbeFailed(errno),
225 )),
226 }
227}
228
229#[derive(Debug, Clone, Copy, PartialEq, Eq)]
231enum StoppedWord {
232 Unchanged,
234 Unreadable,
237}
238
239fn require_unchanged_stopped_word(
241 field: &'static str,
242 before: Result<libc::time_t, Errno>,
243 after: Result<libc::time_t, Errno>,
244) -> Result<StoppedWord, Error> {
245 match (before, after) {
246 (Ok(before), Ok(after)) if before == after => Ok(StoppedWord::Unchanged),
247 (Err(_), Err(_)) => Ok(StoppedWord::Unreadable),
248 _ => Err(tv_repair_error(
249 field,
250 TvRepairFailureKind::StoppedWordChanged,
251 )),
252 }
253}
254
255fn time_word_is_fully_mapped(mut ranges: Vec<(u64, u64)>, word: u64) -> bool {
258 let Some(end) = word.checked_add(std::mem::size_of::<libc::time_t>() as u64) else {
259 return false;
260 };
261 ranges.sort_unstable();
262 let mut covered = word;
263 for (start, stop) in ranges {
264 if start <= covered && covered < stop {
265 covered = stop;
266 if covered >= end {
267 return true;
268 }
269 }
270 }
271 false
272}
273
274fn require_unmapped_unreadable_word(
288 field: &'static str,
289 maps: Result<Vec<(u64, u64)>, Error>,
290 word: u64,
291) -> Result<(), Error> {
292 let ranges = match maps {
293 Ok(ranges) if !ranges.is_empty() => ranges,
294 Ok(_) => {
295 error!("gettimeofday tv repair: the guest's memory map is empty");
296 return Err(tv_repair_error(field, TvRepairFailureKind::MapsUnavailable));
297 }
298 Err(err) => {
299 error!("gettimeofday tv repair: reading the guest's memory map: {err}");
300 return Err(tv_repair_error(field, TvRepairFailureKind::MapsUnavailable));
301 }
302 };
303 if time_word_is_fully_mapped(ranges, word) {
304 Err(tv_repair_error(
305 field,
306 TvRepairFailureKind::StoppedWordUnreadable,
307 ))
308 } else {
309 Ok(())
310 }
311}
312
313type TimevalWordSnapshot = [Result<libc::time_t, Errno>; 2];
318
319const TIMEVAL_WORDS: [(&str, usize); 2] = [
320 ("tv_sec", std::mem::offset_of!(Timeval, tv_sec)),
321 ("tv_usec", std::mem::offset_of!(Timeval, tv_usec)),
322];
323
324fn snapshot_timeval_words<'a, G, T>(
325 guest: &mut G,
326 tv_addr: AddrMut<'a, Timeval>,
327) -> TimevalWordSnapshot
328where
329 G: Guest<Detcore<T>>,
330 T: RecordOrReplay,
331{
332 TIMEVAL_WORDS.map(|(field, offset)| {
333 let addr = timeval_word_addr(field, tv_addr, offset).map_err(|_| Errno::EFAULT)?;
334 guest.memory().read_value(addr)
335 })
336}
337
338fn timeval_word_addr<'a>(
339 field: &'static str,
340 tv_addr: AddrMut<'a, Timeval>,
341 offset: usize,
342) -> Result<AddrMut<'a, libc::time_t>, Error> {
343 tv_addr
344 .as_raw()
345 .checked_add(offset)
346 .and_then(AddrMut::<libc::time_t>::from_raw)
347 .ok_or_else(|| tv_repair_error(field, TvRepairFailureKind::AddressOverflow))
348}
349
350fn require_complete_time_word_overwrite(
351 field: &'static str,
352 expected: usize,
353 result: Result<usize, Errno>,
354) -> Result<(), Error> {
355 match result {
356 Ok(reported) if reported == expected => Ok(()),
357 Ok(reported) => Err(tv_repair_error(
358 field,
359 TvRepairFailureKind::OverwriteCount { expected, reported },
360 )),
361 Err(errno) => Err(tv_repair_error(
362 field,
363 TvRepairFailureKind::OverwriteFailed(errno),
364 )),
365 }
366}
367
368fn require_live_time_store_probe(replay_data_is_some: bool) -> Result<(), Error> {
369 if replay_data_is_some {
370 Err(tv_repair_error("tv", TvRepairFailureKind::ReplayMode))
371 } else {
372 Ok(())
373 }
374}
375
376fn should_repair_failed_gettimeofday_tv(backend_is_kvm: bool) -> bool {
377 !backend_is_kvm
378}
379
380async fn overwrite_failed_gettimeofday_tv<'a, G, T>(
434 guest: &mut G,
435 tv_addr: AddrMut<'a, Timeval>,
436 tv: &Timeval,
437 before: &TimevalWordSnapshot,
438) -> Result<(), Error>
439where
440 G: Guest<Detcore<T>>,
441 T: RecordOrReplay,
442{
443 let values = [tv.tv_sec as libc::time_t, tv.tv_usec as libc::time_t];
444 for (index, (field, offset)) in TIMEVAL_WORDS.into_iter().enumerate() {
445 let addr = timeval_word_addr(field, tv_addr, offset)?;
446 let probe = syscalls::Time::new().with_tloc(Some(addr));
447 match classify_time_store_probe(field, guest.inject(probe).await)? {
448 TimeStoreProbe::Stored => {
449 let bytes = values[index].to_ne_bytes();
450 let overwrite = guest
451 .memory()
452 .write_with_user_access(addr.cast::<u8>(), &bytes);
453 require_complete_time_word_overwrite(field, bytes.len(), overwrite)?;
454 }
455 TimeStoreProbe::Stopped => {
456 let control = syscalls::Time::new().with_tloc(None);
457 require_native_time_control_probe(field, guest.inject(control).await)?;
458 for (stopped, (field, offset)) in TIMEVAL_WORDS.into_iter().enumerate().skip(index)
459 {
460 let addr = timeval_word_addr(field, tv_addr, offset)?;
461 let after = guest.memory().read_value(addr);
462 match require_unchanged_stopped_word(field, before[stopped], after)? {
463 StoppedWord::Unchanged => {}
464 StoppedWord::Unreadable => {
465 let maps = procmaps::from_pid(guest.pid(), |_| true)
466 .map(|maps| maps.into_iter().map(|map| map.address).collect());
467 require_unmapped_unreadable_word(field, maps, addr.as_raw() as u64)?;
468 }
469 }
470 }
471 break;
472 }
473 }
474 }
475 Ok(())
476}
477
478fn remaining_sleep_duration(target: LogicalTime, now: LogicalTime) -> Duration {
479 if target > now {
480 target.duration_since(now)
481 } else {
482 Duration::ZERO
483 }
484}
485
486impl<T: RecordOrReplay> Detcore<T> {
487 pub async fn sleep_request<G: Guest<Self>>(guest: &mut G, ns_delta: Duration) -> Resources {
489 let base_time = thread_observe_time(guest).await;
490 let target_time = base_time + ns_delta;
491 let resource = ResourceID::SleepUntil(target_time);
492 guest.thread_state().mk_request(resource, Permission::W)
493 }
494
495 pub async fn sleep_request_abs<G: Guest<Self>>(guest: &mut G, time: LogicalTime) -> Resources {
497 let resource = ResourceID::SleepUntil(time);
499 guest.thread_state().mk_request(resource, Permission::W)
500 }
501
502 pub fn yield_request<G: Guest<Self>>(guest: &mut G) -> Resources {
505 let resource = ResourceID::SleepUntil(LogicalTime::from_nanos(0));
506 guest.thread_state().mk_request(resource, Permission::W)
507 }
508
509 pub fn sched_yield_request<G: Guest<Self>>(guest: &mut G) -> Resources {
511 guest
512 .thread_state()
513 .mk_request(ResourceID::SchedYield, Permission::W)
514 }
515
516 pub fn random_priority_changepoint_request<G: Guest<Self>>(
518 guest: &mut G,
519 change_time: LogicalTime,
520 ) -> Resources {
521 let entropy = guest.thread_state_mut().chaos_prng_next_u64("priority");
522 let new_priority = entropy_to_priority(entropy);
523 Self::priority_changepoint_request(guest, change_time, new_priority)
524 }
525
526 pub fn priority_changepoint_request<G: Guest<Self>>(
528 guest: &mut G,
529 change_time: LogicalTime,
530 new_priority: Priority,
531 ) -> Resources {
532 let epochs = guest.thread_state_mut().take_pending_chaos_epochs();
535 let rcbs = guest.thread_state().committed_clock_value;
536 let resource = ResourceID::PriorityChangePoint(new_priority, change_time, rcbs, epochs);
537 guest.thread_state().mk_request(resource, Permission::W)
538 }
539
540 pub async fn handle_gettimeofday<G: Guest<Self>>(
542 &self,
543 guest: &mut G,
544 call: syscalls::Gettimeofday,
545 ) -> Result<i64, Error> {
546 let time_ns = guest_clock_time(guest).await;
547
548 let repair_on_efault = should_repair_failed_gettimeofday_tv(guest.config().backend_is_kvm);
549 let before = match call.tv() {
552 Some(tp) if repair_on_efault => Some(snapshot_timeval_words(guest, tp.into())),
553 _ => None,
554 };
555
556 let result = self
559 .record_or_replay_preserving_tool_errors(guest, call)
560 .await;
561
562 let tv: Timeval = time_ns.into();
563
564 if let Some(tp) = call.tv() {
565 match (&result, &before) {
566 (Ok(_), _) => guest.memory().write_value(tp, &tv)?,
567 (Err(Error::Errno(Errno::EFAULT)), Some(before)) => {
573 require_live_time_store_probe(self.cfg.replay_data.is_some())?;
574 overwrite_failed_gettimeofday_tv(guest, tp.into(), &tv, before).await?
575 }
576 (Err(_), _) => {}
577 }
578 }
579
580 result
581 }
582
583 pub async fn handle_time<G: Guest<Self>>(
585 &self,
586 guest: &mut G,
587 call: syscalls::Time,
588 ) -> Result<i64, Error> {
589 let time_ns = guest_clock_time(guest).await;
590 let secs = time_ns.as_secs() as i64;
591
592 if let Some(tloc) = call.tloc() {
593 let mut memory = guest.memory();
594 memory.write_value(tloc, &secs)?;
595 }
596
597 Ok(secs)
598 }
599
600 pub async fn handle_clock_gettime<G: Guest<Self>>(
602 &self,
603 guest: &mut G,
604 call: syscalls::ClockGettime,
605 ) -> Result<i64, Error> {
606 let time_ns = guest_clock_time(guest).await;
607 trace!("Converting nanoseconds into clock_gettime: {}", time_ns);
608
609 let tp = call.tp().ok_or(Errno::EFAULT)?;
610
611 let t: Timespec = time_ns.into();
612
613 guest.memory().write_value(tp, &t)?;
614
615 Ok(0)
616 }
617
618 pub async fn handle_clock_getres<G: Guest<Self>>(
620 &self,
621 guest: &mut G,
622 call: syscalls::ClockGetres,
623 ) -> Result<i64, Error> {
624 if let Some(res) = call.res() {
631 let clock_res = 10;
633
634 let t = Timespec {
635 tv_sec: 0,
636 tv_nsec: 1000 * clock_res as i64,
637 };
638
639 guest.memory().write_value(res, &t)?;
640 }
641
642 Ok(0)
643 }
644
645 pub async fn handle_adjtimex<G: Guest<Self>>(
650 &self,
651 guest: &mut G,
652 call: syscalls::Adjtimex,
653 ) -> Result<i64, Error> {
654 self.write_deterministic_timex(guest, call.buf()).await
655 }
656
657 pub async fn handle_clock_adjtime<G: Guest<Self>>(
662 &self,
663 guest: &mut G,
664 call: syscalls::ClockAdjtime,
665 ) -> Result<i64, Error> {
666 if call.clockid() != ClockId::CLOCK_REALTIME {
667 return Err(Errno::EOPNOTSUPP.into());
668 }
669 self.write_deterministic_timex(guest, call.buf()).await
670 }
671
672 async fn write_deterministic_timex<G: Guest<Self>>(
673 &self,
674 guest: &mut G,
675 buf: Option<reverie::syscalls::AddrMut<'_, libc::timex>>,
676 ) -> Result<i64, Error> {
677 let buf = buf.ok_or(Errno::EFAULT)?;
678 let request: libc::timex = guest.memory().read_value(buf)?;
679 if !timex_mode_is_query(request.modes) {
680 return Err(Errno::EPERM.into());
681 }
682
683 let now: Timespec = thread_observe_time(guest).await.into();
684 guest.memory().write_value(buf, &deterministic_timex(now))?;
685 Ok(libc::TIME_ERROR as i64)
686 }
687
688 async fn wait_and_return<R: Guest<Self>>(
691 guest: &mut R,
692 request: Resources,
693 call: NanosleepFamily,
694 ) -> Result<i64, Error> {
695 let target_time = time_from_resources(&request).expect("a sleepuntil resource request");
696 match crate::tool_global::parked_wait_request(
697 guest,
698 request,
699 crate::scheduler::parked::ParkedWaitPolicy::NanosleepNoHandlerRestart {
700 absolute_deadline: target_time,
701 },
702 )
703 .await
704 {
705 ResumeStatus::Normal => Ok(0),
706 ResumeStatus::Signaled(_) => {
707 let now = thread_observe_time(guest).await;
708 let delta = remaining_sleep_duration(target_time, now);
709 let addr2 = if call.flags() & libc::TIMER_ABSTIME == 0 {
712 call.rem()
713 } else {
714 None
715 };
716 if let Some(addr2) = addr2 {
717 info!(
718 "[interrupted] sleep till (until {}), woke up {:?} early, writing into nanosleep rem argument.",
719 target_time, delta
720 );
721 let t = Timespec {
722 tv_sec: delta.as_secs() as i64,
723 tv_nsec: delta.subsec_nanos() as i64,
724 };
725 guest.memory().write_value(addr2, &t)?;
726 } else {
727 info!("[interrupted] nanosleep rem argument is null, not writing it.")
728 }
729 Err(reverie::Error::Errno(Errno::EINTR))
730 }
731 }
732 }
733
734 pub async fn handle_nanosleep_family<R: Guest<Self>>(
736 &self,
737 guest: &mut R,
738 call: NanosleepFamily,
739 ) -> Result<i64, Error> {
740 if call.flags() > libc::TIMER_ABSTIME {
741 trace!("Unhandled clock_nanosleep flags, letting syscall through...");
742 return Ok(guest.inject(Syscall::from(call)).await?);
743 }
744
745 let addr = call.req().ok_or(Errno::EFAULT)?;
746 let t: Timespec = guest.memory().read_value(addr)?;
747
748 if t.tv_sec < 0 || t.tv_nsec < 0 || t.tv_nsec > 999_999_999 {
764 return Err(Errno::EINVAL.into());
765 }
766
767 match call.flags() {
768 0 => {
769 if self.cfg.sequentialize_threads {
770 let time = Duration::from_secs(t.tv_sec as u64)
771 + Duration::from_nanos(t.tv_nsec as u64);
772 let request = Self::sleep_request(guest, time).await;
773 trace!(
774 "nanosleep adding delta {:?} to yield request {:?}",
775 time, &request
776 );
777 Self::wait_and_return(guest, request, call).await
778 } else {
779 trace!("Not sequentializing threads, letting nanosleep through...");
780 Ok(guest.inject(Syscall::from(call)).await?)
781 }
782 }
783 libc::TIMER_ABSTIME => {
784 let target_time = LogicalTime::from_secs(t.tv_sec as u64)
785 + LogicalTime::from_nanos(t.tv_nsec as u64);
786 if self.cfg.sequentialize_threads {
787 if self.cfg.virtualize_time {
788 let request = Self::sleep_request_abs(guest, target_time).await;
789 trace!(
790 "nanosleep setting absolute time {:?} to yield request {:?}",
791 target_time, &request
792 );
793 Self::wait_and_return(guest, request, call).await
794 } else {
795 error!(
797 "Sequentializing but not virtualizing, so can't rely on passed abs time, especially when replaying a recording, just yelding"
798 );
799 let request = Self::yield_request(guest);
800 Self::wait_and_return(guest, request, call).await
801 }
802 } else if self.cfg.virtualize_time {
803 trace!(
804 "Not sequentializing, but virtualizing so calculating relative time and invoking nanosleep..."
805 );
806 let relative_ts = Self::relative_time_from_abs_target(guest, target_time).await;
807 let mut stack = guest.stack().await;
808 let req = stack.push(relative_ts);
809 stack.commit()?;
810 let modified_call = syscalls::Nanosleep::new().with_req(Some(req));
811 Ok(guest.inject(modified_call).await?)
812 } else {
813 trace!(
814 "Not sequentializing threads not virtualizing, letting nanosleep through..."
815 );
816 Ok(guest.inject(Syscall::from(call)).await?)
817 }
818 }
819 _ => unreachable!("Unexpected, unhandled flag value"),
820 }
821 }
822
823 async fn relative_time_from_abs_target<G: Guest<Self>>(
824 guest: &mut G,
825 target_time: LogicalTime,
826 ) -> Timespec {
827 let base_time = thread_observe_time(guest).await;
828
829 let relative_logical = if target_time <= base_time {
842 LogicalTime::from_nanos(0)
843 } else {
844 target_time - base_time
845 };
846
847 Timespec {
848 tv_sec: relative_logical.as_secs() as i64,
849 tv_nsec: relative_logical.subsec_nanos() as i64,
850 }
851 }
852
853 pub async fn handle_timer_create<G: Guest<Self>>(
858 &self,
859 guest: &mut G,
860 call: syscalls::TimerCreate,
861 ) -> Result<i64, Error> {
862 let timerid_ptr = call.timerid().ok_or(Errno::EFAULT)?;
864 let clockid = call.clockid();
865 let signal = if let Some(event_ptr) = call.sevp() {
866 let event: libc::sigevent = guest.memory().read_value(event_ptr)?;
867 match event.sigev_notify {
868 libc::SIGEV_NONE => None,
869 libc::SIGEV_SIGNAL | 4 => {
872 if !(1..=64).contains(&event.sigev_signo) {
873 return Err(Errno::EINVAL.into());
874 }
875 Signal::try_from(event.sigev_signo).ok()
876 }
877 _ => return Err(Errno::ENOSYS.into()),
878 }
879 } else {
880 Some(Signal::SIGALRM)
881 };
882 let id = {
883 let mut timers = guest.thread_state().posix_timers.lock().unwrap();
884 timers.create(signal.map(|sig| sig as i32))
885 };
886 guest
887 .memory()
888 .write_value(timerid_ptr, &(id as libc::c_int))?;
889 detlog!(
890 "[dtid {}] timer_create(clockid={:?}) => deterministic timer id {}, signal {:?}",
891 guest.thread_state().dettid,
892 clockid,
893 id,
894 signal,
895 );
896 Ok(0)
897 }
898
899 pub async fn handle_timer_settime<G: Guest<Self>>(
904 &self,
905 guest: &mut G,
906 call: syscalls::TimerSettime,
907 ) -> Result<i64, Error> {
908 let id = call.timerid();
909 let new_ptr = call.new_value().ok_or(Errno::EINVAL)?;
910 let new: libc::itimerspec = guest.memory().read_value(new_ptr)?;
911 let interval_ns = timespec_to_ns(new.it_interval);
912 let value_ns = timespec_to_ns(new.it_value);
913
914 let now = thread_observe_time(guest).await;
915 let deadline = if value_ns == 0 {
916 None
917 } else if call.flags() & libc::TIMER_ABSTIME != 0 {
918 Some(LogicalTime::from_nanos(value_ns))
920 } else {
921 Some(now + Duration::from_nanos(value_ns))
922 };
923
924 let (old, signal_number) = {
925 let mut timers = guest.thread_state().posix_timers.lock().unwrap();
926 let old = timers.settime(id, interval_ns, deadline, now);
927 let signal = timers.signal(id);
928 (old, signal)
929 };
930 let (old_remaining_ns, old_interval_ns) = old.ok_or(Errno::EINVAL)?;
931 let signal_number = signal_number.ok_or(Errno::EINVAL)?;
932
933 if let Some(old_ptr) = call.old_value() {
934 let old_spec = libc::itimerspec {
935 it_interval: ns_to_timespec(old_interval_ns),
936 it_value: ns_to_timespec(old_remaining_ns),
937 };
938 guest.memory().write_value(old_ptr, &old_spec)?;
939 }
940
941 if let Some(signal) = signal_number.and_then(|signum| Signal::try_from(signum).ok()) {
942 register_posix_timer(
943 guest,
944 id,
945 deadline,
946 LogicalTime::from_nanos(interval_ns),
947 signal,
948 )
949 .await;
950 }
951
952 detlog!(
953 "[dtid {}] timer_settime(id={}, interval_ns={}, value_ns={}) armed against virtual clock",
954 guest.thread_state().dettid,
955 id,
956 interval_ns,
957 value_ns,
958 );
959 Ok(0)
960 }
961
962 pub async fn handle_timer_gettime<G: Guest<Self>>(
965 &self,
966 guest: &mut G,
967 call: syscalls::TimerGettime,
968 ) -> Result<i64, Error> {
969 let id = call.timerid();
970 let value_ptr = call.value().ok_or(Errno::EFAULT)?;
971 let now = thread_observe_time(guest).await;
972 let cur = {
973 let timers = guest.thread_state().posix_timers.lock().unwrap();
974 timers.gettime(id, now)
975 };
976 let (remaining_ns, interval_ns) = cur.ok_or(Errno::EINVAL)?;
977 let spec = libc::itimerspec {
978 it_interval: ns_to_timespec(interval_ns),
979 it_value: ns_to_timespec(remaining_ns),
980 };
981 guest.memory().write_value(value_ptr, &spec)?;
982 Ok(0)
983 }
984
985 pub async fn handle_timer_getoverrun<G: Guest<Self>>(
988 &self,
989 guest: &mut G,
990 call: syscalls::TimerGetoverrun,
991 ) -> Result<i64, Error> {
992 let id = call.timerid();
993 let exists = guest
994 .thread_state()
995 .posix_timers
996 .lock()
997 .unwrap()
998 .contains(id);
999 if exists {
1000 Ok(0)
1001 } else {
1002 Err(Errno::EINVAL.into())
1003 }
1004 }
1005
1006 pub async fn handle_timer_delete<G: Guest<Self>>(
1010 &self,
1011 guest: &mut G,
1012 call: syscalls::TimerDelete,
1013 ) -> Result<i64, Error> {
1014 let id = call.timerid();
1015 let signal_number = guest
1016 .thread_state()
1017 .posix_timers
1018 .lock()
1019 .unwrap()
1020 .signal(id)
1021 .ok_or(Errno::EINVAL)?;
1022 let existed = {
1023 let mut timers = guest.thread_state().posix_timers.lock().unwrap();
1024 timers.remove(id)
1025 };
1026 if existed {
1027 if let Some(signal) = signal_number.and_then(|signum| Signal::try_from(signum).ok()) {
1028 register_posix_timer(guest, id, None, LogicalTime::ZERO, signal).await;
1029 }
1030 detlog!(
1031 "[dtid {}] timer_delete(id={})",
1032 guest.thread_state().dettid,
1033 id,
1034 );
1035 Ok(0)
1036 } else {
1037 Err(Errno::EINVAL.into())
1038 }
1039 }
1040}
1041
1042#[cfg(test)]
1043mod tests {
1044 use super::*;
1045
1046 #[test]
1047 fn timex_policy_distinguishes_queries_from_mutations() {
1048 assert!(timex_mode_is_query(0));
1049 assert!(timex_mode_is_query(libc::ADJ_OFFSET_SS_READ));
1050 assert!(!timex_mode_is_query(libc::ADJ_OFFSET));
1051 assert!(!timex_mode_is_query(libc::ADJ_FREQUENCY));
1052 }
1053
1054 #[test]
1055 fn timex_snapshot_is_unsynchronized_and_uses_virtual_time() {
1056 let tx = deterministic_timex(Timespec {
1057 tv_sec: 123,
1058 tv_nsec: 456_789_000,
1059 });
1060 assert_eq!(tx.status, libc::STA_UNSYNC);
1061 assert_eq!(tx.tick, 10_000);
1062 assert_eq!(tx.time.tv_sec, 123);
1063 assert_eq!(tx.time.tv_usec, 456_789);
1064 }
1065
1066 #[test]
1067 fn interrupted_sleep_remaining_time_floors_at_zero() {
1068 let target = LogicalTime::from_nanos(1_000);
1069
1070 assert_eq!(
1071 remaining_sleep_duration(target, LogicalTime::from_nanos(750)),
1072 Duration::from_nanos(250)
1073 );
1074 assert_eq!(remaining_sleep_duration(target, target), Duration::ZERO);
1075 assert_eq!(
1076 remaining_sleep_duration(target, LogicalTime::from_nanos(1_250)),
1077 Duration::ZERO
1078 );
1079 }
1080
1081 mod failed_gettimeofday_tv {
1082 use super::*;
1083
1084 fn failure(error: Error) -> TvRepairFailure {
1085 match error {
1086 Error::Tool(error) => *error
1087 .downcast_ref::<TvRepairFailure>()
1088 .expect("a typed repair failure"),
1089 other => panic!("expected a Tool error, got {other:?}"),
1090 }
1091 }
1092
1093 #[test]
1094 fn successful_time_store_probe_requires_an_overwrite() {
1095 assert_eq!(
1096 classify_time_store_probe("tv_sec", Ok(1)).unwrap(),
1097 TimeStoreProbe::Stored
1098 );
1099 }
1100
1101 #[test]
1102 fn efault_time_store_probe_stops_without_an_overwrite() {
1103 assert_eq!(
1104 classify_time_store_probe("tv_usec", Err(Errno::EFAULT)).unwrap(),
1105 TimeStoreProbe::Stopped
1106 );
1107 }
1108
1109 #[test]
1110 fn any_control_probe_error_means_the_efault_was_not_a_store_fault() {
1111 require_native_time_control_probe("tv_sec", Ok(1_767_225_600)).unwrap();
1112 for errno in [Errno::EFAULT, Errno::EPERM, Errno::ENOSYS] {
1113 let error = require_native_time_control_probe("tv_usec", Err(errno))
1114 .expect_err("time(NULL) cannot fail natively");
1115 assert_eq!(
1116 failure(error),
1117 TvRepairFailure {
1118 field: "tv_usec",
1119 kind: TvRepairFailureKind::ControlProbeFailed(errno),
1120 }
1121 );
1122 }
1123 }
1124
1125 #[test]
1126 fn a_stopped_word_must_keep_its_contents_and_readability() {
1127 assert_eq!(
1128 require_unchanged_stopped_word("tv_sec", Ok(7), Ok(7)).unwrap(),
1129 StoppedWord::Unchanged
1130 );
1131 for (before, after) in [(Errno::EFAULT, Errno::EFAULT), (Errno::EIO, Errno::EPERM)] {
1132 assert_eq!(
1133 require_unchanged_stopped_word("tv_sec", Err(before), Err(after)).unwrap(),
1134 StoppedWord::Unreadable
1135 );
1136 }
1137 for (before, after) in [
1138 (Ok(7), Ok(1_791_041_091)),
1139 (Ok(7), Err(Errno::EFAULT)),
1140 (Err(Errno::EFAULT), Ok(7)),
1141 ] {
1142 let error = require_unchanged_stopped_word("tv_usec", before, after)
1143 .expect_err("a changed stopped word means the call stored it");
1144 assert_eq!(
1145 failure(error),
1146 TvRepairFailure {
1147 field: "tv_usec",
1148 kind: TvRepairFailureKind::StoppedWordChanged,
1149 }
1150 );
1151 }
1152 }
1153
1154 #[test]
1155 fn an_unreadable_word_is_unstored_only_if_part_of_it_is_unmapped() {
1156 const PAGE: u64 = 0x1000;
1157 let two_pages = || Ok(vec![(3 * PAGE, 4 * PAGE), (2 * PAGE, 3 * PAGE)]);
1158 for word in [1, 2 * PAGE - 4, 4 * PAGE - 4, 5 * PAGE, u64::MAX - 3] {
1160 require_unmapped_unreadable_word("tv_sec", two_pages(), word).unwrap();
1161 }
1162 for word in [2 * PAGE, 3 * PAGE - 4, 4 * PAGE - 8] {
1164 let error = require_unmapped_unreadable_word("tv_usec", two_pages(), word)
1165 .expect_err("a failed read of a mapped word is not a fault");
1166 assert_eq!(
1167 failure(error),
1168 TvRepairFailure {
1169 field: "tv_usec",
1170 kind: TvRepairFailureKind::StoppedWordUnreadable,
1171 }
1172 );
1173 }
1174 }
1175
1176 #[test]
1177 fn an_unreadable_word_needs_a_readable_nonempty_map() {
1178 let unreadable = Err(Error::Errno(Errno::EPERM));
1179 for maps in [Ok(Vec::new()), unreadable] {
1180 let error = require_unmapped_unreadable_word("tv_sec", maps, 1)
1181 .expect_err("without a map an unreadable word proves nothing");
1182 assert_eq!(
1183 failure(error),
1184 TvRepairFailure {
1185 field: "tv_sec",
1186 kind: TvRepairFailureKind::MapsUnavailable,
1187 }
1188 );
1189 }
1190 }
1191
1192 #[test]
1193 fn failed_gettimeofday_repair_is_skipped_only_for_kvm() {
1194 assert!(should_repair_failed_gettimeofday_tv(false));
1195 assert!(!should_repair_failed_gettimeofday_tv(true));
1196 }
1197
1198 #[test]
1199 fn other_time_store_probe_errors_fail_closed() {
1200 for errno in [Errno::ENOSYS, Errno::EPERM, Errno::EIO] {
1201 let error = classify_time_store_probe("tv_sec", Err(errno))
1202 .expect_err("a non-EFAULT probe error must fail the repair");
1203 assert_eq!(
1204 failure(error),
1205 TvRepairFailure {
1206 field: "tv_sec",
1207 kind: TvRepairFailureKind::ProbeFailed(errno),
1208 }
1209 );
1210 }
1211 }
1212
1213 #[test]
1214 fn overwrite_errors_and_nonexact_counts_fail_closed() {
1215 assert_eq!(
1216 failure(
1217 require_complete_time_word_overwrite("tv_usec", 8, Err(Errno::EFAULT),)
1218 .unwrap_err()
1219 ),
1220 TvRepairFailure {
1221 field: "tv_usec",
1222 kind: TvRepairFailureKind::OverwriteFailed(Errno::EFAULT),
1223 }
1224 );
1225 for reported in [0, 3, 7, 9] {
1226 assert_eq!(
1227 failure(
1228 require_complete_time_word_overwrite("tv_sec", 8, Ok(reported))
1229 .unwrap_err()
1230 ),
1231 TvRepairFailure {
1232 field: "tv_sec",
1233 kind: TvRepairFailureKind::OverwriteCount {
1234 expected: 8,
1235 reported,
1236 },
1237 }
1238 );
1239 }
1240 require_complete_time_word_overwrite("tv_sec", 8, Ok(8)).unwrap();
1241
1242 require_live_time_store_probe(false).unwrap();
1243 assert_eq!(
1244 failure(require_live_time_store_probe(true).unwrap_err()),
1245 TvRepairFailure {
1246 field: "tv",
1247 kind: TvRepairFailureKind::ReplayMode,
1248 }
1249 );
1250 }
1251
1252 #[test]
1253 fn timeval_word_addresses_follow_kernel_order_and_overflow_fails_closed() {
1254 assert_eq!(TIMEVAL_WORDS, [("tv_sec", 0), ("tv_usec", 8)]);
1255 let tv_addr = AddrMut::<Timeval>::from_raw(0x10_0000).unwrap();
1256 assert_eq!(
1257 timeval_word_addr("tv_sec", tv_addr, std::mem::offset_of!(Timeval, tv_sec))
1258 .unwrap()
1259 .as_raw(),
1260 tv_addr.as_raw()
1261 );
1262 assert_eq!(
1263 timeval_word_addr("tv_usec", tv_addr, std::mem::offset_of!(Timeval, tv_usec))
1264 .unwrap()
1265 .as_raw(),
1266 tv_addr.as_raw() + 8
1267 );
1268
1269 let overflowing = AddrMut::<Timeval>::from_raw(usize::MAX - 3).unwrap();
1270 let error = timeval_word_addr("tv_usec", overflowing, 8)
1271 .expect_err("overflowing field address must fail the repair");
1272 assert_eq!(
1273 failure(error),
1274 TvRepairFailure {
1275 field: "tv_usec",
1276 kind: TvRepairFailureKind::AddressOverflow,
1277 }
1278 );
1279 }
1280 }
1281}