Messages in this thread | | | From | Zhiyi Huang <> | Subject | Re: Re: Slab corruption after unloading a module | Date | Thu, 13 Apr 2006 11:04:39 +1200 |
| |
> 2.6.8 is an old kernel, you could very well be hitting a kernel bug > that has been fixed already. Can you reproduce this with 2.6.16?
I will try that soon.
> Also, > you're not including sources to your module so it's impossible to tell > whether you're doing something wrong. > > Pekka
Below is my baby module which only uses kmalloc and kfree for my device structure. I found the slab corruption address is the address of the structure. It seems to be a bug for kmalloc and kfree.
/ *---------------------------------------------------------------- ------------*/ /* File: tem.c */ /* Date: 13/03/2006 */ /* Author: Zhiyi Huang */ /* Version: 0.1 */ / *---------------------------------------------------------------- ------------*/ /* This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */
#include <linux/config.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/proc_fs.h> #include <linux/fcntl.h> #include <linux/aio.h> #include <asm/uaccess.h>
#include <linux/ioctl.h> #include <linux/cdev.h>
MODULE_LICENSE("GPL"); MODULE_AUTHOR("Zhiyi Huang"); MODULE_DESCRIPTION("A template module");
/* The parameter for testing */ int major=0; MODULE_PARM(major, "i"); MODULE_PARM_DESC(major, "device major number");
#define MAX_DSIZE 3071 struct my_dev { char data[MAX_DSIZE+1]; size_t size; /* 32-bit will suffice */ struct semaphore sem; /* Mutual exclusion */ struct cdev cdev; } *temp_dev;
int temp_open (struct inode *inode, struct file *filp) { return 0; }
int temp_release (struct inode *inode, struct file *filp) { return 0; }
ssize_t temp_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos) { int rv=0;
if (down_interruptible (&temp_dev->sem)) return -ERESTARTSYS; if (*f_pos > MAX_DSIZE) goto wrap_up; if (*f_pos + count > MAX_DSIZE) count = MAX_DSIZE - *f_pos; if (copy_to_user (buf, temp_dev->data+*f_pos, count)) { rv = -EFAULT; goto wrap_up; } up (&temp_dev->sem); *f_pos += count; return count;
wrap_up: up (&temp_dev->sem); return rv; }
ssize_t temp_write (struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { int count1=count, rv=count;
if (down_interruptible (&temp_dev->sem)) return -ERESTARTSYS;
if (*f_pos > MAX_DSIZE) goto wrap_up; if (*f_pos + count > MAX_DSIZE) count1 = MAX_DSIZE - *f_pos;
if (copy_from_user (temp_dev->data+*f_pos, buf, count1)) { rv = -EFAULT; goto wrap_up; } up (&temp_dev->sem); *f_pos += count1; return count;
wrap_up: up (&temp_dev->sem); return rv; }
int temp_ioctl (struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg) {
return 0; }
loff_t temp_llseek (struct file *filp, loff_t off, int whence) { long newpos;
switch(whence) { case 0: /* SEEK_SET */ newpos = off; break;
case 1: /* SEEK_CUR */ newpos = filp->f_pos + off; break;
case 2: /* SEEK_END */ newpos = temp_dev->size + off; break;
default: /* can't happen */ return -EINVAL; } if (newpos<0 || newpos>MAX_DSIZE) return -EINVAL; filp->f_pos = newpos; return newpos; }
struct file_operations temp_fops = { .owner = THIS_MODULE, .llseek = temp_llseek, .read = temp_read, .write = temp_write, .ioctl = temp_ioctl, .open = temp_open, .release = temp_release, };
/** * Initialise the module and create the master device */ int __init tem_init_module(void){ int rv; dev_t devno = MKDEV(major, 0);
if(major) { rv = register_chrdev_region(devno, 1, "temp"); if(rv < 0){ printk(KERN_WARNING "Can't use the major number %d; try atomatic allocation...\n", major); rv = alloc_chrdev_region(&devno, 0, 1, "temp"); major = MAJOR(devno); } } else { rv = alloc_chrdev_region(&devno, 0, 1, "temp"); major = MAJOR(devno); }
if(rv < 0) return rv;
temp_dev = kmalloc(sizeof(struct my_dev), GFP_KERNEL); if(temp_dev == NULL){ rv = -ENOMEM; unregister_chrdev_region(devno, 1); return rv; }
memset(temp_dev, 0, sizeof(struct my_dev)); cdev_init(&temp_dev->cdev, &temp_fops); temp_dev->cdev.owner = THIS_MODULE; temp_dev->cdev.ops = &temp_fops; temp_dev->size = MAX_DSIZE; sema_init (&temp_dev->sem, 1); rv = cdev_add (&temp_dev->cdev, devno, 1); if (rv) printk(KERN_WARNING "Error %d adding device temp", rv);
printk(KERN_WARNING "Hello world from Template Module\n"); printk(KERN_WARNING "temp device MAJOR is %d, dev addr: %lx\n", major, (unsigned long)temp_dev);
return 0; }
/** * Finalise the module */ void __exit tem_exit_module(void){
kfree(temp_dev); unregister_chrdev_region(MKDEV(major, 0), 1); printk(KERN_WARNING "Good bye from Template Module\n"); }
module_init(tem_init_module); module_exit(tem_exit_module);
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |