public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* OOPS: found a fatal bug in Redhat Enterprise Server 3 Update 9 <2.4.21-50.EL> on x86_64, who can help to fix it
@ 2008-04-10  7:27 Gang He
  2008-04-11 18:31 ` Chris Snook
  0 siblings, 1 reply; 2+ messages in thread
From: Gang He @ 2008-04-10  7:27 UTC (permalink / raw)
  To: linux-kernel; +Cc: jlieskov

[-- Attachment #1: Type: text/plain, Size: 781 bytes --]

Hi all,

I found a fatal bug in Redhat Enterprise Server 3 Update 9
<2.4.21-50.EL> on x86_64 when I used "wait_queue_head_t" data
structure, the same program works very well on i386, but porting it to
x86_64 will bring Linux kernel crash, who can help to take a look at
it, thanks.
all source code are as follows:
ghe.c - kernel module source file
mk.sh - command lines to compile all source files
read.c - read operation
write.c - write operation
rhel3u9-64bit.txt - oops output

Reproduce bug:
1) run  "./mk.sh" to compile all source files
2) run "insmod ghe.o" to insert kernel module to kernel
3) run "mknod /dev/ghe xxx" to create char device file
4) run "./devread" to read data from /dev/ghe
5) run "./devwrite" to write data to /dev/ghe, bug will take place.


Thanks
Gang

[-- Attachment #2: ghe.c --]
[-- Type: application/octet-stream, Size: 4908 bytes --]

#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
	#include <linux/config.h>
#endif
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/compatmac.h>
#include <linux/proc_fs.h>
#include <linux/wait.h>

// define the module license mode
MODULE_LICENSE("GPL");

#ifdef MODULE_ALIAS
MODULE_ALIAS("ghe");
#endif

#define GHE_DEVNAME	"/dev/ghe"
#define GHE_PROCNAME	"ghe"

static int devmajor = -1;
static char *devbuf = NULL;
static char *procbuf = NULL;
static int devoffset = 0;
static int devend = 0;
static int devlimit = 1024;

static wait_queue_head_t* aaa = NULL;

static void shift_buf()
{
	int i;
	int len;

	if (devoffset == 0)
		return;

	len = devend - devoffset;
	for (i = 0; i < len; i++) {
		devbuf[i] = devbuf[devoffset+i];
	}
	devend = devend - devoffset;
	devoffset = 0;	
}

static int ghe_open(struct inode *ino, struct file *filp)
{
	printk("ghe_open: inode: %lu, file: %p\n", ino->i_ino, filp);
	return 0;
}

static int ghe_release(struct inode *ino, struct file *filp)
{
	printk("ghe_release: inode: %lu, file: %p\n", ino->i_ino, filp);
	return ( (devend-devoffset) > 0 ? 1 : 0 );
}

static ssize_t ghe_read(struct file *filp, char *buf, size_t sz, loff_t *ppos)
{
	size_t len;
	int rc;
	
	printk("ghe_read: file: %p buf: %p sz: %d *ppos: %d\n", filp, buf, sz, *ppos);
	if (devend - devoffset <= 0) { // no data
		printk("No data to read, waiting ... \n");
		rc = wait_event_interruptible( (*aaa), ((devend-devoffset) > 0));
        	printk("Wait return %d\n", rc);	
	}

	if (devend - devoffset >= sz) {
		len = sz;
	} else {
		len = devend - devoffset;
	}
	 
	if (copy_to_user(buf, devbuf+devoffset, len) != 0)
		return -EFAULT;
	devoffset += len;
	*ppos += len;
	return len;
}

static ssize_t ghe_write(struct file *filp, const char *buf, size_t sz, loff_t *ppos)
{
	size_t len;
	int flag = 1;
	
	printk("ghe_write: file: %p buf: %p sz: %d *ppos: %d\n", filp, buf, sz, *ppos);
	if (devend - devoffset >= devlimit) { // no space
		printk("No space to be written, return.\n");
		return 0;
	}

	do {
		if (devlimit - devend >= sz) {
                	len = sz;
			break;
        	} else {
			if (flag) {
				shift_buf();
                		flag = 0;
			} else {
				len = devlimit - devend;
				break;
			}
        	}
	} while (1);

	if (copy_from_user(devbuf+devend, buf, len) != 0)
        	return -EFAULT;
	devend += len;
	*ppos += len;

	printk("Wakeup read user ... \n");
	wake_up_interruptible(aaa);
	printk("Wakeup read user ... end\n");

        return len;
}

struct file_operations ghe_file_operations = {
	ioctl: 0,
	open: ghe_open,
	release: ghe_release,
	read: ghe_read,
	write: ghe_write,
	owner: THIS_MODULE,  
};

int ghe_init(void);
void ghe_exit(void);

module_init(ghe_init);
module_exit(ghe_exit);
static struct proc_dir_entry* proc_res = NULL;

int get_proc_info()
{
	if (!procbuf) 
		return -1;

	sprintf(procbuf,
		"Device statistics:\n"
		"Device major: %d buffer limit: %d\n"
		"Buffer offset: %d end: %d\n",
		devmajor, devlimit,
		devoffset, devend);
	return strlen(procbuf);	
}

int ghe_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
{
	int len;

	len = get_proc_info();
	if (len < 0) {
		strcpy(page, "error");
		len = 5;
	} else {
		strcpy(page, procbuf);
	}

	*eof = 1;
	return len;	
}

int ghe_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
{
	return  count;
}


int ghe_init(void)
{
	int rs = 0;

	aaa = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
	init_waitqueue_head(aaa);
	spin_lock_init(&aaa->lock);

	if (!(devbuf = kmalloc(devlimit, GFP_KERNEL))) {
                printk("can not alloc memory(%d)\n", devlimit);
                return -1;
        }
	
	if (!(procbuf = kmalloc(1024, GFP_KERNEL))) {
                printk("can not alloc memory(%d)\n", 1024);
                return -1;
        }


	if ((rs = register_chrdev(0, GHE_DEVNAME, &ghe_file_operations)) < 0) {
        	printk("%s: cannot register device\n", GHE_DEVNAME);
		return -1;
    	}
	devmajor = rs;

	if (!(proc_res = create_proc_entry(GHE_PROCNAME, S_IFREG | S_IRUSR | S_IWUSR, &proc_root)))
	{
		printk("%s: cannot register proc file\n", GHE_PROCNAME);
	} else {
	
		
		proc_res->read_proc = ghe_read_proc;
		proc_res->write_proc = ghe_write_proc;
	}

	printk("register device %s: (%d)\n", GHE_DEVNAME, devmajor);
	return 0;
}

void ghe_exit(void)
{
	int rs = 0;

	if (devbuf)
		kfree(devbuf);
	if (procbuf)
                kfree(procbuf);

	if (proc_res)
		remove_proc_entry(GHE_PROCNAME, &proc_root);

	if (devmajor >= 0) {
		rs = unregister_chrdev(devmajor, GHE_DEVNAME);
		printk("unregister device %s: (%d)\n", GHE_DEVNAME, rs);
	}
}


[-- Attachment #3: mk.sh --]
[-- Type: application/x-sh, Size: 140 bytes --]

[-- Attachment #4: read.c --]
[-- Type: application/octet-stream, Size: 524 bytes --]

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>

int
main(int argc, char *argv[])
{
	int fd = -1;
	char *ghedev = "/dev/ghe";
	char buf[1024];
	ssize_t rs;


	if ((fd = open(ghedev, O_RDWR)) < 0)
	{
        	perror(ghedev);
		exit(1);
	}

again:
	memset(buf, 0, sizeof(buf));
	rs = read(fd, buf, 128);
	printf("read rs = %d (%s)\n", rs, buf);

	if (getchar() == '\n')
		goto again;
	

	if (fd > 0)
		close(fd);

	return 0;
}





[-- Attachment #5: write.c --]
[-- Type: application/octet-stream, Size: 567 bytes --]

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>

int
main(int argc, char *argv[])
{
	int i = 0;
	int fd = -1;
	char *ghedev = "/dev/ghe";
	char buf[1024];
	ssize_t rs;


	if ((fd = open(ghedev, O_RDWR)) < 0)
	{
        	perror(ghedev);
		exit(1);
	}

again:
	i++;
	memset(buf, 0, sizeof(buf));
	sprintf(buf, "%d", i);
	rs = write(fd, buf, strlen(buf));
	printf("write rs = %d \n", rs);

	if (getchar() == '\n')
		goto again;
	

	if (fd > 0)
		close(fd);

	return 0;
}





[-- Attachment #6: rhel3u9-64bit.txt --]
[-- Type: text/plain, Size: 2459 bytes --]

ghe_read: file: 0000010039860c80 buf: 0000007fbfffb7f0 sz: 128 *ppos: 0

No data to read, waiting ... 

ghe_open: inode: 72997, file: 0000010039860380

ghe_write: file: 0000010039860380 buf: 0000007fbfffc820 sz: 1 *ppos: 0

Wakeup read user ... 

Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000

 printing rip:

ffffffff8012199b

PML4 39435067 PGD 3961d067 PMD 0 

Oops: 0000

CPU 0 

Pid: 1583, comm: devwrite Not tainted

RIP: 0010:[<ffffffff8012199b>]{__wake_up+91}

RSP: 0018:0000010039653ed8  EFLAGS: 00010046

RAX: 0000000000000000 RBX: 000001003cb71580 RCX: 0000010039652000

RDX: 0000000000000000 RSI: 0000000000000073 RDI: 0000000000000000

RBP: 0000010039653f18 R08: ffffffffffffffff R09: 0000000000000001

R10: ffffffff805f2040 R11: 0000000000000000 R12: 0000000000000001

R13: 000001003cb71500 R14: 000001003cb71588 R15: 000001003cb71580

FS:  0000002a958c94c0(0000) GS:ffffffff805eb3c0(0000) knlGS:0000000000000000

CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b

CR2: 0000000000000000 CR3: 0000000000101000 CR4: 00000000000006e0


Call Trace: [<ffffffff801219af>]{__wake_up+111} [<ffffffffa01023f4>]{:ghe:ghe_write+244} 

       [<ffffffff80161b52>]{sys_write+178} [<ffffffff801102f7>]{system_call+119} 

       

Process devwrite (pid: 1583, stackpage=10039653000)

Stack: 0000010039653ed8 0000000000000018 ffffffff801219af 0000000000000002 

       00000001805f2088 0000000000000202 0000000000000001 0000000000000001 

       00000100398603b8 0000007fbfffc820 0000000000000000 0000000000000001 

       ffffffffa01023f4 0000000000000001 0000010039860380 ffffffffffffffea 

       0000007fbfffc820 0000000000000000 ffffffff80161b52 0000000000000000 

       0000002a9566b020 0000007fbfffcc40 0000000000400670 0000000000000000 

       ffffffff801102f7 0000000000000246 0000002a9568baa0 0000000000000000 

       fefefefefefefeff 0000000000000001 0000000000000031 0000000000000001 

       0000007fbfffc820 0000000000000003 0000000000000001 0000002a957501d2 

       0000000000000033 0000000000010202 0000007fbfffc808 000000000000002b 

Call Trace: [<ffffffff801219af>]{__wake_up+111} [<ffffffffa01023f4>]{:ghe:ghe_write+244} 

       [<ffffffff80161b52>]{sys_write+178} [<ffffffff801102f7>]{system_call+119} 

       


Code: 48 8b 07 85 45 cc 74 1b 8b 75 cc 31 c9 31 d2 e8 71 e1 ff ff


Kernel panic: Fatal exception


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: OOPS: found a fatal bug in Redhat Enterprise Server 3 Update 9 <2.4.21-50.EL> on x86_64, who can help to fix it
  2008-04-10  7:27 OOPS: found a fatal bug in Redhat Enterprise Server 3 Update 9 <2.4.21-50.EL> on x86_64, who can help to fix it Gang He
@ 2008-04-11 18:31 ` Chris Snook
  0 siblings, 0 replies; 2+ messages in thread
From: Chris Snook @ 2008-04-11 18:31 UTC (permalink / raw)
  To: Gang He; +Cc: linux-kernel, jlieskov

Gang He wrote:
> I found a fatal bug in Redhat Enterprise Server 3 Update 9

Please report this at bugzilla.redhat.com, or to Red Hat support.  This 
kernel is very out of scope for this mailing list, unless you can 
reproduce the problem on newer kernels.

-- Chris

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-04-11 18:31 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-04-10  7:27 OOPS: found a fatal bug in Redhat Enterprise Server 3 Update 9 <2.4.21-50.EL> on x86_64, who can help to fix it Gang He
2008-04-11 18:31 ` Chris Snook

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox