diff --git a/Cargo.lock b/Cargo.lock index b81c0586dd2c93cd1fb1d20c6056e14ed39f6c4b..efd70e066ad03cd25ae0c4845f8e0c44b741cc9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,8 +35,8 @@ dependencies = [ "heck", "indexmap", "log", - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.69", + "quote 1.0.33", "serde", "serde_json", "syn 1.0.109", @@ -55,9 +55,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.80" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f1226cd9da55587234753d1245dd5b132343ea240f26b6a9003d68706141ba" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "libc", ] @@ -113,25 +113,14 @@ version = "0.1.0" [[package]] name = "errno" -version = "0.3.2" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ - "errno-dragonfly", "libc", "windows-sys 0.48.0", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "fastrand" version = "1.9.0" @@ -175,9 +164,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "indexmap" @@ -204,7 +193,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.3", "libc", "windows-sys 0.48.0", ] @@ -251,15 +240,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -272,9 +261,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] @@ -306,9 +295,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -324,11 +313,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ - "proc-macro2 1.0.66", + "proc-macro2 1.0.69", ] [[package]] @@ -389,7 +378,8 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" version = "0.3.5" -source = "git+https://gitlab.redox-os.org/redox-os/syscall#a525620c818a801bb7038e111b71033eff56a3ee" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags", ] @@ -397,8 +387,7 @@ dependencies = [ [[package]] name = "redox_syscall" version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +source = "git+https://gitlab.redox-os.org/4lDO2/syscall?branch=sendfd#0200e818a4ba752c1869be9718eb7f090c19d65c" dependencies = [ "bitflags", ] @@ -522,29 +511,29 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.180" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea67f183f058fe88a4e3ec6e2788e003840893b91bac4559cabedd00863b3ed" +checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.180" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e744d7782b686ab3b73267ef05697159cc0e5abbed3f47f9933165e5219036" +checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", - "syn 2.0.28", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 2.0.38", ] [[package]] name = "serde_json" -version = "1.0.104" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -589,19 +578,19 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.69", + "quote 1.0.33", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.28" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.69", + "quote 1.0.33", "unicode-ident", ] @@ -620,9 +609,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] @@ -650,15 +639,15 @@ checksum = "e92e959f029e4f8ee25d70d15ab58d2b46f98a17bc238b9265ff0c26f6f3d67f" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unicode-xid" @@ -684,9 +673,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -712,7 +701,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -732,17 +721,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -753,9 +742,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -765,9 +754,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -777,9 +766,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -789,9 +778,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -801,9 +790,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" @@ -813,9 +802,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -825,6 +814,6 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Cargo.toml b/Cargo.toml index f7ae07026d754bc7456c6d8b220f56681fd28108..6ebbe4613d4897fcd79d4a533a5a8b33690d91ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,4 +61,4 @@ panic = "abort" [patch.crates-io] libc = { git = "https://gitlab.redox-os.org/redox-os/liblibc.git", branch = "redox_0.2.138" } -redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall" } +redox_syscall = { git = "https://gitlab.redox-os.org/4lDO2/syscall", branch = "sendfd" } diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 307edf543fab80c90495e8099f6674ebb9175c0c..5bdb26f87a97dba2e72db6c100d3996eec60ea1e 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -144,6 +144,9 @@ impl Pal for Sys { unsafe fn execve(path: &CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int { e(syscall!(EXECVE, path.as_ptr(), argv, envp)) as c_int } + unsafe fn fexecve(fildes: c_int, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int { + todo!("not yet used by relibc") + } fn exit(status: c_int) -> ! { unsafe { diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index e05c9c3ff70a853cea9527380fbb251b05b0a9f5..d4268820d941a18a95c2cf8cb0dd62395d1f7f33 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -48,6 +48,7 @@ pub trait Pal { fn dup2(fildes: c_int, fildes2: c_int) -> c_int; unsafe fn execve(path: &CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int; + unsafe fn fexecve(fildes: c_int, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int; fn exit(status: c_int) -> !; diff --git a/src/platform/redox/exec.rs b/src/platform/redox/exec.rs index 77cb697733328e83d8c8fd42fe896b24147d0878..b327f7193a7a52c0547c17396ce294a5c1c90f1f 100644 --- a/src/platform/redox/exec.rs +++ b/src/platform/redox/exec.rs @@ -13,7 +13,8 @@ use redox_exec::{ExtraInfo, FdGuard, FexecResult}; use syscall::{data::Stat, error::*, flag::*}; fn fexec_impl( - file: File, + exec_file: FdGuard, + open_via_dup: FdGuard, path: &[u8], args: &[&[u8]], envs: &[&[u8]], @@ -21,15 +22,10 @@ fn fexec_impl( extrainfo: &ExtraInfo, interp_override: Option<redox_exec::InterpOverride>, ) -> Result<usize> { - let fd = *file; - core::mem::forget(file); - let image_file = FdGuard::new(fd as usize); - - let open_via_dup = FdGuard::new(syscall::open("thisproc:current/open_via_dup", 0)?); let memory = FdGuard::new(syscall::open("memory:", 0)?); let addrspace_selection_fd = match redox_exec::fexec_impl( - image_file, + exec_file, open_via_dup, &memory, path, @@ -55,7 +51,7 @@ fn fexec_impl( let path_cstr = CStr::from_bytes_with_nul(&path).map_err(|_| Error::new(ENOEXEC))?; return execve( - path_cstr, + Executable::AtPath(path_cstr), ArgEnv::Parsed { total_args_envs_size, args, @@ -83,20 +79,31 @@ pub enum ArgEnv<'a> { total_args_envs_size: usize, }, } + +pub enum Executable<'a> { + AtPath(&'a CStr), + InFd { file: File, arg0: &'a [u8] }, +} + pub fn execve( - path: &CStr, + exec: Executable<'_>, arg_env: ArgEnv, interp_override: Option<redox_exec::InterpOverride>, ) -> Result<usize> { // NOTE: We must omit O_CLOEXEC and close manually, otherwise it will be closed before we // have even read it! - let mut image_file = File::open(path, O_RDONLY as c_int).map_err(|_| Error::new(ENOENT))?; + let (mut image_file, arg0) = match exec { + Executable::AtPath(path) => (File::open(path, O_RDONLY as c_int).map_err(|_| Error::new(ENOENT))?, path.to_bytes()), + Executable::InFd { file, arg0 } => (file, arg0), + }; // With execve now being implemented in userspace, we need to check ourselves that this // file is actually executable. While checking for read permission is unnecessary as the - // scheme will not allow us to read otherwise, the execute bit is completely unenforced. We - // have the permission to mmap executable memory and fill it with the program even if it is - // unset, so the best we can do is check that nothing is executed by accident. + // scheme will not allow us to read otherwise, the execute bit is completely unenforced. + // + // But we do (currently) have the permission to mmap executable memory and fill it with any + // program, even marked non-executable, so really the best we can do is check that nothing is + // executed by accident. // // TODO: At some point we might have capabilities limiting the ability to allocate // executable memory, and in that case we might use the `escalate:` scheme as we already do @@ -260,25 +267,23 @@ pub fn execve( } } - if !is_interpreted && wants_setugid { - // Make sure the last file descriptor not covered by O_CLOEXEC is not leaked. - drop(image_file); + let this_context_fd = FdGuard::new(syscall::open("thisproc:current/open_via_dup", 0)?); + // TODO: Convert image_file to FdGuard earlier? + let exec_fd_guard = FdGuard::new(image_file.fd as usize); + core::mem::forget(image_file); + if !is_interpreted && wants_setugid { // We are now going to invoke `escalate:` rather than loading the program ourselves. let escalate_fd = FdGuard::new(syscall::open("escalate:", O_WRONLY)?); - // First, we write the path. - // - // TODO: For improved security, use a hypothetical SYS_DUP_FORWARD syscall to give the - // scheme our file descriptor. It can check through the kernel-overwritten stat.st_dev - // field that it pertains to a "trusted" scheme (i.e. of at least the privilege the - // new uid/gid has), although for now only root can open schemes. Passing a file - // descriptor and not a path will allow escalated to run in a limited namespace. - // - // TODO: Plus, at this point fexecve is not implemented (but specified in - // POSIX.1-2008), and to avoid bad syscalls such as fpath, passing a file descriptor - // would be better. - let _ = syscall::write(*escalate_fd, path.to_bytes()); + // First, send the context handle of this process to escalated. + send_fd_guard(*escalate_fd, this_context_fd)?; + + // Then, send the file descriptor containing the file descriptor to be executed. + send_fd_guard(*escalate_fd, exec_fd_guard)?; + + // Then, write the path (argv[0]). + let _ = syscall::write(*escalate_fd, arg0); // Second, we write the flattened args and envs with NUL characters separating // individual items. This can be copied directly into the new executable's memory. @@ -298,8 +303,9 @@ pub fn execve( } else { let extrainfo = ExtraInfo { cwd: Some(&cwd) }; fexec_impl( - image_file, - path.to_bytes(), + exec_fd_guard, + this_context_fd, + arg0, &args, &envs, total_args_envs_size, @@ -319,3 +325,10 @@ where } vec.into_boxed_slice() } + +fn send_fd_guard(dst_socket: usize, fd: FdGuard) -> Result<()> { + syscall::sendfd(dst_socket, *fd, 0, 0)?; + // The kernel closes file descriptors that are sent, so don't call SYS_CLOSE redundantly. + core::mem::forget(fd); + Ok(()) +} diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index c09bb4586b2141118b885fcdd84f51473b5d3ec3..14e93760a2c2f8f541d84467e638a3ca76fa442d 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -63,7 +63,7 @@ macro_rules! path_from_c_str { }}; } -use self::path::canonicalize; +use self::{path::canonicalize, exec::Executable}; pub fn e(sys: Result<usize>) -> usize { match sys { @@ -231,7 +231,14 @@ impl Pal for Sys { unsafe fn execve(path: &CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int { e(self::exec::execve( - path, + Executable::AtPath(path), + self::exec::ArgEnv::C { argv, envp }, + None, + )) as c_int + } + unsafe fn fexecve(fildes: c_int, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int { + e(self::exec::execve( + Executable::InFd { file: File::new(fildes), arg0: CStr::from_ptr(argv.read()).to_bytes() }, self::exec::ArgEnv::C { argv, envp }, None, )) as c_int