hc
2024-10-09 05e59e5fb0064c97a1c10921ecd549f2d4a58565
kernel/net/ipv6/ip6_input.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * IPv6 input
34 * Linux INET6 implementation
....@@ -7,11 +8,6 @@
78 * Ian P. Morris <I.P.Morris@soton.ac.uk>
89 *
910 * Based in linux/net/ipv4/ip_input.c
10
- *
11
- * This program is free software; you can redistribute it and/or
12
- * modify it under the terms of the GNU General Public License
13
- * as published by the Free Software Foundation; either version
14
- * 2 of the License, or (at your option) any later version.
1511 */
1612 /* Changes
1713 *
....@@ -29,6 +25,7 @@
2925 #include <linux/icmpv6.h>
3026 #include <linux/mroute6.h>
3127 #include <linux/slab.h>
28
+#include <linux/indirect_call_wrapper.h>
3229
3330 #include <linux/netfilter.h>
3431 #include <linux/netfilter_ipv6.h>
....@@ -47,18 +44,25 @@
4744 #include <net/inet_ecn.h>
4845 #include <net/dst_metadata.h>
4946
47
+void udp_v6_early_demux(struct sk_buff *);
48
+void tcp_v6_early_demux(struct sk_buff *);
5049 static void ip6_rcv_finish_core(struct net *net, struct sock *sk,
5150 struct sk_buff *skb)
5251 {
53
- void (*edemux)(struct sk_buff *skb);
54
-
55
- if (net->ipv4.sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) {
56
- const struct inet6_protocol *ipprot;
57
-
58
- ipprot = rcu_dereference(inet6_protos[ipv6_hdr(skb)->nexthdr]);
59
- if (ipprot && (edemux = READ_ONCE(ipprot->early_demux)))
60
- edemux(skb);
52
+ if (READ_ONCE(net->ipv4.sysctl_ip_early_demux) &&
53
+ !skb_dst(skb) && !skb->sk) {
54
+ switch (ipv6_hdr(skb)->nexthdr) {
55
+ case IPPROTO_TCP:
56
+ if (READ_ONCE(net->ipv4.sysctl_tcp_early_demux))
57
+ tcp_v6_early_demux(skb);
58
+ break;
59
+ case IPPROTO_UDP:
60
+ if (READ_ONCE(net->ipv4.sysctl_udp_early_demux))
61
+ udp_v6_early_demux(skb);
62
+ break;
63
+ }
6164 }
65
+
6266 if (!skb_valid_dst(skb))
6367 ip6_route_input(skb);
6468 }
....@@ -86,11 +90,27 @@
8690 }
8791 }
8892
93
+static bool ip6_can_use_hint(const struct sk_buff *skb,
94
+ const struct sk_buff *hint)
95
+{
96
+ return hint && !skb_dst(skb) &&
97
+ ipv6_addr_equal(&ipv6_hdr(hint)->daddr, &ipv6_hdr(skb)->daddr);
98
+}
99
+
100
+static struct sk_buff *ip6_extract_route_hint(const struct net *net,
101
+ struct sk_buff *skb)
102
+{
103
+ if (fib6_routes_require_src(net) || fib6_has_custom_rules(net))
104
+ return NULL;
105
+
106
+ return skb;
107
+}
108
+
89109 static void ip6_list_rcv_finish(struct net *net, struct sock *sk,
90110 struct list_head *head)
91111 {
112
+ struct sk_buff *skb, *next, *hint = NULL;
92113 struct dst_entry *curr_dst = NULL;
93
- struct sk_buff *skb, *next;
94114 struct list_head sublist;
95115
96116 INIT_LIST_HEAD(&sublist);
....@@ -104,9 +124,15 @@
104124 skb = l3mdev_ip6_rcv(skb);
105125 if (!skb)
106126 continue;
107
- ip6_rcv_finish_core(net, sk, skb);
127
+
128
+ if (ip6_can_use_hint(skb, hint))
129
+ skb_dst_copy(skb, hint);
130
+ else
131
+ ip6_rcv_finish_core(net, sk, skb);
108132 dst = skb_dst(skb);
109133 if (curr_dst != dst) {
134
+ hint = ip6_extract_route_hint(net, skb);
135
+
110136 /* dispatch old sublist */
111137 if (!list_empty(&sublist))
112138 ip6_sublist_rcv_finish(&sublist);
....@@ -180,7 +206,8 @@
180206 */
181207 if ((ipv6_addr_loopback(&hdr->saddr) ||
182208 ipv6_addr_loopback(&hdr->daddr)) &&
183
- !(dev->flags & IFF_LOOPBACK))
209
+ !(dev->flags & IFF_LOOPBACK) &&
210
+ !netif_is_l3_master(dev))
184211 goto err;
185212
186213 /* RFC4291 Errata ID: 3480
....@@ -252,7 +279,8 @@
252279 rcu_read_unlock();
253280
254281 /* Must drop socket now because of tproxy. */
255
- skb_orphan(skb);
282
+ if (!skb_sk_is_prefetched(skb))
283
+ skb_orphan(skb);
256284
257285 return skb;
258286 err:
....@@ -314,34 +342,36 @@
314342 list_add_tail(&skb->list, &sublist);
315343 }
316344 /* dispatch final sublist */
317
- ip6_sublist_rcv(&sublist, curr_dev, curr_net);
345
+ if (!list_empty(&sublist))
346
+ ip6_sublist_rcv(&sublist, curr_dev, curr_net);
318347 }
348
+
349
+INDIRECT_CALLABLE_DECLARE(int udpv6_rcv(struct sk_buff *));
350
+INDIRECT_CALLABLE_DECLARE(int tcp_v6_rcv(struct sk_buff *));
319351
320352 /*
321353 * Deliver the packet to the host
322354 */
323
-
324
-
325
-static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
355
+void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
356
+ bool have_final)
326357 {
327358 const struct inet6_protocol *ipprot;
328359 struct inet6_dev *idev;
329360 unsigned int nhoff;
330
- int nexthdr;
331361 bool raw;
332
- bool have_final = false;
333362
334363 /*
335364 * Parse extension headers
336365 */
337366
338
- rcu_read_lock();
339367 resubmit:
340368 idev = ip6_dst_idev(skb_dst(skb));
341
- if (!pskb_pull(skb, skb_transport_offset(skb)))
342
- goto discard;
343369 nhoff = IP6CB(skb)->nhoff;
344
- nexthdr = skb_network_header(skb)[nhoff];
370
+ if (!have_final) {
371
+ if (!pskb_pull(skb, skb_transport_offset(skb)))
372
+ goto discard;
373
+ nexthdr = skb_network_header(skb)[nhoff];
374
+ }
345375
346376 resubmit_final:
347377 raw = raw6_local_deliver(skb, nexthdr);
....@@ -360,6 +390,8 @@
360390 }
361391 } else if (ipprot->flags & INET6_PROTO_FINAL) {
362392 const struct ipv6hdr *hdr;
393
+ int sdif = inet6_sdif(skb);
394
+ struct net_device *dev;
363395
364396 /* Only do this once for first final protocol */
365397 have_final = true;
....@@ -367,14 +399,24 @@
367399 /* Free reference early: we don't need it any more,
368400 and it may hold ip_conntrack module loaded
369401 indefinitely. */
370
- nf_reset(skb);
402
+ nf_reset_ct(skb);
371403
372404 skb_postpull_rcsum(skb, skb_network_header(skb),
373405 skb_network_header_len(skb));
374406 hdr = ipv6_hdr(skb);
407
+
408
+ /* skb->dev passed may be master dev for vrfs. */
409
+ if (sdif) {
410
+ dev = dev_get_by_index_rcu(net, sdif);
411
+ if (!dev)
412
+ goto discard;
413
+ } else {
414
+ dev = skb->dev;
415
+ }
416
+
375417 if (ipv6_addr_is_multicast(&hdr->daddr) &&
376
- !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
377
- &hdr->saddr) &&
418
+ !ipv6_chk_mcast_addr(dev, &hdr->daddr,
419
+ &hdr->saddr) &&
378420 !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb)))
379421 goto discard;
380422 }
....@@ -382,7 +424,8 @@
382424 !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
383425 goto discard;
384426
385
- ret = ipprot->handler(skb);
427
+ ret = INDIRECT_CALL_2(ipprot->handler, tcp_v6_rcv, udpv6_rcv,
428
+ skb);
386429 if (ret > 0) {
387430 if (ipprot->flags & INET6_PROTO_FINAL) {
388431 /* Not an extension header, most likely UDP
....@@ -412,13 +455,19 @@
412455 consume_skb(skb);
413456 }
414457 }
415
- rcu_read_unlock();
416
- return 0;
458
+ return;
417459
418460 discard:
419461 __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
420
- rcu_read_unlock();
421462 kfree_skb(skb);
463
+}
464
+
465
+static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
466
+{
467
+ rcu_read_lock();
468
+ ip6_protocol_deliver_rcu(net, skb, 0, false);
469
+ rcu_read_unlock();
470
+
422471 return 0;
423472 }
424473
....@@ -433,21 +482,38 @@
433482
434483 int ip6_mc_input(struct sk_buff *skb)
435484 {
485
+ int sdif = inet6_sdif(skb);
436486 const struct ipv6hdr *hdr;
487
+ struct net_device *dev;
437488 bool deliver;
438489
439490 __IP6_UPD_PO_STATS(dev_net(skb_dst(skb)->dev),
440491 __in6_dev_get_safely(skb->dev), IPSTATS_MIB_INMCAST,
441492 skb->len);
442493
494
+ /* skb->dev passed may be master dev for vrfs. */
495
+ if (sdif) {
496
+ rcu_read_lock();
497
+ dev = dev_get_by_index_rcu(dev_net(skb->dev), sdif);
498
+ if (!dev) {
499
+ rcu_read_unlock();
500
+ kfree_skb(skb);
501
+ return -ENODEV;
502
+ }
503
+ } else {
504
+ dev = skb->dev;
505
+ }
506
+
443507 hdr = ipv6_hdr(skb);
444
- deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
508
+ deliver = ipv6_chk_mcast_addr(dev, &hdr->daddr, NULL);
509
+ if (sdif)
510
+ rcu_read_unlock();
445511
446512 #ifdef CONFIG_IPV6_MROUTE
447513 /*
448514 * IPv6 multicast router mode is now supported ;)
449515 */
450
- if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding &&
516
+ if (atomic_read(&dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding) &&
451517 !(ipv6_addr_type(&hdr->daddr) &
452518 (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) &&
453519 likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {