Skip to content

Commit

Permalink
Fix get_unmapped_area sanity tests
Browse files Browse the repository at this point in the history
As noted by Chris Wright, we need to do the full range of tests regardless
of whether MAP_FIXED is set or not, so re-organize get_unmapped_area()
slightly to do the sanity checks unconditionally.
  • Loading branch information
Linus Torvalds committed May 20, 2005
1 parent 66e60f9 commit 07ab67c
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 29 deletions.
4 changes: 3 additions & 1 deletion include/linux/err.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
* This should be a per-architecture thing, to allow different
* error and pointer decisions.
*/
#define IS_ERR_VALUE(x) unlikely((x) > (unsigned long)-1000L)

static inline void *ERR_PTR(long error)
{
return (void *) error;
Expand All @@ -25,7 +27,7 @@ static inline long PTR_ERR(const void *ptr)

static inline long IS_ERR(const void *ptr)
{
return unlikely((unsigned long)ptr > (unsigned long)-1000L);
return IS_ERR_VALUE((unsigned long)ptr);
}

#endif /* _LINUX_ERR_H */
59 changes: 31 additions & 28 deletions mm/mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1302,37 +1302,40 @@ unsigned long
get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags)
{
if (flags & MAP_FIXED) {
unsigned long ret;
unsigned long ret;

if (addr > TASK_SIZE - len)
return -ENOMEM;
if (addr & ~PAGE_MASK)
return -EINVAL;
if (file && is_file_hugepages(file)) {
/*
* Check if the given range is hugepage aligned, and
* can be made suitable for hugepages.
*/
ret = prepare_hugepage_range(addr, len);
} else {
/*
* Ensure that a normal request is not falling in a
* reserved hugepage range. For some archs like IA-64,
* there is a separate region for hugepages.
*/
ret = is_hugepage_only_range(current->mm, addr, len);
}
if (ret)
return -EINVAL;
return addr;
}
if (!(flags & MAP_FIXED)) {
unsigned long (*get_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);

if (file && file->f_op && file->f_op->get_unmapped_area)
return file->f_op->get_unmapped_area(file, addr, len,
pgoff, flags);
get_area = current->mm->get_unmapped_area;
if (file && file->f_op && file->f_op->get_unmapped_area)
get_area = file->f_op->get_unmapped_area;
addr = get_area(file, addr, len, pgoff, flags);
if (IS_ERR_VALUE(addr))
return addr;
}

return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
if (addr > TASK_SIZE - len)
return -ENOMEM;
if (addr & ~PAGE_MASK)
return -EINVAL;
if (file && is_file_hugepages(file)) {
/*
* Check if the given range is hugepage aligned, and
* can be made suitable for hugepages.
*/
ret = prepare_hugepage_range(addr, len);
} else {
/*
* Ensure that a normal request is not falling in a
* reserved hugepage range. For some archs like IA-64,
* there is a separate region for hugepages.
*/
ret = is_hugepage_only_range(current->mm, addr, len);
}
if (ret)
return -EINVAL;
return addr;
}

EXPORT_SYMBOL(get_unmapped_area);
Expand Down

0 comments on commit 07ab67c

Please sign in to comment.