2014-10-12 20:17:18 +00:00
|
|
|
/*
|
2023-09-10 00:18:08 +00:00
|
|
|
* Copyright (c) 2006-2023 Ali Mashtizadeh
|
2022-12-10 04:51:45 +00:00
|
|
|
* All rights reserved.
|
2014-10-12 20:17:18 +00:00
|
|
|
* Generic Copyin/Copyout routines
|
|
|
|
*/
|
|
|
|
|
2014-10-14 20:58:34 +00:00
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
2014-10-14 23:23:50 +00:00
|
|
|
#include <sys/kassert.h>
|
2014-10-14 20:58:34 +00:00
|
|
|
#include <machine/pmap.h>
|
|
|
|
|
2014-10-12 20:17:18 +00:00
|
|
|
extern int copy_unsafe(void *to_addr, void *from_addr, uintptr_t len);
|
2015-01-20 01:57:20 +00:00
|
|
|
extern int copystr_unsafe(void *to_addr, void *from_addr, uintptr_t len);
|
2014-10-12 20:17:18 +00:00
|
|
|
|
2023-09-10 00:18:08 +00:00
|
|
|
/**
|
2022-12-10 04:51:45 +00:00
|
|
|
* Copy_In --
|
|
|
|
*
|
2023-09-10 20:12:25 +00:00
|
|
|
* Safely copy memory from userspace. Prevents userspace pointers from
|
|
|
|
* reading kernel memory.
|
2022-12-10 04:51:45 +00:00
|
|
|
*
|
|
|
|
* Side effects:
|
2023-09-10 20:12:25 +00:00
|
|
|
* Kernel page fault may have occurred.
|
|
|
|
*
|
|
|
|
* @param [in] fromuser User address to copy from.
|
|
|
|
* @param [in] tokernel Kernel address to copy to.
|
|
|
|
* @param [in] len Length of the data to copy.
|
|
|
|
*
|
|
|
|
* @retval EFAULT if the address is invalid or causes a fault.
|
2022-12-10 04:51:45 +00:00
|
|
|
*/
|
2014-10-12 20:17:18 +00:00
|
|
|
int
|
2022-12-10 04:51:45 +00:00
|
|
|
Copy_In(uintptr_t fromuser, void *tokernel, uintptr_t len)
|
2014-10-12 20:17:18 +00:00
|
|
|
{
|
|
|
|
if (len == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Kernel space
|
2014-10-14 23:23:50 +00:00
|
|
|
if (fromuser >= MEM_USERSPACE_TOP) {
|
2022-12-10 04:51:45 +00:00
|
|
|
kprintf("Copy_In: address exceeds userspace top\n");
|
2014-10-12 20:17:18 +00:00
|
|
|
return EFAULT;
|
2014-10-14 23:23:50 +00:00
|
|
|
}
|
2014-10-12 20:17:18 +00:00
|
|
|
|
|
|
|
// Wrap around
|
2014-10-14 23:23:50 +00:00
|
|
|
if (len > (MEM_USERSPACE_TOP - fromuser)) {
|
2022-12-10 04:51:45 +00:00
|
|
|
kprintf("Copy_In: length exceeds userspace top\n");
|
2014-10-12 20:17:18 +00:00
|
|
|
return EFAULT;
|
2014-10-14 23:23:50 +00:00
|
|
|
}
|
2014-10-12 20:17:18 +00:00
|
|
|
|
2014-10-14 20:58:34 +00:00
|
|
|
return copy_unsafe(tokernel, (void *)fromuser, len);
|
2014-10-12 20:17:18 +00:00
|
|
|
}
|
|
|
|
|
2023-09-10 00:18:08 +00:00
|
|
|
/**
|
2022-12-10 04:51:45 +00:00
|
|
|
* Copy_Out --
|
|
|
|
*
|
2023-09-10 20:12:25 +00:00
|
|
|
* Safely copy memory to userspace. Prevents userspace pointers from
|
|
|
|
* writing kernel memory.
|
2022-12-10 04:51:45 +00:00
|
|
|
*
|
|
|
|
* Side effects:
|
2023-09-10 20:12:25 +00:00
|
|
|
* Kernel page fault may have occurred.
|
|
|
|
*
|
|
|
|
* @param [in] fromkernel Kernel address to copy from.
|
|
|
|
* @param [in] touser User address to copy to.
|
|
|
|
* @param [in] len Length of the data to copy.
|
|
|
|
*
|
|
|
|
* @retval EFAULT if the address is invalid or causes a fault.
|
2022-12-10 04:51:45 +00:00
|
|
|
*/
|
2014-10-12 20:17:18 +00:00
|
|
|
int
|
2022-12-10 04:51:45 +00:00
|
|
|
Copy_Out(void *fromkernel, uintptr_t touser, uintptr_t len)
|
2014-10-12 20:17:18 +00:00
|
|
|
{
|
|
|
|
if (len == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Kernel space
|
2014-10-14 23:23:50 +00:00
|
|
|
if (touser >= MEM_USERSPACE_TOP) {
|
2022-12-10 04:51:45 +00:00
|
|
|
kprintf("Copy_Out: address exceeds userspace top\n");
|
2014-10-12 20:17:18 +00:00
|
|
|
return EFAULT;
|
2014-10-14 23:23:50 +00:00
|
|
|
}
|
2014-10-12 20:17:18 +00:00
|
|
|
|
|
|
|
// Wrap around
|
2014-10-14 23:23:50 +00:00
|
|
|
if (len > (MEM_USERSPACE_TOP - touser)) {
|
2022-12-10 04:51:45 +00:00
|
|
|
kprintf("Copy_Out: length exceeds userspace top\n");
|
2014-10-12 20:17:18 +00:00
|
|
|
return EFAULT;
|
2014-10-14 23:23:50 +00:00
|
|
|
}
|
2014-10-12 20:17:18 +00:00
|
|
|
|
2014-10-14 20:58:34 +00:00
|
|
|
return copy_unsafe((void *)touser, fromkernel, len);
|
2014-10-12 20:17:18 +00:00
|
|
|
}
|
|
|
|
|
2023-09-10 00:18:08 +00:00
|
|
|
/**
|
2022-12-10 04:51:45 +00:00
|
|
|
* Copy_StrIn --
|
|
|
|
*
|
2023-09-10 20:12:25 +00:00
|
|
|
* Safely copy a string from userspace. Prevents userspace pointers from
|
|
|
|
* reading kernel memory.
|
2022-12-10 04:51:45 +00:00
|
|
|
*
|
|
|
|
* Side effects:
|
2023-09-10 20:12:25 +00:00
|
|
|
* Kernel page fault may have occurred.
|
|
|
|
*
|
|
|
|
* @param [in] fromuser User address to copy from.
|
|
|
|
* @param [in] tokernel Kernel address to copy to.
|
|
|
|
* @param [in] len Maximum string length.
|
|
|
|
*
|
|
|
|
* @retval EFAULT if the address is invalid or causes a fault.
|
2022-12-10 04:51:45 +00:00
|
|
|
*/
|
2015-01-20 01:57:20 +00:00
|
|
|
int
|
2022-12-10 04:51:45 +00:00
|
|
|
Copy_StrIn(uintptr_t fromuser, void *tokernel, uintptr_t len)
|
2015-01-20 01:57:20 +00:00
|
|
|
{
|
|
|
|
if (len == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Kernel space
|
|
|
|
if (fromuser >= MEM_USERSPACE_TOP) {
|
2022-12-10 04:51:45 +00:00
|
|
|
kprintf("Copy_StrIn: address exceeds userspace top\n");
|
2015-01-20 01:57:20 +00:00
|
|
|
return EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wrap around
|
|
|
|
if (len > (MEM_USERSPACE_TOP - fromuser)) {
|
2022-12-10 04:51:45 +00:00
|
|
|
kprintf("Copy_StrIn: length exceeds userspace top\n");
|
2015-01-20 01:57:20 +00:00
|
|
|
return EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return copystr_unsafe(tokernel, (void *)fromuser, len);
|
|
|
|
}
|
|
|
|
|
2023-09-10 00:18:08 +00:00
|
|
|
/**
|
2022-12-10 04:51:45 +00:00
|
|
|
* Copy_StrOut --
|
|
|
|
*
|
2023-09-10 20:12:25 +00:00
|
|
|
* Safely copy a string to userspace. Prevents userspace pointers from
|
|
|
|
* writing kernel memory.
|
2022-12-10 04:51:45 +00:00
|
|
|
*
|
|
|
|
* Side effects:
|
2023-09-10 20:12:25 +00:00
|
|
|
* Kernel page fault may have occurred.
|
|
|
|
*
|
|
|
|
* @param [in] fromkernel Kernel address to copy from.
|
|
|
|
* @param [in] touser User address to copy to.
|
|
|
|
* @param [in] len Maximum string length.
|
|
|
|
*
|
|
|
|
* @retval EFAULT if the address is invalid or causes a fault.
|
2022-12-10 04:51:45 +00:00
|
|
|
*/
|
2015-01-20 01:57:20 +00:00
|
|
|
int
|
2022-12-10 04:51:45 +00:00
|
|
|
Copy_StrOut(void *fromkernel, uintptr_t touser, uintptr_t len)
|
2015-01-20 01:57:20 +00:00
|
|
|
{
|
|
|
|
if (len == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Kernel space
|
|
|
|
if (touser >= MEM_USERSPACE_TOP) {
|
2022-12-10 04:51:45 +00:00
|
|
|
kprintf("Copy_StrOut: address exceeds userspace top\n");
|
2015-01-20 01:57:20 +00:00
|
|
|
return EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wrap around
|
|
|
|
if (len > (MEM_USERSPACE_TOP - touser)) {
|
2022-12-10 04:51:45 +00:00
|
|
|
kprintf("Copy_StrOut: length exceeds userspace top\n");
|
2015-01-20 01:57:20 +00:00
|
|
|
return EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return copystr_unsafe((void *)touser, fromkernel, len);
|
|
|
|
}
|
|
|
|
|