# Meeting 2023-11-29
<!-- Leave your topic starting with ### in the relevant sections below -->
## Critical
<!-- bugs, soundness issues, urgent patches/reviews etc. -->
## Status Reports
<!-- You want to report on something you are working on/request reviews.
Or you want to know the status of something someone else is doing -->
## Discussion Questions
<!-- Anything that requires lengthy discussion/more general questions also fit here -->
### Abstraction registry page
* [ ] Disclaimer.
* [ ] Start with asking people to add themselves.
### Safety Standard
Benno: I have been working on this for some time. Hope to have something ready to send to the list soon-ish. But wanted to know if you have any particular recommendation as to what it should contain.
One thing that I wanted to ask you guys is how we want to handle `unsafe` blocks with lots of stuff in them. This example from the list if of course not ok
```rust
unsafe {
let mut index: core::ffi::c_ulong = 0;
let mut entry = bindings::xa_find(
self.xa.get(),
&mut index,
core::ffi::c_ulong::MAX,
bindings::BINDINGS_XA_PRESENT,
);
while !entry.is_null() {
T::from_foreign(entry);
entry = bindings::xa_find_after(
self.xa.get(),
&mut index,
core::ffi::c_ulong::MAX,
bindings::BINDINGS_XA_PRESENT,
);
}
}
```
but this is more of a gray zone:
```rust
let ret = unsafe {
bindings::xa_alloc(
self.xa.get(),
&mut id,
new as *mut _,
bindings::xa_limit { min, max },
bindings::GFP_KERNEL,
)
};
```
Since `get()` is a safe operation and the construction of the `xa_limit` struct as well as the cast are also safe.
I was thinking about making a list of allowed safe operations inside `unsafe` blocks, what do you think?
Gary: The second example looks legit, I don't think further splitting make sense.
Another example:
```rust
// SAFETY: `self.xa` is always valid by the type invariant.
let p = unsafe {
bindings::xa_lock(self.xa.get());
bindings::xa_load(self.xa.get(), index.try_into().ok()?)
};
```
Duplication?
<https://github.com/Darksonn/linux/blob/dca45e6c7848e024709b165a306cdbe88e5b086a/rust/kernel/list.rs#L357-L368>
What about?
<https://github.com/Darksonn/linux/blob/dca45e6c7848e024709b165a306cdbe88e5b086a/rust/kernel/list.rs#L432-L437>
### formally verifying Klint (only if we have time!)
I resumed my work on this and finally got to a resonable theory. But I encountered the following issue:
First some definitions:
Since Rust is way to complex, I settled on this simpler toy language:
```
datatype
com = SKIP
| SLEEP
| LOCK var
| UNLOCK var
| Inc var
| Dec var
| CALL var
| Seq com com
| While var a com
```
Here is the operational semantics:
```
inductive small_step :: "'a com × state ⇒ 'a com × state ⇒ bool" (infix "→" 55)
where
Seq1: "(SKIP;;c, s) → (c, s)"
| Call: "(CALL f, s) → (funcs f, s)"
| Sleep: "can_sleep s ⟹ (SLEEP, s) → (SKIP, s)"
| Lock: "unlocked s x ⟹ (LOCK x, s) → (SKIP, lock s x)"
| Unlock: "locked s x ⟹ (UNLOCK x, s) → (SKIP, unlock s x)"
| Inc: "(x++, s) → (SKIP, inc s x)"
| Dec: "(x--, s) → (SKIP, dec s x)"
| Seq2: "(c, s) → (c', s') ⟹ (c;;d, s) → (c';;d, s')"
| WhileTrue: "val s x ≠ 0 ⟹ (WHILE x ≠ 0 DO c, s) → (c;; WHILE x ≠ 0 DO c, s)"
| WhileFalse: "val s x = 0 ⟹ (WHILE x ≠ 0 DO c, s) → (SKIP, s)"
```
I defined soundness like this:
```
definition sound :: "'a com ⇒ bool"
where "⊨ c ≡ ∃l. ∀v. (∃s. (c, (l, v)) →* (SKIP, s))
∨ (∃π. is_exec π ∧ π 0 = (c, (l, v)))"
```
Which in normal language reads:
```!
A program `c` is considered sound, if there exists some set of locked variables `l` such that for every possible assignment of values to variables `v` the program `c` can terminate or run for ever when starting with the state `(l, v)`.
```
To model what klint does I have defined a "typing": each command is given a "type" -- which is just a tuple of the adjustment and the expected range.
```
(a, (s, e)) ⊢ c
```
where `a` is the adjustment, and `[s, e]` is the interval (both s and e are inclusive).
Here is the definition of the typing:
```
inductive typing :: "ty ⇒ 'a com ⇒ bool" (infix "⊢" 30)
where
SkipT[intro!]: "(0, (0, ∞)) ⊢ SKIP" |
IncT[intro!]: "(0, (0, ∞)) ⊢ x++" |
DecT[intro!]: "(0, (0, ∞)) ⊢ x--" |
SleepT[intro!]: "(0, (0, 0)) ⊢ SLEEP" |
UnlockT[intro!]:"(-1, (1, ∞)) ⊢ UNLOCK x" |
LockT[intro!]: "(1, (0, ∞)) ⊢ LOCK x" |
SeqT[intro!]: "⟦(i⇩1, (r⇩1, u⇩1)) ⊢ c⇩1; (i⇩2, (r⇩2, u⇩2)) ⊢ c⇩2;
Fin (max (int r⇩2) (int r⇩1 + i⇩1))
≤ min (to_eint u⇩2) (to_eint u⇩1 + Fin i⇩1);
r = nat (max (int r⇩2 - i⇩1) (int r⇩1));
u = to_enat (min (to_eint u⇩2 - Fin i⇩1) (to_eint u⇩1));
i = i⇩1 + i⇩2⟧
⟹ (i, (r, u)) ⊢ c⇩1;; c⇩2" |
CallT[intro!]: "Γ ⊢ funcs f ⟹ Γ ⊢ CALL f" |
WhileT[intro!]: "⟦(0, (r, u)) ⊢ c⟧ ⟹ (0, (r, u)) ⊢ (WHILE x ≠ 0 DO c)"
```
I was able to prove that
```
(0, (0, 0)) ⊢ SLEEP;; LOCK ''a'';; UNLOCK ''b''
```
but also able to show that
```
¬ ⊨ SLEEP;; LOCK ''a'';; UNLOCK ''b''
```
Which is a counterexample to the correctness theorem that I tried to prove:
```
(i, (s, e)) ⊢ c ⟹ ⊨ c
```
My questions:
1. is the definition of `sound` what you also have in mind?
2. if I should not change `sound`, what should I change?
If I am thinking correctly, this should not be a real issue, since in Rust every lock that is unlocked needs to be locked first, which means that the count will be `> 0` when the function is called, which klint will deny.
Gary: We can do
```
| Sleep: "can_sleep s ⟹ (SLEEP, s) → (SKIP, s)"
| SleepV: "¬ can_sleep s ⟹ (SLEEP, s) → (ABORT, s)"
| SeqAbort: "(ABORT;;c, s) → (ABORT, s)"
definition good :: "'a com ⇒ bool"
where "⊨ c ≡ ∃l. ∀v. ¬(∃s. (c, (l, v)) →* (ABORT, s))"
```
so UB will stuck and atomic context violation will abort.
Alice suggested something that Gary thinks is similar to the one above, but swap the ABORT and stuck states?
## Miscellaneous
<!-- stuff that does not fit into other categories -->