Skip to content

Commit fde3733

Browse files
committed
selinux: improve the error display
1 parent 832dd49 commit fde3733

File tree

2 files changed

+47
-15
lines changed

2 files changed

+47
-15
lines changed

src/uucore/src/lib/features/selinux.rs

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6+
use std::error::Error;
67
use std::path::Path;
78

89
use selinux::SecurityContext;
@@ -45,6 +46,22 @@ pub fn is_selinux_enabled() -> bool {
4546
selinux::kernel_support() != selinux::KernelSupport::Unsupported
4647
}
4748

49+
/// Returns a string describing the error and its causes.
50+
fn selinux_error_description(mut error: &dyn Error) -> String {
51+
let mut description = String::new();
52+
while let Some(source) = error.source() {
53+
let error_text = source.to_string();
54+
// Check if this is an OS error and trim it
55+
if let Some(idx) = error_text.find(" (os error ") {
56+
description.push_str(&error_text[..idx]);
57+
} else {
58+
description.push_str(&error_text);
59+
}
60+
error = source;
61+
}
62+
description
63+
}
64+
4865
/// Sets the SELinux security context for the given filesystem path.
4966
///
5067
/// If a specific context is provided, it attempts to set this context explicitly.
@@ -99,28 +116,40 @@ pub fn set_selinux_security_context(
99116
if let Some(ctx_str) = context {
100117
// Create a CString from the provided context string
101118
let c_context = std::ffi::CString::new(ctx_str.as_str()).map_err(|e| {
102-
SeLinuxError::ContextConversionFailure(ctx_str.to_string(), e.to_string())
119+
SeLinuxError::ContextConversionFailure(
120+
ctx_str.to_string(),
121+
selinux_error_description(&e),
122+
)
103123
})?;
104124

105125
// Convert the CString into an SELinux security context
106126
let security_context =
107127
selinux::OpaqueSecurityContext::from_c_str(&c_context).map_err(|e| {
108-
SeLinuxError::ContextConversionFailure(ctx_str.to_string(), e.to_string())
128+
SeLinuxError::ContextConversionFailure(
129+
ctx_str.to_string(),
130+
selinux_error_description(&e),
131+
)
109132
})?;
110133

111134
// Set the provided security context on the specified path
112135
SecurityContext::from_c_str(
113136
&security_context.to_c_string().map_err(|e| {
114-
SeLinuxError::ContextConversionFailure(ctx_str.to_string(), e.to_string())
137+
SeLinuxError::ContextConversionFailure(
138+
ctx_str.to_string(),
139+
selinux_error_description(&e),
140+
)
115141
})?,
116142
false,
117143
)
118144
.set_for_path(path, false, false)
119-
.map_err(|e| SeLinuxError::ContextSetFailure(ctx_str.to_string(), e.to_string()))
145+
.map_err(|e| {
146+
SeLinuxError::ContextSetFailure(ctx_str.to_string(), selinux_error_description(&e))
147+
})
120148
} else {
121149
// If no context provided, set the default SELinux context for the path
122-
SecurityContext::set_default_for_path(path)
123-
.map_err(|e| SeLinuxError::ContextSetFailure(String::new(), e.to_string()))
150+
SecurityContext::set_default_for_path(path).map_err(|e| {
151+
SeLinuxError::ContextSetFailure(String::new(), selinux_error_description(&e))
152+
})
124153
}
125154
}
126155

@@ -171,18 +200,23 @@ pub fn get_selinux_security_context(path: &Path) -> Result<String, SeLinuxError>
171200
return Err(SeLinuxError::SELinuxNotEnabled);
172201
}
173202

174-
let f = std::fs::File::open(path).map_err(|e| SeLinuxError::FileOpenFailure(e.to_string()))?;
203+
let f = std::fs::File::open(path)
204+
.map_err(|e| SeLinuxError::FileOpenFailure(selinux_error_description(&e)))?;
175205

176206
// Get the security context of the file
177207
let context = match SecurityContext::of_file(&f, false) {
178208
Ok(Some(ctx)) => ctx,
179209
Ok(None) => return Ok(String::new()), // No context found, return empty string
180-
Err(e) => return Err(SeLinuxError::ContextRetrievalFailure(e.to_string())),
210+
Err(e) => {
211+
return Err(SeLinuxError::ContextRetrievalFailure(
212+
selinux_error_description(&e),
213+
));
214+
}
181215
};
182216

183-
let context_c_string = context
184-
.to_c_string()
185-
.map_err(|e| SeLinuxError::ContextConversionFailure(String::new(), e.to_string()))?;
217+
let context_c_string = context.to_c_string().map_err(|e| {
218+
SeLinuxError::ContextConversionFailure(String::new(), selinux_error_description(&e))
219+
})?;
186220

187221
if let Some(c_str) = context_c_string {
188222
// Convert the C string to a Rust String
@@ -336,7 +370,8 @@ mod tests {
336370
println!("Context conversion failure for '{}': {}", ctx, e);
337371
}
338372
SeLinuxError::ContextSetFailure(ctx, e) => {
339-
assert!(false);
373+
assert!(!e.is_empty(), "Error message should not be empty");
374+
println!("Context conversion failure for '{}': {}", ctx, e);
340375
}
341376
SeLinuxError::FileOpenFailure(e) => {
342377
assert!(

util/build-gnu.sh

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,3 @@ sed -i 's/\/usr\/bin\/tr/$(which tr)/' tests/init.sh
351351
# upstream doesn't having the program name in the error message
352352
# but we do. We should keep it that way.
353353
sed -i 's/echo "changing security context/echo "chcon: changing security context/' tests/chcon/chcon.sh
354-
355-
# we produce a different error message
356-
sed -i -e "s|-e 's/ Not supported$//'|-e 's/ context_new() failed$//'|g" tests/mkdir/selinux.sh

0 commit comments

Comments
 (0)