Network hooks hanging the system - linux-kernel

I was testing the network hook code given in https://en.wikipedia.org/wiki/Hooking . My kernel version is 3.11.
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <net/ip.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/in.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
/* Port we want to drop packets on */
static const uint16_t port = 25;
/* This is the hook function itself */
static unsigned int hook_func(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *)){
struct iphdr *iph = ip_hdr(*pskb);
struct tcphdr *tcph, tcpbuf;
if (iph->protocol != IPPROTO_TCP)
return NF_ACCEPT;
tcph = skb_header_pointer(*pskb, ip_hdrlen(*pskb), sizeof(*tcph), &tcpbuf);
if (tcph == NULL)
return NF_ACCEPT;
return (tcph->dest == port) ? NF_DROP : NF_ACCEPT;
}
/* Used to register our hook function */
static struct nf_hook_ops nfho = {
.hook = hook_func,
.hooknum = NF_INET_PRE_ROUTING,
.pf = NFPROTO_IPV4,
.priority = NF_IP_PRI_FIRST,
};
static __init int my_init(void)
{
return nf_register_hook(&nfho);
}
static __exit void my_exit(void)
{
nf_unregister_hook(&nfho);
}
module_init(my_init);
module_exit(my_exit);
But after loading , the above code is freezing the system. Can anybody please tell, what is the reason for that?. I think that the above code might have already tested in some lower versions of kernel. So I doubt, some kernel parameters or features have been changed.

Related

the probe function not being called?

I want to understand why the probe function not being called.
what do I need to study to fix the problem with any USB type to auto-detected after the insertion automatically?
I use key a keyboard, kernel 5.6.3
Here's my code:
#include <linux/module.h> /*included for all kernel modules*/
#include <linux/kernel.h> /*included for KERN_DEBUG*/
#include <linux/init.h> /*included for __init and __exit macros*/
#include <linux/usb.h>
#include <linux/usb/input.h>
#include <linux/hid.h>
#define MY_USB_VENDOR_ID 0x045e
#define MY_USB_PRODUCT_ID 0x0800
static struct usb_device_id my_usb_table[] = {
{ USB_DEVICE(MY_USB_VENDOR_ID, MY_USB_PRODUCT_ID) },
{},
};
MODULE_DEVICE_TABLE(usb, my_usb_table);
static int
my_pdrv_probe(struct usb_interface *pdev, const struct usb_device_id *id) {
pr_err("Hello\n");
return 0;
}
static void my_pdrv_remove(struct usb_interface *pdev) {
pr_err("Bye\n");
}
static struct usb_driver mypdrv = {
.name = "my first usb driver",
.probe = my_pdrv_probe,
.disconnect = my_pdrv_remove,
};
// module_usb_driver(mypdrv);
static int __init my_pdev_init(void)
{
pr_err("Hello Guy\n");
/* Refister with kernel */
usb_register(&mypdrv);
return 0;
}
static void __exit my_pdev_remove(void)
{
pr_err("Bye Guy\n");
/* Unregister from kernel */
usb_deregister(&mypdrv);
}
module_init(my_pdev_init);
module_exit(my_pdev_remove);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sohaib Mohammed");
MODULE_DESCRIPTION("first usb driver module");
MODULE_VERSION("0.1");

register_kretprobe fails with a return value of -2

I have written a kretprobe to hook on to the randomize_stack_top() function mentioned in fs/binfmt_elf.c file. On loading the LKM with insmod the register_kretprobe() call fails with a return value of -2. How do I go about debugging/rectifying that in order to get my module started ?
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/binfmts.h>
#include <linux/elf.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/current.h>
#include <asm/param.h>
/* Global variables */
int randomize_stack_retval;
// randomize_stack_top() kretprobe specific declarations
static char stack_name[NAME_MAX] = "randomize_stack_top";
static int randomize_stack_top_entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
return 0;
}
static int randomize_stack_top_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
randomize_stack_retval = regs_return_value(regs); //store in global variable
printk(KERN_INFO "%d\n",randomize_stack_retval);
return 0;
}
//randomize_stack_top return probe
static struct kretprobe randomize_kretprobe = {
.handler = randomize_stack_top_ret_handler,
.entry_handler = randomize_stack_top_entry_handler,
.maxactive = NR_CPUS,
};
/* Register kretprobe */
static int __init kretprobe_init(void)
{
int ret;
randomize_kretprobe.kp.symbol_name = stack_name;
ret = register_kretprobe(&randomize_kretprobe);
if (ret < 0) {
printk(KERN_INFO "register_kretprobe failed, returned %d\n",
ret);
return -1;
}
printk(KERN_INFO "Planted return probe at %s: %p\n",
randomize_kretprobe.kp.symbol_name, randomize_kretprobe.kp.addr);
return 0;
}
/* Unregister kretprobe */
static void __exit kretprobe_exit(void)
{
unregister_kretprobe(&randomize_kretprobe);
printk(KERN_INFO "kretprobe at %p unregistered\n",
randomize_kretprobe.kp.addr);
// nmissed > 0 suggests that maxactive was set too low.
printk(KERN_INFO "Missed probing %d instances of %s\n",
randomize_kretprobe.nmissed, randomize_kretprobe.kp.symbol_name);
}
module_init(kretprobe_init);
module_exit(kretprobe_exit);
MODULE_LICENSE("GPL");
-2 corresponds to -ENOENT (you can check that in include/uapi/asm-generic/errno-base.h). Probably, it means that kprobe cannot find symbol with given name.
Note, that randomize_stack_top is static function with a short implementation and it is used only once. So it can be inlined by the gcc.

