From 6bd3f3bdbb55482e7ab3682b8439f73b7b53dff5 Mon Sep 17 00:00:00 2001 From: Jay Bosamiya Date: Wed, 16 Sep 2026 14:35:40 -0700 Subject: [PATCH 1/2] Directory write check logic sits better in shim --- litebox/src/fs/in_mem.rs | 5 ----- litebox/src/fs/nine_p/mod.rs | 5 ----- litebox_shim_linux/src/syscalls/file.rs | 17 +++++++++++++++-- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/litebox/src/fs/in_mem.rs b/litebox/src/fs/in_mem.rs index 68efcfe673..3b5b1fe6c9 100644 --- a/litebox/src/fs/in_mem.rs +++ b/litebox/src/fs/in_mem.rs @@ -298,11 +298,6 @@ impl super::backend::Backend for InMe flags: super::OFlags, ) -> Result { assert_supported_oflags(flags); - if flags.intersects(super::OFlags::WRONLY | super::OFlags::RDWR) { - // TODO(jayb): POSIX requires `EISDIR` when write access is requested on a directory, - // but `OpenError` has no such variant yet. - unimplemented!() - } Ok(super::backend::DirHandle::from_typed::( InMemDirHandle { flags, diff --git a/litebox/src/fs/nine_p/mod.rs b/litebox/src/fs/nine_p/mod.rs index 721c488a06..a1c13f6315 100644 --- a/litebox/src/fs/nine_p/mod.rs +++ b/litebox/src/fs/nine_p/mod.rs @@ -352,11 +352,6 @@ where flags: OFlags, ) -> Result { assert_supported_oflags(flags); - if flags.intersects(OFlags::WRONLY | OFlags::RDWR) { - // TODO(jayb): POSIX requires `EISDIR` when write access is requested on a directory, - // but `OpenError` has no such variant yet. - unimplemented!() - } let (fid, is_backend_root) = dir.into_typed::().into_dir(); if flags.contains(OFlags::PATH) { // An `O_PATH` handle is never opened server-side, so the walked fid can be handed over diff --git a/litebox_shim_linux/src/syscalls/file.rs b/litebox_shim_linux/src/syscalls/file.rs index 8bf5bafdb6..eb4cf6306e 100644 --- a/litebox_shim_linux/src/syscalls/file.rs +++ b/litebox_shim_linux/src/syscalls/file.rs @@ -365,10 +365,23 @@ impl Task { let files = self.files.borrow(); let fs = self.fs.borrow(); let context = fs.context.read(); - files + let file = files .fs .open(&context, path, flags - OFlags::CLOEXEC, mode) - .map_err(Errno::from) + .map_err(Errno::from)?; + if flags.intersects(OFlags::WRONLY | OFlags::RDWR) + && !flags.contains(OFlags::PATH) + && files + .fs + .fd_file_status(&file) + .map_err(Errno::from)? + .file_type + == litebox::fs::FileType::Directory + { + files.fs.close(&file).unwrap(); + return Err(Errno::EISDIR); + } + Ok(file) } fn do_openat( From de4d72381fc5d0246f508f9b036dceefbadda2ed Mon Sep 17 00:00:00 2001 From: Jay Bosamiya Date: Thu, 17 Sep 2026 18:13:36 -0700 Subject: [PATCH 2/2] Prevent fd leak --- litebox_shim_linux/src/syscalls/file.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/litebox_shim_linux/src/syscalls/file.rs b/litebox_shim_linux/src/syscalls/file.rs index eb4cf6306e..98c5ed5ef3 100644 --- a/litebox_shim_linux/src/syscalls/file.rs +++ b/litebox_shim_linux/src/syscalls/file.rs @@ -374,7 +374,10 @@ impl Task { && files .fs .fd_file_status(&file) - .map_err(Errno::from)? + .map_err(|error| { + files.fs.close(&file).unwrap(); + Errno::from(error) + })? .file_type == litebox::fs::FileType::Directory {