@@ -13,27 +13,27 @@ pub enum SeLinuxError {
13
13
#[ error( "SELinux is not enabled on this system" ) ]
14
14
SELinuxNotEnabled ,
15
15
16
- #[ error( "Failed to open the file" ) ]
17
- FileOpenFailure ,
16
+ #[ error( "Failed to open the file: {0} " ) ]
17
+ FileOpenFailure ( String ) ,
18
18
19
- #[ error( "Failed to retrieve the security context" ) ]
20
- ContextRetrievalFailure ,
19
+ #[ error( "Failed to retrieve the security context: {0} " ) ]
20
+ ContextRetrievalFailure ( String ) ,
21
21
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 ) ,
24
24
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 ) ,
27
27
}
28
28
29
29
impl From < SeLinuxError > for i32 {
30
30
fn from ( error : SeLinuxError ) -> i32 {
31
31
match error {
32
32
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 ,
37
37
}
38
38
}
39
39
}
@@ -98,26 +98,29 @@ pub fn set_selinux_security_context(
98
98
99
99
if let Some ( ctx_str) = context {
100
100
// 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
+ } ) ?;
103
104
104
105
// 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
+ } ) ?;
107
110
108
111
// Set the provided security context on the specified path
109
112
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
+ } ) ?,
113
116
false ,
114
117
)
115
118
. 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 ( ) ) )
117
120
} else {
118
121
// If no context provided, set the default SELinux context for the path
119
122
SecurityContext :: set_default_for_path ( path)
120
- . map_err ( |_ | SeLinuxError :: ContextSetFailure ( "" . to_string ( ) ) )
123
+ . map_err ( |e | SeLinuxError :: ContextSetFailure ( String :: new ( ) , e . to_string ( ) ) )
121
124
}
122
125
}
123
126
@@ -156,28 +159,29 @@ pub fn set_selinux_security_context(
156
159
/// }
157
160
/// },
158
161
/// 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),
162
166
/// }
163
167
/// ```
164
168
pub fn get_selinux_security_context ( path : & Path ) -> Result < String , SeLinuxError > {
165
169
if !is_selinux_enabled ( ) {
166
170
return Err ( SeLinuxError :: SELinuxNotEnabled ) ;
167
171
}
168
172
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 ( ) ) ) ?;
170
174
171
175
// Get the security context of the file
172
176
let context = match SecurityContext :: of_file ( & f, false ) {
173
177
Ok ( Some ( ctx) ) => ctx,
174
178
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 ( ) ) ) ,
176
180
} ;
177
181
178
182
let context_c_string = context
179
183
. to_c_string ( )
180
- . map_err ( |_ | SeLinuxError :: ContextConversionFailure ) ?;
184
+ . map_err ( |e | SeLinuxError :: ContextConversionFailure ( String :: new ( ) , e . to_string ( ) ) ) ?;
181
185
182
186
if let Some ( c_str) = context_c_string {
183
187
// Convert the C string to a Rust String
@@ -204,19 +208,16 @@ mod tests {
204
208
assert ! ( true , "Successfully set SELinux context" ) ;
205
209
} else {
206
210
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
+ }
220
221
}
221
222
}
222
223
@@ -230,10 +231,18 @@ mod tests {
230
231
let result = set_selinux_security_context ( path, Some ( & invalid_context) ) ;
231
232
232
233
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
+ }
237
246
}
238
247
239
248
#[ test]
@@ -267,12 +276,23 @@ mod tests {
267
276
// Valid error types
268
277
match err {
269
278
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" ) ;
273
286
}
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
+ ) ;
276
296
}
277
297
}
278
298
}
@@ -285,9 +305,16 @@ mod tests {
285
305
let result = get_selinux_security_context ( path) ;
286
306
287
307
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
+ }
292
319
}
293
320
}
0 commit comments