Attempt a basic PC range check as part of hubris.validate#711
Conversation
`validate` on a hubris archive will verify the `image_id` present in an archive matches what's in flash. This has an unfortunate failure mode for the RoT where we partition the flash manually. It's possible to have the image ID check succeed on the archive but actually be running the opposite image. This causes all kinds of confusion. Add a basic spot check that the PC is in at least one module range. This could cause potential failures if the PC is actually running in a range that does not correspond to a module. Based on other work, the chances of this happening are very limited and should be transient.
|
| if let Ok(pc) = core.read_reg(ARMRegister::PC) { | ||
| if self.instr_mod(pc).is_none() { | ||
| bail!("PC at 0x{pc:x} is not part of any module. This is \ | ||
| likely an incorrect archive."); | ||
| } | ||
| } |
There was a problem hiding this comment.
i believe clippy would like you to have written something more like:
| if let Ok(pc) = core.read_reg(ARMRegister::PC) { | |
| if self.instr_mod(pc).is_none() { | |
| bail!("PC at 0x{pc:x} is not part of any module. This is \ | |
| likely an incorrect archive."); | |
| } | |
| } | |
| if let Ok(pc) = core.read_reg(ARMRegister::PC) | |
| && self.instr_mod(pc).is_none() { | |
| bail!("PC at 0x{pc:x} is not part of any module. \ | |
| This is likely an incorrect archive."); | |
| } |
| core.halt()?; | ||
| if let Ok(pc) = core.read_reg(ARMRegister::PC) { | ||
| if self.instr_mod(pc).is_none() { | ||
| bail!("PC at 0x{pc:x} is not part of any module. This is \ |
There was a problem hiding this comment.
unimportant turbo nitpick: if we write
| bail!("PC at 0x{pc:x} is not part of any module. This is \ | |
| bail!("PC at {pc:#x} is not part of any module. This is \ |
that tells the formatter to emit the 0x prefix itself. which...changes absolutely nothing here so it doesn't matter...
| core.halt()?; | ||
| if let Ok(pc) = core.read_reg(ARMRegister::PC) { | ||
| if self.instr_mod(pc).is_none() { | ||
| bail!("PC at 0x{pc:x} is not part of any module. This is \ |
There was a problem hiding this comment.
I think the way this interacts with flashing is not ideal. If you try to re-flash an A image that's already been flashed to the A slot while the RoT is running a B image:
- the old behavior was to fail with "archive appears to be already flashed on attached device; use -F ("--force") to force re-flash"
- this PR's behavior is to re-flash the A image
- the ideal behavior is probably to warn the user that they probably meant to flash the other image, then fail with the "archive appears to be already flashed" error.
There was a problem hiding this comment.
yeah you're right that's confusing behavior. I think that would point to needing to fix validate to return a more specific error
There was a problem hiding this comment.
Or don't use validate for the pre-flash check. In my PR, I considered a bunch of different return types then gave up trying to make the same validate function work for flashing and for both of the HubrisValidate options.
validateon a hubris archive will verify theimage_idpresent in an archive matches what's in flash. This has an unfortunate failure mode for the RoT where we partition the flash manually. It's possible to have the image ID check succeed on the archive but actually be running the opposite image. This causes all kinds of confusion. Add a basic spot check that the PC is in at least one module range. This could cause potential failures if the PC is actually running in a range that does not correspond to a module. Based on other work, the chances of this happening are very limited and should be transient.