From 66c6209d2eb938ff9aa2b300d9f585cbf4d5017f Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Thu, 23 Apr 2026 16:44:43 -0700 Subject: [PATCH 1/2] implement memfd --- etc/syscalls_linux_aarch64.md | 2 +- src/arch/arm64/exceptions/syscall.rs | 3 + src/fs/memfd.rs | 88 ++++++++++++++++++++++++++++ src/fs/mod.rs | 1 + 4 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 src/fs/memfd.rs diff --git a/etc/syscalls_linux_aarch64.md b/etc/syscalls_linux_aarch64.md index 8696d05e..db3c8e59 100644 --- a/etc/syscalls_linux_aarch64.md +++ b/etc/syscalls_linux_aarch64.md @@ -263,7 +263,7 @@ | 0x114 (276) | renameat2 | (int olddfd, const char *oldname, int newdfd, const char *newname, unsigned int flags) | __arm64_sys_renameat2 | true | | 0x115 (277) | seccomp | (unsigned int op, unsigned int flags, void *uargs) | __arm64_sys_seccomp | false | | 0x116 (278) | getrandom | (char *ubuf, size_t len, unsigned int flags) | __arm64_sys_getrandom | true | -| 0x117 (279) | memfd_create | (const char *uname, unsigned int flags) | __arm64_sys_memfd_create | false | +| 0x117 (279) | memfd_create | (const char *uname, unsigned int flags) | __arm64_sys_memfd_create | true | | 0x118 (280) | bpf | (int cmd, union bpf_attr *uattr, unsigned int size) | __arm64_sys_bpf | false | | 0x119 (281) | execveat | (int fd, const char *filename, const char *const *argv, const char *const *envp, int flags) | __arm64_sys_execveat | false | | 0x11a (282) | userfaultfd | (int flags) | __arm64_sys_userfaultfd | false | diff --git a/src/arch/arm64/exceptions/syscall.rs b/src/arch/arm64/exceptions/syscall.rs index 6ecef8c9..00205baa 100644 --- a/src/arch/arm64/exceptions/syscall.rs +++ b/src/arch/arm64/exceptions/syscall.rs @@ -8,6 +8,7 @@ use crate::{ }, fs::{ dir::sys_getdents64, + memfd::sys_memfd_create, pipe::sys_pipe2, syscalls::{ at::{ @@ -755,6 +756,8 @@ pub async fn handle_syscall(mut ctx: ProcessCtx) { .await } 0x116 => sys_getrandom(TUA::from_value(arg1 as _), arg2 as _, arg3 as _).await, + 0x117 => sys_memfd_create(&ctx, TUA::from_value(arg1 as _), arg2 as _).await, + 0x118 => Err(KernelError::NotSupported), 0x11d => { sys_copy_file_range( &ctx, diff --git a/src/fs/memfd.rs b/src/fs/memfd.rs new file mode 100644 index 00000000..f7cfb159 --- /dev/null +++ b/src/fs/memfd.rs @@ -0,0 +1,88 @@ +use crate::fs::fops::FileOps; +use crate::fs::open_file::{FileCtx, OpenFile}; +use crate::memory::uaccess::{copy_from_user_slice, copy_to_user_slice}; +use crate::process::fd_table::FdFlags; +use crate::sched::syscall_ctx::ProcessCtx; +use crate::sync::Mutex; +use alloc::boxed::Box; +use alloc::sync::Arc; +use alloc::vec::Vec; +use async_trait::async_trait; +use core::ffi::c_char; +use libkernel::fs::OpenFlags; +use libkernel::memory::address::{TUA, UA}; + +pub struct MemFd { + data: Mutex>, +} + +impl MemFd { + fn new() -> Self { + Self { + data: Mutex::new(Vec::new()), + } + } +} + +#[async_trait] +impl FileOps for MemFd { + async fn readat( + &mut self, + buf: UA, + count: usize, + offset: u64, + ) -> libkernel::error::Result { + if count == 0 { + return Ok(0); + } + let data = self.data.lock().await; + let offset = offset as usize; + if offset >= data.len() { + return Ok(0); + } + let available = data.len() - offset; + let read_len = available.min(count); + copy_to_user_slice(&data[offset..offset + read_len], buf).await?; + Ok(read_len) + } + + async fn writeat( + &mut self, + buf: UA, + count: usize, + offset: u64, + ) -> libkernel::error::Result { + if count == 0 { + return Ok(0); + } + let mut data = self.data.lock().await; + let offset = offset as usize; + let end = offset + count; + if end > data.len() { + data.resize(end, 0); + } + copy_from_user_slice(buf, &mut data[offset..end]).await?; + Ok(count) + } + + async fn truncate(&mut self, _ctx: &FileCtx, new_size: usize) -> libkernel::error::Result<()> { + let mut data = self.data.lock().await; + data.resize(new_size, 0); + Ok(()) + } +} + +pub async fn sys_memfd_create( + ctx: &ProcessCtx, + _name: TUA, + _flags: u32, +) -> libkernel::error::Result { + let memfd = MemFd::new(); + let open_file = Arc::new(OpenFile::new(Box::new(memfd), OpenFlags::empty())); + Ok(ctx + .shared() + .fd_table + .lock_save_irq() + .insert_with_flags(open_file, FdFlags::empty())? + .as_raw() as usize) +} diff --git a/src/fs/mod.rs b/src/fs/mod.rs index 0db5a581..a4b80b79 100644 --- a/src/fs/mod.rs +++ b/src/fs/mod.rs @@ -22,6 +22,7 @@ use reg::RegFile; pub mod dir; pub mod fops; +pub mod memfd; pub mod open_file; pub mod pipe; pub mod reg; From e2cf6998a7c3b8821c02226c086da4a954f27c9b Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Sun, 26 Apr 2026 21:36:10 -0700 Subject: [PATCH 2/2] memfd seek --- src/fs/memfd.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/fs/memfd.rs b/src/fs/memfd.rs index f7cfb159..da59f9a3 100644 --- a/src/fs/memfd.rs +++ b/src/fs/memfd.rs @@ -9,7 +9,7 @@ use alloc::sync::Arc; use alloc::vec::Vec; use async_trait::async_trait; use core::ffi::c_char; -use libkernel::fs::OpenFlags; +use libkernel::fs::{OpenFlags, SeekFrom}; use libkernel::memory::address::{TUA, UA}; pub struct MemFd { @@ -70,6 +70,25 @@ impl FileOps for MemFd { data.resize(new_size, 0); Ok(()) } + + async fn seek(&mut self, ctx: &mut FileCtx, pos: SeekFrom) -> libkernel::error::Result { + fn saturating_add_signed(u: u64, i: i64) -> u64 { + if i >= 0 { + u.saturating_add(i as u64) + } else { + u.saturating_sub((-i) as u64) + } + } + + let size = self.data.lock().await.len() as u64; + ctx.pos = match pos { + SeekFrom::Start(x) => x, + SeekFrom::End(x) => saturating_add_signed(size, x), + SeekFrom::Current(x) => saturating_add_signed(ctx.pos, x), + }; + + Ok(ctx.pos) + } } pub async fn sys_memfd_create(