aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/mem.c
diff options
context:
space:
mode:
authorVenki Pallipadi <venkatesh.pallipadi@intel.com>2008-03-07 02:01:47 -0500
committerIngo Molnar <mingo@elte.hu>2008-04-24 17:40:47 -0400
commite2beb3eae627211b67e456c53f946cede2ac10d7 (patch)
treef0b629adb961004b9026cb3b2ff4d1d370dbc01f /drivers/char/mem.c
parentae531c26c5c2a28ca1b35a75b39b3b256850f2c8 (diff)
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>
Diffstat (limited to 'drivers/char/mem.c')
-rw-r--r--drivers/char/mem.c27
1 files changed, 16 insertions, 11 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index dcf6e31970a1..964ff3b1cff4 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -109,24 +109,26 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
109#endif 109#endif
110 110
111#ifdef CONFIG_NONPROMISC_DEVMEM 111#ifdef CONFIG_NONPROMISC_DEVMEM
112static inline int range_is_allowed(unsigned long from, unsigned long to) 112static inline int range_is_allowed(unsigned long pfn, unsigned long size)
113{ 113{
114 unsigned long cursor; 114 u64 from = ((u64)pfn) << PAGE_SHIFT;
115 u64 to = from + size;
116 u64 cursor = from;
115 117
116 cursor = from >> PAGE_SHIFT; 118 while (cursor < to) {
117 while ((cursor << PAGE_SHIFT) < to) { 119 if (!devmem_is_allowed(pfn)) {
118 if (!devmem_is_allowed(cursor)) { 120 printk(KERN_INFO
119 printk(KERN_INFO "Program %s tried to read /dev/mem " 121 "Program %s tried to access /dev/mem between %Lx->%Lx.\n",
120 "between %lx->%lx.\n",
121 current->comm, from, to); 122 current->comm, from, to);
122 return 0; 123 return 0;
123 } 124 }
124 cursor++; 125 cursor += PAGE_SIZE;
126 pfn++;
125 } 127 }
126 return 1; 128 return 1;
127} 129}
128#else 130#else
129static inline int range_is_allowed(unsigned long from, unsigned long to) 131static inline int range_is_allowed(unsigned long pfn, unsigned long size)
130{ 132{
131 return 1; 133 return 1;
132} 134}
@@ -181,7 +183,7 @@ static ssize_t read_mem(struct file * file, char __user * buf,
181 */ 183 */
182 ptr = xlate_dev_mem_ptr(p); 184 ptr = xlate_dev_mem_ptr(p);
183 185
184 if (!range_is_allowed(p, p+count)) 186 if (!range_is_allowed(p >> PAGE_SHIFT, count))
185 return -EPERM; 187 return -EPERM;
186 if (copy_to_user(buf, ptr, sz)) 188 if (copy_to_user(buf, ptr, sz))
187 return -EFAULT; 189 return -EFAULT;
@@ -240,7 +242,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
240 */ 242 */
241 ptr = xlate_dev_mem_ptr(p); 243 ptr = xlate_dev_mem_ptr(p);
242 244
243 if (!range_is_allowed(p, p+sz)) 245 if (!range_is_allowed(p >> PAGE_SHIFT, sz))
244 return -EPERM; 246 return -EPERM;
245 copied = copy_from_user(ptr, buf, sz); 247 copied = copy_from_user(ptr, buf, sz);
246 if (copied) { 248 if (copied) {
@@ -309,6 +311,9 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
309 if (!private_mapping_ok(vma)) 311 if (!private_mapping_ok(vma))
310 return -ENOSYS; 312 return -ENOSYS;
311 313
314 if (!range_is_allowed(vma->vm_pgoff, size))
315 return -EPERM;
316
312 vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, 317 vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
313 size, 318 size,
314 vma->vm_page_prot); 319 vma->vm_page_prot);