| From 95198d0a67841846139a0ddfb0ebf5dbc034e3c3 Mon Sep 17 00:00:00 2001 |
| From: Hong Zhiguo <zhiguohong@tencent.com> |
| Date: Sat, 14 Sep 2013 22:42:28 +0800 |
| Subject: bridge: fix NULL pointer deref of br_port_get_rcu |
| |
| From: Hong Zhiguo <zhiguohong@tencent.com> |
| |
| [ Upstream commit 716ec052d2280d511e10e90ad54a86f5b5d4dcc2 ] |
| |
| The NULL deref happens when br_handle_frame is called between these |
| 2 lines of del_nbp: |
| dev->priv_flags &= ~IFF_BRIDGE_PORT; |
| /* --> br_handle_frame is called at this time */ |
| netdev_rx_handler_unregister(dev); |
| |
| In br_handle_frame the return of br_port_get_rcu(dev) is dereferenced |
| without check but br_port_get_rcu(dev) returns NULL if: |
| !(dev->priv_flags & IFF_BRIDGE_PORT) |
| |
| Eric Dumazet pointed out the testing of IFF_BRIDGE_PORT is not necessary |
| here since we're in rcu_read_lock and we have synchronize_net() in |
| netdev_rx_handler_unregister. So remove the testing of IFF_BRIDGE_PORT |
| and by the previous patch, make sure br_port_get_rcu is called in |
| bridging code. |
| |
| Signed-off-by: Hong Zhiguo <zhiguohong@tencent.com> |
| Acked-by: Eric Dumazet <edumazet@google.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/bridge/br_private.h | 5 +---- |
| 1 file changed, 1 insertion(+), 4 deletions(-) |
| |
| --- a/net/bridge/br_private.h |
| +++ b/net/bridge/br_private.h |
| @@ -202,10 +202,7 @@ struct net_bridge_port |
| |
| static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev) |
| { |
| - struct net_bridge_port *port = |
| - rcu_dereference_rtnl(dev->rx_handler_data); |
| - |
| - return br_port_exists(dev) ? port : NULL; |
| + return rcu_dereference(dev->rx_handler_data); |
| } |
| |
| static inline struct net_bridge_port *br_port_get_rtnl(const struct net_device *dev) |