Inspired by @comintern.
Replacing /dev/null. Engaging sneaky mode. Requires kernel headers, superuser mode and a working compiler.
# make # rm /dev/null # insmod devnull.ko # chmod go+rw /dev/null
Have fun.
Makefile:
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
Source code:
#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 <[email protected]>"); 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);
Warning this may force you to reboot!
To remove it:
# rmmod -f devnull # or a reboot # rm -rf /dev/null # mknod /dev/null c 1 3 # chmod go+rw /dev/null
while(1)malloc(999);? \$\endgroup\$