From 2a2fc4dffe0117ce874a6cf1dcc34321ed8add77 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Wed, 25 Jan 2023 01:02:04 +0100 Subject: kernel/virt: replace the virt_cpy api with a more foolproof one --- src/kernel/mem/virt.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++----- src/kernel/mem/virt.h | 52 ++++++------------------------- 2 files changed, 85 insertions(+), 51 deletions(-) (limited to 'src/kernel/mem') diff --git a/src/kernel/mem/virt.c b/src/kernel/mem/virt.c index bff4b5e..8bf5e69 100644 --- a/src/kernel/mem/virt.c +++ b/src/kernel/mem/virt.c @@ -1,13 +1,50 @@ +/* Copies stuff between different pagedirs. Mostly a wrapper behind an old, + * bad interface. */ + +// TODO ensure the behaviour of kernel vs user fs on faults is the same + #include #include #include +#include #include #include -void virt_iter_new( - struct virt_iter *iter, void __user *virt, size_t length, - struct pagedir *pages, bool user, bool writeable) -{ +struct virt_iter { + void *frag; + size_t frag_len; + size_t prior; // sum of all prior frag_lens + bool error; + + void __user *_virt; + size_t _remaining; + struct pagedir *_pages; + bool _user; + 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, + struct pagedir *pages, bool user, bool writeable +); +static bool virt_iter_next(struct virt_iter *); +static size_t virt_cpy( + struct pagedir *dest_pages, void __user *dest, + struct pagedir *src_pages, const void __user *src, + size_t length, struct virt_cpy_error *err +); + + +static void +virt_iter_new( + struct virt_iter *iter, void __user *virt, size_t length, + struct pagedir *pages, bool user, bool writeable +) { iter->frag = NULL; iter->frag_len = 0; iter->prior = 0; @@ -19,7 +56,9 @@ void virt_iter_new( iter->_writeable = writeable; } -bool virt_iter_next(struct virt_iter *iter) { +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. @@ -53,11 +92,12 @@ bool virt_iter_next(struct virt_iter *iter) { return true; } -size_t virt_cpy( +static size_t +virt_cpy( struct pagedir *dest_pages, void __user *dest, struct pagedir *src_pages, const void __user *src, - size_t length, struct virt_cpy_error *err) -{ + size_t length, struct virt_cpy_error *err +) { struct virt_iter dest_iter, src_iter; size_t total = 0, partial; @@ -90,3 +130,31 @@ size_t virt_cpy( assert(total == length); return total; } + +size_t +pcpy_to(struct process *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); +} + +size_t +pcpy_from(struct process *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); +} + +size_t +pcpy_bi( + struct process *dstp, __user void *dst, + struct process *srcp, const __user void *src, + size_t len +) { + assert(dstp && srcp); + if (!dstp->pages) return 0; + if (!srcp->pages) return 0; + return virt_cpy(dstp->pages, dst, srcp->pages, src, len, NULL); +} diff --git a/src/kernel/mem/virt.h b/src/kernel/mem/virt.h index 1f9ef14..fc35078 100644 --- a/src/kernel/mem/virt.h +++ b/src/kernel/mem/virt.h @@ -1,48 +1,14 @@ -/* contains utilities for interacting with virtual memory */ +// move this to proc.h, maybe? #pragma once #include -#include -#include #include -struct virt_iter { - void *frag; - size_t frag_len; - size_t prior; // sum of all prior frag_lens - bool error; +struct process; - void __user *_virt; - size_t _remaining; - struct pagedir *_pages; - bool _user; - bool _writeable; -}; - -struct virt_cpy_error { - bool read_fail, write_fail; -}; - -/* if pages == NULL, create an iterator over physical memory. */ -void virt_iter_new( - struct virt_iter *iter, void __user *virt, size_t length, - struct pagedir *pages, bool user, bool writeable); - -bool virt_iter_next(struct virt_iter *); - -size_t virt_cpy( - struct pagedir *dest_pages, void __user *dest, - struct pagedir *src_pages, const void __user *src, - size_t length, struct virt_cpy_error *err); - - -/* copies to virtual memory, returns true on success */ -static inline bool virt_cpy_to(struct pagedir *dest_pages, - void __user *dest, const void *src, size_t length) { - return length == virt_cpy(dest_pages, dest, NULL, (userptr_t)src, length, NULL); -} - -/* copies from virtual memory, returns true on success */ -static inline bool virt_cpy_from(struct pagedir *src_pages, - void *dest, const void __user *src, size_t length) { - return length == virt_cpy(NULL, (userptr_t)dest, src_pages, src, length, NULL); -} +size_t pcpy_to(struct process *p, __user void *dst, const void *src, size_t len); +size_t pcpy_from(struct process *p, void *dst, const __user void *src, size_t len); +size_t pcpy_bi( + struct process *dstp, __user void *dst, + struct process *srcp, const __user void *src, + size_t len +); -- cgit v1.2.3