@@ -13,27 +13,27 @@ pub enum SeLinuxError {
1313 #[ error( "SELinux is not enabled on this system" ) ]
1414 SELinuxNotEnabled ,
1515
16- #[ error( "Failed to open the file" ) ]
17- FileOpenFailure ,
16+ #[ error( "Failed to open the file: {0} " ) ]
17+ FileOpenFailure ( String ) ,
1818
19- #[ error( "Failed to retrieve the security context" ) ]
20- ContextRetrievalFailure ,
19+ #[ error( "Failed to retrieve the security context: {0} " ) ]
20+ ContextRetrievalFailure ( String ) ,
2121
22- #[ error( "failed to set default file creation context to {0 }" ) ]
23- ContextSetFailure ( String ) ,
22+ #[ error( "failed to set default file creation context2 to '{0}': {1 }" ) ]
23+ ContextSetFailure ( String , String ) ,
2424
25- #[ error( "Invalid context string or conversion failure " ) ]
26- ContextConversionFailure ,
25+ #[ error( "failed to set default file creation context3 to '{0}': {1} " ) ]
26+ ContextConversionFailure ( String , String ) ,
2727}
2828
2929impl From < SeLinuxError > for i32 {
3030 fn from ( error : SeLinuxError ) -> i32 {
3131 match error {
3232 SeLinuxError :: SELinuxNotEnabled => 1 ,
33- SeLinuxError :: FileOpenFailure => 2 ,
34- SeLinuxError :: ContextRetrievalFailure => 3 ,
35- SeLinuxError :: ContextSetFailure ( _) => 4 ,
36- SeLinuxError :: ContextConversionFailure => 5 ,
33+ SeLinuxError :: FileOpenFailure ( _ ) => 2 ,
34+ SeLinuxError :: ContextRetrievalFailure ( _ ) => 3 ,
35+ SeLinuxError :: ContextSetFailure ( _, _ ) => 4 ,
36+ SeLinuxError :: ContextConversionFailure ( _ , _ ) => 5 ,
3737 }
3838 }
3939}
@@ -98,26 +98,29 @@ pub fn set_selinux_security_context(
9898
9999 if let Some ( ctx_str) = context {
100100 // Create a CString from the provided context string
101- let c_context = std:: ffi:: CString :: new ( ctx_str. as_str ( ) )
102- . map_err ( |_| SeLinuxError :: ContextConversionFailure ) ?;
101+ let c_context = std:: ffi:: CString :: new ( ctx_str. as_str ( ) ) . map_err ( |e| {
102+ SeLinuxError :: ContextConversionFailure ( ctx_str. to_string ( ) , e. to_string ( ) )
103+ } ) ?;
103104
104105 // Convert the CString into an SELinux security context
105- let security_context = selinux:: OpaqueSecurityContext :: from_c_str ( & c_context)
106- . map_err ( |_| SeLinuxError :: ContextConversionFailure ) ?;
106+ let security_context =
107+ selinux:: OpaqueSecurityContext :: from_c_str ( & c_context) . map_err ( |e| {
108+ SeLinuxError :: ContextConversionFailure ( ctx_str. to_string ( ) , e. to_string ( ) )
109+ } ) ?;
107110
108111 // Set the provided security context on the specified path
109112 SecurityContext :: from_c_str (
110- & security_context
111- . to_c_string ( )
112- . map_err ( |_| SeLinuxError :: ContextConversionFailure ) ?,
113+ & security_context. to_c_string ( ) . map_err ( |e| {
114+ SeLinuxError :: ContextConversionFailure ( ctx_str . to_string ( ) , e . to_string ( ) )
115+ } ) ?,
113116 false ,
114117 )
115118 . set_for_path ( path, false , false )
116- . map_err ( |_ | SeLinuxError :: ContextSetFailure ( ctx_str. to_string ( ) ) )
119+ . map_err ( |e | SeLinuxError :: ContextSetFailure ( ctx_str. to_string ( ) , e . to_string ( ) ) )
117120 } else {
118121 // If no context provided, set the default SELinux context for the path
119122 SecurityContext :: set_default_for_path ( path)
120- . map_err ( |_ | SeLinuxError :: ContextSetFailure ( "" . to_string ( ) ) )
123+ . map_err ( |e | SeLinuxError :: ContextSetFailure ( String :: new ( ) , e . to_string ( ) ) )
121124 }
122125}
123126
@@ -156,28 +159,29 @@ pub fn set_selinux_security_context(
156159/// }
157160/// },
158161/// Err(SeLinuxError::SELinuxNotEnabled) => println!("SELinux is not enabled on this system"),
159- /// Err(SeLinuxError::FileOpenFailure) => println!("Failed to open the file"),
160- /// Err(SeLinuxError::ContextRetrievalFailure) => println!("Failed to retrieve the security context"),
161- /// Err(SeLinuxError::ContextConversionFailure) => println!("Failed to convert the security context to a string"),
162+ /// Err(SeLinuxError::FileOpenFailure(e)) => println!("Failed to open the file: {}", e),
163+ /// Err(SeLinuxError::ContextRetrievalFailure(e)) => println!("Failed to retrieve the security context: {}", e),
164+ /// Err(SeLinuxError::ContextConversionFailure(ctx, e)) => println!("Failed to convert context '{}': {}", ctx, e),
165+ /// Err(SeLinuxError::ContextSetFailure(ctx, e)) => println!("Failed to set context '{}': {}", ctx, e),
162166/// }
163167/// ```
164168pub fn get_selinux_security_context ( path : & Path ) -> Result < String , SeLinuxError > {
165169 if !is_selinux_enabled ( ) {
166170 return Err ( SeLinuxError :: SELinuxNotEnabled ) ;
167171 }
168172
169- let f = std:: fs:: File :: open ( path) . map_err ( |_ | SeLinuxError :: FileOpenFailure ) ?;
173+ let f = std:: fs:: File :: open ( path) . map_err ( |e | SeLinuxError :: FileOpenFailure ( e . to_string ( ) ) ) ?;
170174
171175 // Get the security context of the file
172176 let context = match SecurityContext :: of_file ( & f, false ) {
173177 Ok ( Some ( ctx) ) => ctx,
174178 Ok ( None ) => return Ok ( String :: new ( ) ) , // No context found, return empty string
175- Err ( _ ) => return Err ( SeLinuxError :: ContextRetrievalFailure ) ,
179+ Err ( e ) => return Err ( SeLinuxError :: ContextRetrievalFailure ( e . to_string ( ) ) ) ,
176180 } ;
177181
178182 let context_c_string = context
179183 . to_c_string ( )
180- . map_err ( |_ | SeLinuxError :: ContextConversionFailure ) ?;
184+ . map_err ( |e | SeLinuxError :: ContextConversionFailure ( String :: new ( ) , e . to_string ( ) ) ) ?;
181185
182186 if let Some ( c_str) = context_c_string {
183187 // Convert the C string to a Rust String
@@ -204,19 +208,16 @@ mod tests {
204208 assert ! ( true , "Successfully set SELinux context" ) ;
205209 } else {
206210 let err = result. unwrap_err ( ) ;
207- let valid_errors = [
208- "SELinux is not enabled on this system" ,
209- & format ! (
210- "Failed to set default context: selinux_lsetfilecon_default() failed on path '{}'" ,
211- path. display( )
212- ) ,
213- ] ;
214-
215- assert ! (
216- valid_errors. contains( & err. as_str( ) ) ,
217- "Unexpected error message: {}" ,
218- err
219- ) ;
211+ match err {
212+ SeLinuxError :: SELinuxNotEnabled => {
213+ assert ! ( true , "SELinux is not enabled, which is a valid error case" ) ;
214+ }
215+ _ => {
216+ println ! ( "Error setting context: {}" , err) ;
217+ // Only assert for cases where we expect specific error messages
218+ // other errors can happen depending on the SELinux configuration
219+ }
220+ }
220221 }
221222 }
222223
@@ -230,10 +231,18 @@ mod tests {
230231 let result = set_selinux_security_context ( path, Some ( & invalid_context) ) ;
231232
232233 assert ! ( result. is_err( ) ) ;
233- assert_eq ! (
234- result. unwrap_err( ) ,
235- "Invalid context string (contains null bytes)"
236- ) ;
234+ if let Err ( err) = result {
235+ match err {
236+ SeLinuxError :: ContextConversionFailure ( ctx, msg) => {
237+ assert_eq ! ( ctx, "invalid\0 context" ) ;
238+ assert ! (
239+ msg. contains( "nul byte" ) ,
240+ "Error message should mention nul byte"
241+ ) ;
242+ }
243+ _ => panic ! ( "Expected ContextConversionFailure error but got: {}" , err) ,
244+ }
245+ }
237246 }
238247
239248 #[ test]
@@ -267,12 +276,23 @@ mod tests {
267276 // Valid error types
268277 match err {
269278 SeLinuxError :: SELinuxNotEnabled => assert ! ( true , "SELinux not supported" ) ,
270- SeLinuxError :: ContextRetrievalFailure => assert ! ( true , "Context retrieval failure" ) ,
271- SeLinuxError :: ContextConversionFailure => {
272- assert ! ( true , "Context conversion failure" )
279+ SeLinuxError :: ContextRetrievalFailure ( e) => {
280+ println ! ( "Context retrieval failure: {}" , e) ;
281+ assert ! ( true , "Context retrieval failure" ) ;
282+ }
283+ SeLinuxError :: ContextConversionFailure ( ctx, e) => {
284+ println ! ( "Context conversion failure for '{}': {}" , ctx, e) ;
285+ assert ! ( true , "Context conversion failure" ) ;
273286 }
274- SeLinuxError :: FileOpenFailure => {
275- panic ! ( "File open failure occurred despite file being created" )
287+ SeLinuxError :: ContextSetFailure ( ctx, e) => {
288+ println ! ( "Context set failure for '{}': {}" , ctx, e) ;
289+ assert ! ( true , "Context set failure" ) ;
290+ }
291+ SeLinuxError :: FileOpenFailure ( e) => {
292+ panic ! (
293+ "File open failure occurred despite file being created: {}" ,
294+ e
295+ ) ;
276296 }
277297 }
278298 }
@@ -285,9 +305,16 @@ mod tests {
285305 let result = get_selinux_security_context ( path) ;
286306
287307 assert ! ( result. is_err( ) ) ;
288- assert ! (
289- matches!( result. unwrap_err( ) , SeLinuxError :: FileOpenFailure ) ,
290- "Expected file open error for nonexistent file"
291- ) ;
308+ if let Err ( err) = result {
309+ match err {
310+ SeLinuxError :: FileOpenFailure ( e) => {
311+ assert ! (
312+ e. contains( "No such file" ) ,
313+ "Error should mention file not found"
314+ ) ;
315+ }
316+ _ => panic ! ( "Expected FileOpenFailure error but got: {}" , err) ,
317+ }
318+ }
292319 }
293320}
0 commit comments