分享

Access kernel space from user space by using mmap

 mediatv 2013-08-04


This post will introduce a funny way to access physical memory from user space,  I will:

  • write a kernel module and load it. The module will allocate a page in kernel space and write some characters in this page.
  • write a user program, read the content of that page and print.

What’s the difficulty in doing this ?

As we know, a user program (or process) has its own virtual address space, when it calls malloc() to apply a block of memory, the malloc will return the start address of  the allocated virtual memory,  user program doesn’t know the actual start address of physical memory.

Here, I will access the physicall address from a user program with the help of /dev/mem.

Firstly, let’s talk about /dev/mem, and enable access to /dev/mem

/dev/mem is a virtual device which provides a way to access to system physical memory, but unfortunately, in most Linux distributions,  userspace(including root) can’t read /dev/mem by default [1].   So, if you want to use this feature, please compile a new kernel by yourself.  I will show you step by step.

  • go to www.kernel.org download a latest version of linux kernel.
  • decompress it.

the following is in command line ( shell ):
$ sudo su                           //change to root
# make menuconfig      // this will generate a .config file
# vim .config
set
CONFIG_STRICT_DEVMEM=n
CONFIG_X86_PAT=n
CONFIG_EXPERT=y

ok, continue to compile it.
# make -j4
# make modules
# make module_install
# make install
reboot my computer, and I will enter OS with a new kernel.

Secondly, let’s write a kernel module.

mmap.c :

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>

MODULE_LICENSE(“GPL”);
MODULE_AUTHOR(“Runzhen”);
MODULE_DESCRIPTION(“mmap demo”);

static unsigned long addr = 0;

static int __init mod_init(void)
{
//alloc a page
addr = __get_free_pages(GFP_KERNEL, 0); //kernel virtual address
SetPageReserved(virt_to_page(addr));

printk(“addr= 0x%08x\n”, (int)addr);

// write something
strcpy((char *)addr, “With great power, comes great responsibility\n”);
return 0;
}

static void __exit mod_exit(void)
{
ClearPageReserved(virt_to_page(addr));
free_pages(addr, 0);
}

module_init(mod_init);
module_exit(mod_exit);

 

to compile the kernel module,  I need a Makefile:

obj-m:=mmap.o

CURRENT_PATH :=$(shell pwd)
LINUX_PATH :=/home/run/linux-3.6.11/

all :
make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules

# make
after make, a kernel module “mmap.ko” will appears in my current directory.
# insmod mmap.ko
then, look the “printk(“addr= 0x%08x\n”, (int)addr);” in `dmesg`
# dmesg         // will show:

[80005.141345] addr= 0×77128000

Finally, write a user program using mmap() function.

the declaration of mmap is:

void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

`man 2 mmap` says:

The contents of a file mapping are initialized using `length` bytes starting at offset `offset` in the file (or other object) referred to by the file descriptor fd. `offset` must be a multiple of the page size.

so,  I can use the address printed by mmap.ko (0×77128000) as the `offset` parameter.

user.c

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

#define PAGE_SIZE (4 * 1024)

#define KERNEL_PHY_ADDR 0×77128000
int main()
{
char *buf;
int fd;

fd = open(“/dev/mem”,O_RDWR);
if (fd == -1)
perror(“open”);

buf = mmap(0, PAGE_SIZE,
PROT_READ|PROT_WRITE, MAP_SHARED,
fd, KERNEL_PHY_ADDR);

if (buf == MAP_FAILED)
perror(“mmap”);

puts(buf);

munmap(buf,PAGE_SIZE);

close(fd);
return 0;
}

Attention, the KERNEL_PHY_ADDR may vary every time you load the mmap.ko, so, if you copy the code and complie it on your own computer, please remember to change it.

ok, compile user.c
# gcc -o user user.c

make sure you are a super user
# ./user

the out put is:

With great power, comes great responsibility

Game Over.

If you meet any problem, please feel free to contact with me.

Code

https://github.com/run/misc_code/tree/master/mmap

References

[1] http:///Articles/267427/
[2] http:///questions/9662193/how-to-access-kernel-space-from-user-spacein-linux
[3] http://hi.baidu.com/damonzhou/item/e15d06e9ae20f1f5e1a5d4a9

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多