lkml.org 
[lkml]   [2006]   [Apr]   [12]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
/
FromZhiyi Huang <>
SubjectRe: Re: Slab corruption after unloading a module
DateThu, 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/

\
 
 \ /
  Last update: 2006-04-12 23:07    [from the cache]
©2003-2008