Skip to content

Commit 2e458cc

Browse files
Update Firecracker block example (rust-lang#1135)
1 parent 2baaf57 commit 2e458cc

File tree

6 files changed

+265
-112
lines changed

6 files changed

+265
-112
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
[package]
5+
name = "firecracker-block-example"
6+
version = "0.1.0"
7+
edition = "2018"
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
This example accompanies Kani's post on Firecracker. This describes a proof
2+
harness for ensuring that the Firecracker block device `parse` method adheres
3+
to a virtio requirement (see below). We implement this as a standalone example
4+
with some simplifications (search for "Kani change" in the source).
5+
6+
This example is based on code from Firecracker. In particular,
7+
8+
- <https://github.com/firecracker-microvm/firecracker/tree/main/src/devices/src/virtio/block>
9+
- <https://github.com/firecracker-microvm/firecracker/blob/main/src/devices/src/virtio/queue.rs>
10+
11+
## Virtio requirement
12+
13+
We implement a simple finite-state-machine checker in `descriptor_permission_checker.rs` that ensures the following:
14+
15+
> 2.6.4.2 Driver Requirements: Message Framing
16+
>
17+
> The driver MUST place any device-writable descriptor elements after any device-readable descriptor elements.
18+
>
19+
> Source: https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-280004
20+
21+
## Reproducing results locally
22+
23+
### Dependencies
24+
25+
- Rust edition 2018
26+
- [Kani](https://model-checking.github.io/kani/getting-started.html)
27+
28+
If you have problems installing Kani then please file an [issue](https://github.com/model-checking/kani/issues/new/choose).
29+
30+
### Using Kani
31+
32+
Since there is only one harness in this example you can simply do the
33+
following, where the expected result is verification success.
34+
35+
```bash
36+
$ cargo kani
37+
# expected result: verification success
38+
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
VERIFICATION:- SUCCESSFUL
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
use crate::virtio_defs::*;
5+
6+
#[derive(Clone, Copy)]
7+
pub enum DescriptorPermission {
8+
ReadOnly,
9+
WriteOnly,
10+
}
11+
12+
impl DescriptorPermission {
13+
pub fn from_flags(flags: u16) -> Self {
14+
if 0 != (flags & VIRTQ_DESC_F_WRITE) { Self::WriteOnly } else { Self::ReadOnly }
15+
}
16+
}
17+
18+
// ANCHOR: fsm
19+
#[derive(std::cmp::PartialEq, Clone, Copy)]
20+
enum State {
21+
ReadOrWriteOk,
22+
OnlyWriteOk,
23+
Invalid,
24+
}
25+
26+
/// State machine checker for virtio requirement 2.6.4.2
27+
pub struct DescriptorPermissionChecker {
28+
state: State,
29+
}
30+
31+
impl DescriptorPermissionChecker {
32+
pub fn new() -> Self {
33+
DescriptorPermissionChecker { state: State::ReadOrWriteOk }
34+
}
35+
36+
pub fn update(&mut self, next_permission: DescriptorPermission) {
37+
let next_state = match (self.state, next_permission) {
38+
(State::ReadOrWriteOk, DescriptorPermission::WriteOnly) => State::OnlyWriteOk,
39+
(State::OnlyWriteOk, DescriptorPermission::ReadOnly) => State::Invalid,
40+
(_, _) => self.state,
41+
};
42+
self.state = next_state;
43+
}
44+
45+
pub fn virtio_2642_holds(&self) -> bool {
46+
self.state != State::Invalid
47+
}
48+
}
49+
// ANCHOR_END: fsm

0 commit comments

Comments
 (0)