datapath: Fix RHEL compat for netdev_rx_handler_register
authorChris Wright <chrisw@sous-sol.org>
Wed, 14 Aug 2013 01:02:48 +0000 (18:02 -0700)
committerPravin B Shelar <pshelar@nicira.com>
Wed, 14 Aug 2013 01:02:48 +0000 (18:02 -0700)
Andrei Andone reported an oops on CentOS 6.4 when adding a device to an
ovs instance.  The problem is easy to reproduce and generates the
following stack trace:

kernel tried to execute NX-protected page - exploit attempt? (uid: 0)
BUG: unable to handle kernel paging request at ffff88033afa49c0
IP: [<ffff88033afa49c0>] 0xffff88033afa49c0
...
Call Trace:
 <IRQ>
 [<ffffffff814487ba>] ? __netif_receive_skb+0x60a/0x750
 [<ffffffff81055f96>] ? enqueue_task+0x66/0x80
 [<ffffffff8144aa38>] netif_receive_skb+0x58/0x60
 [<ffffffff8144ab40>] napi_skb_finish+0x50/0x70
 [<ffffffff8144d0e9>] napi_gro_receive+0x39/0x50
 [<ffffffffa025f46c>] igb_poll+0x7ec/0xc70 [igb]
 [<ffffffff810e6881>] ? cpu_quiet_msk+0xc1/0x130
...

As you can see, we jumped to data rather than code.  This is caused by
a mistake in the compat code for netdev_rx_handler_register which sets
the handler to rx_handler_data rather than rx_handler.  This was
introduced by commit "3e35fe3 datapath: rhel: Move RHEL OVS hook
registration to netdev_rx_handler_register() backport".

Reported-by: Andrei Andone <andrei.andone@softvision.ro>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Cc: Thomas Graf <tgraf@redhat.com>
Cc: Pravin Shelar <pshelar@nicira.com>
Acked-by: Kyle Mestery <kmestery@cisco.com>
Reviewed-by: Thomas Graf <tgraf@redhat.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
datapath/linux/compat/include/linux/netdevice.h

index f62bd6d..2ceff22 100644 (file)
@@ -98,7 +98,7 @@ static inline int netdev_rx_handler_register(struct net_device *dev,
 #ifdef HAVE_RHEL_OVS_HOOK
        rcu_assign_pointer(dev->ax25_ptr, rx_handler_data);
        nr_bridges++;
-       rcu_assign_pointer(openvswitch_handle_frame_hook, rx_handler_data);
+       rcu_assign_pointer(openvswitch_handle_frame_hook, rx_handler);
 #else
        if (dev->br_port)
                return -EBUSY;