This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / char / mem.c
index 3274c3a..54185b9 100644 (file)
@@ -31,9 +31,6 @@
 # include <linux/efi.h>
 #endif
 
-#ifdef CONFIG_FB
-extern void fbmem_init(void);
-#endif
 #if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
 extern void tapechar_init(void);
 #endif
@@ -86,7 +83,7 @@ static inline int uncached_access(struct file *file, unsigned long addr)
         * above the IO hole... Ah, and of course, XFree86 doesn't pass
         * O_SYNC when mapping us to tap IO space. Surprised ?
         */
-       return !page_is_ram(addr);
+       return !page_is_ram(addr >> PAGE_SHIFT);
 #else
        /*
         * Accessing memory above the top the kernel knows about or through a file pointer
@@ -114,6 +111,18 @@ static inline int valid_phys_addr_range(unsigned long addr, size_t *count)
 }
 #endif
 
+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))
+                       return 0;
+               cursor++;
+       }
+       return 1;
+}
 static ssize_t do_write_mem(void *p, unsigned long realp,
                            const char __user * buf, size_t count, loff_t *ppos)
 {
@@ -133,6 +142,8 @@ static ssize_t do_write_mem(void *p, unsigned long realp,
                written+=sz;
        }
 #endif
+       if (!range_is_allowed(realp, realp+count))
+               return -EPERM;
        copied = copy_from_user(p, buf, count);
        if (copied) {
                ssize_t ret = written + (count - copied);
@@ -176,6 +187,8 @@ static ssize_t read_mem(struct file * file, char __user * buf,
                }
        }
 #endif
+       if (!range_is_allowed(p, p+count))
+               return -EPERM;
        if (copy_to_user(buf, __va(p), count))
                return -EFAULT;
        read += count;
@@ -232,6 +245,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
        ssize_t read = 0;
        ssize_t virtr = 0;
        char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
+       
+       return -EPERM;
                
        if (p < (unsigned long) high_memory) {
                read = count;
@@ -285,65 +300,6 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
        return virtr + read;
 }
 
-/*
- * This function writes to the *virtual* memory as seen by the kernel.
- */
-static ssize_t write_kmem(struct file * file, const char __user * buf, 
-                         size_t count, loff_t *ppos)
-{
-       unsigned long p = *ppos;
-       ssize_t wrote = 0;
-       ssize_t virtr = 0;
-       ssize_t written;
-       char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
-
-       if (p < (unsigned long) high_memory) {
-
-               wrote = count;
-               if (count > (unsigned long) high_memory - p)
-                       wrote = (unsigned long) high_memory - p;
-
-               written = do_write_mem((void*)p, p, buf, wrote, ppos);
-               if (written != wrote)
-                       return written;
-               wrote = written;
-               p += wrote;
-               buf += wrote;
-               count -= wrote;
-       }
-
-       if (count > 0) {
-               kbuf = (char *)__get_free_page(GFP_KERNEL);
-               if (!kbuf)
-                       return wrote ? wrote : -ENOMEM;
-               while (count > 0) {
-                       int len = count;
-
-                       if (len > PAGE_SIZE)
-                               len = PAGE_SIZE;
-                       if (len) {
-                               written = copy_from_user(kbuf, buf, len);
-                               if (written) {
-                                       ssize_t ret;
-
-                                       free_page((unsigned long)kbuf);
-                                       ret = wrote + virtr + (len - written);
-                                       return ret ? ret : -EFAULT;
-                               }
-                       }
-                       len = vwrite(kbuf, (char *)p, len);
-                       count -= len;
-                       buf += len;
-                       virtr += len;
-                       p += len;
-               }
-               free_page((unsigned long)kbuf);
-       }
-
-       *ppos = p;
-       return virtr + wrote;
-}
-
 #if defined(CONFIG_ISA) || !defined(__mc68000__)
 static ssize_t read_port(struct file * file, char __user * buf,
                         size_t count, loff_t *ppos)
@@ -416,7 +372,7 @@ static inline size_t read_zero_pagealigned(char __user * buf, size_t size)
 
                if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0)
                        goto out_up;
-               if (vma->vm_flags & VM_SHARED)
+               if (vma->vm_flags & (VM_SHARED | VM_HUGETLB))
                        break;
                count = vma->vm_end - addr;
                if (count > size)
@@ -594,7 +550,6 @@ static struct file_operations mem_fops = {
 static struct file_operations kmem_fops = {
        .llseek         = memory_lseek,
        .read           = read_kmem,
-       .write          = write_kmem,
        .mmap           = mmap_kmem,
        .open           = open_kmem,
 };
@@ -700,7 +655,6 @@ static const struct {
        struct file_operations  *fops;
 } devlist[] = { /* list of minor devices */
        {1, "mem",     S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
-       {2, "kmem",    S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
        {3, "null",    S_IRUGO | S_IWUGO,           &null_fops},
 #if defined(CONFIG_ISA) || !defined(__mc68000__)
        {4, "port",    S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
@@ -730,9 +684,6 @@ static int __init chr_dev_init(void)
                                S_IFCHR | devlist[i].mode, devlist[i].name);
        }
        
-#if defined (CONFIG_FB)
-       fbmem_init();
-#endif
        return 0;
 }