From 54294640194fa659af63b3848a4be43587bb206a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Bombo?= Date: Mon, 22 Sep 2025 18:06:40 -0500 Subject: [PATCH] agent/rustjail: Fix double free in TTY handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The repro below would show this error in the logs (in debug mode only): fatal runtime error: IO Safety violation: owned file descriptor already closed The issue was that the `pseudo.slave` file descriptor was being owned by multiple variables simultaneously. When any of those variables would go out of scope, they would close the same file descriptor, which is undefined behavior. To fix this, we clone: we create a new file descriptOR that refers to the same file descriptION as the original. When the cloned descriptor is closed, this affect neither the original descriptor nor the description. Only when the last descriptor is closed does the kernel cleans up the description. Note that we purposely consume (not clone) the original descriptor with `child_stdin` as `pseudo` is NOT dropped automatically. Repro ----- Prerequisites: - Use Rust 1.80+. - Build the agent in debug mode. $ cat busybox.yaml apiVersion: v1 kind: Pod metadata: name: busybox spec: containers: - image: busybox:latest name: busybox runtimeClassName: kata $ kubectl apply -f busyboox.yaml pod/busybox created $ kubectl exec -it busybox -- sh error: Internal error occurred: Internal error occurred: error executing command in container: failed to exec in container: failed to start exec "e6c602352849647201860c1e1888d99ea3166512f1cc548b9d7f2533129508a9": cannot enter container 76a499cbf747b9806689e51f6ba35e46d735064a3f176f9be034777e93a242d5, with err ttrpc: closed Fixes: #11054 Signed-off-by: Aurélien Bombo --- src/agent/rustjail/src/container.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/agent/rustjail/src/container.rs b/src/agent/rustjail/src/container.rs index 291f19af1f..1fb05260e3 100644 --- a/src/agent/rustjail/src/container.rs +++ b/src/agent/rustjail/src/container.rs @@ -1045,8 +1045,8 @@ impl BaseContainer for LinuxContainer { .map_err(|e| warn!(logger, "fcntl pseudo.slave {:?}", e)); child_stdin = unsafe { std::process::Stdio::from_raw_fd(pseudo.slave) }; - child_stdout = unsafe { std::process::Stdio::from_raw_fd(pseudo.slave) }; - child_stderr = unsafe { std::process::Stdio::from_raw_fd(pseudo.slave) }; + child_stdout = unsafe { std::process::Stdio::from_raw_fd(unistd::dup(pseudo.slave)?) }; + child_stderr = unsafe { std::process::Stdio::from_raw_fd(unistd::dup(pseudo.slave)?) }; if let Some(proc_io) = &mut p.proc_io { // A reference count used to clean up the term master fd.