mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Fixed various bugs in user buffer validation/mapping and mmap() syscall path.
This commit is contained in:
@@ -61,7 +61,7 @@ void *mmap2(void *start, size_t length, int prot, int flags, int fd, off_t pgoff
|
||||
errno = -(int)ret;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ void handle_requests(void)
|
||||
case L4_IPC_TAG_MMAP: {
|
||||
struct sys_mmap_args *args = (struct sys_mmap_args *)mr[0];
|
||||
ret = (int)sys_mmap(sender, args);
|
||||
break;
|
||||
}
|
||||
case L4_IPC_TAG_MUNMAP: {
|
||||
ret = sys_munmap(sender, (void *)mr[0], (unsigned long)mr[1]);
|
||||
|
||||
@@ -615,7 +615,7 @@ int sys_read(struct tcb *task, int fd, void *buf, int count)
|
||||
|
||||
/* Check user buffer validity. */
|
||||
if ((ret = pager_validate_user_range(task, buf,
|
||||
(unsigned long)(buf + count),
|
||||
(unsigned long)count,
|
||||
VM_READ)) < 0)
|
||||
return -EFAULT;
|
||||
|
||||
@@ -685,7 +685,7 @@ int sys_write(struct tcb *task, int fd, void *buf, int count)
|
||||
|
||||
/* Check user buffer validity. */
|
||||
if ((ret = pager_validate_user_range(task, buf,
|
||||
(unsigned long)(buf + count),
|
||||
(unsigned long)count,
|
||||
VM_WRITE | VM_READ)) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
@@ -193,7 +193,9 @@ void *do_mmap(struct vm_file *mapfile, unsigned long file_offset,
|
||||
|
||||
/* Check invalid map address */
|
||||
if (!mmap_address_validate(task, map_address, flags)) {
|
||||
if (!(map_address = mmap_new_address(task, flags, npages)))
|
||||
if (flags & VMA_FIXED)
|
||||
return PTR_ERR(-EINVAL);
|
||||
else if (!(map_address = mmap_new_address(task, flags, npages)))
|
||||
return PTR_ERR(-ENOMEM);
|
||||
} else {
|
||||
/*
|
||||
@@ -262,31 +264,22 @@ void *do_mmap(struct vm_file *mapfile, unsigned long file_offset,
|
||||
|
||||
/* mmap system call implementation */
|
||||
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 file_offset)
|
||||
{
|
||||
unsigned long npages = __pfn(page_align_up(length));
|
||||
unsigned long base = (unsigned long)start;
|
||||
struct vm_file *file = 0;
|
||||
unsigned int vmflags = 0;
|
||||
struct vm_file *file = 0;
|
||||
int err;
|
||||
|
||||
/* Check fd validity */
|
||||
/* Check file validity */
|
||||
if (!(flags & MAP_ANONYMOUS))
|
||||
if (!task->files->fd[fd].vmfile)
|
||||
if ((err = file_open(task, fd)) < 0)
|
||||
return PTR_ERR(err);
|
||||
|
||||
if (base < task->start || base >= task->end)
|
||||
/* Check file offset is page aligned */
|
||||
if (!is_page_aligned(file_offset))
|
||||
return PTR_ERR(-EINVAL);
|
||||
|
||||
/* Exclude task's stack, text and data from mmappable area in task's space */
|
||||
if (base < task->map_start || base >= task->map_end || !base) {
|
||||
if (flags & MAP_FIXED) /* Its fixed, we cannot satisfy it */
|
||||
return PTR_ERR(-EINVAL);
|
||||
else
|
||||
start = 0;
|
||||
}
|
||||
|
||||
/* TODO:
|
||||
* Check that @start does not already have a mapping.
|
||||
* Check that pfn + npages range is within the file range.
|
||||
@@ -318,7 +311,8 @@ void *__sys_mmap(struct tcb *task, void *start, size_t length, int prot,
|
||||
if (prot & PROT_EXEC)
|
||||
vmflags |= VM_EXEC;
|
||||
|
||||
return do_mmap(file, __pfn_to_addr(pfn), task, base, vmflags, npages);
|
||||
return do_mmap(file, file_offset, task, (unsigned long)start,
|
||||
vmflags, __pfn(page_align_up(length)));
|
||||
}
|
||||
|
||||
void *sys_mmap(struct tcb *task, struct sys_mmap_args *args)
|
||||
@@ -332,8 +326,9 @@ void *sys_mmap(struct tcb *task, struct sys_mmap_args *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);
|
||||
ret = __sys_mmap(task, mapped_args->start, mapped_args->length,
|
||||
mapped_args->prot, mapped_args->flags, mapped_args->fd,
|
||||
mapped_args->offset);
|
||||
|
||||
pager_unmap_user_range(mapped_args, sizeof(*args));
|
||||
|
||||
|
||||
@@ -68,6 +68,6 @@ void *pager_validate_map_user_range(struct tcb *user, void *userptr,
|
||||
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)));
|
||||
__pfn(page_align_up(size)));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user