From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from s3.sipsolutions.net ([144.76.43.152]:59249 "EHLO sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757407Ab3HGMeX (ORCPT ); Wed, 7 Aug 2013 08:34:23 -0400 From: Johannes Berg To: linux-wireless@vger.kernel.org, netdev@vger.kernel.org, Thomas Graf Cc: Andrei Otcheretianski , Ilan Peer , Johannes Berg Subject: [PATCH 3.11] genetlink: fix family dump race Date: Wed, 7 Aug 2013 14:34:14 +0200 Message-Id: <1375878854-29997-1-git-send-email-johannes@sipsolutions.net> (sfid-20130807_143431_202253_42E326A6) Sender: linux-wireless-owner@vger.kernel.org List-ID: From: Johannes Berg When dumping generic netlink families, only the first dump call is locked with genl_lock(), which protects the list of families, and thus subsequent calls can access the data without locking, racing against family addition/removal. This can cause a crash. Fix it - the locking needs to be conditional because the first time around it's already locked. BUG: unable to handle kernel paging request at f8467360 IP: [] ctrl_dumpfamily+0x6b/0xe0 EIP: 0060:[] EFLAGS: 00210297 CPU: 2 EIP is at ctrl_dumpfamily+0x6b/0xe0 EAX: f8467378 EBX: f8467340 ECX: 00000000 EDX: ec1610c4 ESI: 00000001 EDI: c2077cc0 EBP: c46c3c00 ESP: c46c3bd4 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 CR0: 80050033 CR2: f8467360 CR3: 26e54000 CR4: 001407d0 DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 DR6: ffff0ff0 DR7: 00000400 Process wpa_supplicant (pid: 20081, ti=c46c2000 task=c44640b0 task.ti=c46c2000) Call Trace: [] netlink_dump+0x5c/0x200 [] __netlink_dump_start+0x140/0x160 [] genl_rcv_msg+0x102/0x270 [] netlink_rcv_skb+0x8e/0xb0 [] genl_rcv+0x1c/0x30 [] netlink_unicast+0x17b/0x1c0 [] netlink_sendmsg+0x224/0x370 [] sock_sendmsg+0xff/0x120 [] __sys_sendmsg+0x24a/0x260 [] sys_sendmsg+0x3b/0x60 [] sys_socketcall+0x283/0x2e0 [] sysenter_do_call+0x12/0x38 Code: 8d 3c c5 c0 7c 07 c2 8b 04 c5 c0 7c 07 c2 39 c7 8d 58 c8 75 16 eb 71 90 81 7d ec 00 1f 86 c1 74 10 8b 43 38 39 c7 8d 58 c8 74 5d <80> 7b 20 00 74 e7 83 c6 01 3b 75 f0 7c e8 8b 55 e8 8b 42 04 8b Cc: stable@vger.kernel.org Reported-by: Andrei Otcheretianski Signed-off-by: Johannes Berg --- net/netlink/genetlink.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 2fd6dbe..07a0b18 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -790,6 +790,9 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) int chains_to_skip = cb->args[0]; int fams_to_skip = cb->args[1]; + if (chains_to_skip) + genl_lock(); + for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) { n = 0; list_for_each_entry(rt, genl_family_chain(i), family_list) { @@ -810,6 +813,9 @@ errout: cb->args[0] = i; cb->args[1] = n; + if (chains_to_skip) + genl_unlock(); + return skb->len; } -- 1.8.0