chipset: PIT restore accepts a control word with rw = 0, then hits `unreachable!()` on the next access

Aperta Adatta ai principianti
#1,066 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
85/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
rust

Direzione di ricerca

La fix appartiene in vm/devices/chipset/src/pit/mod.rs: aggiungi la variante d'errore MissingAccessMode e convalida le parole di controllo in restore come mostrato nel diff. Metti il test allegato in vm/devices/chipset/tests/ ed esegui cargo test -p chipset --test pit_restore_rw0. Fatto significa che restore rifiuta rw=0 con InvalidSavedState e non si verifica alcun panic.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Summary

PitDevice::restore installs each saved control word through ControlWord::from, which accepts any byte. rw = 0 is the encoding of the counter-latch command. set_control handles it as a latch and never stores it, but restore does store it. The next read or write of that counter then hits unreachable!() in Timer::write (pit/mod.rs:334) or Timer::read (pit/mod.rs:375).

Repro

pit_restore_rw0.txt

Add the attached pit_restore_rw0.rs (.txt) to vm/devices/chipset/tests/ and run:

cargo test -p chipset --test pit_restore_rw0

The test saves a fresh PIT and changes counter 0's control field in the encoded saved state from 0x10 to 0x00. It then restores into a new device and accesses port 0x40.

Expected

restore fails with RestoreError::InvalidSavedState, and the device stays usable.

Actual

restore returns Ok:

thread 'restored_rw0_control_is_rejected' panicked at vm/devices/chipset/tests/pit_restore_rw0.rs:41:9:
saved state with a rw = 0 control word was accepted

A later access to the counter then panics:

panicked at vm/devices/chipset/src/pit/mod.rs:334:18:
internal error: entered unreachable code

Suggested fix

Validate the control words before installing any state:

--- a/vm/devices/chipset/src/pit/mod.rs
+++ b/vm/devices/chipset/src/pit/mod.rs
@@ -755,6 +755,8 @@ pub struct SavedState {
     enum PitDeviceRestoreError {
         #[error("last tick time is after current time")]
         InvalidLastTick,
+        #[error("timer {0} has no read/write mode in its control word")]
+        MissingAccessMode(usize),
     }
 
     impl SaveRestore for PitDevice {
@@ -812,6 +814,17 @@ fn save(&mut self) -> Result<Self::SavedState, SaveError> {
         fn restore(&mut self, state: Self::SavedState) -> Result<(), RestoreError> {
             let state::SavedState { timers, last } = state;
 
+            // rw = 0 encodes the counter latch command, which is never stored
+            // as a timer's access mode.
+            if let Some(i) = timers
+                .iter()
+                .position(|timer| ControlWord::from(timer.control).rw() == 0)
+            {
+                return Err(RestoreError::InvalidSavedState(
+                    PitDeviceRestoreError::MissingAccessMode(i).into(),
+                ));
+            }
+
             for (timer, state) in self.timers.iter_mut().zip(timers) {
                 let state::SavedTimerState {
                     ce,
Lingua principale
Rust
Stelle
758
Fork
48
Merge medio
18h 7m
PR unite (30g)
457

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di microsoft/nvx

Tutte le issue di microsoft/nvx

Issue simili

Altre issue su Rust

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.