[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#597904: [PATCH] phonet: Restrict to initial namespace



The lifetime management for per-namespace state in phonet is broken in
2.6.32.  When a network namespace is destroyed it will crash
(repeatably):

[   73.925565] BUG: unable to handle kernel NULL pointer dereference at
(null)
[   73.927385] IP: [<d0823135>] phonet_device_destroy+0x81/0xf8 [phonet]
[   73.928020] *pde = 00000000
[   73.928020] Oops: 0000 [#1] SMP
[   73.928020] last sysfs file: /sys/devices/virtual/vc/vcsa7/uevent
[   73.928020] Modules linked in: phonet loop processor snd_pcm
snd_timer button serio_raw snd soundcore snd_page_alloc psmouse
parport_pc evdev parport i2c_piix4 pcspkr i2c_core ext3 jbd mbcache fan
sg sr_mod cdrom sd_mod crc_t10dif ata_generic ata_piix thermal libata
thermal_sys floppy e1000 scsi_mod [last unloaded: scsi_wait_scan]
[   73.928020]
[   73.928020] Pid: 9, comm: netns Not tainted (2.6.32-5-686 #1) Bochs
[   73.928020] EIP: 0060:[<d0823135>] EFLAGS: 00010207 CPU: 0
[   73.928020] EIP is at phonet_device_destroy+0x81/0xf8 [phonet]
[   73.928020] EAX: ce6ec1c0 EBX: 00000000 ECX: ce32fc00 EDX: 00000000
[   73.928020] ESI: ce6ec1c8 EDI: 00000000 EBP: ce32fc00 ESP: cf453f00
[   73.928020]  DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[   73.928020] Process netns (pid: 9, ti=cf452000 task=cf426200
task.ti=cf452000)
[   73.928020] Stack:
[   73.928020]  d0825694 ce32fc00 00000000 00000000 d08234ef fffffff2
00000000 ce32fc00
[   73.928020] <0> c11e5b27 c13ad2fc e6064da0 d0825694 fffffff1 c126ec00
ce32fc00 00000006
[   73.928020] <0> ce32fc00 cf838000 cf453fb0 cf838010 c1046fd2 ffffffff
00000000 c11d9920
[   73.928020] Call Trace:
[   73.928020]  [<d08234ef>] ? phonet_device_notify+0x94/0xae [phonet]
[   73.928020]  [<c11e5b27>] ? dropmon_net_event+0xf5/0x114
[   73.928020]  [<c126ec00>] ? notifier_call_chain+0x2a/0x47
[   73.928020]  [<c1046fd2>] ? raw_notifier_call_chain+0x9/0xc
[   73.928020]  [<c11d9920>] ? rollback_registered+0x9a/0xec
[   73.928020]  [<c11d99a1>] ? unregister_netdevice+0x2f/0x54
[   73.928020]  [<c11d99d5>] ? unregister_netdev+0xf/0x15
[   73.928020]  [<c11d5773>] ? cleanup_net+0x43/0x7d
[   73.928020]  [<c1040c33>] ? worker_thread+0x141/0x1bd
[   73.928020]  [<c11d5730>] ? cleanup_net+0x0/0x7d
[   73.928020]  [<c104396a>] ? autoremove_wake_function+0x0/0x2d
[   73.928020]  [<c1040af2>] ? worker_thread+0x0/0x1bd
[   73.928020]  [<c1043738>] ? kthread+0x61/0x66
[   73.928020]  [<c10436d7>] ? kthread+0x0/0x66
[   73.928020]  [<c1003d47>] ? kernel_thread_helper+0x7/0x10
[   73.928020] Code: b8 59 82 d0 8b 85 44 02 00 00 85 d2 8b 80 98 04 00
00 74 04 3b 10 76 04 0f 0b eb fe 8b 44 90 08 8b 18 eb 07 39 6b 08 74 10
89 d3 <8b> 13 0f 18 02 90 39 c3 75 ef 31 db eb 19 85 db 74 15 8b 43 04
[   73.928020] EIP: [<d0823135>] phonet_device_destroy+0x81/0xf8
[phonet] SS:ESP 0068:cf453f00
[   73.928020] CR2: 0000000000000000
[   74.003675] ---[ end trace 0efbc7b3acd94bdf ]---
[   74.006363] Kernel panic - not syncing: Fatal exception in interrupt
[   74.009738] Pid: 9, comm: netns Tainted: G      D    2.6.32-5-686 #1
[   74.013033] Call Trace:
[   74.014327]  [<c126b429>] ? panic+0x38/0xe4
[   74.016595]  [<c126da31>] ? oops_end+0x91/0x9d
[   74.018894]  [<c101b5db>] ? no_context+0x105/0x10e
[   74.021384]  [<c101b6f9>] ? __bad_area_nosemaphore+0x115/0x11d
[   74.028368]  [<c12188b8>] ? snmp_mib_free+0x1a/0x29
[   74.032077]  [<c1238b09>] ? addrconf_ifdown+0x23f/0x260
[   74.034725]  [<c123a20c>] ? addrconf_notify+0x6a4/0x776
[   74.038354]  [<c126e8cf>] ? do_page_fault+0x0/0x307
[   74.040046]  [<c101b70b>] ? bad_area_nosemaphore+0xa/0xc
[   74.041325]  [<c126d123>] ? error_code+0x73/0x78
[   74.042515]  [<d0823135>] ? phonet_device_destroy+0x81/0xf8 [phonet]
[   74.044350]  [<d08234ef>] ? phonet_device_notify+0x94/0xae [phonet]
[   74.045958]  [<c11e5b27>] ? dropmon_net_event+0xf5/0x114
[   74.047361]  [<c126ec00>] ? notifier_call_chain+0x2a/0x47
[   74.048789]  [<c1046fd2>] ? raw_notifier_call_chain+0x9/0xc
[   74.050221]  [<c11d9920>] ? rollback_registered+0x9a/0xec
[   74.051651]  [<c11d99a1>] ? unregister_netdevice+0x2f/0x54
[   74.053111]  [<c11d99d5>] ? unregister_netdev+0xf/0x15
[   74.054635]  [<c11d5773>] ? cleanup_net+0x43/0x7d
[   74.055942]  [<c1040c33>] ? worker_thread+0x141/0x1bd
[   74.057183]  [<c11d5730>] ? cleanup_net+0x0/0x7d
[   74.058275]  [<c104396a>] ? autoremove_wake_function+0x0/0x2d
[   74.059737]  [<c1040af2>] ? worker_thread+0x0/0x1bd
[   74.060935]  [<c1043738>] ? kthread+0x61/0x66
[   74.062014]  [<c10436d7>] ? kthread+0x0/0x66
[   74.063097]  [<c1003d47>] ? kernel_thread_helper+0x7/0x10

This bug is known to be triggered by using Chromium (which
creates a network namespace) and some Nokia phones (which trigger
loading of phonet).

Reference: http://code.google.com/p/chromium/issues/detail?id=54617
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
I'm submitting this for 2.6.32 only.  The bug is reported to be fixed in
later kernel versions, but it's not clear exactly which change fixed it
or whether that is suitable for stable.  Rémi may be able to suggest a
better way to fix this.

Ben.

 net/phonet/pn_dev.c |   29 ++++++++++++++++++++++++++---
 1 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c
index 5f42f30..af9e553 100644
--- a/net/phonet/pn_dev.c
+++ b/net/phonet/pn_dev.c
@@ -39,9 +39,19 @@ struct phonet_net {
 
 int phonet_net_id;
 
+static struct phonet_device_list empty_device_list = {
+	.list = LIST_HEAD_INIT(empty_device_list.list),
+	.lock = SPIN_LOCK_UNLOCKED
+};
+
 struct phonet_device_list *phonet_device_list(struct net *net)
 {
-	struct phonet_net *pnn = net_generic(net, phonet_net_id);
+	struct phonet_net *pnn;
+
+	if (!net_eq(net, &init_net))
+		return &empty_device_list;
+
+	pnn = net_generic(net, phonet_net_id);
 	return &pnn->pndevs;
 }
 
@@ -122,6 +132,9 @@ int phonet_address_add(struct net_device *dev, u8 addr)
 	struct phonet_device *pnd;
 	int err = 0;
 
+	if (!net_eq(dev_net(dev), &init_net))
+		return -EPERM;
+
 	spin_lock_bh(&pndevs->lock);
 	/* Find or create Phonet-specific device data */
 	pnd = __phonet_get(dev);
@@ -246,7 +259,12 @@ static struct notifier_block phonet_device_notifier = {
 /* Per-namespace Phonet devices handling */
 static int phonet_init_net(struct net *net)
 {
-	struct phonet_net *pnn = kmalloc(sizeof(*pnn), GFP_KERNEL);
+	struct phonet_net *pnn;
+
+	if (!net_eq(net, &init_net))
+		return 0;
+
+	pnn = kmalloc(sizeof(*pnn), GFP_KERNEL);
 	if (!pnn)
 		return -ENOMEM;
 
@@ -263,9 +281,14 @@ static int phonet_init_net(struct net *net)
 
 static void phonet_exit_net(struct net *net)
 {
-	struct phonet_net *pnn = net_generic(net, phonet_net_id);
+	struct phonet_net *pnn;
 	struct net_device *dev;
 
+	if (!net_eq(net, &init_net))
+		return;
+
+	pnn = net_generic(net, phonet_net_id);
+
 	rtnl_lock();
 	for_each_netdev(net, dev)
 		phonet_device_destroy(dev);
-- 
1.7.1





Reply to: