]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/char/mem.c
x86: introduce /dev/mem restrictions with a config option
[linux-2.6-omap-h63xx.git] / drivers / char / mem.c
index 0e937f64a789f8cafe985236e1164f632de1589a..dcf6e31970a1cf62d02142dd8299aba2906e4f19 100644 (file)
@@ -41,7 +41,7 @@
  */
 static inline int uncached_access(struct file *file, unsigned long addr)
 {
-#if defined(__i386__)
+#if defined(__i386__) && !defined(__arch_um__)
        /*
         * On the PPro and successors, the MTRRs are used to set
         * memory types for physical addresses outside main memory,
@@ -57,7 +57,7 @@ static inline int uncached_access(struct file *file, unsigned long addr)
                  test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
                  test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) )
          && addr >= __pa(high_memory);
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) && !defined(__arch_um__)
        /* 
         * This is broken because it can generate memory type aliases,
         * which can cause cache corruptions
@@ -108,6 +108,30 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
 }
 #endif
 
+#ifdef CONFIG_NONPROMISC_DEVMEM
+static inline int range_is_allowed(unsigned long from, unsigned long to)
+{
+       unsigned long cursor;
+
+       cursor = from >> PAGE_SHIFT;
+       while ((cursor << PAGE_SHIFT) < to) {
+               if (!devmem_is_allowed(cursor)) {
+                       printk(KERN_INFO "Program %s tried to read /dev/mem "
+                               "between %lx->%lx.\n",
+                               current->comm, from, to);
+                       return 0;
+               }
+               cursor++;
+       }
+       return 1;
+}
+#else
+static inline int range_is_allowed(unsigned long from, unsigned long to)
+{
+       return 1;
+}
+#endif
+
 /*
  * This funcion reads the *physical* memory. The f_pos points directly to the 
  * memory location. 
@@ -157,6 +181,8 @@ static ssize_t read_mem(struct file * file, char __user * buf,
                 */
                ptr = xlate_dev_mem_ptr(p);
 
+               if (!range_is_allowed(p, p+count))
+                       return -EPERM;
                if (copy_to_user(buf, ptr, sz))
                        return -EFAULT;
                buf += sz;
@@ -214,6 +240,8 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
                 */
                ptr = xlate_dev_mem_ptr(p);
 
+               if (!range_is_allowed(p, p+sz))
+                       return -EPERM;
                copied = copy_from_user(ptr, buf, sz);
                if (copied) {
                        written += sz - copied;