I am attempting to do a kernel module that is meant to check which USB devices are currently connected, and compare them to a list of allowed USB devices. I've written the following code:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/buffer_head.h>
static int __init dummy_init(void)
{
struct file * fp;
struct file * ftmp;
struct file * faux;
loff_t file_size;
int no_words;
char* usb_content;
char* pch;
char vendor_id[5];
char** word_mat;
int word_size;
int count;
int check;
char product_id[5];
char* to_write;
ftmp = filp_open("/var/tmp/usb_temp.txt", O_CREAT | O_RDWR | O_APPEND, \
S_IRWXU | S_IRWXG | S_IRWXO);
fp = filp_open("/sys/kernel/debug/usb/devices", O_CREAT | O_RDWR | O_APPEND, \
S_IRWXU | S_IRWXG | S_IRWXO);
faux = filp_open("/var/tmp/rejection_list.txt", O_CREAT | O_RDWR, \
S_IRWXU | S_IRWXG | S_IRWXO);
if(ftmp != NULL)
{
loff_t ppos = 0;
file_size = vfs_llseek(ftmp,0,SEEK_END);
usb_content = kvmalloc(file_size, GFP_ATOMIC);
if(usb_content == NULL)
{
printk(KERN_ERR "Error allocating memory for USB buffer!");
}
vfs_llseek(ftmp,0,SEEK_SET);
kernel_read(ftmp, usb_content, file_size, &ppos);
usb_content[file_size] = '\0';
no_words = ((file_size * 2)/10);
word_mat = kvmalloc(no_words, GFP_ATOMIC);
count = 0;
while( (pch = strsep(&usb_content," \n")) != NULL )
{
word_size = strlen(pch);
word_mat[count] = kvmalloc(word_size+1, GFP_ATOMIC);
strcpy(word_mat[count], pch);
count++;
}
kvfree(usb_content);
ppos = 0;
if(fp == NULL)
{
printk(KERN_ERR "Cannot open Kernel USB files!\n");
}
else
{
usb_content = kvmalloc(2000, GFP_ATOMIC);
if(usb_content == NULL)
{
printk(KERN_ERR "Error allocating memory for USB buffer!");
}
vfs_llseek(fp,0,SEEK_SET);
kernel_read(fp, usb_content, 2000, &ppos);
ppos = 0;
while( (pch = strsep(&usb_content,"\n")) != NULL )
{
if(strstr(pch,"Vendor") != NULL)
{
check = 0;
vendor_id[0] = pch[11];
vendor_id[1] = pch[12];
vendor_id[2] = pch[13];
vendor_id[3] = pch[14];
vendor_id[4] = '\0';
product_id[0] = pch[23];
product_id[1] = pch[24];
product_id[2] = pch[25];
product_id[3] = pch[26];
product_id[4] = '\0';
printk(KERN_INFO "Checking for %s %s\n",vendor_id,product_id);
for(count = 0; count < no_words; count = count+2)
{
if(vendor_id[0] == word_mat[count][0] && vendor_id[1] == word_mat[count][1] && vendor_id[2] == word_mat[count][2] && vendor_id[3] == word_mat[count][3] && product_id[0] == word_mat[count+1][0] && product_id[1] == word_mat[count+1][1] && product_id[2] == word_mat[count+1][2] && product_id[3] == word_mat[count+1][3])
{
printk(KERN_INFO "Approved for %s %s\n",vendor_id,product_id);
check = 1;
break;
}
}
if(check == 0)
{
printk(KERN_INFO "Calling script for blocking %s %s...\n", vendor_id, product_id);
to_write = kvmalloc(10, GFP_ATOMIC);
strncpy(to_write, vendor_id, 4);
strcat(to_write, "");
strncat(to_write,product_id,4);
strcat(to_write, "\n");
kernel_write(faux,to_write,10,&ppos);
kvfree(to_write);
}
}
}
kvfree(usb_content);
for(count = 0; count < no_words; count++)
{
kvfree(word_mat[count]);
}
kvfree(word_mat);
}
}
else{
printk(KERN_ERR "Error! Cannot open file\n");
}
filp_close(ftmp, NULL);
filp_close(fp, NULL);
filp_close(faux, NULL);
}
static void __exit dummy_exit(void)
{
printk(KERN_INFO "Unloaded successfully!");
}
module_init(dummy_init);
module_exit(dummy_exit);
The module is loaded by a service each time an USB is inserted. My problem is that after a couple of insmod-rmmod operations Linux freezes and I must restart the machine.
P.S. I have previously tried to declare all variables global, but has not worked.