在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#
从以上的应用层打印地址和内核的打印地址信息看, 两个值是相等的!