From 7eb9955a96efbf914f4c095c3fed7dd34d25fad1 Mon Sep 17 00:00:00 2001 From: Matheus Date: Wed, 18 Sep 2024 19:18:15 -0300 Subject: [PATCH] vfs: vfs_read/vfs_write: accept user addresses --- kernel-src/fs/vfs.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/kernel-src/fs/vfs.c b/kernel-src/fs/vfs.c index 6e3d8bdf..5329d1b5 100644 --- a/kernel-src/fs/vfs.c +++ b/kernel-src/fs/vfs.c @@ -229,6 +229,7 @@ static int writenocache(vnode_t *node, page_t *page, uintmax_t pageoffset) { return e; } +// buffer can be a user address int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t *written, int flags) { int err = 0; if (vfs_iscacheable(node)) { @@ -291,7 +292,11 @@ int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t size_t writesize = min(PAGE_SIZE - startoffset, size); void *address = MAKE_HHDM(pmm_getpageaddress(page)); - memcpy((void *)((uintptr_t)address + startoffset), buffer, writesize); + err = USERCOPY_POSSIBLY_FROM_USER((void *)((uintptr_t)address + startoffset), buffer, writesize); + if (err) { + pmm_release(FROM_HHDM(address)); + goto leave; + } vmmcache_makedirty(page); *written += writesize; @@ -314,7 +319,13 @@ int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t size_t writesize = min(PAGE_SIZE, size - *written); void *address = MAKE_HHDM(pmm_getpageaddress(page)); - memcpy(address, (void *)((uintptr_t)buffer + *written), writesize); + + err = USERCOPY_POSSIBLY_FROM_USER(address, (void *)((uintptr_t)buffer + *written), writesize); + if (err) { + pmm_release(FROM_HHDM(address)); + goto leave; + } + vmmcache_makedirty(page); *written += writesize; @@ -394,7 +405,13 @@ int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t size_t readsize = min(PAGE_SIZE - startoffset, size); void *address = MAKE_HHDM(pmm_getpageaddress(page)); - memcpy(buffer, (void *)((uintptr_t)address + startoffset), readsize); + + err = USERCOPY_POSSIBLY_TO_USER(buffer, (void *)((uintptr_t)address + startoffset), readsize); + if (err) { + pmm_release(FROM_HHDM(address)); + goto leave; + } + *bytesread += readsize; pageoffset += 1; pagecount -= 1; @@ -403,6 +420,7 @@ int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t // try to turn it into anonymous memory vmmcache_evict(page); } + pmm_release(FROM_HHDM(address)); } @@ -414,7 +432,13 @@ int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t size_t readsize = min(PAGE_SIZE, size - *bytesread); void *address = MAKE_HHDM(pmm_getpageaddress(page)); - memcpy((void *)((uintptr_t)buffer + *bytesread), address, readsize); + + err = USERCOPY_POSSIBLY_TO_USER((void *)((uintptr_t)buffer + *bytesread), address, readsize); + if (err) { + pmm_release(FROM_HHDM(address)); + goto leave; + } + *bytesread += readsize; if (flags & V_FFLAGS_NOCACHE) { // try to turn it into anonymous memory