aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2010-05-02 21:10:06 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2010-06-14 19:37:27 -0400
commit81bdf5bd7349bd4523538cbd7878f334bc2bfe14 (patch)
tree8b12ba3191eca882d550369a7a4826a501a3b215
parent2c666df80764389886110c942a7916ba9622583d (diff)
net: Make accesses to ->br_port safe for sparse RCU
The new versions of the rcu_dereference() APIs requires that any pointers passed to one of these APIs be fully defined. The ->br_port field in struct net_device points to a struct net_bridge_port, which is an incomplete type. This commit therefore changes ->br_port to be a void*, and introduces a br_port() helper function to convert the type to struct net_bridge_port, and applies this new helper function where required. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: David Miller <davem@davemloft.net> Cc: Stephen Hemminger <shemminger@linux-foundation.org> Cc: Eric Dumazet <eric.dumazet@gmail.com>
-rw-r--r--include/linux/if_bridge.h3
-rw-r--r--net/bridge/br_fdb.c2
-rw-r--r--net/bridge/br_private.h5
-rw-r--r--net/bridge/netfilter/ebt_redirect.c2
-rw-r--r--net/bridge/netfilter/ebt_ulog.c4
-rw-r--r--net/bridge/netfilter/ebtables.c4
-rw-r--r--net/netfilter/nfnetlink_log.c4
-rw-r--r--net/netfilter/nfnetlink_queue.c4
8 files changed, 18 insertions, 10 deletions
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 938b7e81df95..d001d782922d 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -101,6 +101,9 @@ struct __fdb_entry {
101 101
102#include <linux/netdevice.h> 102#include <linux/netdevice.h>
103 103
104/* br_handle_frame_hook() needs the following forward declaration. */
105struct net_bridge_port;
106
104extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *)); 107extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
105extern struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p, 108extern struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
106 struct sk_buff *skb); 109 struct sk_buff *skb);
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 26637439965b..845710bca49c 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -246,7 +246,7 @@ int br_fdb_test_addr(struct net_device *dev, unsigned char *addr)
246 return 0; 246 return 0;
247 247
248 rcu_read_lock(); 248 rcu_read_lock();
249 fdb = __br_fdb_get(dev->br_port->br, addr); 249 fdb = __br_fdb_get(br_port(dev)->br, addr);
250 ret = fdb && fdb->dst->dev != dev && 250 ret = fdb && fdb->dst->dev != dev &&
251 fdb->dst->state == BR_STATE_FORWARDING; 251 fdb->dst->state == BR_STATE_FORWARDING;
252 rcu_read_unlock(); 252 rcu_read_unlock();
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 0f4a74bc6a9b..3255188355b5 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -268,6 +268,11 @@ static inline int br_is_root_bridge(const struct net_bridge *br)
268 return !memcmp(&br->bridge_id, &br->designated_root, 8); 268 return !memcmp(&br->bridge_id, &br->designated_root, 8);
269} 269}
270 270
271static inline struct net_bridge_port *br_port(const struct net_device *dev)
272{
273 return rcu_dereference(dev->br_port);
274}
275
271/* br_device.c */ 276/* br_device.c */
272extern void br_dev_setup(struct net_device *dev); 277extern 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,
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index 9e19166ba453..a39df0ae0f81 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -25,7 +25,7 @@ ebt_redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
25 25
26 if (par->hooknum != NF_BR_BROUTING) 26 if (par->hooknum != NF_BR_BROUTING)
27 memcpy(eth_hdr(skb)->h_dest, 27 memcpy(eth_hdr(skb)->h_dest,
28 par->in->br_port->br->dev->dev_addr, ETH_ALEN); 28 br_port(par->in)->br->dev->dev_addr, ETH_ALEN);
29 else 29 else
30 memcpy(eth_hdr(skb)->h_dest, par->in->dev_addr, ETH_ALEN); 30 memcpy(eth_hdr(skb)->h_dest, par->in->dev_addr, ETH_ALEN);
31 skb->pkt_type = PACKET_HOST; 31 skb->pkt_type = PACKET_HOST;
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index ae3c7cef1484..5a4996bbb090 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -178,7 +178,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
178 strcpy(pm->physindev, in->name); 178 strcpy(pm->physindev, in->name);
179 /* If in isn't a bridge, then physindev==indev */ 179 /* If in isn't a bridge, then physindev==indev */
180 if (in->br_port) 180 if (in->br_port)
181 strcpy(pm->indev, in->br_port->br->dev->name); 181 strcpy(pm->indev, br_port(in)->br->dev->name);
182 else 182 else
183 strcpy(pm->indev, in->name); 183 strcpy(pm->indev, in->name);
184 } else 184 } else
@@ -187,7 +187,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
187 if (out) { 187 if (out) {
188 /* If out exists, then out is a bridge port */ 188 /* If out exists, then out is a bridge port */
189 strcpy(pm->physoutdev, out->name); 189 strcpy(pm->physoutdev, out->name);
190 strcpy(pm->outdev, out->br_port->br->dev->name); 190 strcpy(pm->outdev, br_port(out)->br->dev->name);
191 } else 191 } else
192 pm->outdev[0] = pm->physoutdev[0] = '\0'; 192 pm->outdev[0] = pm->physoutdev[0] = '\0';
193 193
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 59ca00e40dec..4c2aab8cbfc7 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -141,10 +141,10 @@ ebt_basic_match(const struct ebt_entry *e, const struct ethhdr *h,
141 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT)) 141 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
142 return 1; 142 return 1;
143 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check( 143 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
144 e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN)) 144 e->logical_in, br_port(in)->br->dev), EBT_ILOGICALIN))
145 return 1; 145 return 1;
146 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check( 146 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
147 e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT)) 147 e->logical_out, br_port(out)->br->dev), EBT_ILOGICALOUT))
148 return 1; 148 return 1;
149 149
150 if (e->bitmask & EBT_SOURCEMAC) { 150 if (e->bitmask & EBT_SOURCEMAC) {
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index fc9a211e629e..78957cfa3bdd 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -404,7 +404,7 @@ __build_packet_message(struct nfulnl_instance *inst,
404 htonl(indev->ifindex)); 404 htonl(indev->ifindex));
405 /* this is the bridge group "brX" */ 405 /* this is the bridge group "brX" */
406 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV, 406 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV,
407 htonl(indev->br_port->br->dev->ifindex)); 407 htonl(br_port(indev)->br->dev->ifindex));
408 } else { 408 } else {
409 /* Case 2: indev is bridge group, we need to look for 409 /* Case 2: indev is bridge group, we need to look for
410 * physical device (when called from ipv4) */ 410 * physical device (when called from ipv4) */
@@ -431,7 +431,7 @@ __build_packet_message(struct nfulnl_instance *inst,
431 htonl(outdev->ifindex)); 431 htonl(outdev->ifindex));
432 /* this is the bridge group "brX" */ 432 /* this is the bridge group "brX" */
433 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, 433 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV,
434 htonl(outdev->br_port->br->dev->ifindex)); 434 htonl(br_port(outdev)->br->dev->ifindex));
435 } else { 435 } else {
436 /* Case 2: indev is a bridge group, we need to look 436 /* Case 2: indev is a bridge group, we need to look
437 * for physical device (when called from ipv4) */ 437 * for physical device (when called from ipv4) */
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 12e1ab37fcd8..c3c17498298e 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -297,7 +297,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
297 htonl(indev->ifindex)); 297 htonl(indev->ifindex));
298 /* this is the bridge group "brX" */ 298 /* this is the bridge group "brX" */
299 NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV, 299 NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV,
300 htonl(indev->br_port->br->dev->ifindex)); 300 htonl(br_port(indev)->br->dev->ifindex));
301 } else { 301 } else {
302 /* Case 2: indev is bridge group, we need to look for 302 /* Case 2: indev is bridge group, we need to look for
303 * physical device (when called from ipv4) */ 303 * physical device (when called from ipv4) */
@@ -322,7 +322,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
322 htonl(outdev->ifindex)); 322 htonl(outdev->ifindex));
323 /* this is the bridge group "brX" */ 323 /* this is the bridge group "brX" */
324 NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV, 324 NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV,
325 htonl(outdev->br_port->br->dev->ifindex)); 325 htonl(br_port(outdev)->br->dev->ifindex));
326 } else { 326 } else {
327 /* Case 2: outdev is bridge group, we need to look for 327 /* Case 2: outdev is bridge group, we need to look for
328 * physical output device (when called from ipv4) */ 328 * physical output device (when called from ipv4) */