#include "uaccess.h" #include "assert.h" #include "errno.h" #include "minmax.h" #include "mmuContext.h" #include "paging.h" #include "process.h" #include "thread.h" #include "types.h" static int bindtoUserContext() { struct thread *currentThread; struct mmu_context *ctx; currentThread = getCurrentThread(); assert(NULL != currentThread->process); /* Switch to the user's address space */ ctx = processGetMMUContext(currentThread->process); return threadChangeCurrentContext(ctx); } static int unbindUserContext() { return threadChangeCurrentContext(NULL); } static int memcpyUserMemNoCheck(vaddr_t dest, vaddr_t src, size_t size) { int ret; ret = bindtoUserContext(); if (ret != 0) return ret; memcpy((void *)dest, (void *)src, size); ret = unbindUserContext(); if (ret != 0) return ret; return size; } int memcpyToUser(uaddr_t to, vaddr_t from, size_t size) { if ((uint)to < PAGING_BASE_USER_ADDRESS) return -EPERM; if ((uint)to > PAGING_TOP_USER_ADDRESS - size) return -EPERM; return memcpyUserMemNoCheck(to, from, size); } int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size) { if ((uint)from < PAGING_BASE_USER_ADDRESS) return -EPERM; if ((uint)from > PAGING_TOP_USER_ADDRESS - size) return -EPERM; return memcpyUserMemNoCheck(to, from, size); } static int strzcpyFromUserNoCheck(char *to, char *from, size_t size) { int ret; ret = bindtoUserContext(); if (ret != 0) return ret; for (unsigned int i = 0; i < size; i++) { to[i] = from[i]; if (from[i] == '\0') break; } if (size > 0) to[size - 1] = '\0'; ret = unbindUserContext(); if (ret != 0) return ret; return size; } int strzcpyFromUser(vaddr_t *to, uaddr_t *from, size_t size) { if ((uint)from < PAGING_BASE_USER_ADDRESS) return -EPERM; if ((uint)from > PAGING_TOP_USER_ADDRESS - size) return -EPERM; return strzcpyFromUserNoCheck((char *)to, (char *)from, size); }