mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 11:07:44 +00:00
selinux: improve the error display
This commit is contained in:
parent
832dd495bf
commit
fde3733bf5
2 changed files with 47 additions and 15 deletions
|
@ -3,6 +3,7 @@
|
||||||
// For the full copyright and license information, please view the LICENSE
|
// For the full copyright and license information, please view the LICENSE
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use selinux::SecurityContext;
|
use selinux::SecurityContext;
|
||||||
|
@ -45,6 +46,22 @@ pub fn is_selinux_enabled() -> bool {
|
||||||
selinux::kernel_support() != selinux::KernelSupport::Unsupported
|
selinux::kernel_support() != selinux::KernelSupport::Unsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a string describing the error and its causes.
|
||||||
|
fn selinux_error_description(mut error: &dyn Error) -> String {
|
||||||
|
let mut description = String::new();
|
||||||
|
while let Some(source) = error.source() {
|
||||||
|
let error_text = source.to_string();
|
||||||
|
// Check if this is an OS error and trim it
|
||||||
|
if let Some(idx) = error_text.find(" (os error ") {
|
||||||
|
description.push_str(&error_text[..idx]);
|
||||||
|
} else {
|
||||||
|
description.push_str(&error_text);
|
||||||
|
}
|
||||||
|
error = source;
|
||||||
|
}
|
||||||
|
description
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets the SELinux security context for the given filesystem path.
|
/// Sets the SELinux security context for the given filesystem path.
|
||||||
///
|
///
|
||||||
/// If a specific context is provided, it attempts to set this context explicitly.
|
/// If a specific context is provided, it attempts to set this context explicitly.
|
||||||
|
@ -99,28 +116,40 @@ pub fn set_selinux_security_context(
|
||||||
if let Some(ctx_str) = context {
|
if let Some(ctx_str) = context {
|
||||||
// Create a CString from the provided context string
|
// Create a CString from the provided context string
|
||||||
let c_context = std::ffi::CString::new(ctx_str.as_str()).map_err(|e| {
|
let c_context = std::ffi::CString::new(ctx_str.as_str()).map_err(|e| {
|
||||||
SeLinuxError::ContextConversionFailure(ctx_str.to_string(), e.to_string())
|
SeLinuxError::ContextConversionFailure(
|
||||||
|
ctx_str.to_string(),
|
||||||
|
selinux_error_description(&e),
|
||||||
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Convert the CString into an SELinux security context
|
// Convert the CString into an SELinux security context
|
||||||
let security_context =
|
let security_context =
|
||||||
selinux::OpaqueSecurityContext::from_c_str(&c_context).map_err(|e| {
|
selinux::OpaqueSecurityContext::from_c_str(&c_context).map_err(|e| {
|
||||||
SeLinuxError::ContextConversionFailure(ctx_str.to_string(), e.to_string())
|
SeLinuxError::ContextConversionFailure(
|
||||||
|
ctx_str.to_string(),
|
||||||
|
selinux_error_description(&e),
|
||||||
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Set the provided security context on the specified path
|
// Set the provided security context on the specified path
|
||||||
SecurityContext::from_c_str(
|
SecurityContext::from_c_str(
|
||||||
&security_context.to_c_string().map_err(|e| {
|
&security_context.to_c_string().map_err(|e| {
|
||||||
SeLinuxError::ContextConversionFailure(ctx_str.to_string(), e.to_string())
|
SeLinuxError::ContextConversionFailure(
|
||||||
|
ctx_str.to_string(),
|
||||||
|
selinux_error_description(&e),
|
||||||
|
)
|
||||||
})?,
|
})?,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.set_for_path(path, false, false)
|
.set_for_path(path, false, false)
|
||||||
.map_err(|e| SeLinuxError::ContextSetFailure(ctx_str.to_string(), e.to_string()))
|
.map_err(|e| {
|
||||||
|
SeLinuxError::ContextSetFailure(ctx_str.to_string(), selinux_error_description(&e))
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
// If no context provided, set the default SELinux context for the path
|
// If no context provided, set the default SELinux context for the path
|
||||||
SecurityContext::set_default_for_path(path)
|
SecurityContext::set_default_for_path(path).map_err(|e| {
|
||||||
.map_err(|e| SeLinuxError::ContextSetFailure(String::new(), e.to_string()))
|
SeLinuxError::ContextSetFailure(String::new(), selinux_error_description(&e))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,18 +200,23 @@ pub fn get_selinux_security_context(path: &Path) -> Result<String, SeLinuxError>
|
||||||
return Err(SeLinuxError::SELinuxNotEnabled);
|
return Err(SeLinuxError::SELinuxNotEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
let f = std::fs::File::open(path).map_err(|e| SeLinuxError::FileOpenFailure(e.to_string()))?;
|
let f = std::fs::File::open(path)
|
||||||
|
.map_err(|e| SeLinuxError::FileOpenFailure(selinux_error_description(&e)))?;
|
||||||
|
|
||||||
// Get the security context of the file
|
// Get the security context of the file
|
||||||
let context = match SecurityContext::of_file(&f, false) {
|
let context = match SecurityContext::of_file(&f, false) {
|
||||||
Ok(Some(ctx)) => ctx,
|
Ok(Some(ctx)) => ctx,
|
||||||
Ok(None) => return Ok(String::new()), // No context found, return empty string
|
Ok(None) => return Ok(String::new()), // No context found, return empty string
|
||||||
Err(e) => return Err(SeLinuxError::ContextRetrievalFailure(e.to_string())),
|
Err(e) => {
|
||||||
|
return Err(SeLinuxError::ContextRetrievalFailure(
|
||||||
|
selinux_error_description(&e),
|
||||||
|
));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let context_c_string = context
|
let context_c_string = context.to_c_string().map_err(|e| {
|
||||||
.to_c_string()
|
SeLinuxError::ContextConversionFailure(String::new(), selinux_error_description(&e))
|
||||||
.map_err(|e| SeLinuxError::ContextConversionFailure(String::new(), e.to_string()))?;
|
})?;
|
||||||
|
|
||||||
if let Some(c_str) = context_c_string {
|
if let Some(c_str) = context_c_string {
|
||||||
// Convert the C string to a Rust String
|
// Convert the C string to a Rust String
|
||||||
|
@ -336,7 +370,8 @@ mod tests {
|
||||||
println!("Context conversion failure for '{}': {}", ctx, e);
|
println!("Context conversion failure for '{}': {}", ctx, e);
|
||||||
}
|
}
|
||||||
SeLinuxError::ContextSetFailure(ctx, e) => {
|
SeLinuxError::ContextSetFailure(ctx, e) => {
|
||||||
assert!(false);
|
assert!(!e.is_empty(), "Error message should not be empty");
|
||||||
|
println!("Context conversion failure for '{}': {}", ctx, e);
|
||||||
}
|
}
|
||||||
SeLinuxError::FileOpenFailure(e) => {
|
SeLinuxError::FileOpenFailure(e) => {
|
||||||
assert!(
|
assert!(
|
||||||
|
|
|
@ -351,6 +351,3 @@ sed -i 's/\/usr\/bin\/tr/$(which tr)/' tests/init.sh
|
||||||
# upstream doesn't having the program name in the error message
|
# upstream doesn't having the program name in the error message
|
||||||
# but we do. We should keep it that way.
|
# but we do. We should keep it that way.
|
||||||
sed -i 's/echo "changing security context/echo "chcon: changing security context/' tests/chcon/chcon.sh
|
sed -i 's/echo "changing security context/echo "chcon: changing security context/' tests/chcon/chcon.sh
|
||||||
|
|
||||||
# we produce a different error message
|
|
||||||
sed -i -e "s|-e 's/ Not supported$//'|-e 's/ context_new() failed$//'|g" tests/mkdir/selinux.sh
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue