aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netconsole.c
diff options
context:
space:
mode:
authorDan Aloni <alonid@postram.com>2013-08-30 06:59:46 -0400
committerDavid S. Miller <davem@davemloft.net>2013-09-03 22:10:49 -0400
commit7a163bfb7ce50895bbe67300ea610d31b9c09230 (patch)
tree99e6951072a9c1cf7e0700528f3f10d3d56a09a2 /drivers/net/netconsole.c
parentfd9af07c3404ac9ecbd0d859563360f51ce1ffde (diff)
netconsole: avoid a crash with multiple sysfs writers
When my 'ifup eth' script was fired multiple times and ran concurrent on my laptop, for some obscure /etc scripting reason, it was revealed that the store_enabled() function in netconsole doesn't handle it nicely, as recorded by the Oops below (a syslog paste, but not mangled too much to prevent from discerning the traceback). On Linux 3.10.4, this patch seeks to remedy the problem, and it has been running stable on my laptop for a few days. [52608.609325] BUG: unable to handle kernel NULL pointer dereference at 00000000000003e0 [52608.609331] IP: [<ffffffff81532a17>] __netpoll_cleanup+0x27/0xe0 [52608.609339] PGD 15e51a067 PUD 15433e067 PMD 0 [52608.609343] Oops: 0000 [#1] SMP re firewire_ohci firewire_core crc_itu_t [last unloaded: kvm_intel] [52608.609347] Modules linked in: kvm_intel tun vfat fat ppdev parport_pc parport fuse ipt_MASQUERADE usb_storage nf_conntrack_netbios_ns nf_conn [..garbled..] [52608.609433] RAX: 0000000000000000 RBX: ffff880210bbcc68 RCX: 0000000000000000 [52608.609435] RDX: 0000000000000000 RSI: ffff8801ba447da0 RDI: ffff880210bbcc68 [52608.609437] RBP: ffff8801ba447e18 R08: 0000000000000000 R09: 0000000000000001 [52608.609439] R10: 000000000000000a R11: f000000000000000 R12: ffff880210bbcc68 [52608.609441] R13: ffff88020bc41000 R14: 0000000000000002 R15: 000000000000000200000000000 [52608.609443] FS: 00007f38d7bff740(0000) GS:ffff88021dc40000(0000) knlGS:0000000000000000 [52608.609446] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003300000000001427e0 [52608.609448] CR2: 00000000000003e0 CR3: 0000000154103000 CR4: 00000000001427e0 [52608.609450] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [52608.609452] netpoll: netconsole: local port 6665ess 10.0.0.27 [52608.609454] netpoll: netconsole: local IPv4 address 10.0.0.27 [52608.609456] netpoll: netconsole: interface 'em1' [52608.609457] netpoll: netconsole: remote port 514ress 10.0.0.15 [52608.609459] netpoll: netconsole: remote IPv4 address 10.0.0.15:65:a8:9a:c7 [52608.609461] netpoll: netconsole: remote ethernet address 1c:6f:65:a8:9a:c7 [52608.609463] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [52608.609464] Stack:801ba447e08 ffff880210bbcc68 ffffffffffffffea ffff88020bc41000 [52608.609466] ffff8801ba447e08 ffff880210bbcc68 ffffffffffffffea ffff88020bc41000 [52608.609471] 0000000000000002 0000000000000002 ffff8801ba447e38 ffffffff81532af4 [52608.609475] 0000000000000000 ffff880210bbcc00 ffff8801ba447e78 ffffffff81420e7c [52608.609479] Call Trace: [52608.609484] [<ffffffff81532af4>] netpoll_cleanup+0x24/0x50 [52608.609489] [<ffffffff81420e7c>] store_enabled+0x5c/0xe0 [52608.609492] [<ffffffff81420abe>] netconsole_target_attr_store+0x2e/0x40 [52608.609498] [<ffffffff811ff2a2>] configfs_write_file+0xd2/0x130 [52608.609503] [<ffffffff81188f95>] vfs_write+0xc5/0x1f0 [52608.609506] [<ffffffff81189482>] SyS_write+0x52/0xa0/0x10 [52608.609511] [<ffffffff81628c2e>] ? do_page_fault+0xe/0x10 [52608.609516] [<ffffffff8162d402>] system_call_fastpath+0x16/0x1b [52608.609517] Code: 1f 44 00 00 0f 1f 44 00 00 55 48 89 e5 48 83 ec 30 4c 89 65 e0 48 89 5d d8 49 89 fc 4c 89 6d e8 4c 89 75 f0 4c 89 7d f8 48 8 [..garbled..] [52608.609559] RIP [<ffffffff81532a17>] __netpoll_cleanup+0x27/0xe0 [52608.609563] RSP <ffff8801ba447de8> [52608.609564] CR2: 00000000000003e0 [52608.609567] ---[ end trace d25ec343349b61d2 ]--- Signed-off-by: Dan Aloni <alonid@postram.com> Signed-off-by: Neil Horman <nhorman@tuxdriver.com> CC: David S. Miller <davem@davemloft.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netconsole.c')
-rw-r--r--drivers/net/netconsole.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 4822aafe638b..dcb21347c670 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -102,6 +102,7 @@ struct netconsole_target {
102 struct config_item item; 102 struct config_item item;
103#endif 103#endif
104 int enabled; 104 int enabled;
105 struct mutex mutex;
105 struct netpoll np; 106 struct netpoll np;
106}; 107};
107 108
@@ -181,6 +182,7 @@ static struct netconsole_target *alloc_param_target(char *target_config)
181 strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ); 182 strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
182 nt->np.local_port = 6665; 183 nt->np.local_port = 6665;
183 nt->np.remote_port = 6666; 184 nt->np.remote_port = 6666;
185 mutex_init(&nt->mutex);
184 memset(nt->np.remote_mac, 0xff, ETH_ALEN); 186 memset(nt->np.remote_mac, 0xff, ETH_ALEN);
185 187
186 /* Parse parameters and setup netpoll */ 188 /* Parse parameters and setup netpoll */
@@ -322,6 +324,7 @@ static ssize_t store_enabled(struct netconsole_target *nt,
322 return -EINVAL; 324 return -EINVAL;
323 } 325 }
324 326
327 mutex_lock(&nt->mutex);
325 if (enabled) { /* 1 */ 328 if (enabled) { /* 1 */
326 329
327 /* 330 /*
@@ -331,8 +334,10 @@ static ssize_t store_enabled(struct netconsole_target *nt,
331 netpoll_print_options(&nt->np); 334 netpoll_print_options(&nt->np);
332 335
333 err = netpoll_setup(&nt->np); 336 err = netpoll_setup(&nt->np);
334 if (err) 337 if (err) {
338 mutex_unlock(&nt->mutex);
335 return err; 339 return err;
340 }
336 341
337 printk(KERN_INFO "netconsole: network logging started\n"); 342 printk(KERN_INFO "netconsole: network logging started\n");
338 343
@@ -341,6 +346,7 @@ static ssize_t store_enabled(struct netconsole_target *nt,
341 } 346 }
342 347
343 nt->enabled = enabled; 348 nt->enabled = enabled;
349 mutex_unlock(&nt->mutex);
344 350
345 return strnlen(buf, count); 351 return strnlen(buf, count);
346} 352}
@@ -597,6 +603,7 @@ static struct config_item *make_netconsole_target(struct config_group *group,
597 strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ); 603 strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
598 nt->np.local_port = 6665; 604 nt->np.local_port = 6665;
599 nt->np.remote_port = 6666; 605 nt->np.remote_port = 6666;
606 mutex_init(&nt->mutex);
600 memset(nt->np.remote_mac, 0xff, ETH_ALEN); 607 memset(nt->np.remote_mac, 0xff, ETH_ALEN);
601 608
602 /* Initialize the config_item member */ 609 /* Initialize the config_item member */
@@ -682,7 +689,11 @@ restart:
682 * we might sleep in __netpoll_cleanup() 689 * we might sleep in __netpoll_cleanup()
683 */ 690 */
684 spin_unlock_irqrestore(&target_list_lock, flags); 691 spin_unlock_irqrestore(&target_list_lock, flags);
692
693 mutex_lock(&nt->mutex);
685 __netpoll_cleanup(&nt->np); 694 __netpoll_cleanup(&nt->np);
695 mutex_unlock(&nt->mutex);
696
686 spin_lock_irqsave(&target_list_lock, flags); 697 spin_lock_irqsave(&target_list_lock, flags);
687 dev_put(nt->np.dev); 698 dev_put(nt->np.dev);
688 nt->np.dev = NULL; 699 nt->np.dev = NULL;