内核空间可以直接访问应用层空间地址

在linux驱动编写过程中, 如果要实现内核和应用的数据传递通常用copy_from/to_user()函数, 如果如果直接用mmecpy来传递, 可能会导致内核安全漏洞! 内核可以直接操作应用层的地址空间。

以下是个例子:

==========================内核 ko部分=======================

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>

#define DEVNAME "wdt"

struct wdt_regs {
    u32 wtcon;
    u32 wtdat;
    u32 wtcnt;
    u32 wtclrint;
};

enum {
    START = 100,
    STOP = 101,
    COUNT = 102,
    RESET = 103,
    INT = 104,
};

static struct wdt_info {
    struct miscdevice dev;
    struct file_operations fops;
    struct wdt_regs *regs;
} info;

static long wdt_ioctl(struct file *fp, unsigned int cmd, unsigned long data)
{
    struct wdt_regs *p = NULL;
    switch (cmd) {
        case START:
        printk("int data = %d\n", data);
        break;
    case STOP:
        p = (struct wdt_regs *)data;
        printk("addr=%p p->wtcon=%d\n", p, p->wtcon);
        break;
    case COUNT:
        break;
    case RESET:
         break;
    case INT:
        break;
    }
}

static int wdt_init(void)
{
    printk("%s\n", __FUNCTION__);
    info.dev.minor = MISC_DYNAMIC_MINOR;
    info.dev.name = DEVNAME;
    info.dev.fops = &info.fops;
    info.fops.unlocked_ioctl = wdt_ioctl;
    if (misc_register(&info.dev) < 0) {
        printk("misc_register failed\n");
        goto err_misc_register;
    }
    return 0;
err_misc_register:
    return -1;
}

static void wdt_exit(void)
{
    printk("%s\n", __FUNCTION__);
    misc_deregister(&info.dev);
}

module_init(wdt_init);
module_exit(wdt_exit);
MODULE_LICENSE("GPL");

 

==============================应用层部分=========================

#include <stdio.h>
#include <fcntl.h>

typedef unsigned int u32;

struct wdt_regs {
    u32 wtcon;
    u32 wtdat;
    u32 wtcnt;
    u32 wtclrint;
}data;

enum {
    START = 100,
    STOP = 101,
    COUNT = 102,
    RESET = 103,
    INT = 104,
};

int main()
{
    int tt = 111;
    int fd = open("/dev/wdt", O_RDWR);
    if (fd < 0) {
        perror("open");
        goto err_open;
    }
    data.wtcon = 1001;
    ioctl(fd, START, tt);
    printf("p=%p\n", &data);
    ioctl(fd, STOP, &data);

    close(fd);

    return 0;

err_open:
    return -1;
}

 

 

==================运行结果=========================

root@ubuntu:~/Desktop/test-ioctl# insmod test.ko

root@ubuntu:~/Desktop/test-ioctl# ./a.out
p=0x601070
root@ubuntu:~/Desktop/test-ioctl# dmesg
[322937.889964] int data = 111
[322937.890010] addr=0000000000601070 p->wtcon=1001
root@ubuntu:~/Desktop/test-ioctl#

从以上的应用层打印地址和内核的打印地址信息看, 两个值是相等的!

 

posted on 2019-06-10 10:34  绿色star  阅读(576)  评论(0编辑  收藏  举报

导航