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