注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

蒙奇D小豌豆的博客

蒙奇D小豌豆的学习记录

 
 
 

日志

 
 

userspace access kernel address through /dev/kmem  

2012-01-17 19:26:49|  分类: kernel |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
IN X86 
/* CONFIG_STRICT_DEVMEM use function range_is_allowed to allow ram<1M and no ram I/O  return 1*/
1. if the address is ram and  > 1M:
must be check CONFIG_STRICT_DEVMEM both in drivers/char/mem.c and arch/x86/mm/pat.c  can not use range_is_allowed return 0.
2. the address is not support HIGHMEM(< 896M)

mmap_dev_kmem.c

#include <linux/version.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/mm.h>
/*must be open CONFIG_DEVKMEM*/
/*must be check CONFIG_STRICT_DEVMEM both in drivers/char/mem.c
arch/x86/mm/pat.c  can not use range_is_allowed return 0*/
/* CONFIG_STRICT_DEVMEM use function range_is_allowed to allow ram<1M and no ram I/O  return 1*/
#define PROC_MEMSHARE_DIR                                "memshare"
#define PROC_MEMSHARE_VIRTADDR                        "virtual_addr"
#define PROC_MEMSHARE_SIZE                                "virtual_size"

/*alloc one page. 4096 bytes*/
#define PAGE_ORDER                                0
/*this value can get from PAGE_ORDER*/
#define PAGES_NUMBER                                1

struct proc_dir_entry *proc_memshare_dir ;
struct proc_dir_entry *proc_entry_addr ;
struct proc_dir_entry *proc_entry_size ;
unsigned long kernel_memaddr = 0;
unsigned long kernel_memsize= 0;

char* test_string = "hello world!";

static ssize_t proc_read_virtmem_addr(char *page, char **start, off_t off, int count, int*eof, void *data)
{
        return sprintf(page, "%08lx\n", kernel_memaddr);
}
static ssize_t proc_read_virtmem_size(char *page, char **start, off_t off, int count, int*eof, void *data)
{
        return sprintf(page, "%lu\n", kernel_memsize);
}

static int __init init(void)
{
        /*build proc dir "memshare"and two proc files: phymem_addr, phymem_size in the dir*/
        proc_memshare_dir = proc_mkdir(PROC_MEMSHARE_DIR, NULL);
        proc_entry_addr = create_proc_entry(PROC_MEMSHARE_VIRTADDR, 0666, proc_memshare_dir);
        proc_entry_size = create_proc_entry(PROC_MEMSHARE_SIZE, 0666, proc_memshare_dir);
proc_entry_addr->read_proc = proc_read_virtmem_addr;
proc_entry_size->read_proc = proc_read_virtmem_size;

        /*alloc one page*/
        kernel_memaddr =__get_free_page(GFP_KERNEL);
        if(!kernel_memaddr)
        {
                printk("Allocate memory failure!\n");
        }
        else
        {
                SetPageReserved(virt_to_page(kernel_memaddr));
                kernel_memsize = PAGES_NUMBER * PAGE_SIZE;
                printk("Allocate memory success!. The virt mem addr=0x%08lx, size=0x%lx\n", kernel_memaddr, kernel_memsize);
strcpy((char*)kernel_memaddr, test_string);
printk("The content defeaut is: %s\n", (unsigned char *)kernel_memaddr);
        }
        return 0;
}

static void __exit fini(void)
{
        printk("The content written by user is: %s\n", (unsigned char *)kernel_memaddr);
        ClearPageReserved(virt_to_page(kernel_memaddr));
        free_pages(kernel_memaddr, PAGE_ORDER);
        remove_proc_entry(PROC_MEMSHARE_VIRTADDR, proc_memshare_dir);
        remove_proc_entry(PROC_MEMSHARE_SIZE, proc_memshare_dir);
        remove_proc_entry(PROC_MEMSHARE_DIR, NULL);

        return;
}
module_init(init);
module_exit(fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wenx05124561@163.com)");
MODULE_DESCRIPTION("Kernel memory share module.");


test.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>


#define PAGE_SHIFT      12
#define PAGE_SIZE       ((1UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
int kfd = -1;

void* get_var(unsigned long addr, unsigned long size, unsigned long *offset) {
        *offset = addr & ~(PAGE_MASK);
        unsigned long ptr = addr & PAGE_MASK;
        void *map;
        

        kfd = open("/dev/kmem",O_RDWR);
        if (kfd < 0) {
                perror("open");
                exit(0);
        }
        map = mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,kfd,ptr);
        if (map == MAP_FAILED) {
                perror("mmap");
                exit(-1);
        }
        return map + *offset;
}

int main(int argc, char* argv[])
{
        
        
        unsigned long virtual_addr, virtual_size;
        void *map_addr;
        char s[256];
        int fd;
unsigned long offset;

if(argc != 2)
        {
                printf("Usage: %s string\n", argv[0]);
                return 0;
        }
        
        /*get the virtual address of allocated memory in kernel*/
        fd = open("/proc/memshare/virtual_addr", O_RDONLY);
        if(fd < 0)
        {
                printf("cannot open file /proc/memshare/virtual_addr\n");
                return 0;
        }
        read(fd, s, sizeof(s));
        sscanf(s, "%lx", &virtual_addr);
        close(fd);

        /*get the size of allocated memory in kernel*/
        fd = open("/proc/memshare/virtual_size", O_RDONLY);
        if(fd < 0)
        {
                printf("cannot open file /proc/memshare/virtual_size\n");
                return 0;
        }
        read(fd, s, sizeof(s));
        sscanf(s, "%lu", &virtual_size);
        close(fd);
        
        printf("vitual_addr=0x%lx, vitual_size=0x%lx\n", virtual_addr, virtual_size);
map_addr = get_var(virtual_addr, virtual_size, &offset);
printf("after map\n");
        strcpy(map_addr, argv[1]);
printf("mem content is:%s\n", (char*)map_addr);

        munmap(map_addr - offset, virtual_size);
        close(kfd);

        return 0;
}

  评论这张
 
阅读(323)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018