Fixed various bugs in user buffer validation/mapping and mmap() syscall path.

This commit is contained in:
Bahadir Balban
2008-11-07 12:32:10 +02:00
parent ca8959eee0
commit 3cb36b632a
5 changed files with 18 additions and 22 deletions

View File

@@ -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;
}

View File

@@ -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]);

View File

@@ -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;

View File

@@ -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));

View File

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