Initial commit: Schunix as it stands before the SchOS rename
An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
This commit is contained in:
commit
d0f7acf9eb
275 changed files with 51417 additions and 0 deletions
79
kernel/core/uaccess.c
Normal file
79
kernel/core/uaccess.c
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// User-memory access helpers — see include/uaccess.h for the rules.
|
||||
//
|
||||
// Everything here validates against the *current* process's page table
|
||||
// (myproc()->pgdir), which is also the live CR3 while a syscall runs, so a
|
||||
// range that passes access_ok() can be dereferenced directly by kernel
|
||||
// code for the remainder of the syscall (single-threaded processes can't
|
||||
// unmap it out from under us mid-call).
|
||||
|
||||
#include "types.h"
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "memlayout.h"
|
||||
#include "mmu.h"
|
||||
#include "proc.h"
|
||||
#include "errno.h"
|
||||
#include "uaccess.h"
|
||||
|
||||
int
|
||||
access_ok(addr_t uaddr, uint64 size)
|
||||
{
|
||||
addr_t a, end;
|
||||
|
||||
if(size == 0)
|
||||
return 1;
|
||||
end = uaddr + size;
|
||||
if(end < uaddr || end > KERNBASE)
|
||||
return 0;
|
||||
for(a = PGROUNDDOWN(uaddr); a < end; a += PGSIZE)
|
||||
if(uva2ka(myproc()->pgdir, (char*)a) == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void*
|
||||
user_ptr(addr_t uaddr, uint64 size)
|
||||
{
|
||||
if(uaddr == 0 || !access_ok(uaddr, size))
|
||||
return 0;
|
||||
return (void*)uaddr;
|
||||
}
|
||||
|
||||
int
|
||||
copy_from_user(void *dst, addr_t uaddr, uint64 n)
|
||||
{
|
||||
if(uaddr + n < uaddr || uaddr + n > KERNBASE)
|
||||
return -EFAULT;
|
||||
if(copyin(myproc()->pgdir, uaddr, dst, n) < 0)
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
copy_to_user(addr_t uaddr, const void *src, uint64 n)
|
||||
{
|
||||
if(uaddr + n < uaddr || uaddr + n > KERNBASE)
|
||||
return -EFAULT;
|
||||
if(copyout(myproc()->pgdir, uaddr, (void*)src, n) < 0)
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
strlen_user(addr_t uaddr)
|
||||
{
|
||||
addr_t a = uaddr;
|
||||
|
||||
while(a - uaddr < USER_STR_MAX){
|
||||
// Scan through the per-page kernel alias so an unmapped page is a
|
||||
// clean failure instead of a fault.
|
||||
char *ka = uva2ka(myproc()->pgdir, (char*)a);
|
||||
if(ka == 0)
|
||||
return -EFAULT;
|
||||
addr_t pgend = PGROUNDDOWN(a) + PGSIZE;
|
||||
for(; a < pgend; a++, ka++)
|
||||
if(*ka == 0)
|
||||
return a - uaddr;
|
||||
}
|
||||
return -EFAULT;
|
||||
}
|
||||
Loading…
Reference in a new issue