Skip to content

Commit 19fa3ff

Browse files
verification: add NonNull<T> specification for Verus
Recent changes introduced NonNull<T> usage in SlabPage and VirtAddr, which caused Verus verification to fail because NonNull is not supported by default in Verus. Add external type specification for core::ptr::NonNull<T> following the vstd pattern used for similar types like ManuallyDrop. The spec uses accept_recursive_types to allow self-referential structures like SlabPage, and provides an assume_specification for as_ptr with a non-null guarantee. Also mark From<NonNull<T>> for VirtAddr as external_body and fix the allocate_slab_page spec to reference the const generic N instead of the undefined variable item_size. Closes coconut-svsm#938 Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
1 parent 697e6c5 commit 19fa3ff

5 files changed

Lines changed: 45 additions & 2 deletions

File tree

kernel/src/address.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ impl<T> From<*mut T> for VirtAddr {
527527

528528
#[verus_verify]
529529
impl<T> From<NonNull<T>> for VirtAddr {
530-
#[verus_verify]
530+
#[verus_verify(external_body)]
531531
#[inline]
532532
fn from(value: NonNull<T>) -> Self {
533533
Self::from(value.as_ptr())

kernel/src/mm/alloc.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1029,9 +1029,10 @@ impl HeapMemoryRegion {
10291029
with Tracked(perm): Tracked<&mut Option<UnitDeallocPerm>>
10301030
requires
10311031
old(self).wf_next_pages(),
1032+
N as u64 <= PageStorageType::SLAB_MASK,
10321033
ensures
10331034
old(self).ens_allocate_pages_info(self, 0, PageInfo::Slab(SlabPageInfo {
1034-
item_size: item_size as u64,
1035+
item_size: N as u64,
10351036
}) , ret, *perm),
10361037
)]
10371038
fn allocate_slab_page<const N: usize>(&mut self) -> Result<VirtAddr, AllocError> {

verification/verify_external/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@
1414
#![no_std]
1515
#![allow(unused_braces)]
1616
#![allow(unexpected_cfgs)]
17+
#![cfg_attr(verus_keep_ghost, feature(sized_hierarchy))]
1718

1819
// Add spec for convert traits
1920
pub mod convert;
2021

2122
pub mod hw_spec;
2223

24+
pub mod nonnull;
25+
2326
pub mod ptr;
2427

2528
use verus_builtin_macros::*;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
3+
#[cfg(verus_keep_ghost)]
4+
include!("nonnull.verus.rs");
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
use core::ptr::NonNull;
3+
use vstd::prelude::*;
4+
use vstd::raw_ptr::*;
5+
6+
verus! {
7+
8+
/// External type specification for core::ptr::NonNull<T>
9+
///
10+
/// We use both external_type_specification and external_body because NonNull
11+
/// has private fields which are not supported for transparent datatypes.
12+
/// This pattern is used in vstd for similar types like ManuallyDrop.
13+
///
14+
/// We use accept_recursive_types to allow types like SlabPage that have
15+
/// Option<NonNull<Self>> fields to be verified.
16+
#[allow(missing_debug_implementations)]
17+
#[verifier::external_type_specification]
18+
#[verifier::external_body]
19+
#[verifier::accept_recursive_types(T)]
20+
pub struct ExNonNull<T: core::marker::PointeeSized>(NonNull<T>);
21+
22+
/// Specification for NonNull::as_ptr
23+
///
24+
/// Returns the underlying raw pointer. The returned pointer is guaranteed
25+
/// to be non-null (addr != 0).
26+
pub assume_specification<T: core::marker::PointeeSized>[ NonNull::<T>::as_ptr ](
27+
self_: NonNull<T>,
28+
) -> (ret: *mut T)
29+
ensures
30+
ret@.addr != 0,
31+
opens_invariants none
32+
no_unwind
33+
;
34+
35+
} // verus!

0 commit comments

Comments
 (0)