@@ -164,6 +164,7 @@ fn main() {
164164 let mut args: Args ;
165165
166166 let is_child = get_env_var ( "ULEXEC_CHILD" ) == "1" ;
167+
167168 #[ cfg( target_os = "windows" ) ]
168169 {
169170 if is_child {
@@ -235,12 +236,11 @@ fn main() {
235236 exec_file = data;
236237 #[ cfg( target_os = "linux" ) ]
237238 if args. reexec && is_child {
238- let _ = std:: fs:: remove_file ( & file_path) ;
239239 file_path = PathBuf :: new ( ) ;
240+ env:: remove_var ( "ULEXEC_URL" ) ;
241+ env:: remove_var ( "ULEXEC_FILE" ) ;
240242 env:: remove_var ( "ULEXEC_CHILD" ) ;
241243 env:: remove_var ( "ULEXEC_REEXEC" ) ;
242- env:: remove_var ( "ULEXEC_FILE" ) ;
243- env:: remove_var ( "ULEXEC_URL" ) ;
244244 }
245245 }
246246 Err ( err) => {
@@ -277,11 +277,15 @@ fn main() {
277277 #[ cfg( target_os = "linux" ) ]
278278 {
279279 use std:: time;
280+ use std:: process;
281+ use std:: fs:: File ;
280282 use std:: ffi:: CString ;
281283 use std:: os:: fd:: AsRawFd ;
282- use nix:: unistd:: { write, close} ;
283284 use std:: thread:: { spawn, sleep} ;
285+
286+ use nix:: sys:: stat:: Mode ;
284287 use goblin:: elf:: { Elf , program_header} ;
288+ use nix:: unistd:: { write, close, mkfifo} ;
285289 use memfd_exec:: { Stdio , MemFdExecutable } ;
286290 use nix:: sys:: memfd:: { memfd_create, MemFdCreateFlag } ;
287291
@@ -301,23 +305,55 @@ fn main() {
301305 }
302306 }
303307
304- if args. reexec && !is_child {
305- let tmp_file = env:: temp_dir ( ) . join ( std:: process:: id ( ) . to_string ( ) ) ;
306- match std:: fs:: File :: create ( tmp_file. clone ( ) ) {
307- Ok ( mut file) => {
308- if let Err ( err) = file. write_all ( & exec_file) {
309- eprintln ! ( "Failed to write the binary file: {err}: {:?}" , file_path) ;
308+ fn ul_exec ( file_path : PathBuf , exec_args : Vec < String > ) {
309+ let mut args_cstrs: Vec < CString > = exec_args. iter ( )
310+ . map ( |arg|
311+ CString :: new ( arg. clone ( ) ) . unwrap ( )
312+ ) . collect ( ) ;
313+
314+ let file_cstr = CString :: new (
315+ file_path. to_str ( ) . unwrap ( )
316+ ) . unwrap ( ) ;
317+ args_cstrs. insert ( 0 , file_cstr) ;
318+
319+ let envs: Vec < CString > = env:: vars ( )
320+ . map ( |( key, value) |
321+ CString :: new ( format ! ( "{}={}" , key, value) ) . unwrap ( )
322+ ) . collect ( ) ;
323+
324+ userland_execve:: exec (
325+ & file_path,
326+ & args_cstrs,
327+ & envs,
328+ )
329+ }
330+
331+ if args. reexec && !is_child && !args. mfdexec {
332+ let fifo_path = & env:: temp_dir ( ) . join ( process:: id ( ) . to_string ( ) ) ;
333+ if let Err ( err) = mkfifo ( fifo_path, Mode :: S_IRWXU ) {
334+ eprintln ! ( "Failed to create fifo: {err}: {:?}" , fifo_path) ;
335+ exit ( 1 )
336+ }
337+ env:: set_var ( "ULEXEC_CHILD" , "1" ) ;
338+ env:: set_var ( "ULEXEC_REEXEC" , "1" ) ;
339+ env:: set_var ( "ULEXEC_FILE" , fifo_path) ;
340+ let fifo_path = fifo_path. clone ( ) ;
341+ let exec_file = exec_file. clone ( ) ;
342+ spawn ( move || {
343+ match File :: create ( & fifo_path) {
344+ Ok ( mut fifo) => {
345+ if let Err ( err) = fifo. write_all ( & exec_file) {
346+ eprintln ! ( "Failed to write the binary file to fifo: {err}: {:?}" , fifo_path) ;
347+ exit ( 1 )
348+ }
349+ let _ = std:: fs:: remove_file ( & fifo_path) ;
350+ }
351+ Err ( err) => {
352+ eprintln ! ( "Failed to open fifo: {err}: {:?}" , fifo_path) ;
310353 exit ( 1 )
311354 }
312- env:: set_var ( "ULEXEC_CHILD" , "1" ) ;
313- env:: set_var ( "ULEXEC_REEXEC" , "1" ) ;
314- env:: set_var ( "ULEXEC_FILE" , tmp_file. clone ( ) ) ;
315- }
316- Err ( err) => {
317- eprintln ! ( "Failed to create the binary file: {err}: {:?}" , file_path) ;
318- exit ( 1 )
319355 }
320- }
356+ } ) ;
321357 }
322358
323359 let memfd_name = "exec" ;
@@ -330,54 +366,39 @@ fn main() {
330366 . envs ( env:: vars ( ) )
331367 . status ( ) . unwrap ( ) . code ( ) . unwrap ( ) )
332368 } else {
333- let mut args_cstrs: Vec < CString > = args. exec_args . iter ( )
334- . map ( |arg|
335- CString :: new ( arg. clone ( ) ) . unwrap ( )
336- ) . collect ( ) ;
369+ if file_path. to_str ( ) . unwrap ( ) . is_empty ( ) && !exec_file. is_empty ( ) {
370+ match & memfd_create (
371+ CString :: new ( memfd_name) . unwrap ( ) . as_c_str ( ) ,
372+ MemFdCreateFlag :: MFD_CLOEXEC ,
373+ ) {
374+ Ok ( memfd) => {
375+ let memfd_raw = memfd. as_raw_fd ( ) ;
337376
338- match & memfd_create (
339- CString :: new ( memfd_name) . unwrap ( ) . as_c_str ( ) ,
340- MemFdCreateFlag :: MFD_CLOEXEC ,
341- ) {
342- Ok ( memfd) => {
343- let memfd_raw = memfd. as_raw_fd ( ) ;
344-
345- if file_path. to_str ( ) . unwrap ( ) . is_empty ( ) && !exec_file. is_empty ( ) {
346377 file_path = PathBuf :: from (
347378 format ! ( "/proc/self/fd/{}" , memfd_raw. to_string( ) )
348379 ) ;
380+
349381 if let Err ( err) = write ( memfd, & exec_file) {
350382 eprintln ! ( "Failed to write the binary file to memfd: {err}: {:?}" , file_path) ;
351383 exit ( 1 )
352384 }
385+ drop ( exec_file) ;
386+
387+ spawn ( move || {
388+ sleep ( time:: Duration :: from_millis ( 1 ) ) ;
389+ close ( memfd_raw) . unwrap ( )
390+ } ) ;
391+
392+ ul_exec ( file_path, args. exec_args )
393+ }
394+ Err ( err) => {
395+ eprintln ! ( "Failed to create memfd: {err}" ) ;
396+ exit ( 1 )
353397 }
354- drop ( exec_file) ;
355-
356- let file_cstr = CString :: new (
357- file_path. to_str ( ) . unwrap ( )
358- ) . unwrap ( ) ;
359- args_cstrs. insert ( 0 , file_cstr) ;
360-
361- let envs: Vec < CString > = env:: vars ( )
362- . map ( |( key, value) |
363- CString :: new ( format ! ( "{}={}" , key, value) ) . unwrap ( )
364- ) . collect ( ) ;
365-
366- spawn ( move || {
367- sleep ( time:: Duration :: from_millis ( 1 ) ) ;
368- close ( memfd_raw) . unwrap ( )
369- } ) ;
370-
371- userland_execve:: exec (
372- & file_path,
373- & args_cstrs,
374- & envs,
375- )
376- }
377- Err ( err) => {
378- eprintln ! ( "Failed to create memfd: {err}" ) ;
379- exit ( 1 )
380398 }
399+ } else {
400+ drop ( exec_file) ;
401+ ul_exec ( file_path, args. exec_args )
381402 }
382403 }
383404 }
0 commit comments