@@ -15,6 +15,8 @@ use std::collections::HashSet;
1515#[ cfg( not( any( target_os = "freebsd" , target_os = "windows" ) ) ) ]
1616use uutests:: at_and_ucmd;
1717use uutests:: new_ucmd;
18+ #[ cfg( target_os = "linux" ) ]
19+ use uutests:: util:: TestScenario ;
1820
1921#[ test]
2022fn test_invalid_arg ( ) {
@@ -1091,3 +1093,62 @@ fn test_df_hides_binfmt_misc_by_default() {
10911093 }
10921094 // If binfmt_misc is not mounted, skip the test silently
10931095}
1096+
1097+ /// Run df inside a mount namespace where /proc is masked with tmpfs.
1098+ /// Returns (success, stdout, stderr).
1099+ #[ cfg( target_os = "linux" ) ]
1100+ fn run_df_with_masked_proc ( args : & str ) -> Option < ( bool , String , String ) > {
1101+ use std:: process:: Command ;
1102+
1103+ // Check if user namespaces are available
1104+ if !Command :: new ( "unshare" )
1105+ . args ( [ "-rm" , "true" ] )
1106+ . status ( )
1107+ . is_ok_and ( |s| s. success ( ) )
1108+ {
1109+ return None ;
1110+ }
1111+
1112+ let df_path = TestScenario :: new ( "df" ) . bin_path . clone ( ) ;
1113+ let output = Command :: new ( "unshare" )
1114+ . args ( [ "-rm" , "sh" , "-c" ] )
1115+ . arg ( format ! (
1116+ "mount -t tmpfs tmpfs /proc && {} df {args}" ,
1117+ df_path. display( )
1118+ ) )
1119+ . output ( )
1120+ . ok ( ) ?;
1121+
1122+ Some ( (
1123+ output. status . success ( ) ,
1124+ String :: from_utf8_lossy ( & output. stdout ) . to_string ( ) ,
1125+ String :: from_utf8_lossy ( & output. stderr ) . to_string ( ) ,
1126+ ) )
1127+ }
1128+
1129+ /// Test df fallback when /proc is masked - should work with path, fail without or with filters.
1130+ #[ test]
1131+ #[ cfg( target_os = "linux" ) ]
1132+ fn test_df_masked_proc_fallback ( ) {
1133+ if let Some ( ( ok, stdout, stderr) ) = run_df_with_masked_proc ( "." ) {
1134+ assert ! ( ok, "df . should succeed: {stderr}" ) ;
1135+ assert ! ( stderr. contains( "cannot read table of mounted file systems" ) ) ;
1136+ assert ! ( stdout. contains( "Filesystem" ) ) ;
1137+ }
1138+
1139+ if let Some ( ( ok, _, _) ) = run_df_with_masked_proc ( "" ) {
1140+ assert ! ( !ok, "df without args should fail when /proc is masked" ) ;
1141+ }
1142+
1143+ for args in [ "-a ." , "-l ." , "-t ext4 ." , "-x tmpfs ." ] {
1144+ if let Some ( ( ok, _, _) ) = run_df_with_masked_proc ( args) {
1145+ assert ! ( !ok, "df {args} should fail when /proc is masked" ) ;
1146+ }
1147+ }
1148+
1149+ for args in [ "-i ." , "-T ." , "--total ." ] {
1150+ if let Some ( ( ok, _, stderr) ) = run_df_with_masked_proc ( args) {
1151+ assert ! ( ok, "df {args} should succeed: {stderr}" ) ;
1152+ }
1153+ }
1154+ }
0 commit comments