Hey there, I'm currently debugging a kernel oops with kernel 2.6.21.7 that occurs from time to time with our netfilter accounting module ipt_ACCOUNT (http://www.intra2net.com/de/produkte/opensource/ipt_account/). What basically happens is that the module allocates memory inside an interrupt handler like many other netfilter modules do. Except that it does it very often if you have a large, busy network. To me it looks like I found a bug in the kernel memory handler. I've written a minimalistic netfilter module ipt_CRASH that just allocates and frees memory to demonstrate the problem. Here's a screenshot of the oops: http://img231.imageshack.us/img231/9064/kerneloopsiptcrashzb1.jpg Another shot of it with a "tainted" kernel: http://img529.imageshack.us/img529/6681/kerneloopsey1.jpg I would have included the backtrace as text, but unfortunately the USB serial console dies before it outputs anything useful. You need a fast machine with lots of RAM to reproduce it, I used a 3 Ghz machine with 3 GB of RAM. ipt_CRASH allocates and frees memory for every packet, a packet generator like "sendip" might help: http://www.earth.li/projectpurple/progs/sendip.html The machine dies after 15-30 minutes or as soon as I try to reboot it. Please CC: answers, I'm only on netfilter-devel. Thanks in advance, Thomas
Attachment:
crashit.sh
Description: application/shellscript
/* Shared library add-on to iptables to add CRASH support. Author: Intra2net AG <[email protected]> Licensed under the GPL v2. */ #include <stdio.h> #include <netdb.h> #include <string.h> #include <stdlib.h> #include <syslog.h> #include <getopt.h> #include <iptables.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_CRASH.h> static struct option opts[] = { { .name = 0 } }; /* Function which prints out usage message. */ static void help(void) { printf( "CRASH v%s options:\n", IPTABLES_VERSION); } /* Initialize the target. */ static void init(struct ipt_entry_target *t, unsigned int *nfcache) { /* Can't cache this */ *nfcache |= NFC_UNKNOWN; } /* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, struct ipt_entry_target **target) { return 0; } /* Final check; nothing. */ static void final_check(unsigned int flags) { } static void print_it(const struct ipt_ip *ip, const struct ipt_entry_target *target, char do_prefix) { if (!do_prefix) printf("CRASH "); } /* Prints out the targinfo. */ static void print(const struct ipt_ip *ip, const struct ipt_entry_target *target, int numeric) { print_it (ip, target, 0); } /* Saves the union ipt_targinfo in parsable form to stdout. */ static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target) { print_it(ip, target, 1); } static struct iptables_target crash = { .next = NULL, .name = "CRASH", .version = IPTABLES_VERSION, .size = IPT_ALIGN(sizeof(struct ipt_crash_info)), .userspacesize = IPT_ALIGN(sizeof(struct ipt_crash_info)), .help = &help, .init = &init, .parse = &parse, .final_check = &final_check, .print = &print, .save = &save, .extra_opts = opts }; void _init(void) { register_target(&crash); }
/*************************************************************************** * Copyright (C) 2007 by Intra2net AG * * [email protected] * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License * * version 2 as published by the Free Software Foundation; * * * ***************************************************************************/ #include <linux/module.h> #include <linux/version.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <net/icmp.h> #include <net/udp.h> #include <net/tcp.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_CRASH.h> #include <asm/semaphore.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/string.h> #include <linux/spinlock.h> #include <asm/uaccess.h> /* Spinlock used during memory allocation */ static DEFINE_SPINLOCK(ipt_crash_lock); static unsigned int ipt_crash_target(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) const struct xt_target *target, #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) const void *targinfo) #else const void *targinfo, void *userinfo) #endif { char *data; spin_lock_bh(&ipt_crash_lock); if ((data = (char *)get_zeroed_page(GFP_ATOMIC)) == NULL) { printk("ipt_CRASH: Out of memory!\n"); } else { // Fill memory with pattern int i, j = 123; for (i = 0; i < PAGE_SIZE; i++) { data[i] = j; j++; } free_page((unsigned long)data); } spin_unlock_bh(&ipt_crash_lock); return IPT_CONTINUE; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) static struct xt_target xt_crash_reg = { #else static struct ipt_target ipt_crash_reg = { #endif .name = "CRASH", #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) .family = AF_INET, #endif .target = ipt_crash_target, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) .targetsize = sizeof(struct ipt_crash_info), #endif .me = THIS_MODULE }; static int __init init(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) if (xt_register_target(&xt_crash_reg)) #else if (ipt_register_target(&ipt_crash_reg)) #endif return -EINVAL; return 0; } static void __exit fini(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) xt_unregister_target(&xt_crash_reg); #else ipt_unregister_target(&ipt_crash_reg); #endif } module_init(init); module_exit(fini); MODULE_LICENSE("GPL");
/*************************************************************************** * Copyright (C) 2004-2005 by Intra2net AG * * [email protected] * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License * * version 2 as published by the Free Software Foundation; * * * ***************************************************************************/ #ifndef _IPT_CRASH_H #define _IPT_CRASH_H /* Structure for the userspace part of ipt_CRASH */ struct ipt_crash_info { }; #endif /*_IPT_CRASH_H*/
- Follow-Ups:
- Re: Kernel oops during netfilter memory allocation
- From: Alexey Dobriyan <[email protected]>
- Re: Kernel oops during netfilter memory allocation
- Prev by Date: Re: [2.6.23-rc3 possible regression] 8250 claims nonexisting device blocking IO port
- Next by Date: Re: [patch] Refine FAT chmod checks
- Previous by thread: perfmon2 kernel: git tree up and running
- Next by thread: Re: Kernel oops during netfilter memory allocation
- Index(es):