@@ -7,11 +7,13 @@ use crate::{
77} ;
88use core:: mem;
99use litebox:: utils:: TruncateExt ;
10+ use modular_bitfield:: Specifier ;
1011use num_enum:: TryFromPrimitive ;
1112use x86_64:: {
12- PhysAddr , VirtAddr ,
13+ PhysAddr ,
1314 structures:: paging:: { PageSize , Size4KiB } ,
1415} ;
16+ use zerocopy:: { FromBytes , Immutable , KnownLayout } ;
1517
1618bitflags:: bitflags! {
1719 #[ derive( Clone , Copy , Debug , PartialEq ) ]
@@ -42,8 +44,9 @@ pub(crate) fn mem_attr_to_hv_page_prot_flags(attr: MemAttr) -> HvPageProtFlags {
4244 flags
4345}
4446
45- #[ derive( Default , Debug , TryFromPrimitive , PartialEq ) ]
46- #[ repr( u64 ) ]
47+ #[ derive( Default , Debug , TryFromPrimitive , PartialEq , Specifier ) ]
48+ #[ bits = 16 ]
49+ #[ repr( u16 ) ]
4750pub enum HekiKdataType {
4851 SystemCerts = 0 ,
4952 RevocationCerts = 1 ,
@@ -52,22 +55,36 @@ pub enum HekiKdataType {
5255 KernelData = 4 ,
5356 PatchInfo = 5 ,
5457 KexecTrampoline = 6 ,
58+ SymbolInfo = 7 ,
59+ ModuleInfo = 8 ,
60+ PermInfo = 9 ,
61+ KexecInfo = 10 ,
62+ DataPage = 0xff ,
5563 #[ default]
56- Unknown = 0xffff_ffff_ffff_ffff ,
64+ Unknown = 0xffff ,
65+ }
66+
67+ #[ derive( Debug , TryFromPrimitive , PartialEq ) ]
68+ #[ repr( u16 ) ]
69+ pub enum HekiSymbolInfoType {
70+ SymbolTable = 0 ,
71+ GplSymbolTable = 1 ,
72+ SymbolStringTable = 2 ,
73+ Unknown = 0xffff ,
5774}
5875
5976#[ derive( Default , Debug , TryFromPrimitive , PartialEq ) ]
60- #[ repr( u64 ) ]
77+ #[ repr( u16 ) ]
6178pub enum HekiKexecType {
6279 KexecImage = 0 ,
6380 KexecKernelBlob = 1 ,
6481 KexecPages = 2 ,
6582 #[ default]
66- Unknown = 0xffff_ffff_ffff_ffff ,
83+ Unknown = 0xffff ,
6784}
6885
6986#[ derive( Clone , Copy , Default , Debug , TryFromPrimitive , PartialEq ) ]
70- #[ repr( u64 ) ]
87+ #[ repr( u16 ) ]
7188pub enum ModMemType {
7289 Text = 0 ,
7390 Data = 1 ,
@@ -79,7 +96,7 @@ pub enum ModMemType {
7996 ElfBuffer = 7 ,
8097 Patch = 8 ,
8198 #[ default]
82- Unknown = 0xffff_ffff_ffff_ffff ,
99+ Unknown = 0xffff ,
83100}
84101
85102pub ( crate ) fn mod_mem_type_to_mem_attr ( mod_mem_type : ModMemType ) -> MemAttr {
@@ -103,150 +120,6 @@ pub(crate) fn mod_mem_type_to_mem_attr(mod_mem_type: ModMemType) -> MemAttr {
103120 mem_attr
104121}
105122
106- /// `HekiRange` is a generic container for various types of memory ranges.
107- /// It has an `attributes` field which can be interpreted differently based on the context like
108- /// `MemAttr`, `KdataType`, `ModMemType`, or `KexecType`.
109- #[ derive( Default , Clone , Copy ) ]
110- #[ repr( C , packed) ]
111- pub struct HekiRange {
112- pub va : u64 ,
113- pub pa : u64 ,
114- pub epa : u64 ,
115- pub attributes : u64 ,
116- }
117-
118- impl HekiRange {
119- #[ inline]
120- pub fn is_aligned < U > ( & self , align : U ) -> bool
121- where
122- U : Into < u64 > + Copy ,
123- {
124- let va = self . va ;
125- let pa = self . pa ;
126- let epa = self . epa ;
127-
128- VirtAddr :: new ( va) . is_aligned ( align)
129- && PhysAddr :: new ( pa) . is_aligned ( align)
130- && PhysAddr :: new ( epa) . is_aligned ( align)
131- }
132-
133- #[ inline]
134- pub fn mem_attr ( & self ) -> Option < MemAttr > {
135- let attr = self . attributes ;
136- MemAttr :: from_bits ( attr)
137- }
138-
139- #[ inline]
140- pub fn mod_mem_type ( & self ) -> ModMemType {
141- let attr = self . attributes ;
142- ModMemType :: try_from ( attr) . unwrap_or ( ModMemType :: Unknown )
143- }
144-
145- #[ inline]
146- pub fn heki_kdata_type ( & self ) -> HekiKdataType {
147- let attr = self . attributes ;
148- HekiKdataType :: try_from ( attr) . unwrap_or ( HekiKdataType :: Unknown )
149- }
150-
151- #[ inline]
152- pub fn heki_kexec_type ( & self ) -> HekiKexecType {
153- let attr = self . attributes ;
154- HekiKexecType :: try_from ( attr) . unwrap_or ( HekiKexecType :: Unknown )
155- }
156-
157- pub fn is_valid ( & self ) -> bool {
158- let va = self . va ;
159- let pa = self . pa ;
160- let epa = self . epa ;
161- let Ok ( pa) = PhysAddr :: try_new ( pa) else {
162- return false ;
163- } ;
164- let Ok ( epa) = PhysAddr :: try_new ( epa) else {
165- return false ;
166- } ;
167- !( VirtAddr :: try_new ( va) . is_err ( )
168- || epa < pa
169- || ( self . mem_attr ( ) . is_none ( )
170- && self . heki_kdata_type ( ) == HekiKdataType :: Unknown
171- && self . heki_kexec_type ( ) == HekiKexecType :: Unknown
172- && self . mod_mem_type ( ) == ModMemType :: Unknown ) )
173- }
174- }
175-
176- impl core:: fmt:: Debug for HekiRange {
177- fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
178- let va = self . va ;
179- let pa = self . pa ;
180- let epa = self . epa ;
181- let attr = self . attributes ;
182- f. debug_struct ( "HekiRange" )
183- . field ( "va" , & format_args ! ( "{va:#x}" ) )
184- . field ( "pa" , & format_args ! ( "{pa:#x}" ) )
185- . field ( "epa" , & format_args ! ( "{epa:#x}" ) )
186- . field ( "attr" , & format_args ! ( "{attr:#x}" ) )
187- . field ( "type" , & format_args ! ( "{:?}" , self . heki_kdata_type( ) ) )
188- . field ( "size" , & format_args ! ( "{:?}" , self . epa - self . pa) )
189- . finish ( )
190- }
191- }
192-
193- #[ expect( clippy:: cast_possible_truncation) ]
194- pub const HEKI_MAX_RANGES : usize =
195- ( ( PAGE_SIZE as u32 - u64:: BITS * 3 / 8 ) / core:: mem:: size_of :: < HekiRange > ( ) as u32 ) as usize ;
196-
197- #[ derive( Clone , Copy ) ]
198- #[ repr( align( 4096 ) ) ]
199- #[ repr( C ) ]
200- pub struct HekiPage {
201- pub next : * mut HekiPage ,
202- pub next_pa : u64 ,
203- pub nranges : u64 ,
204- pub ranges : [ HekiRange ; HEKI_MAX_RANGES ] ,
205- pad : u64 ,
206- }
207-
208- impl HekiPage {
209- pub fn new ( ) -> Self {
210- HekiPage {
211- next : core:: ptr:: null_mut ( ) ,
212- ..Default :: default ( )
213- }
214- }
215-
216- pub fn is_valid ( & self ) -> bool {
217- if PhysAddr :: try_new ( self . next_pa ) . is_err ( ) {
218- return false ;
219- }
220- let Some ( nranges) = usize:: try_from ( self . nranges )
221- . ok ( )
222- . filter ( |& n| n <= HEKI_MAX_RANGES )
223- else {
224- return false ;
225- } ;
226- for heki_range in & self . ranges [ ..nranges] {
227- if !heki_range. is_valid ( ) {
228- return false ;
229- }
230- }
231- true
232- }
233- }
234-
235- impl Default for HekiPage {
236- fn default ( ) -> Self {
237- Self :: new ( )
238- }
239- }
240-
241- impl < ' a > IntoIterator for & ' a HekiPage {
242- type Item = & ' a HekiRange ;
243- type IntoIter = core:: slice:: Iter < ' a , HekiRange > ;
244-
245- fn into_iter ( self ) -> Self :: IntoIter {
246- self . ranges [ ..usize:: try_from ( self . nranges ) . unwrap_or ( 0 ) ] . iter ( )
247- }
248- }
249-
250123#[ derive( Default , Clone , Copy , Debug ) ]
251124#[ repr( C ) ]
252125pub struct HekiPatch {
@@ -304,12 +177,12 @@ impl HekiPatch {
304177 }
305178}
306179
307- #[ derive( Default , Clone , Copy , Debug , PartialEq ) ]
308- #[ repr( u32 ) ]
180+ #[ derive( Default , Clone , Copy , Debug , PartialEq , TryFromPrimitive ) ]
181+ #[ repr( u16 ) ]
309182pub enum HekiPatchType {
310183 JumpLabel = 0 ,
311184 #[ default]
312- Unknown = 0xffff_ffff ,
185+ Unknown = 0xffff ,
313186}
314187
315188#[ derive( Clone , Copy , Debug ) ]
@@ -348,6 +221,7 @@ impl HekiPatchInfo {
348221 }
349222}
350223
224+ #[ derive( FromBytes , KnownLayout , Immutable ) ]
351225#[ repr( C ) ]
352226#[ allow( clippy:: struct_field_names) ]
353227// TODO: Account for kernel config changing the size and meaning of the field members
@@ -380,37 +254,3 @@ impl HekiKernelSymbol {
380254 }
381255 }
382256}
383-
384- #[ repr( C ) ]
385- #[ allow( clippy:: struct_field_names) ]
386- pub struct HekiKernelInfo {
387- pub ksymtab_start : * const HekiKernelSymbol ,
388- pub ksymtab_end : * const HekiKernelSymbol ,
389- pub ksymtab_gpl_start : * const HekiKernelSymbol ,
390- pub ksymtab_gpl_end : * const HekiKernelSymbol ,
391- // Skip unused arch info
392- }
393-
394- impl HekiKernelInfo {
395- const KINFO_LEN : usize = mem:: size_of :: < HekiKernelInfo > ( ) ;
396-
397- pub fn from_bytes ( bytes : & [ u8 ] ) -> Result < Self , VsmError > {
398- if bytes. len ( ) < Self :: KINFO_LEN {
399- return Err ( VsmError :: BufferTooSmall ( "HekiKernelInfo" ) ) ;
400- }
401-
402- #[ allow( clippy:: cast_ptr_alignment) ]
403- let kinfo_ptr = bytes. as_ptr ( ) . cast :: < HekiKernelInfo > ( ) ;
404- assert ! ( kinfo_ptr. is_aligned( ) , "kinfo_ptr is not aligned" ) ;
405-
406- // SAFETY: Casting from vtl0 buffer that contained the struct
407- unsafe {
408- Ok ( HekiKernelInfo {
409- ksymtab_start : ( * kinfo_ptr) . ksymtab_start ,
410- ksymtab_end : ( * kinfo_ptr) . ksymtab_end ,
411- ksymtab_gpl_start : ( * kinfo_ptr) . ksymtab_gpl_start ,
412- ksymtab_gpl_end : ( * kinfo_ptr) . ksymtab_gpl_end ,
413- } )
414- }
415- }
416- }
0 commit comments