devmem: add range_is_allowed() check to mmap of /dev/mem
Earlier patch that introduced CONFIG_NONPROMISC_DEVMEM, did the range_is_allowed() check only for read and write. Add range_is_allowed() check to mmap of /dev/mem as well. Changes the paramaters of range_is_allowed() to pfn and size to handle more than 32 bits of physical address on 32 bit arch cleanly. Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
ae531c26c5
commit
e2beb3eae6
1 changed files with 16 additions and 11 deletions
|
@ -109,24 +109,26 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NONPROMISC_DEVMEM
|
#ifdef CONFIG_NONPROMISC_DEVMEM
|
||||||
static inline int range_is_allowed(unsigned long from, unsigned long to)
|
static inline int range_is_allowed(unsigned long pfn, unsigned long size)
|
||||||
{
|
{
|
||||||
unsigned long cursor;
|
u64 from = ((u64)pfn) << PAGE_SHIFT;
|
||||||
|
u64 to = from + size;
|
||||||
|
u64 cursor = from;
|
||||||
|
|
||||||
cursor = from >> PAGE_SHIFT;
|
while (cursor < to) {
|
||||||
while ((cursor << PAGE_SHIFT) < to) {
|
if (!devmem_is_allowed(pfn)) {
|
||||||
if (!devmem_is_allowed(cursor)) {
|
printk(KERN_INFO
|
||||||
printk(KERN_INFO "Program %s tried to read /dev/mem "
|
"Program %s tried to access /dev/mem between %Lx->%Lx.\n",
|
||||||
"between %lx->%lx.\n",
|
|
||||||
current->comm, from, to);
|
current->comm, from, to);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
cursor++;
|
cursor += PAGE_SIZE;
|
||||||
|
pfn++;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline int range_is_allowed(unsigned long from, unsigned long to)
|
static inline int range_is_allowed(unsigned long pfn, unsigned long size)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -181,7 +183,7 @@ static ssize_t read_mem(struct file * file, char __user * buf,
|
||||||
*/
|
*/
|
||||||
ptr = xlate_dev_mem_ptr(p);
|
ptr = xlate_dev_mem_ptr(p);
|
||||||
|
|
||||||
if (!range_is_allowed(p, p+count))
|
if (!range_is_allowed(p >> PAGE_SHIFT, count))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
if (copy_to_user(buf, ptr, sz))
|
if (copy_to_user(buf, ptr, sz))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -240,7 +242,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
|
||||||
*/
|
*/
|
||||||
ptr = xlate_dev_mem_ptr(p);
|
ptr = xlate_dev_mem_ptr(p);
|
||||||
|
|
||||||
if (!range_is_allowed(p, p+sz))
|
if (!range_is_allowed(p >> PAGE_SHIFT, sz))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
copied = copy_from_user(ptr, buf, sz);
|
copied = copy_from_user(ptr, buf, sz);
|
||||||
if (copied) {
|
if (copied) {
|
||||||
|
@ -309,6 +311,9 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
|
||||||
if (!private_mapping_ok(vma))
|
if (!private_mapping_ok(vma))
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
|
||||||
|
if (!range_is_allowed(vma->vm_pgoff, size))
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
|
vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
|
||||||
size,
|
size,
|
||||||
vma->vm_page_prot);
|
vma->vm_page_prot);
|
||||||
|
|
Loading…
Reference in a new issue