matos/core/uaccess.c

102 lines
2.1 KiB
C

#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);
}