aboutsummaryrefslogtreecommitdiffstats
path: root/net/packet
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-12-06 05:36:15 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-15 18:28:46 -0500
commitc3ac8a134305ed1522d8987e62249a85efb09c98 (patch)
tree0ba2f10ff56d4b922f3f062d5272d14edee0c556 /net/packet
parent4ea85d9e4113ba0b2d67d762a29c809df948426a (diff)
packet: fix send path when running with proto == 0
[ Upstream commit 66e56cd46b93ef407c60adcac62cf33b06119d50 ] Commit e40526cb20b5 introduced a cached dev pointer, that gets hooked into register_prot_hook(), __unregister_prot_hook() to update the device used for the send path. We need to fix this up, as otherwise this will not work with sockets created with protocol = 0, plus with sll_protocol = 0 passed via sockaddr_ll when doing the bind. So instead, assign the pointer directly. The compiler can inline these helper functions automagically. While at it, also assume the cached dev fast-path as likely(), and document this variant of socket creation as it seems it is not widely used (seems not even the author of TX_RING was aware of that in his reference example [1]). Tested with reproducer from e40526cb20b5. [1] http://wiki.ipxwarzone.com/index.php5?title=Linux_packet_mmap#Example Fixes: e40526cb20b5 ("packet: fix use after free race in send path when dev is released") Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Tested-by: Salam Noureddine <noureddine@aristanetworks.com> Tested-by: Jesper Dangaard Brouer <brouer@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/packet')
-rw-r--r--net/packet/af_packet.c65
1 files changed, 40 insertions, 25 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index c503ad6f610f..e8b5a0dfca21 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -237,6 +237,30 @@ struct packet_skb_cb {
237static void __fanout_unlink(struct sock *sk, struct packet_sock *po); 237static void __fanout_unlink(struct sock *sk, struct packet_sock *po);
238static void __fanout_link(struct sock *sk, struct packet_sock *po); 238static void __fanout_link(struct sock *sk, struct packet_sock *po);
239 239
240static struct net_device *packet_cached_dev_get(struct packet_sock *po)
241{
242 struct net_device *dev;
243
244 rcu_read_lock();
245 dev = rcu_dereference(po->cached_dev);
246 if (likely(dev))
247 dev_hold(dev);
248 rcu_read_unlock();
249
250 return dev;
251}
252
253static void packet_cached_dev_assign(struct packet_sock *po,
254 struct net_device *dev)
255{
256 rcu_assign_pointer(po->cached_dev, dev);
257}
258
259static void packet_cached_dev_reset(struct packet_sock *po)
260{
261 RCU_INIT_POINTER(po->cached_dev, NULL);
262}
263
240/* register_prot_hook must be invoked with the po->bind_lock held, 264/* register_prot_hook must be invoked with the po->bind_lock held,
241 * or from a context in which asynchronous accesses to the packet 265 * or from a context in which asynchronous accesses to the packet
242 * socket is not possible (packet_create()). 266 * socket is not possible (packet_create()).
@@ -246,12 +270,10 @@ static void register_prot_hook(struct sock *sk)
246 struct packet_sock *po = pkt_sk(sk); 270 struct packet_sock *po = pkt_sk(sk);
247 271
248 if (!po->running) { 272 if (!po->running) {
249 if (po->fanout) { 273 if (po->fanout)
250 __fanout_link(sk, po); 274 __fanout_link(sk, po);
251 } else { 275 else
252 dev_add_pack(&po->prot_hook); 276 dev_add_pack(&po->prot_hook);
253 rcu_assign_pointer(po->cached_dev, po->prot_hook.dev);
254 }
255 277
256 sock_hold(sk); 278 sock_hold(sk);
257 po->running = 1; 279 po->running = 1;
@@ -270,12 +292,11 @@ static void __unregister_prot_hook(struct sock *sk, bool sync)
270 struct packet_sock *po = pkt_sk(sk); 292 struct packet_sock *po = pkt_sk(sk);
271 293
272 po->running = 0; 294 po->running = 0;
273 if (po->fanout) { 295
296 if (po->fanout)
274 __fanout_unlink(sk, po); 297 __fanout_unlink(sk, po);
275 } else { 298 else
276 __dev_remove_pack(&po->prot_hook); 299 __dev_remove_pack(&po->prot_hook);
277 RCU_INIT_POINTER(po->cached_dev, NULL);
278 }
279 300
280 __sock_put(sk); 301 __sock_put(sk);
281 302
@@ -2048,19 +2069,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
2048 return tp_len; 2069 return tp_len;
2049} 2070}
2050 2071
2051static struct net_device *packet_cached_dev_get(struct packet_sock *po)
2052{
2053 struct net_device *dev;
2054
2055 rcu_read_lock();
2056 dev = rcu_dereference(po->cached_dev);
2057 if (dev)
2058 dev_hold(dev);
2059 rcu_read_unlock();
2060
2061 return dev;
2062}
2063
2064static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) 2072static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
2065{ 2073{
2066 struct sk_buff *skb; 2074 struct sk_buff *skb;
@@ -2077,7 +2085,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
2077 2085
2078 mutex_lock(&po->pg_vec_lock); 2086 mutex_lock(&po->pg_vec_lock);
2079 2087
2080 if (saddr == NULL) { 2088 if (likely(saddr == NULL)) {
2081 dev = packet_cached_dev_get(po); 2089 dev = packet_cached_dev_get(po);
2082 proto = po->num; 2090 proto = po->num;
2083 addr = NULL; 2091 addr = NULL;
@@ -2231,7 +2239,7 @@ static int packet_snd(struct socket *sock,
2231 * Get and verify the address. 2239 * Get and verify the address.
2232 */ 2240 */
2233 2241
2234 if (saddr == NULL) { 2242 if (likely(saddr == NULL)) {
2235 dev = packet_cached_dev_get(po); 2243 dev = packet_cached_dev_get(po);
2236 proto = po->num; 2244 proto = po->num;
2237 addr = NULL; 2245 addr = NULL;
@@ -2440,6 +2448,8 @@ static int packet_release(struct socket *sock)
2440 2448
2441 spin_lock(&po->bind_lock); 2449 spin_lock(&po->bind_lock);
2442 unregister_prot_hook(sk, false); 2450 unregister_prot_hook(sk, false);
2451 packet_cached_dev_reset(po);
2452
2443 if (po->prot_hook.dev) { 2453 if (po->prot_hook.dev) {
2444 dev_put(po->prot_hook.dev); 2454 dev_put(po->prot_hook.dev);
2445 po->prot_hook.dev = NULL; 2455 po->prot_hook.dev = NULL;
@@ -2495,14 +2505,17 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc
2495 2505
2496 spin_lock(&po->bind_lock); 2506 spin_lock(&po->bind_lock);
2497 unregister_prot_hook(sk, true); 2507 unregister_prot_hook(sk, true);
2508
2498 po->num = protocol; 2509 po->num = protocol;
2499 po->prot_hook.type = protocol; 2510 po->prot_hook.type = protocol;
2500 if (po->prot_hook.dev) 2511 if (po->prot_hook.dev)
2501 dev_put(po->prot_hook.dev); 2512 dev_put(po->prot_hook.dev);
2502 po->prot_hook.dev = dev;
2503 2513
2514 po->prot_hook.dev = dev;
2504 po->ifindex = dev ? dev->ifindex : 0; 2515 po->ifindex = dev ? dev->ifindex : 0;
2505 2516
2517 packet_cached_dev_assign(po, dev);
2518
2506 if (protocol == 0) 2519 if (protocol == 0)
2507 goto out_unlock; 2520 goto out_unlock;
2508 2521
@@ -2615,7 +2628,8 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
2615 po = pkt_sk(sk); 2628 po = pkt_sk(sk);
2616 sk->sk_family = PF_PACKET; 2629 sk->sk_family = PF_PACKET;
2617 po->num = proto; 2630 po->num = proto;
2618 RCU_INIT_POINTER(po->cached_dev, NULL); 2631
2632 packet_cached_dev_reset(po);
2619 2633
2620 sk->sk_destruct = packet_sock_destruct; 2634 sk->sk_destruct = packet_sock_destruct;
2621 sk_refcnt_debug_inc(sk); 2635 sk_refcnt_debug_inc(sk);
@@ -3369,6 +3383,7 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void
3369 sk->sk_error_report(sk); 3383 sk->sk_error_report(sk);
3370 } 3384 }
3371 if (msg == NETDEV_UNREGISTER) { 3385 if (msg == NETDEV_UNREGISTER) {
3386 packet_cached_dev_reset(po);
3372 po->ifindex = -1; 3387 po->ifindex = -1;
3373 if (po->prot_hook.dev) 3388 if (po->prot_hook.dev)
3374 dev_put(po->prot_hook.dev); 3389 dev_put(po->prot_hook.dev);