From patchwork Sun Mar 14 02:28:55 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: michael-dev X-Patchwork-Id: 47725 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 93C50B7D57 for ; Sun, 14 Mar 2010 13:29:24 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754547Ab0CNC3G (ORCPT ); Sat, 13 Mar 2010 21:29:06 -0500 Received: from moutng.kundenserver.de ([212.227.17.9]:50530 "EHLO moutng.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753756Ab0CNC3D (ORCPT ); Sat, 13 Mar 2010 21:29:03 -0500 Received: from gate.zuhauseall.homeip.net (p57A21487.dip0.t-ipconnect.de [87.162.20.135]) by mrelayeu.kundenserver.de (node=mreu1) with ESMTP (Nemesis) id 0LaHYA-1NNerq00B4-00lvim; Sun, 14 Mar 2010 03:29:00 +0100 Message-ID: <4B9C49E7.1080703@fami-braun.de> Date: Sun, 14 Mar 2010 03:28:55 +0100 From: michael-dev@fami-braun.de User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.8.1.23) Gecko/20090817 Lightning/0.9 Thunderbird/2.0.0.23 Mnenhy/0.7.6.666 MIME-Version: 1.0 To: netdev@vger.kernel.org Subject: [PATCH] BUG: unable to handle kernel NULL pointer dereference at br_multicast_leave_group X-Enigmail-Version: 0.95.7 X-Virus-Scanned: clamav-milter 0.95.2 at gate X-Virus-Status: Clean X-Provags-ID: V01U2FsdGVkX1+YYvgRdEQ5DUCz/qGAuyDHLVtoI1LqP4LQQSI ZtEEhHU/0Bn9abm71marBQQDqMvnjmXl/2aTztTcCiUWGQ+Rls rrGPEjgcKM1nrizRUW/JC6TjcblON00 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Hi, I'm currently using linux-next and have been running into an OOPs which I think might be caused by a patch you submitted on 2010-02-27. It's a linux-next kernel from 2010-03-12 on an x86 system and it OOPs in the bridge module in br_mdp_ip_get (called by br_multicast_leave_group) because the br->mdb is null. Digging deeper it seems that when a igmp leave packet is received, it is not checked wether mdb has been populated yet. Though, if the group does not exist, the code just skips leaving. So it seems the same action cna be taken if mdb is still NULL. As far as I can see, commit eb1d16414339a6e113d89e2cca2556005d7ce919 added multicast code to bridge and so likely causes this crash. This crash does not happen on 2.6.33. I've therefore modified br_multicast so that the leave is skipped if mdb is empty. Please don't hesitate to contact me if there are any questions. Sincerely, M. Braun // gdb output // (gdb) print *((struct net_bridge*) 0xcec68800) $3 = {lock = {{rlock = {raw_lock = {}}}}, port_list = {next = 0xcec41790, prev = 0xcfb209f8}, dev = 0xcec68520, hash_lock = {{rlock = {raw_lock = {}}}}, hash = {{first = 0x0}, {first = 0x0}, {first = 0x0}, {first = 0x0}, { first = 0xcfb4d980}, {first = 0x0} , {first = 0xcec41200}, {first = 0x0} , {first = 0xcf00ea80}, {first = 0x0} , {first = 0xcfb6d680}, {first = 0x0} , {first = 0xcec40b00}, {first = 0x0}, { first = 0x0}, {first = 0x0}, {first = 0x0}, {first = 0x0}, {first = 0x0}, {first = 0x0}, {first = 0xcf00d1c0}, {first = 0x0} }, feature_mask = 16726117, fake_rtable = {u = {dst = {rcu_head = {next = 0x0, func = 0}, child = 0x0, dev = 0xcec68520, error = 0, obsolete = 0, flags = 2, expires = 0, header_len = 0, trailer_len = 0, rate_tokens = 0, rate_last = 0, path = 0xcec68c10, neighbour = 0x0, hh = 0x0, xfrm = 0x0, input = 0, output = 0, ops = 0xd0cc2a40, metrics = {0, 1500, 0 }, tclassid = 0, __refcnt = {counter = 2}, __use = 0, lastuse = 0, {next = 0x0, rt_next = 0x0, rt6_next = 0x0, dn_next = 0x0}}}, fl = {oif = 0, iif = 0, mark = 0, nl_u = {ip4_u = {daddr = 0, saddr = 0, tos = 0 '\000', scope = 0 '\000'}, ip6_u = {daddr = {in6_u = { u6_addr8 = '\000' , u6_addr16 = {0, 0, 0, 0, 0, 0, 0, 0}, u6_addr32 = {0, 0, 0, 0}}}, saddr = {in6_u = {u6_addr8 = '\000' , u6_addr16 = {0, 0, 0, 0, 0, 0, 0, 0}, u6_addr32 = {0, 0, 0, 0}}}, flowlabel = 0}, dn_u = { daddr = 0, saddr = 0, scope = 0 '\000'}}, proto = 0 '\000', flags = 0 '\000', uli_u = {ports = {sport = 0, dport = 0}, icmpt = {type = 0 '\000', code = 0 '\000'}, dnports = {sport = 0, dport = 0}, spi = 0, mht = {type = 0 '\000'}}, secid = 0}, idev = 0x0, rt_genid = 0, rt_flags = 0, rt_type = 0, rt_dst = 0, rt_src = 0, rt_iif = 0, rt_gateway = 0, rt_spec_dst = 0, peer = 0x0}, flags = 0, designated_root = {prio = "\200", addr = "\000\016\216\031\356v"}, bridge_id = {prio = "\200", addr = "\000\016\216\031\356v"}, root_path_cost = 0, max_age = 20000, hello_time = 2000, forward_delay = 15000, bridge_max_age = 20000, ageing_time = 300000, bridge_hello_time = 2000, bridge_forward_delay = 15000, group_addr = "\001\200\302\000\000", root_port = 0, stp_enabled = BR_KERNEL_STP, topology_change = 0 '\000', topology_change_detected = 0 '\000', multicast_router = 1 '\001', multicast_disabled = 0 '\000', hash_elasticity = 4, hash_max = 512, multicast_last_member_count = 2, multicast_startup_queries_sent = 2, multicast_startup_query_count = 2, multicast_last_member_interval = 1000, multicast_membership_interval = 260000, multicast_querier_interval = 255000, multicast_query_interval = 125000, multicast_query_response_interval = 10000, multicast_startup_query_interval = 31250, multicast_lock = {{rlock = { raw_lock = {}}}}, mdb = 0x0, router_list = {first = 0x0}, mglist = {first = 0x0}, multicast_router_timer = {entry = {next = 0x0, prev = 0x0}, expires = 0, function = 0xd0cbf264 , data = 0, base = 0xc0579640}, multicast_querier_timer = {entry = {next = 0x0, prev = 0x0}, expires = 0, function = 0xd0cbf264 , data = 0, base = 0xc0579640}, multicast_query_timer = {entry = {next = 0xd0a1f630, prev = 0xc057a1a4}, expires = 1756782, function = 0xd0cc01e1 , data = 3469117440, base = 0xc0579640}, hello_timer = {entry = {next = 0xc0579f14, prev = 0xcfcb6e10}, expires = 1694000, function = 0xd0cbc75b , data = 3469117440, base = 0xc0579640}, tcn_timer = {entry = {next = 0x0, prev = 0x0}, expires = 0, function = 0xd0cbc6ce , data = 3469117440, base = 0xc0579640}, topology_change_timer = {entry = {next = 0x0, prev = 0x200200}, expires = 225844, function = 0xd0cbc42c , data = 3469117440, base = 0xc0579640}, gc_timer = {entry = {next = 0xcfcb6e10, prev = 0xc0579f14}, expires = 1694000, function = 0xd0cb8d8f , data = 3469117440, base = 0xc0579640}, ifobj = 0xcfca1164} (gdb) print ((struct net_bridge*) 0xcec68800)->mdb $4 = (struct net_bridge_mdb_htable *) 0x0 (gdb) bt #0 jhash_3words (mdb=0x0, dst=0) at include/linux/jhash.h:128 #1 jhash_1word (mdb=0x0, dst=0) at include/linux/jhash.h:140 #2 br_ip_hash (mdb=0x0, dst=0) at net/bridge/br_multicast.c:32 #3 br_mdb_ip_get (mdb=0x0, dst=0) at net/bridge/br_multicast.c:52 #4 0xd0cc0ec8 in br_multicast_leave_group (br=0xcec68800, port=, skb=0xcf00e580) at net/bridge/br_multicast.c:902 #5 br_multicast_ipv4_rcv (br=0xcec68800, port=, skb=0xcf00e580) at net/bridge/br_multicast.c:1033 #6 br_multicast_rcv (br=0xcec68800, port=, skb=0xcf00e580) at net/bridge/br_multicast.c:1052 #7 0xd0cb9c06 in br_handle_frame_finish (skb=0xcf00e580) at net/bridge/br_input.c:55 #8 0xd0cbea59 in NF_HOOK_THRESH (skb=0xcf00e580) at include/linux/netfilter.h:206 #9 br_nf_pre_routing_finish (skb=0xcf00e580) at net/bridge/br_netfilter.c:420 #10 0xd0cbf015 in NF_HOOK_THRESH (hook=, skb=0xcf00e580, in=, out=0x0, okfn=0xd0cb9bad ) at include/linux/netfilter.h:206 #11 NF_HOOK (hook=, skb=0xcf00e580, in=, out=0x0, okfn=0xd0cb9bad ) at include/linux/netfilter.h:228 #12 br_nf_pre_routing (hook=, skb=0xcf00e580, in=, out=0x0, okfn=0xd0cb9bad ) at net/bridge/br_netfilter.c:610 #13 0xc0377247 in ?? () // commit // commit eb1d16414339a6e113d89e2cca2556005d7ce919 Author: Herbert Xu Date: Sat Feb 27 19:41:45 2010 +0000 bridge: Add core IGMP snooping support This patch adds the core functionality of IGMP snooping support without actually hooking it up. So this patch should be a no-op as far as the bridge's external behaviour is concerned. All the new code and data is controlled by the Kconfig option BRIDGE_IGMP_SNOOPING. A run-time toggle is also available. The multicast switching is done using an hash table that is lockless on the read-side through RCU. On the write-side the new multicast_lock is used for all operations. The hash table supports dynamic growth/rehashing. The hash table will be rehashed if any chain length exceeds a preset limit. If rehashing does not reduce the maximum chain length then snooping will be disabled. These features may be added in future (in no particular order): * IGMPv3 source support * Non-querier router detection * IPv6 Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 12ce1ea..85ca985 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -899,6 +899,8 @@ static void br_multicast_leave_group(struct net_bridge *br, goto out; mdb = br->mdb; + if (!mdb) + goto out; mp = br_mdb_ip_get(mdb, group); if (!mp) goto out;