@@ -2,14 +2,12 @@ use crate::helpers::{
22 CheckGroup , CheckGroupCategory , CheckGroupResult , CheckResult ,
33 CheckResultValue :: { Errored , Failed , Passed } ,
44 host_executor:: HostNamespaceExecutor ,
5+ kernel as khelper,
56} ;
67
7- use anyhow:: { Result , bail} ;
88use async_trait:: async_trait;
99use futures:: { FutureExt , future:: join_all} ;
10- use log:: debug;
11- use procfs:: { Current , sys:: kernel} ;
12- use std:: { fs, path:: PathBuf , process:: Command } ;
10+ use procfs:: sys:: kernel;
1311
1412const GROUP_IDENTIFIER : & str = "byokernel" ;
1513const NAME : & str = "Bring-Your-Own Kernel Checks" ;
@@ -65,157 +63,54 @@ impl BYOKernelChecks {
6563
6664 async fn version_is_good ( & self ) -> CheckResult {
6765 let name = String :: from ( "Host Kernel Version Is Good" ) ;
68- let mut result = Passed ;
66+ let floor = kernel :: Version :: new ( KVER_FLOOR_MAJOR , KVER_FLOOR_MINOR , KVER_FLOOR_PATCH ) ;
6967
70- // Get host kernel version
71- let current = self
72- . host_executor
73- . spawn_in_host_ns ( async { kernel:: Version :: current ( ) } )
74- . await
75- . expect ( "error spawning in host" ) ;
68+ let passed = khelper:: host_kver_above_floor ( & self . host_executor , floor) . await ;
7669
77- if let Err ( e) = current {
78- return CheckResult :: new ( & name, Errored ( e. to_string ( ) ) ) ;
70+ match passed {
71+ Err ( e) => CheckResult :: new ( & name, Errored ( e. to_string ( ) ) ) ,
72+ Ok ( true ) => CheckResult :: new ( & name, Passed ) ,
73+ Ok ( false ) => CheckResult :: new (
74+ & name,
75+ Failed ( String :: from ( "current kernel version is unsupported" ) ) ,
76+ ) ,
7977 }
80- let current = current. unwrap ( ) ;
81- let lowest = kernel:: Version :: new ( KVER_FLOOR_MAJOR , KVER_FLOOR_MINOR , KVER_FLOOR_PATCH ) ;
82-
83- if current < lowest {
84- result = Failed ( String :: from ( "current kernel version is unsupported" ) ) ;
85- }
86- CheckResult :: new ( & name, result)
8778 }
8879
8980 async fn has_modules ( & self ) -> CheckResult {
9081 let name = String :: from ( "Host Has Necessary Modules" ) ;
91- let mut result = Passed ;
9282
9383 let required_modules: Vec < String > =
9484 REQUIRED_MODULES . iter ( ) . map ( |s| s. to_string ( ) ) . collect ( ) ;
9585
9686 // Search builtin modules
97- let remaining = match self . find_builtins ( & required_modules) . await {
87+ let remaining = match khelper :: find_builtins ( & self . host_executor , & required_modules) . await {
9888 Ok ( r) => r,
9989 Err ( e) => {
10090 return CheckResult :: new ( & name, Errored ( format ! ( "getting kernel builtins {e}" ) ) ) ;
10191 }
10292 } ;
10393
10494 // Search loaded modules
105- let remaining = match self . find_loaded ( & remaining) . await {
95+ let remaining = match khelper :: find_loaded ( & self . host_executor , & remaining) . await {
10696 Ok ( r) => r,
10797 Err ( e) => {
10898 return CheckResult :: new ( & name, Errored ( format ! ( "getting kernel modules {e}" ) ) ) ;
10999 }
110100 } ;
111101
112102 // Search loadable modules
113- let remaining = match self . find_loadable ( & remaining) . await {
103+ let remaining = match khelper :: find_loadable ( & self . host_executor , & remaining) . await {
114104 Ok ( r) => r,
115105 Err ( e) => {
116106 return CheckResult :: new ( & name, Errored ( format ! ( "getting kernel modules {e}" ) ) ) ;
117107 }
118108 } ;
119109 if !remaining. is_empty ( ) {
120- result = Failed ( format ! ( "missing {:?}" , remaining) )
121- }
122-
123- CheckResult :: new ( & name, result)
124- }
125-
126- /// Looks at builtins for kernel_version and compares that to the list of
127- /// required modules.
128- /// Returns a vec of everything from required_modules that WAS NOT found in builtins.
129- async fn find_builtins ( & self , required_modules : & [ String ] ) -> Result < Vec < String > > {
130- let mut modules_to_find: Vec < String > = required_modules. to_owned ( ) ;
131-
132- // read host builtins
133- let builtins = self
134- . host_executor
135- . spawn_in_host_ns ( async move {
136- // Get kernel version
137- let output = Command :: new ( "uname" ) . arg ( "-r" ) . output ( ) ?;
138-
139- if !output. status . success ( ) {
140- let error_message = String :: from_utf8_lossy ( & output. stderr ) ;
141- bail ! ( "{}" , error_message) ;
142- }
143- let kernel_version = String :: from_utf8_lossy ( & output. stdout ) . trim ( ) . to_string ( ) ;
144- let path = PathBuf :: from ( format ! ( "/lib/modules/{kernel_version}/modules.builtin" ) ) ;
145- fs:: read_to_string ( path) . map_err ( |e| anyhow:: anyhow!( e) )
146- } )
147- . await ??;
148-
149- for builtin in builtins. lines ( ) {
150- let found = modules_to_find
151- . iter ( )
152- . position ( |required| builtin. contains ( required) ) ;
153-
154- if let Some ( index) = found {
155- debug ! ( "builtin {}" , modules_to_find[ index] ) ;
156- modules_to_find. remove ( index) ;
157- }
158- }
159-
160- Ok ( modules_to_find)
161- }
162-
163- /// Looks at loaded modules for the current host kernel and compares that to the list of
164- /// required modules.
165- /// Returns a vec of everything from required_modules that WAS NOT loaded.
166- async fn find_loaded ( & self , required_modules : & [ String ] ) -> Result < Vec < String > > {
167- let mut modules_to_find: Vec < String > = required_modules. to_owned ( ) ;
168-
169- let modules = self
170- . host_executor
171- . spawn_in_host_ns ( async move { procfs:: KernelModules :: current ( ) } )
172- . await ?;
173-
174- let modules = modules. unwrap ( ) ;
175-
176- for ( name, _) in modules. 0 . iter ( ) {
177- let found = modules_to_find. iter ( ) . position ( |required| required == name) ;
178-
179- if let Some ( index) = found {
180- debug ! ( "module {}" , modules_to_find[ index] ) ;
181- modules_to_find. remove ( index) ;
182- }
110+ return CheckResult :: new ( & name, Failed ( format ! ( "missing {:?}" , remaining) ) ) ;
183111 }
184112
185- Ok ( modules_to_find)
186- }
187-
188- /// Looks at not-loaded-but-loadable modules for the current host kernel and compares
189- /// that to the list of required modules.
190- /// Returns a vec of everything from required_modules that is available to load (exists in
191- /// modules.dep) but is NOT currently loaded or builtin.
192- async fn find_loadable ( & self , required_modules : & [ String ] ) -> Result < Vec < String > > {
193- let mut modules_to_find: Vec < String > = required_modules. to_owned ( ) ;
194- let dep_file = self
195- . host_executor
196- . spawn_in_host_ns ( async move {
197- let output = Command :: new ( "uname" ) . arg ( "-r" ) . output ( ) ?;
198- if !output. status . success ( ) {
199- let error_message = String :: from_utf8_lossy ( & output. stderr ) ;
200- bail ! ( "{}" , error_message) ;
201- }
202- let kernel_version = String :: from_utf8_lossy ( & output. stdout ) . trim ( ) . to_string ( ) ;
203- let path = PathBuf :: from ( format ! ( "/lib/modules/{kernel_version}/modules.dep" ) ) ;
204- fs:: read_to_string ( path) . map_err ( |e| anyhow:: anyhow!( e) )
205- } )
206- . await ??;
207-
208- for line in dep_file. lines ( ) {
209- let module_path = line. split ( ':' ) . next ( ) . unwrap_or ( "" ) ;
210- let found = modules_to_find
211- . iter ( )
212- . position ( |required| module_path. contains ( required. as_str ( ) ) ) ;
213- if let Some ( index) = found {
214- debug ! ( "available {}" , modules_to_find[ index] ) ;
215- modules_to_find. remove ( index) ;
216- }
217- }
218- Ok ( modules_to_find)
113+ CheckResult :: new ( & name, Passed )
219114 }
220115}
221116
0 commit comments