mirror of
https://github.com/drasko/codezero.git
synced 2026-10-01 09:39:27 +02:00
Added new routines that map and check the validity of user buffers.
mmap uses this mechanism to get arguments. It needs to be tested.
This commit is contained in:
@@ -5,4 +5,4 @@ sym final.axf
|
|||||||
break break_virtual
|
break break_virtual
|
||||||
continue
|
continue
|
||||||
stepi
|
stepi
|
||||||
sym start.axf
|
sym /opt/codezero/tasks/mm0/mm0.axf
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#include INC_SUBARCH(mm.h)
|
#include INC_SUBARCH(mm.h)
|
||||||
|
|
||||||
/* Abort debugging conditions */
|
/* Abort debugging conditions */
|
||||||
// #define DEBUG_ABORTS
|
#define DEBUG_ABORTS
|
||||||
#if defined (DEBUG_ABORTS)
|
#if defined (DEBUG_ABORTS)
|
||||||
#define dbg_abort(...) dprintk(__VA_ARGS__)
|
#define dbg_abort(...) dprintk(__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -23,27 +23,12 @@ struct sys_mmap_args {
|
|||||||
off_t offset;
|
off_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
void *sys_mmap(struct tcb *sender, void *start, size_t length, int prot,
|
void *sys_mmap(struct tcb *task, struct sys_mmap_args *args);
|
||||||
int flags, int fd, off_t pfn);
|
|
||||||
|
|
||||||
int sys_munmap(struct tcb *sender, void *vaddr, unsigned long size);
|
int sys_munmap(struct tcb *sender, void *vaddr, unsigned long size);
|
||||||
int sys_msync(struct tcb *task, void *start, unsigned long length, int flags);
|
int sys_msync(struct tcb *task, void *start, unsigned long length, int flags);
|
||||||
|
void *sys_shmat(struct tcb *task, l4id_t shmid, const void *shmadr, int shmflg);
|
||||||
struct sys_shmat_args {
|
|
||||||
l4id_t shmid;
|
|
||||||
const void *shmaddr;
|
|
||||||
int shmflg;
|
|
||||||
};
|
|
||||||
|
|
||||||
void *sys_shmat(struct tcb *requester, l4id_t shmid, const void *shmaddr, int shmflg);
|
|
||||||
int sys_shmdt(struct tcb *requester, const void *shmaddr);
|
int sys_shmdt(struct tcb *requester, const void *shmaddr);
|
||||||
|
|
||||||
struct sys_shmget_args {
|
|
||||||
key_t key;
|
|
||||||
int size;
|
|
||||||
int shmflg;
|
|
||||||
};
|
|
||||||
|
|
||||||
int sys_shmget(key_t key, int size, int shmflg);
|
int sys_shmget(key_t key, int size, int shmflg);
|
||||||
|
|
||||||
int sys_fork(struct tcb *parent);
|
int sys_fork(struct tcb *parent);
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef __USER_H__
|
||||||
|
#define __USER_H__
|
||||||
|
|
||||||
|
#include <task.h>
|
||||||
|
|
||||||
|
int pager_validate_user_range(struct tcb *user, void *userptr, unsigned long size,
|
||||||
|
unsigned int vm_flags);
|
||||||
|
void *pager_validate_map_user_range(struct tcb *user, void *userptr,
|
||||||
|
unsigned long size, unsigned int vm_flags);
|
||||||
|
void pager_unmap_user_range(void *mapped_ptr, unsigned long size);
|
||||||
|
|
||||||
|
#endif /* __USER_H__ */
|
||||||
+3
-6
@@ -71,14 +71,12 @@ void handle_requests(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case L4_IPC_TAG_SHMGET: {
|
case L4_IPC_TAG_SHMGET: {
|
||||||
struct sys_shmget_args *args = (struct sys_shmget_args *)&mr[0];
|
ret = sys_shmget((key_t)mr[0], (int)mr[1], (int)mr[2]);
|
||||||
ret = sys_shmget(args->key, args->size, args->shmflg);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case L4_IPC_TAG_SHMAT: {
|
case L4_IPC_TAG_SHMAT: {
|
||||||
struct sys_shmat_args *args = (struct sys_shmat_args *)&mr[0];
|
ret = (int)sys_shmat(sender, (l4id_t)mr[0], (void *)mr[1], (int)mr[2]);
|
||||||
ret = (int)sys_shmat(sender, args->shmid, args->shmaddr, args->shmflg);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,8 +110,7 @@ void handle_requests(void)
|
|||||||
|
|
||||||
case L4_IPC_TAG_MMAP: {
|
case L4_IPC_TAG_MMAP: {
|
||||||
struct sys_mmap_args *args = (struct sys_mmap_args *)mr[0];
|
struct sys_mmap_args *args = (struct sys_mmap_args *)mr[0];
|
||||||
ret = (int)sys_mmap(sender, args->start, args->length, args->prot,
|
ret = (int)sys_mmap(sender, args);
|
||||||
args->flags, args->fd, args->offset);
|
|
||||||
}
|
}
|
||||||
case L4_IPC_TAG_MUNMAP: {
|
case L4_IPC_TAG_MUNMAP: {
|
||||||
ret = sys_munmap(sender, (void *)mr[0], (unsigned long)mr[1]);
|
ret = sys_munmap(sender, (void *)mr[0], (unsigned long)mr[1]);
|
||||||
|
|||||||
@@ -855,28 +855,6 @@ int page_fault_handler(struct tcb *sender, fault_kdata_t *fkdata)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checks if an address range is a validly mapped area for a task */
|
|
||||||
int validate_task_range(struct tcb *t, unsigned long start,
|
|
||||||
unsigned long end, unsigned int vmflags)
|
|
||||||
{
|
|
||||||
struct vm_area *vma;
|
|
||||||
|
|
||||||
start = page_align(start);
|
|
||||||
end = page_align_up(end);
|
|
||||||
|
|
||||||
/* Find the vma that maps that virtual address */
|
|
||||||
for (unsigned long vaddr = start; vaddr < end; vaddr += PAGE_SIZE) {
|
|
||||||
if (!(vma = find_vma(vaddr, &t->vm_area_head->list))) {
|
|
||||||
printf("%s: No VMA found for 0x%x on task: %d\n",
|
|
||||||
__FUNCTION__, vaddr, t->tid);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if ((vma->flags & vmflags) != vmflags)
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Makes the virtual to page translation for a given user task.
|
* Makes the virtual to page translation for a given user task.
|
||||||
* It traverses the vm_objects and returns the first encountered
|
* It traverses the vm_objects and returns the first encountered
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <globals.h>
|
#include <globals.h>
|
||||||
#include <file.h>
|
#include <file.h>
|
||||||
|
#include <user.h>
|
||||||
|
|
||||||
/* Copy from one page's buffer into another page */
|
/* Copy from one page's buffer into another page */
|
||||||
int page_copy(struct page *dst, struct page *src,
|
int page_copy(struct page *dst, struct page *src,
|
||||||
@@ -613,10 +614,10 @@ int sys_read(struct tcb *task, int fd, void *buf, int count)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Check user buffer validity. */
|
/* Check user buffer validity. */
|
||||||
if ((ret = validate_task_range(task, (unsigned long)buf,
|
if ((ret = pager_validate_user_range(task, buf,
|
||||||
(unsigned long)(buf + count),
|
(unsigned long)(buf + count),
|
||||||
VM_READ)) < 0)
|
VM_READ)) < 0)
|
||||||
return ret;
|
return -EFAULT;
|
||||||
|
|
||||||
vmfile = task->files->fd[fd].vmfile;
|
vmfile = task->files->fd[fd].vmfile;
|
||||||
cursor = task->files->fd[fd].cursor;
|
cursor = task->files->fd[fd].cursor;
|
||||||
@@ -683,10 +684,10 @@ int sys_write(struct tcb *task, int fd, void *buf, int count)
|
|||||||
|
|
||||||
|
|
||||||
/* Check user buffer validity. */
|
/* Check user buffer validity. */
|
||||||
if ((ret = validate_task_range(task, (unsigned long)buf,
|
if ((ret = pager_validate_user_range(task, buf,
|
||||||
(unsigned long)(buf + count),
|
(unsigned long)(buf + count),
|
||||||
VM_WRITE | VM_READ)) < 0)
|
VM_WRITE | VM_READ)) < 0)
|
||||||
return ret;
|
return -EINVAL;
|
||||||
|
|
||||||
vmfile = task->files->fd[fd].vmfile;
|
vmfile = task->files->fd[fd].vmfile;
|
||||||
cursor = task->files->fd[fd].cursor;
|
cursor = task->files->fd[fd].cursor;
|
||||||
|
|||||||
+23
-2
@@ -14,6 +14,8 @@
|
|||||||
#include <mmap.h>
|
#include <mmap.h>
|
||||||
#include <file.h>
|
#include <file.h>
|
||||||
#include <shm.h>
|
#include <shm.h>
|
||||||
|
#include <syscalls.h>
|
||||||
|
#include <user.h>
|
||||||
|
|
||||||
struct vm_area *vma_new(unsigned long pfn_start, unsigned long npages,
|
struct vm_area *vma_new(unsigned long pfn_start, unsigned long npages,
|
||||||
unsigned int flags, unsigned long file_offset)
|
unsigned int flags, unsigned long file_offset)
|
||||||
@@ -259,8 +261,8 @@ void *do_mmap(struct vm_file *mapfile, unsigned long file_offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mmap system call implementation */
|
/* mmap system call implementation */
|
||||||
void *sys_mmap(struct tcb *task, void *start, size_t length, int prot,
|
void *__sys_mmap(struct tcb *task, void *start, size_t length, int prot,
|
||||||
int flags, int fd, unsigned long pfn)
|
int flags, int fd, unsigned long pfn)
|
||||||
{
|
{
|
||||||
unsigned long npages = __pfn(page_align_up(length));
|
unsigned long npages = __pfn(page_align_up(length));
|
||||||
unsigned long base = (unsigned long)start;
|
unsigned long base = (unsigned long)start;
|
||||||
@@ -319,6 +321,25 @@ void *sys_mmap(struct tcb *task, void *start, size_t length, int prot,
|
|||||||
return do_mmap(file, __pfn_to_addr(pfn), task, base, vmflags, npages);
|
return do_mmap(file, __pfn_to_addr(pfn), task, base, vmflags, npages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *sys_mmap(struct tcb *task, struct sys_mmap_args *args)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct sys_mmap_args *mapped_args;
|
||||||
|
void *ret;
|
||||||
|
|
||||||
|
if (!(mapped_args = pager_validate_map_user_range(task, args,
|
||||||
|
sizeof(*args),
|
||||||
|
VM_READ | VM_WRITE)))
|
||||||
|
return PTR_ERR(-EINVAL);
|
||||||
|
|
||||||
|
ret = __sys_mmap(task, args->start, args->length, args->prot,
|
||||||
|
args->flags, args->fd, args->offset);
|
||||||
|
|
||||||
|
pager_unmap_user_range(mapped_args, sizeof(*args));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Sets the end of data segment for sender */
|
/* Sets the end of data segment for sender */
|
||||||
int sys_brk(struct tcb *sender, void *ds_end)
|
int sys_brk(struct tcb *sender, void *ds_end)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Functions to validate, map and unmap user buffers.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Bahadir Balban
|
||||||
|
*/
|
||||||
|
#include <l4lib/arch/syslib.h>
|
||||||
|
#include <vm_area.h>
|
||||||
|
#include <task.h>
|
||||||
|
#include <user.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checks if the given user virtual address range is
|
||||||
|
* validly owned by that user with given flags.
|
||||||
|
*
|
||||||
|
* FIXME: This scans the vmas page by page, we can do it faster
|
||||||
|
* by leaping from one vma to next.
|
||||||
|
*/
|
||||||
|
int pager_validate_user_range(struct tcb *user, void *userptr, unsigned long size,
|
||||||
|
unsigned int vmflags)
|
||||||
|
{
|
||||||
|
struct vm_area *vma;
|
||||||
|
unsigned long start = page_align(userptr);
|
||||||
|
unsigned long end = page_align_up(userptr + size);
|
||||||
|
|
||||||
|
/* Find the vma that maps that virtual address */
|
||||||
|
for (unsigned long vaddr = start; vaddr < end; vaddr += PAGE_SIZE) {
|
||||||
|
if (!(vma = find_vma(vaddr, &user->vm_area_head->list))) {
|
||||||
|
printf("%s: No VMA found for 0x%x on task: %d\n",
|
||||||
|
__FUNCTION__, vaddr, user->tid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((vma->flags & vmflags) != vmflags)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validates and maps the user virtual address range to the pager.
|
||||||
|
* Every virtual page needs to be mapped individually because it's
|
||||||
|
* not guaranteed pages are physically contiguous.
|
||||||
|
*/
|
||||||
|
void *pager_validate_map_user_range(struct tcb *user, void *userptr,
|
||||||
|
unsigned long size, unsigned int vm_flags)
|
||||||
|
{
|
||||||
|
unsigned long start = page_align(userptr);
|
||||||
|
unsigned long end = page_align_up(userptr + size);
|
||||||
|
void *mapped = 0;
|
||||||
|
|
||||||
|
/* Validate that user task owns this address range */
|
||||||
|
if (pager_validate_user_range(user, userptr, size, vm_flags) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Map first page and calculate the mapped address of pointer */
|
||||||
|
mapped = l4_map_helper((void *)page_to_phys(task_virt_to_page(user, start)), 1);
|
||||||
|
mapped = (void *)(((unsigned long)mapped) |
|
||||||
|
((unsigned long)(PAGE_MASK & (unsigned long)userptr)));
|
||||||
|
|
||||||
|
/* Map the rest of the pages, if any */
|
||||||
|
for (unsigned long i = start + PAGE_SIZE; i < end; i += PAGE_SIZE)
|
||||||
|
l4_map_helper((void *)page_to_phys(task_virt_to_page(user,
|
||||||
|
start + i)), 1);
|
||||||
|
|
||||||
|
return mapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pager_unmap_user_range(void *mapped_ptr, unsigned long size)
|
||||||
|
{
|
||||||
|
l4_unmap_helper((void *)page_align(mapped_ptr),
|
||||||
|
__pfn(page_align(mapped_ptr) + page_align_up(size)));
|
||||||
|
}
|
||||||
|
|
||||||
+7
-4
@@ -22,9 +22,10 @@ void wait_pager(l4id_t partner)
|
|||||||
// printf("Pager synced with us.\n");
|
// printf("Pager synced with us.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
printf("\n%s: Started with tid %d.\n", __TASKNAME__, self_tid());
|
printf("\n%s: Started with tid %d.\n", __TASKNAME__, self_tid());
|
||||||
/* Sync with pager */
|
/* Sync with pager */
|
||||||
@@ -32,12 +33,16 @@ void main(void)
|
|||||||
|
|
||||||
dirtest();
|
dirtest();
|
||||||
|
|
||||||
|
/* Check mmap/munmap */
|
||||||
|
mmaptest();
|
||||||
|
|
||||||
printf("Forking...\n");
|
printf("Forking...\n");
|
||||||
|
|
||||||
if ((pid = fork()) < 0)
|
if ((pid = fork()) < 0)
|
||||||
printf("Error forking...\n");
|
printf("Error forking...\n");
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
|
pid = getpid();
|
||||||
printf("Child: file IO test 1.\n");
|
printf("Child: file IO test 1.\n");
|
||||||
if (fileio() == 0)
|
if (fileio() == 0)
|
||||||
printf("-- PASSED --\n");
|
printf("-- PASSED --\n");
|
||||||
@@ -56,12 +61,10 @@ void main(void)
|
|||||||
else
|
else
|
||||||
printf("-- FAILED --\n");
|
printf("-- FAILED --\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
wait_pager(0);
|
wait_pager(0);
|
||||||
#if 0
|
#if 0
|
||||||
/* Check mmap/munmap */
|
|
||||||
mmaptest();
|
|
||||||
|
|
||||||
/* Check shmget/shmat/shmdt */
|
/* Check shmget/shmat/shmdt */
|
||||||
shmtest();
|
shmtest();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <tests.h>
|
#include <tests.h>
|
||||||
|
|
||||||
int global = 0;
|
int global = 0;
|
||||||
|
extern pid_t pid;
|
||||||
|
|
||||||
int forktest(void)
|
int forktest(void)
|
||||||
{
|
{
|
||||||
@@ -18,6 +19,7 @@ int forktest(void)
|
|||||||
fork();
|
fork();
|
||||||
|
|
||||||
myid = getpid();
|
myid = getpid();
|
||||||
|
pid = myid;
|
||||||
if (global != 0) {
|
if (global != 0) {
|
||||||
printf("-- FAILED --\n");
|
printf("-- FAILED --\n");
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
Reference in New Issue
Block a user