@@ -182,7 +182,7 @@ pub fn set_selinux_security_context(
182182/// use uucore::selinux::{get_selinux_security_context, SeLinuxError};
183183///
184184/// // Get the SELinux context for a file
185- /// match get_selinux_security_context(Path::new("/path/to/file")) {
185+ /// match get_selinux_security_context(Path::new("/path/to/file"), false ) {
186186/// Ok(context) => {
187187/// if context.is_empty() {
188188/// println!("No SELinux context found for the file");
@@ -197,16 +197,16 @@ pub fn set_selinux_security_context(
197197/// Err(SeLinuxError::ContextSetFailure(ctx, e)) => println!("Failed to set context '{ctx}': {e}"),
198198/// }
199199/// ```
200- pub fn get_selinux_security_context ( path : & Path ) -> Result < String , SeLinuxError > {
200+ pub fn get_selinux_security_context (
201+ path : & Path ,
202+ follow_symbolic_links : bool ,
203+ ) -> Result < String , SeLinuxError > {
201204 if !is_selinux_enabled ( ) {
202205 return Err ( SeLinuxError :: SELinuxNotEnabled ) ;
203206 }
204207
205- let f = std:: fs:: File :: open ( path)
206- . map_err ( |e| SeLinuxError :: FileOpenFailure ( selinux_error_description ( & e) ) ) ?;
207-
208208 // Get the security context of the file
209- let context = match SecurityContext :: of_file ( & f , false ) {
209+ let context = match SecurityContext :: of_path ( path , follow_symbolic_links , false ) {
210210 Ok ( Some ( ctx) ) => ctx,
211211 Ok ( None ) => return Ok ( String :: new ( ) ) , // No context found, return empty string
212212 Err ( e) => {
@@ -317,7 +317,7 @@ pub fn preserve_security_context(from_path: &Path, to_path: &Path) -> Result<(),
317317 }
318318
319319 // Get context from the source path
320- let context = get_selinux_security_context ( from_path) ?;
320+ let context = get_selinux_security_context ( from_path, false ) ?;
321321
322322 // If no context was found, just return success (nothing to preserve)
323323 if context. is_empty ( ) {
@@ -357,7 +357,7 @@ mod tests {
357357 default_result. err( )
358358 ) ;
359359
360- let context = get_selinux_security_context ( path) . expect ( "Failed to get context" ) ;
360+ let context = get_selinux_security_context ( path, false ) . expect ( "Failed to get context" ) ;
361361 assert ! (
362362 !context. is_empty( ) ,
363363 "Expected non-empty context after setting default context"
@@ -367,7 +367,7 @@ mod tests {
367367 let explicit_result = set_selinux_security_context ( path, Some ( & test_context) ) ;
368368
369369 if explicit_result. is_ok ( ) {
370- let new_context = get_selinux_security_context ( path)
370+ let new_context = get_selinux_security_context ( path, false )
371371 . expect ( "Failed to get context after setting explicit context" ) ;
372372
373373 assert ! (
@@ -420,7 +420,7 @@ mod tests {
420420 }
421421 std:: fs:: write ( path, b"test content" ) . expect ( "Failed to write to tempfile" ) ;
422422
423- let result = get_selinux_security_context ( path) ;
423+ let result = get_selinux_security_context ( path, false ) ;
424424
425425 if result. is_ok ( ) {
426426 let context = result. unwrap ( ) ;
@@ -484,11 +484,70 @@ mod tests {
484484 println ! ( "test skipped: Kernel has no support for SElinux context" ) ;
485485 return ;
486486 }
487- let result = get_selinux_security_context ( path) ;
487+ let result = get_selinux_security_context ( path, false ) ;
488488
489489 assert ! ( result. is_err( ) ) ;
490490 }
491491
492+ #[ test]
493+ fn test_get_selinux_context_symlink ( ) {
494+ use std:: os:: unix:: fs:: symlink;
495+ use tempfile:: tempdir;
496+
497+ if !is_selinux_enabled ( ) {
498+ println ! ( "test skipped: Kernel has no support for SElinux context" ) ;
499+ return ;
500+ }
501+
502+ let tmp_dir = tempdir ( ) . expect ( "Failed to create temporary directory" ) ;
503+ let dir_path = tmp_dir. path ( ) ;
504+
505+ // Create a normal file
506+ let file_path = dir_path. join ( "file" ) ;
507+ std:: fs:: File :: create ( & file_path) . expect ( "Failed to create file" ) ;
508+
509+ // Create a symlink to the file
510+ let symlink_path = dir_path. join ( "symlink" ) ;
511+ symlink ( & file_path, & symlink_path) . expect ( "Failed to create symlink" ) ;
512+
513+ // Set a different context for the file (but not the symlink)
514+ let file_context = String :: from ( "system_u:object_r:user_tmp_t:s0" ) ;
515+ set_selinux_security_context ( & file_path, Some ( & file_context) )
516+ . expect ( "Failed to set security context." ) ;
517+
518+ // Context must be different if we don't follow the link
519+ let file_context = get_selinux_security_context ( & file_path, false )
520+ . expect ( "Failed to get security context." ) ;
521+ let symlink_context = get_selinux_security_context ( & symlink_path, false )
522+ . expect ( "Failed to get security context." ) ;
523+ assert_ne ! ( file_context. to_string( ) , symlink_context. to_string( ) ) ;
524+
525+ // Context must be the same if we follow the link
526+ let symlink_follow_context = get_selinux_security_context ( & symlink_path, true )
527+ . expect ( "Failed to get security context." ) ;
528+ assert_eq ! ( file_context. to_string( ) , symlink_follow_context. to_string( ) ) ;
529+ }
530+
531+ #[ test]
532+ fn test_get_selinux_context_fifo ( ) {
533+ use tempfile:: tempdir;
534+
535+ if !is_selinux_enabled ( ) {
536+ println ! ( "test skipped: Kernel has no support for SElinux context" ) ;
537+ return ;
538+ }
539+
540+ let tmp_dir = tempdir ( ) . expect ( "Failed to create temporary directory" ) ;
541+ let dir_path = tmp_dir. path ( ) ;
542+
543+ // Create a FIFO (pipe)
544+ let fifo_path = dir_path. join ( "my_fifo" ) ;
545+ crate :: fs:: make_fifo ( & fifo_path) . expect ( "Failed to create FIFO" ) ;
546+
547+ // Just getting a context is good enough
548+ get_selinux_security_context ( & fifo_path, false ) . expect ( "Cannot get fifo context" ) ;
549+ }
550+
492551 #[ test]
493552 fn test_contexts_differ ( ) {
494553 let file1 = NamedTempFile :: new ( ) . expect ( "Failed to create first tempfile" ) ;
0 commit comments