aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_private.h
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2010-06-10 12:12:50 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-15 14:00:40 -0400
commit91d2c34a4eed32876ca333b0ca44f3bc56645805 (patch)
tree26799e5cb1dff486a0695e1be8618064d12fe0bd /net/bridge/br_private.h
parentc18370f5b2949d9cca519355f33690b75e1e7c8b (diff)
bridge: Fix netpoll support
There are multiple problems with the newly added netpoll support: 1) Use-after-free on each netpoll packet. 2) Invoking unsafe code on netpoll/IRQ path. 3) Breaks when netpoll is enabled on the underlying device. This patch fixes all of these problems. In particular, we now allocate proper netpoll structures for each underlying device. We only allow netpoll to be enabled on the bridge when all the devices underneath it support netpoll. Once it is enabled, we do not allow non-netpoll devices to join the bridge (until netpoll is disabled again). This allows us to do away with the npinfo juggling that caused problem number 1. Incidentally this patch fixes number 2 by bypassing unsafe code such as multicast snooping and netfilter. Reported-by: Qianfeng Zhang <frzhang@redhat.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_private.h')
-rw-r--r--net/bridge/br_private.h46
1 files changed, 38 insertions, 8 deletions
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index c83519b555b..0f5394c4f2f 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -15,6 +15,7 @@
15 15
16#include <linux/netdevice.h> 16#include <linux/netdevice.h>
17#include <linux/if_bridge.h> 17#include <linux/if_bridge.h>
18#include <linux/netpoll.h>
18#include <net/route.h> 19#include <net/route.h>
19 20
20#define BR_HASH_BITS 8 21#define BR_HASH_BITS 8
@@ -143,6 +144,10 @@ struct net_bridge_port
143#ifdef CONFIG_SYSFS 144#ifdef CONFIG_SYSFS
144 char sysfs_name[IFNAMSIZ]; 145 char sysfs_name[IFNAMSIZ];
145#endif 146#endif
147
148#ifdef CONFIG_NET_POLL_CONTROLLER
149 struct netpoll *np;
150#endif
146}; 151};
147 152
148struct br_cpu_netstats { 153struct br_cpu_netstats {
@@ -273,16 +278,41 @@ extern void br_dev_setup(struct net_device *dev);
273extern netdev_tx_t br_dev_xmit(struct sk_buff *skb, 278extern netdev_tx_t br_dev_xmit(struct sk_buff *skb,
274 struct net_device *dev); 279 struct net_device *dev);
275#ifdef CONFIG_NET_POLL_CONTROLLER 280#ifdef CONFIG_NET_POLL_CONTROLLER
276extern void br_netpoll_cleanup(struct net_device *dev); 281static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br)
277extern void br_netpoll_enable(struct net_bridge *br, 282{
278 struct net_device *dev); 283 return br->dev->npinfo;
279extern void br_netpoll_disable(struct net_bridge *br, 284}
280 struct net_device *dev); 285
286static inline void br_netpoll_send_skb(const struct net_bridge_port *p,
287 struct sk_buff *skb)
288{
289 struct netpoll *np = p->np;
290
291 if (np)
292 netpoll_send_skb(np, skb);
293}
294
295extern int br_netpoll_enable(struct net_bridge_port *p);
296extern void br_netpoll_disable(struct net_bridge_port *p);
281#else 297#else
282#define br_netpoll_cleanup(br) 298static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br)
283#define br_netpoll_enable(br, dev) 299{
284#define br_netpoll_disable(br, dev) 300 return NULL;
301}
302
303static inline void br_netpoll_send_skb(struct net_bridge_port *p,
304 struct sk_buff *skb)
305{
306}
285 307
308static inline int br_netpoll_enable(struct net_bridge_port *p)
309{
310 return 0;
311}
312
313static inline void br_netpoll_disable(struct net_bridge_port *p)
314{
315}
286#endif 316#endif
287 317
288/* br_fdb.c */ 318/* br_fdb.c */