From: Craig Gallek Date: Wed, 6 Jul 2016 22:44:20 +0000 (-0400) Subject: tun: Don't assume type tun in tun_device_event X-Git-Tag: v4.8-rc1~140^2~163 X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Flinux.git;a=commitdiff_plain;h=86dfb4acb378cb3a4eede3db919604c583beaa7c tun: Don't assume type tun in tun_device_event The referenced change added a netlink notifier for processing device queue size events. These events are fired for all devices but the registered callback assumed they only occurred for tun devices. This fix adds a check (borrowed from macvtap.c) to discard non-tun device events. For reference, this fixes the following splat: [ 71.505935] BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 [ 71.513870] IP: [] tun_device_event+0x110/0x340 [ 71.519906] PGD 3f41f56067 PUD 3f264b7067 PMD 0 [ 71.524497] Oops: 0002 [#1] SMP DEBUG_PAGEALLOC [ 71.529374] gsmi: Log Shutdown Reason 0x03 [ 71.533417] Modules linked in:[ 71.533826] mlx4_en: eth1: Link Up [ 71.539616] bonding w1_therm wire cdc_acm ehci_pci ehci_hcd mlx4_en ib_uverbs mlx4_ib ib_core mlx4_core [ 71.549282] CPU: 12 PID: 7915 Comm: set.ixion-haswe Not tainted 4.7.0-dbx-DEV #8 [ 71.556586] Hardware name: Intel Grantley,Wellsburg/Ixion_IT_15, BIOS 2.58.0 05/03/2016 [ 71.564495] task: ffff887f00bb20c0 ti: ffff887f00798000 task.ti: ffff887f00798000 [ 71.571894] RIP: 0010:[] [] tun_device_event+0x110/0x340 [ 71.580327] RSP: 0018:ffff887f0079bbd8 EFLAGS: 00010202 [ 71.585576] RAX: fffffffffffffae8 RBX: ffff887ef6d03378 RCX: 0000000000000000 [ 71.592624] RDX: 0000000000000000 RSI: 0000000000000028 RDI: 0000000000000000 [ 71.599675] RBP: ffff887f0079bc48 R08: 0000000000000000 R09: 0000000000000001 [ 71.606730] R10: 0000000000000004 R11: 0000000000000000 R12: 0000000000000010 [ 71.613780] R13: 0000000000000000 R14: 0000000000000001 R15: ffff887f0079bd00 [ 71.620832] FS: 00007f5cdc581700(0000) GS:ffff883f7f700000(0000) knlGS:0000000000000000 [ 71.628826] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 71.634500] CR2: 0000000000000010 CR3: 0000003f3eb62000 CR4: 00000000001406e0 [ 71.641549] Stack: [ 71.643533] ffff887f0079bc08 0000000000000246 000000000000001e ffff887ef6d00000 [ 71.650871] ffff887f0079bd00 0000000000000000 0000000000000000 ffffffff00000000 [ 71.658210] ffff887f0079bc48 ffffffff81d24070 00000000fffffff9 ffffffff81cec7a0 [ 71.665549] Call Trace: [ 71.667975] [] notifier_call_chain+0x5d/0x80 [ 71.673823] [] ? show_tx_maxrate+0x30/0x30 [ 71.679502] [] __raw_notifier_call_chain+0xe/0x10 [ 71.685778] [] raw_notifier_call_chain+0x16/0x20 [ 71.691976] [] call_netdevice_notifiers_info+0x40/0x70 [ 71.698681] [] call_netdevice_notifiers+0x16/0x20 [ 71.704956] [] change_tx_queue_len+0x66/0x90 [ 71.710807] [] netdev_store.isra.5+0xbf/0xd0 [ 71.716658] [] tx_queue_len_store+0x50/0x60 [ 71.722431] [] dev_attr_store+0x18/0x30 [ 71.727857] [] sysfs_kf_write+0x4f/0x70 [ 71.733274] [] kernfs_fop_write+0x147/0x1d0 [ 71.739045] [] ? rcu_read_lock_sched_held+0x8f/0xa0 [ 71.745499] [] __vfs_write+0x28/0x120 [ 71.750748] [] ? percpu_down_read+0x57/0x90 [ 71.756516] [] ? __sb_start_write+0xc8/0xe0 [ 71.762278] [] ? __sb_start_write+0xc8/0xe0 [ 71.768038] [] vfs_write+0xbe/0x1b0 [ 71.773113] [] SyS_write+0x52/0xa0 [ 71.778110] [] entry_SYSCALL_64_fastpath+0x18/0xa8 [ 71.784472] Code: 45 31 f6 48 8b 93 78 33 00 00 48 81 c3 78 33 00 00 48 39 d3 48 8d 82 e8 fa ff ff 74 25 48 8d b0 40 05 00 00 49 63 d6 41 83 c6 01 <49> 89 34 d4 48 8b 90 18 05 00 00 48 39 d3 48 8d 82 e8 fa ff ff [ 71.803655] RIP [] tun_device_event+0x110/0x340 [ 71.809769] RSP [ 71.813213] CR2: 0000000000000010 [ 71.816512] ---[ end trace 4db6449606319f73 ]--- Fixes: 1576d9860599 ("tun: switch to use skb array for tx") Signed-off-by: Craig Gallek Acked-by: Jason Wang Signed-off-by: David S. Miller --- diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 5eadb7a1ad7b..9c8b5bc2b9d8 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -2503,6 +2503,9 @@ static int tun_device_event(struct notifier_block *unused, struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct tun_struct *tun = netdev_priv(dev); + if (dev->rtnl_link_ops != &tun_link_ops) + return NOTIFY_DONE; + switch (event) { case NETDEV_CHANGE_TX_QUEUE_LEN: if (tun_queue_resize(tun))