zoukankan      html  css  js  c++  java
  • 内核空间可以直接访问应用层空间地址

    在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 ", data);
            break;
        case STOP:
            p = (struct wdt_regs *)data;
            printk("addr=%p p->wtcon=%d ", p, p->wtcon);
            break;
        case COUNT:
            break;
        case RESET:
             break;
        case INT:
            break;
        }
    }

    static int wdt_init(void)
    {
        printk("%s ", __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 ");
            goto err_misc_register;
        }
        return 0;
    err_misc_register:
        return -1;
    }

    static void wdt_exit(void)
    {
        printk("%s ", __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 ", &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#

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

  • 相关阅读:
    漫谈C语言结构体
    如何理解c和c++的复杂类型声明
    STM32 时钟系统
    STM32 系统架构
    运放参数的详细解释和分析-part1,输入偏置电流和输入失调电流【转】
    ROM、RAM、DRAM、SRAM、FLASH的区别?
    FATFS模块应用笔记
    关于I2C和SPI总线协议【转】
    USB编程概念
    Ubuntu手机识别
  • 原文地址:https://www.cnblogs.com/newjiang/p/10996379.html
Copyright © 2011-2022 走看看