Allow /dev/kmem write to vmalloc space

Allow /dev/kmem write to vmalloc space

Post by Andi Klee » Tue, 05 Feb 2002 09:20:10



Hi Linus,

This patch allows to write vmalloc space via /dev/kmem. Without it is
only readable. Writing is useful for example to change debugging variables
in modules.

The patch is originally from Marc Boucher.

Patch against 2.5.3.
Please consider applying it.

Thanks,
-Andi

--- linux/drivers/char/mem.c-KMEM       Wed Jan 23 12:27:33 2002

                          size_t count, loff_t *ppos)
 {
        unsigned long p = *ppos;
+       ssize_t wrote = 0;
+       ssize_t virtr = 0;
+       char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */

-       if (p >= (unsigned long) high_memory)
-               return 0;
-       if (count > (unsigned long) high_memory - p)
-               count = (unsigned long) high_memory - p;
-       return do_write_mem(file, (void*)p, p, buf, count, ppos);
+       if (p < (unsigned long) high_memory) {
+               wrote = count;
+               if (count > (unsigned long) high_memory - p)
+                       wrote = (unsigned long) high_memory - p;
+
+               wrote = do_write_mem(file, (void*)p, p, buf, wrote, ppos);
+
+               p += wrote;
+               buf += wrote;
+               count -= wrote;
+       }
+
+       if (count > 0) {
+               kbuf = (char *)__get_free_page(GFP_KERNEL);
+               if (!kbuf)
+                       return -ENOMEM;
+               while (count > 0) {
+                       int len = count;
+
+                       if (len > PAGE_SIZE)
+                               len = PAGE_SIZE;
+                       if (len && copy_from_user(kbuf, buf, len)) {
+                               free_page((unsigned long)kbuf);
+                               return -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(__mc68000__)
--- linux/include/linux/vmalloc.h-KMEM  Sun Feb  3 11:15:37 2002

 extern void vfree(void * addr);
 extern void * __vmalloc (unsigned long size, int gfp_mask, pgprot_t prot);
 extern long vread(char *buf, char *addr, unsigned long count);
+extern long vwrite(char *buf, char *addr, unsigned long count);
 extern void vmfree_area_pages(unsigned long address, unsigned long size);
 extern int vmalloc_area_pages(unsigned long address, unsigned long size,
                               int gfp_mask, pgprot_t prot);
--- linux/mm/vmalloc.c-KMEM     Tue Jan 15 06:18:19 2002


  */

+#include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>

                        if (count == 0)
                                goto finished;
                        *buf = *addr;
+                       buf++;
+                       addr++;
+                       count--;
+               } while (--n > 0);
+       }
+finished:
+       read_unlock(&vmlist_lock);
+       return buf - buf_start;
+}
+
+long vwrite(char *buf, char *addr, unsigned long count)
+{
+       struct vm_struct *tmp;
+       char *vaddr, *buf_start = buf;
+       unsigned long n;
+
+       /* Don't allow overflow */
+       if ((unsigned long) addr + count < count)
+               count = -(unsigned long) addr;
+
+       read_lock(&vmlist_lock);
+       for (tmp = vmlist; tmp; tmp = tmp->next) {
+               vaddr = (char *) tmp->addr;
+               if (addr >= vaddr + tmp->size - PAGE_SIZE)
+                       continue;
+               while (addr < vaddr) {
+                       if (count == 0)
+                               goto finished;
+                       buf++;
+                       addr++;
+                       count--;
+               }
+               n = vaddr + tmp->size - PAGE_SIZE - addr;
+               do {
+                       if (count == 0)
+                               goto finished;
+                       *addr = *buf;
                        buf++;
                        addr++;
                        count--;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

1. : Reading kmem addr in UnixWare (/dev/kmem)

Hi Netters,

Can anyone please tell me how to read/write a kernel virtual address in
UnixWare using /dev/kmem  ?

The only ioctls defined in kmem(7) are to read and write for a symbol. What
if I want to read a memory location ?

There is no kvm_ functions in Unixware or USL. I used kvm_ in Solaris, but
these are not available under USL.

Thanks in advance

MW

2. Virtual console and X Windows problem

3. How to write to video memory ( /dev/kmem ?????? )

4. How do I setup an HP 842C printer?

5. Permissions on /dev/kmem and /dev/mem for top?

6. IRIX security running Netscape Navigator?

7. /dev/mem and /dev/kmem with world access?

8. kppp and Global Village Platinum

9. How can I read /dev/mem, /dev/kmem ....?

10. 2.4 fix to allow vmalloc at interrupt time

11. vmalloc and user space

12. Can't write vmalloc() mem in interrupt, 2.1.125/6

13. vmalloc() limit, is BG writing a Linux kernel?