Application is never allowed to crash the kernel if the driver does its job correctly. Otherwise, it is a buggy driver or trash kernel. So, application is not allowed to keep holes in kernel or resources leaked. It is job of the driver to find the resources and holes kept by application and remove it in close().
sample program for simple driver and simple application to prove this.
1) First install headers
# apt-get install build-essential linux-headers-$(uname -r)
2) The following is simple kernel driver in module sample_close.c.
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("CollegeBoy");
MODULE_DESCRIPTION("A Crash app module");
/*** define ***/
#define SAMPLE_DRIVER_NAME "sample"
#define SAMPLE_DEVICE_ID "sample_int"
/**** prototype ****/
static int sample_open(struct inode*, struct file*);
static int sample_close(struct inode*, struct file*);
static struct miscdevice g_sample_device; /* device driver information */
/******************************************************************************/
/* Function : sample_open */
/* Description: open SAMPLE driver */
/******************************************************************************/
static
int sample_open(
struct inode *inode,
struct file *fp
)
{
printk(KERN_ERR "Device opened!\n");
return 0;
}
/******************************************************************************/
/* Function : sample_close */
/* Description: close SAMPLE driver */
/******************************************************************************/
static
int sample_close(
struct inode *inode,
struct file *fp
)
{
printk(KERN_ERR "Device Closed!\n");
return 0;
}
/* initialize file_operations */
static struct file_operations g_sample_fops = {
.owner = THIS_MODULE,
.open = sample_open,
.release = sample_close,
};
static int __init hello_init(void)
{
int ret;
printk(KERN_ERR "Module Init!\n");
g_sample_device.name = SAMPLE_DRIVER_NAME;
g_sample_device.fops = &g_sample_fops;
g_sample_device.minor = MISC_DYNAMIC_MINOR;
/* register device driver */
ret = misc_register(&g_sample_device);
if (0 != ret) {
printk(KERN_ERR "[SAMPLEK]ERR| misc_register failed ret[%d]\n", ret);
return -1;
}
return 0;
}
static void __exit hello_cleanup(void)
{
int ret;
printk(KERN_ERR "Module Exit!\n");
/* unregister device driver */
ret = misc_deregister(&g_sample_device);
if (0 != ret) {
printk(KERN_ERR "[SAMPLEK]ERR| misc_deregister failed ret[%d]\n", ret);
}
}
module_init(hello_init);
module_exit(hello_cleanup);
3) Copy into Makefile
ifeq ($(KERNELRELEASE),) KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) .PHONY: build clean build: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c else $(info Building with KERNELRELEASE = ${KERNELRELEASE}) obj-m := sample_close.o endif
4) Do make
root@ubuntu:/mnt/hgfs/UShared/module# make
make -C /lib/modules/3.2.0-23-generic-pae/build M=/mnt/hgfs/UShared/module modules
make[1]: Entering directory `/usr/src/linux-headers-3.2.0-23-generic-pae'
Building with KERNELRELEASE = 3.2.0-23-generic-pae
CC [M] /mnt/hgfs/UShared/module/sample_close.o
Building modules, stage 2.
Building with KERNELRELEASE = 3.2.0-23-generic-pae
MODPOST 1 modules
CC /mnt/hgfs/UShared/module/sample_close.mod.o
LD [M] /mnt/hgfs/UShared/module/sample_close.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.2.0-23-generic-pae'
5) insmod
root@ubuntu:/mnt/hgfs/UShared/module# insmod sample_close.ko root@ubuntu:/mnt/hgfs/UShared/module# dmesg -c [ 3883.685179] Module Init!
6) Application to open driver and to crash itself.
#include
#include
#include
#include
#include
#include
#include
#define ICCOM_DEV "/dev/iccom"
int main(){
int fd;
/* open ICCOM driver */
fd = open(ICCOM_DEV, O_RDWR);
if (fd < 0) {
printf("[ICCOM]ERR| handle->fd[%d]\n", fd);
return -1;
}
*((unsigned int *)0) = 87;
}
7) Sample application main.c
#include#include #include #include #include #include #include #define SAMPLE_DEV "/dev/sample" int main(){ int fd; /* open SAMPLE driver */ fd = open(SAMPLE_DEV, O_RDWR); if (fd < 0) { printf("[SAMPLE]ERR| handle->fd[%d]\n", fd); return -1; } *((unsigned int *)0) = 87; }
8) Compile, execute, and see dmesg
root@ubuntu:/mnt/hgfs/UShared/module/app# cc main.c root@ubuntu:/mnt/hgfs/UShared/module/app# ./a.out Segmentation fault (core dumped) root@ubuntu:/mnt/hgfs/UShared/module/app# dmesg -c [ 4094.987003] Device opened! [ 4094.987028] a.out[7653]: segfault at 0 ip 0804845d sp bf96a100 error 6 in a.out[8048000+1000] [ 4095.103149] Device Closed!
See the device is closed (means, close() function of driver is called by kernel) automatically when the application that opened the driver has crashed. So, your job needs to be remember the current->tgid of the process that is opening the driver in the open() function through fp->private_data. When close function is called, get tgid from the fp->private_data release all the resources and requests raised by the tgid.