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 :

to compile the kernel module, I need a Makefile:

# 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

[80005.141345] addr= 0x77128000

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 (0x77128000) as the `offset` parameter.

user.c

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

That’s all.

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

Tags: ,. 25,745 views
Home

9 Comments so far

Trackbacks/Pingbacks

Leave a comment

Name(required)
Mail (required),(will not be published)
Website(recommended)

Fields in bold are required. Email addresses are never published or distributed.

Some HTML code is allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
URLs must be fully qualified (eg: http://blog.nlogn.cn),and all tags must be properly closed.

Line breaks and paragraphs are automatically converted.

Please keep comments relevant. Off-topic, offensive or inappropriate comments may be edited or removed.