受到@comintern的启发。
替换/ dev / null。参与偷偷摸摸的模式。需要内核头文件,超级用户模式和有效的编译器。
# make
# rm /dev/null
# insmod devnull.ko
# chmod go+rw /dev/null
玩得开心。
生成文件:
MODULE := devnull
KVERS ?= $(shell uname -r)
KDIR ?= /lib/modules/$(KVERS)/build
KMAKE := make -C $(KDIR) M=$(PWD)
obj-m += $(MODULE).o
all:
$(KMAKE) modules
install:
$(KMAKE) modules_install
clean:
$(KMAKE) clean
源代码:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#define DEVICE_NAME "null"
#define MAJOR_NUMBER 0
MODULE_LICENSE("GPL");
MODULE_AUTHOR("nola <florian@n0la.org>");
MODULE_DESCRIPTION("/dev/null - memory leak style");
MODULE_VERSION("0.1");
MODULE_SUPPORTED_DEVICE("null");
static struct class *class_null;
static int major = 0;
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
static loff_t device_llseek(struct file *, loff_t, int);
static struct file_operations fops = {
.owner = THIS_MODULE,
.llseek = &device_llseek,
.read = &device_read,
.write = &device_write,
.open = &device_open,
.release = &device_release
};
static int __init mod_init(void)
{
struct device *dev_null;
if ((major = register_chrdev(MAJOR_NUMBER, DEVICE_NAME, &fops)) < 0) {
return major;
}
/* create /dev/null
* We use udev to make the file.
*/
class_null = class_create(THIS_MODULE, DEVICE_NAME);
if (IS_ERR(class_null)) {
unregister_chrdev(major, DEVICE_NAME);
return -EIO;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
dev_null = device_create(class_null, NULL, MKDEV(major, 0),
NULL, "%s", DEVICE_NAME
);
#else
dev_null = device_create(class_null, NULL, MKDEV(major, 0),
"%s", DEVICE_NAME
);
#endif
if (IS_ERR(dev_null)) {
class_destroy(class_null);
unregister_chrdev(major, DEVICE_NAME);
return -EIO;
}
return 0;
}
static void __exit mod_exit(void)
{
device_destroy(class_null, MKDEV(major, 0));
class_unregister(class_null);
class_destroy(class_null);
unregister_chrdev(major, DEVICE_NAME);
}
static int device_open(struct inode *inode, struct file *file)
{
file->f_pos = 0x00;
try_module_get(THIS_MODULE);
return 0;
}
static int device_release(struct inode *inode, struct file *file)
{
/* decrement usage count: Not. Uncomment the line for less fun. */
/* module_put(THIS_MODULE); */
return 0;
}
static loff_t device_llseek(struct file *filep, loff_t offs, int mode)
{
loff_t newpos;
switch (mode) {
case 2:
case 0:
newpos = offs;
break;
case 1:
newpos = filep->f_pos + offs;
break;
default:
return -EINVAL;
}
if (newpos < 0) {
return -EINVAL;
}
filep->f_pos = newpos;
return newpos;
}
static ssize_t device_read(struct file *filep, char *dst, size_t len,
loff_t *off)
{
char *buf = NULL;
if (dst == NULL || len == 0) {
return -EINVAL;
}
buf = kmalloc(sizeof(char) * len, GFP_KERNEL);
if (buf == NULL) {
return -EINVAL;
}
/* Do how a /dev/null does.
*/
memset(dst, 0, len);
*off += len;
return len;
}
static ssize_t device_write(struct file *filep, const char *src, size_t len,
loff_t *off)
{
char *buf = NULL;
buf = kmalloc(sizeof(char) * len, GFP_KERNEL);
if (buf == NULL) {
return -EINVAL;
}
*off += len;
return len;
}
module_init(mod_init);
module_exit(mod_exit);
警告这可能会迫使您重新启动!
删除它:
# rmmod -f devnull # or a reboot
# rm -rf /dev/null
# mknod /dev/null c 1 3
# chmod go+rw /dev/null