device_create(...) argument 'void * drvdata'

The function
struct device * device_create ( struct class * class,
struct device * parent,
dev_t devt,
void * drvdata,
const char * fmt,
...);
[link to documentation] takes an argument "void * drvdata". It is described as "the data to be added to the device for callbacks". What callbacks exactly are meant here? The file-operation-functions?
SysFS is one example of where this could be useful: whenever userspace communicates with the driver using SysFS (see "Reading/Writing Attribute Data" in the documentation), the kernel calls the corresponding callbacks. The void * drvdata pointer supplied during device_create can then be obtained by calling dev_get_drvdata(dev). The pointer could be used to refer to a structure containing driver's state for example.
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/device.h>
#include <linux/err.h>
MODULE_LICENSE("GPL");
static ssize_t show_period(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t set_period(struct device* dev,
struct device_attribute* attr,
const char* buf,
size_t count);
static DEVICE_ATTR(period, S_IWUSR | S_IRUSR, show_period, set_period);
static struct device *s_pDeviceObject;
static struct class *s_pDeviceClass;
static struct pwm_device_state
{
int m_Period;
} s_DeviceState;
static int __init pwmdriver_init(void)
{
int result;
s_pDeviceClass = class_create(THIS_MODULE, "pwmdriver");
BUG_ON(IS_ERR(s_pDeviceClass));
s_pDeviceObject = device_create(s_pDeviceClass, NULL, 0, &s_DeviceState, "channel");
result = device_create_file(s_pDeviceObject, &dev_attr_period);
BUG_ON(result < 0);
return result;
}
static ssize_t show_period(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pwm_device_state *pwm_device_data;
pwm_device_data = dev_get_drvdata(dev);
return scnprintf(buf, PAGE_SIZE, "%d\n", pwm_device_data->m_Period);
}
static ssize_t set_period(struct device* dev,
struct device_attribute* attr,
const char* buf,
size_t count)
{
long period_value = 0;
struct pwm_device_state *pwm_device_data;
if (kstrtol(buf, 10, &period_value) < 0)
return -EINVAL;
if (period_value < 10) //Safety check
return -EINVAL;
pwm_device_data = dev_get_drvdata(dev);
pwm_device_data->m_Period = period_value;
return count;
}
static void __exit pwmdriver_exit(void)
{
device_remove_file(s_pDeviceObject, &dev_attr_period);
device_destroy(s_pDeviceClass, 0);
class_destroy(s_pDeviceClass);
}
module_init(pwmdriver_init);
module_exit(pwmdriver_exit);

proc_create() example for kernel module

Can someone give me proc_create() example?
Earlier they used create_proc_entry() in the kernel but now they are using proc_create().
This example will create a proc entry which enables reading access. I think you can enable other kinds of access by changing the mode argument passed to the function. I haven't passed a parent directory because there is no need to. The structure file_operations is where you setup your reading and writing callbacks.
struct proc_dir_entry *proc_file_entry;
static const struct file_operations proc_file_fops = {
.owner = THIS_MODULE,
.open = open_callback,
.read = read_callback,
};
int __init init_module(void){
proc_file_entry = proc_create("proc_file_name", 0, NULL, &proc_file_fops);
if(proc_file_entry == NULL)
return -ENOMEM;
return 0;
}
You can check this example for more details: https://www.linux.com/learn/linux-training/37985-the-kernel-newbie-corner-kernel-debugging-using-proc-qsequenceq-files-part-1
Here is a 'hello_proc' code, which makes use of the newer 'proc_create()' interface.
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
static int hello_proc_show(struct seq_file *m, void *v) {
seq_printf(m, "Hello proc!\n");
return 0;
}
static int hello_proc_open(struct inode *inode, struct file *file) {
return single_open(file, hello_proc_show, NULL);
}
static const struct file_operations hello_proc_fops = {
.owner = THIS_MODULE,
.open = hello_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int __init hello_proc_init(void) {
proc_create("hello_proc", 0, NULL, &hello_proc_fops);
return 0;
}
static void __exit hello_proc_exit(void) {
remove_proc_entry("hello_proc", NULL);
}
MODULE_LICENSE("GPL");
module_init(hello_proc_init);
module_exit(hello_proc_exit);
This code has been taken from http://pointer-overloading.blogspot.com/2013/09/linux-creating-entry-in-proc-file.html
This reply is just an update to #Alhaad Gokhale's great answer. The hello world module, as of kernels > 5.6 looks like this:
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
static int hello_proc_show(struct seq_file *m, void *v) {
seq_printf(m, "Hello proc!\n");
return 0;
}
static int hello_proc_open(struct inode *inode, struct file *file) {
return single_open(file, hello_proc_show, NULL);
}
static const struct proc_ops hello_proc_fops = {
.proc_open = hello_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
static int __init hello_proc_init(void) {
proc_create("hello_proc", 0, NULL, &hello_proc_fops);
return 0;
}
static void __exit hello_proc_exit(void) {
remove_proc_entry("hello_proc", NULL);
}
MODULE_LICENSE("GPL");
module_init(hello_proc_init);
module_exit(hello_proc_exit);
Key differences to note are:
struct proc_ops replaces struct file_operations.
member name changes from .open, .read to .proc_open, .proc_read...
Need to remove the .owner line.
Further information:
This patch
This more detailed SO answer on changes.

How to create proc entry under /proc/driver?

I want to create a file under a /proc/driver directory. I would like to use a macro like proc_root_driver (or something else provided) rather than use "driver/MODULE_NAME" explicitly. I use create_proc_entry :
struct proc_dir_entry *simpleproc_fops_entry;
simpleproc_fops_entry = create_proc_entry(MODULE_NAME, 0400, NULL /* proc_root_dir */);
After googling, I found suggestion to use proc_root_driver, but when I use it, I get the error
proc_root_driver undeclared in this function
And also, proc_root_driver is not available in linux/proc_fs.h.
I have tried to declare structure like this:
struct proc_dir_entry proc_root;
struct proc_dir_entry *proc_root_driver = &proc_root;
The compilation errors gone, but the file didn't appear under /proc/driver or /proc. How can I make create an entry in /proc?
Looking at proc_fs.h, proc_root_driver is defined as :
extern struct proc_dir_entry *proc_root_driver;
so long as CONFIG_PROC_FS is enabled. If you have CONFIG_PROC_FS selected when you configure your kernel, you should be able to use it as you suggested yourself i.e. :
#include <linux/proc_fs.h>
struct proc_dir_entry * procfile
procfile = create_proc_entry("myprocfile", 0400, proc_root_driver);
If this does not work, check that you have CONFIG_PROC_FS set. To make sure, you can compile your source file with the -E option and check that the create_proc_entry call includes a non NULL parameter as the last parameter. If it is NULL, or the call is not there at all, then CONFIG_PROC_FS is not enabled.
/* proc entries for ayyaz */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/err.h>
#include <linux/ioctl.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#ifdef CONFIG_PROC_FS
/*====================================================================*/
/* Support for /proc/ayyaz */
static struct proc_dir_entry *proc_ayyaz;
DEFINE_MUTEX(ayyaz_table_mutex);
/*====================================================================*/
/* Init code */
static int ayyaz_read_proc (char *page, char **start, off_t off, int count,
int *eof, void *data_unused)
{
int len, l, i;
off_t begin = 0;
mutex_lock(&ayyaz_table_mutex);
len = sprintf(page, "hello ayyaz here\n");
mutex_unlock(&ayyaz_table_mutex);
if (off >= len+begin)
return 0;
*start = page + (off-begin);
return ((count < begin+len-off) ? count : begin+len-off);
}
static int __init init_ayyaz(void)
{
if ((proc_ayyaz = create_proc_entry( "ayyaz_maps", 0, NULL )))
proc_ayyaz->read_proc = ayyaz_read_proc;
return 0;
}
static void __exit cleanup_ayyaz(void)
{
if (proc_ayyaz)
remove_proc_entry( "ayyaz", NULL);
}
module_init(init_ayyaz);
module_exit(cleanup_ayyaz);
#else
#error "Please add CONFIG_PROC_FS=y in your .config "
#endif /* CONFIG_PROC_FS */
MODULE_LICENSE("proprietary");
MODULE_AUTHOR("Md.Ayyaz A Mulla <md.ayyaz#gmail.com>");
MODULE_DESCRIPTION("proc files for ayyaz");
Compile this driver. If it compiles sucessfully, then you will see /proc/ayyaz.
#define PROC_ENTRY_NAME "driver/XX"
static struct proc_dir_entry *proc_XX;
static int XX_read_proc (char *page, char **start, off_t off, int count,
int *eof, void *data_unused)
{
return 0;
}
static int XX_write_proc (struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
return 0;
}
static int __init XX_add_driver(void)
{
if ((proc_flash = XX_entry(PROC_ENTRY_NAME, 0, NULL))) {
proc_XX->read_proc = XX_read_proc;
proc_XX->write_proc = XX_write_proc;
}
...
}
static void __exit XX_remove(void)
{
if (proc_flash)
remove_proc_entry(PROC_ENTRY_NAME, NULL);
return;
}
Then you can find the /proc/driver/XX entry.

Resources