From 39f5404c5394802e107347e6014297c05951202a Mon Sep 17 00:00:00 2001 From: dzwdz Date: Fri, 16 Aug 2024 19:06:07 +0200 Subject: kernel/pcpy: minor cleanup, implement pcpy_from_str might potentially be used in a reworked open(), mount() etc interface --- src/kernel/pcpy.c | 67 ++++++++++++++++++++++++++++++++++--------------------- src/kernel/proc.h | 4 ++++ 2 files changed, 45 insertions(+), 26 deletions(-) (limited to 'src/kernel') diff --git a/src/kernel/pcpy.c b/src/kernel/pcpy.c index 9cf7c37..5b9efef 100644 --- a/src/kernel/pcpy.c +++ b/src/kernel/pcpy.c @@ -12,7 +12,6 @@ struct virt_iter { void *frag; size_t frag_len; - size_t prior; // sum of all prior frag_lens bool error; void __user *_virt; @@ -22,10 +21,6 @@ struct virt_iter { bool _writeable; }; -struct virt_cpy_error { // unused - bool read_fail, write_fail; -}; - /* if pages == NULL, creates an iterator over physical memory. */ static void virt_iter_new( struct virt_iter *iter, void __user *virt, size_t length, @@ -35,7 +30,7 @@ static bool virt_iter_next(struct virt_iter *); static size_t virt_cpy( Pagedir *dest_pages, void __user *dest, Pagedir *src_pages, const void __user *src, - size_t length, struct virt_cpy_error *err + size_t length ); @@ -46,7 +41,6 @@ virt_iter_new( ) { iter->frag = NULL; iter->frag_len = 0; - iter->prior = 0; iter->error = false; iter->_virt = virt; iter->_remaining = length; @@ -58,13 +52,7 @@ virt_iter_new( static bool virt_iter_next(struct virt_iter *iter) { - /* note: While i'm pretty sure that this should always work, this - * was only tested in cases where the pages were consecutive both in - * virtual and physical memory, which might not always be the case. - * TODO test this */ - size_t partial = iter->_remaining; - iter->prior += iter->frag_len; if (partial <= 0) return false; if (iter->_pages) { // if iterating over virtual memory @@ -95,15 +83,14 @@ static size_t virt_cpy( Pagedir *dest_pages, void __user *dest, Pagedir *src_pages, const void __user *src, - size_t length, struct virt_cpy_error *err + size_t length ) { struct virt_iter dest_iter, src_iter; size_t total = 0, partial; + /* user write */ virt_iter_new(&dest_iter, dest, length, dest_pages, true, true); virt_iter_new( &src_iter, (userptr_t)src, length, src_pages, true, false); - dest_iter.frag_len = 0; - src_iter.frag_len = 0; for (;;) { if (dest_iter.frag_len <= 0 && !virt_iter_next(&dest_iter)) break; @@ -119,14 +106,11 @@ virt_cpy( src_iter.frag += partial; } - if (err) { - err->read_fail = src_iter.error; - err->write_fail = dest_iter.error; - } - if (src_iter.error || dest_iter.error) - assert(total != length); - else + if (src_iter.error || dest_iter.error) { + assert(total < length); + } else { assert(total == length); + } return total; } @@ -135,7 +119,7 @@ pcpy_to(Proc *p, __user void *dst, const void *src, size_t len) { assert(p); if (!p->pages) return 0; - return virt_cpy(p->pages, dst, NULL, (__user void*)src, len, NULL); + return virt_cpy(p->pages, dst, NULL, (__user void*)src, len); } size_t @@ -143,7 +127,7 @@ pcpy_from(Proc *p, void *dst, const __user void *src, size_t len) { assert(p); if (!p->pages) return 0; - return virt_cpy(NULL, (__user void*)dst, p->pages, src, len, NULL); + return virt_cpy(NULL, (__user void*)dst, p->pages, src, len); } size_t @@ -155,5 +139,36 @@ pcpy_bi( assert(dstp && srcp); if (!dstp->pages) return 0; if (!srcp->pages) return 0; - return virt_cpy(dstp->pages, dst, srcp->pages, src, len, NULL); + return virt_cpy(dstp->pages, dst, srcp->pages, src, len); +} + +// XXX: not used atm +size_t +pcpy_from_str(Proc *p, char *dst, const __user char *src, size_t len) +{ + struct virt_iter iter; + size_t pos = 0; + + assert(p); + if (p->pages == NULL) return 0; + + virt_iter_new(&iter, (userptr_t)src, len, p->pages, true, false); + for (;;) { + assert(iter.frag_len == 0); + if (!virt_iter_next(&iter)) { + return 0; + } + + char *c = iter.frag; + for (size_t i = 0; i < iter.frag_len; i++) { + dst[pos++] = c[i]; + if (c[i] == '\0') { + assert(pos <= len); + return pos; + } + } + + iter.frag += iter.frag_len; + iter.frag_len = 0; + } } diff --git a/src/kernel/proc.h b/src/kernel/proc.h index 0de740f..4ad6580 100644 --- a/src/kernel/proc.h +++ b/src/kernel/proc.h @@ -145,3 +145,7 @@ size_t pcpy_bi( Proc *srcp, const __user void *src, size_t len ); +/* Copies a NUL-terminated string from the process. + * Returns the size of the string including the NUL terminator, + * and 0 on error or if the string didn't fit in dst. */ +size_t pcpy_from_str(Proc *p, char *dst, const __user char *src, size_t len); -- cgit v1.2.3