File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 33// For the full copyright and license information, please view the LICENSE
44// file that was distributed with this source code.
55
6- // spell-checker:ignore memfd_create prefixcat rsplit testcat
6+ // spell-checker:ignore execveat fexecve memfd_create prefixcat rsplit testcat
77
88use std:: ffi:: { OsStr , OsString } ;
99use std:: io:: { Write , stderr} ;
@@ -102,10 +102,12 @@ pub fn binary_path(args: &mut impl Iterator<Item = OsString>) -> PathBuf {
102102 let exec_path = Path :: new ( OsStr :: from_bytes ( execfn_bytes) ) ;
103103 let argv0 = args. next ( ) . unwrap ( ) ;
104104 let mut shebang_buf = [ 0u8 ; 2 ] ;
105- // exec_path is wrong when called from shebang or memfd_create (/proc/self/fd/*)
105+ // exec_path is wrong when called from a shebang, or via fexecve/execveat:
106+ // the kernel reports /dev/fd/* and memfd_create/glibc's fallback /proc/self/fd/*
106107 // argv0 is not full-path when called from PATH
107108 if execfn_bytes. rsplit ( |& b| b == b'/' ) . next ( ) == argv0. as_bytes ( ) . rsplit ( |& b| b == b'/' ) . next ( )
108109 || execfn_bytes. starts_with ( b"/proc/" )
110+ || execfn_bytes. starts_with ( b"/dev/fd/" )
109111 || ( File :: open ( Path :: new ( exec_path) )
110112 . and_then ( |mut f| f. read_exact ( & mut shebang_buf) )
111113 . is_ok ( )
Original file line number Diff line number Diff line change @@ -43,6 +43,36 @@ fn binary_name_protection() {
4343 . stdout_contains ( "coreutils" ) ;
4444}
4545
46+ // missing /proc/self/fd on Android?
47+ #[ test]
48+ #[ cfg( all( feature = "true" , target_os = "linux" , target_env = "gnu" ) ) ]
49+ fn binary_name_execfn_fallback ( ) {
50+ use std:: os:: { fd:: AsRawFd , unix:: process:: CommandExt } ;
51+ use std:: process:: Command ;
52+ let ts = TestScenario :: new ( "true" ) ;
53+ let fd = rustix:: fs:: memfd_create ( "a" , rustix:: fs:: MemfdFlags :: empty ( ) ) . unwrap ( ) ;
54+ let mut file = std:: fs:: File :: from ( fd) ;
55+ let mut source = std:: fs:: File :: open ( & ts. bin_path ) . unwrap ( ) ;
56+ std:: io:: copy ( & mut source, & mut file) . unwrap ( ) ;
57+ let raw_fd = file. as_raw_fd ( ) ;
58+
59+ // memfd has AT_EXECFN as below. Fallback to argv[0]
60+ let res1 = Command :: new ( format ! ( "/proc/self/fd/{raw_fd}" ) )
61+ . arg0 ( "true" )
62+ . output ( )
63+ . unwrap ( )
64+ . status
65+ . success ( ) ;
66+ // fexecve uses /dev/fd which is symlink to /proc/self/fd/N
67+ let res2 = Command :: new ( format ! ( "/dev/fd/{raw_fd}" ) )
68+ . arg0 ( "true" )
69+ . output ( )
70+ . unwrap ( )
71+ . status
72+ . success ( ) ;
73+ assert ! ( res1 && res2) ;
74+ }
75+
4676#[ test]
4777fn test_coreutils_help_ignore_args ( ) {
4878 let scenario = TestScenario :: new ( "help_ignoring_args" ) ;
You can’t perform that action at this time.
0 commit comments