Linux设备驱动代码一枚,可用于练习各种漏洞利用。
一、设备驱动
/* demo.c */
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
MODULE_LICENSE("Dual BSD/GPL");
#define DEMO_MAJOR 255
#define DEMO_MINOR 0
#define DEMO_COUNT 1
dev_t dev = 0;
u32 demo_major = 0;
u32 demo_minor = 0;
struct cdev demo_cdev;
struct class *dev_class = NULL;
struct device *dev_device = NULL;
int demo_open(struct inode* inode, struct file *filp) {
printk("enter demo_open() ");
return 0;
}
ssize_t demo_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) {
char s[10] = {0};
printk("enter demo_read() ");
/* ADD CODE HERE */
copy_from_user(s, buf, sizeof(s)-1);
printk("read from userspace = %s ", s);
return 0;
}
ssize_t demo_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset) {
printk("enter demo_write() ");
return 0;
}
/*
int demo_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data)
{
printk("enter demo_ioctl() ");
return 0;
}
*/
int demo_release(struct inode *inode, struct file *filp) {
printk("enter demo_release() ");
return 0;
}
struct file_operations demo_fops = {
.owner = THIS_MODULE,
.open = demo_open,
.read = demo_read,
.write = demo_write,
/*.ioctl = demo_ioctl,*/
.release = demo_release,
};
int __init demo_init(void) {
int ret = 0;
printk("enter demo_init() ");
if(demo_major) {
dev = MKDEV(DEMO_MAJOR, DEMO_MINOR);
ret = register_chrdev_region(dev, DEMO_COUNT, "demo_demo");
} else {
ret = alloc_chrdev_region(&dev, demo_minor, DEMO_COUNT, "demo_demo02");
}
if(ret < 0) {
printk("register_chrdev_region failed! ");
goto fail_register_chrdev;
}
demo_major = MAJOR(dev);
printk("demo_major = %d ", demo_major);
cdev_init(&demo_cdev, &demo_fops);
ret = cdev_add(&demo_cdev, dev, DEMO_COUNT);
if(ret < 0) {
printk("cdev_add failed! ");
goto fail_cdev_add;
}
dev_class = class_create(THIS_MODULE, "demo_class");
if(IS_ERR(dev_class)) {
printk("class_create failed! ");
ret = PTR_ERR("dev_class");
goto fail_class_create;
}
dev_device = device_create(dev_class, NULL, dev, NULL, "demo%d", demo_minor);
if(IS_ERR(dev_device)) {
printk("device_create failed! ");
ret = PTR_ERR(dev_device);
goto fail_device_create;
}
return 0;
fail_device_create:
class_destroy(dev_class);
fail_class_create:
cdev_del(&demo_cdev);
fail_cdev_add:
unregister_chrdev_region(dev, DEMO_COUNT);
fail_register_chrdev:
return ret;
}
void __exit demo_exit(void) {
printk("enter demo_exit() ");
device_destroy(dev_class, dev);
class_destroy(dev_class);
cdev_del(&demo_cdev);
unregister_chrdev_region(dev, DEMO_COUNT);
}
module_init(demo_init);
module_exit(demo_exit);
二、Makefile 文件
/* Makefile */
ifneq ($(KERNELRELEASE),)
obj-m := demo.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers
三、驱动安装脚本
/* setup.sh */
rmmod demo
insmod ./demo.ko
chmod 666 /dev/demo0
四、简单测试
/* client.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
int
main(int arg, char **argv) {
char *s = (char*)malloc(20);
memcpy(s, "hello driver.", 10);
int fd = -1;
if (-1 == (fd = open("/dev/demo0", O_RDONLY))) {
perror("open");
return (-1);
}
read(fd, s, 0, 0);
//system("/bin/sh");
return (0);
}
五、测试结果
kiiim@ubuntu :~/__demo_driver$ ./client
kiiim@ubuntu :~/__demo_driver$ dmesg
……
[ 4405.506553] enter demo_init()
[ 4405.506558] demo_major = 247
[ 4408.702358] enter demo_open()
[ 4408.702365] enter demo_read()
[ 4408.702366] read from userspace = hello dri
[ 4408.702527] enter demo_release()
kiiim@ubuntu :~/__demo_driver$