hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/dccp/ipv6.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * DCCP over IPv6
34 * Linux INET6 implementation
....@@ -5,11 +6,6 @@
56 * Based on net/dccp6/ipv6.c
67 *
78 * Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
8
- *
9
- * This program is free software; you can redistribute it and/or
10
- * modify it under the terms of the GNU General Public License
11
- * as published by the Free Software Foundation; either version
12
- * 2 of the License, or (at your option) any later version.
139 */
1410
1511 #include <linux/module.h>
....@@ -68,10 +64,10 @@
6864
6965 }
7066
71
-static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
67
+static int dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
7268 u8 type, u8 code, int offset, __be32 info)
7369 {
74
- const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
70
+ const struct ipv6hdr *hdr;
7571 const struct dccp_hdr *dh;
7672 struct dccp_sock *dp;
7773 struct ipv6_pinfo *np;
....@@ -80,12 +76,12 @@
8076 __u64 seq;
8177 struct net *net = dev_net(skb->dev);
8278
83
- /* Only need dccph_dport & dccph_sport which are the first
84
- * 4 bytes in dccp header.
85
- * Our caller (icmpv6_notify()) already pulled 8 bytes for us.
86
- */
87
- BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_sport) > 8);
88
- BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_dport) > 8);
79
+ if (!pskb_may_pull(skb, offset + sizeof(*dh)))
80
+ return -EINVAL;
81
+ dh = (struct dccp_hdr *)(skb->data + offset);
82
+ if (!pskb_may_pull(skb, offset + __dccp_basic_hdr_len(dh)))
83
+ return -EINVAL;
84
+ hdr = (const struct ipv6hdr *)skb->data;
8985 dh = (struct dccp_hdr *)(skb->data + offset);
9086
9187 sk = __inet6_lookup_established(net, &dccp_hashinfo,
....@@ -96,16 +92,18 @@
9692 if (!sk) {
9793 __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
9894 ICMP6_MIB_INERRORS);
99
- return;
95
+ return -ENOENT;
10096 }
10197
10298 if (sk->sk_state == DCCP_TIME_WAIT) {
10399 inet_twsk_put(inet_twsk(sk));
104
- return;
100
+ return 0;
105101 }
106102 seq = dccp_hdr_seq(dh);
107
- if (sk->sk_state == DCCP_NEW_SYN_RECV)
108
- return dccp_req_err(sk, seq);
103
+ if (sk->sk_state == DCCP_NEW_SYN_RECV) {
104
+ dccp_req_err(sk, seq);
105
+ return 0;
106
+ }
109107
110108 bh_lock_sock(sk);
111109 if (sock_owned_by_user(sk))
....@@ -183,6 +181,7 @@
183181 out:
184182 bh_unlock_sock(sk);
185183 sock_put(sk);
184
+ return 0;
186185 }
187186
188187
....@@ -204,7 +203,7 @@
204203 fl6.flowi6_oif = ireq->ir_iif;
205204 fl6.fl6_dport = ireq->ir_rmt_port;
206205 fl6.fl6_sport = htons(ireq->ir_num);
207
- security_req_classify_flow(req, flowi6_to_flowi(&fl6));
206
+ security_req_classify_flow(req, flowi6_to_flowi_common(&fl6));
208207
209208
210209 rcu_read_lock();
....@@ -231,7 +230,8 @@
231230 opt = ireq->ipv6_opt;
232231 if (!opt)
233232 opt = rcu_dereference(np->opt);
234
- err = ip6_xmit(sk, skb, &fl6, sk->sk_mark, opt, np->tclass);
233
+ err = ip6_xmit(sk, skb, &fl6, sk->sk_mark, opt, np->tclass,
234
+ sk->sk_priority);
235235 rcu_read_unlock();
236236 err = net_xmit_eval(err);
237237 }
....@@ -279,13 +279,13 @@
279279 fl6.flowi6_oif = inet6_iif(rxskb);
280280 fl6.fl6_dport = dccp_hdr(skb)->dccph_dport;
281281 fl6.fl6_sport = dccp_hdr(skb)->dccph_sport;
282
- security_skb_classify_flow(rxskb, flowi6_to_flowi(&fl6));
282
+ security_skb_classify_flow(rxskb, flowi6_to_flowi_common(&fl6));
283283
284284 /* sk = NULL, but it is safe for now. RST socket required. */
285285 dst = ip6_dst_lookup_flow(sock_net(ctl_sk), ctl_sk, &fl6, NULL);
286286 if (!IS_ERR(dst)) {
287287 skb_dst_set(skb, dst);
288
- ip6_xmit(ctl_sk, skb, &fl6, 0, NULL, 0);
288
+ ip6_xmit(ctl_sk, skb, &fl6, 0, NULL, 0, 0);
289289 DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
290290 DCCP_INC_STATS(DCCP_MIB_OUTRSTS);
291291 return;
....@@ -538,14 +538,12 @@
538538 dccp_done(newsk);
539539 goto out;
540540 }
541
- *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash));
541
+ *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash), NULL);
542542 /* Clone pktoptions received with SYN, if we own the req */
543543 if (*own_req && ireq->pktopts) {
544
- newnp->pktoptions = skb_clone(ireq->pktopts, GFP_ATOMIC);
544
+ newnp->pktoptions = skb_clone_and_charge_r(ireq->pktopts, newsk);
545545 consume_skb(ireq->pktopts);
546546 ireq->pktopts = NULL;
547
- if (newnp->pktoptions)
548
- skb_set_owner_r(newnp->pktoptions, newsk);
549547 }
550548
551549 return newsk;
....@@ -605,7 +603,7 @@
605603 --ANK (980728)
606604 */
607605 if (np->rxopt.all)
608
- opt_skb = skb_clone(skb, GFP_ATOMIC);
606
+ opt_skb = skb_clone_and_charge_r(skb, sk);
609607
610608 if (sk->sk_state == DCCP_OPEN) { /* Fast path */
611609 if (dccp_rcv_established(sk, skb, dccp_hdr(skb), skb->len))
....@@ -669,7 +667,6 @@
669667 np->flow_label = ip6_flowlabel(ipv6_hdr(opt_skb));
670668 if (ipv6_opt_accepted(sk, opt_skb,
671669 &DCCP_SKB_CB(opt_skb)->header.h6)) {
672
- skb_set_owner_r(opt_skb, sk);
673670 memmove(IP6CB(opt_skb),
674671 &DCCP_SKB_CB(opt_skb)->header.h6,
675672 sizeof(struct inet6_skb_parm));
....@@ -836,7 +833,7 @@
836833 if (fl6.flowlabel & IPV6_FLOWLABEL_MASK) {
837834 struct ip6_flowlabel *flowlabel;
838835 flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
839
- if (flowlabel == NULL)
836
+ if (IS_ERR(flowlabel))
840837 return -EINVAL;
841838 fl6_sock_release(flowlabel);
842839 }
....@@ -912,7 +909,7 @@
912909 fl6.flowi6_oif = sk->sk_bound_dev_if;
913910 fl6.fl6_dport = usin->sin6_port;
914911 fl6.fl6_sport = inet->inet_sport;
915
- security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
912
+ security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6));
916913
917914 opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk));
918915 final_p = fl6_update_dst(&fl6, opt, &final);
....@@ -957,6 +954,8 @@
957954
958955 late_failure:
959956 dccp_set_state(sk, DCCP_CLOSED);
957
+ if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
958
+ inet_reset_saddr(sk);
960959 __sk_dst_reset(sk);
961960 failure:
962961 inet->inet_dport = 0;
....@@ -975,10 +974,6 @@
975974 .getsockopt = ipv6_getsockopt,
976975 .addr2sockaddr = inet6_csk_addr2sockaddr,
977976 .sockaddr_len = sizeof(struct sockaddr_in6),
978
-#ifdef CONFIG_COMPAT
979
- .compat_setsockopt = compat_ipv6_setsockopt,
980
- .compat_getsockopt = compat_ipv6_getsockopt,
981
-#endif
982977 };
983978
984979 /*
....@@ -995,11 +990,13 @@
995990 .getsockopt = ipv6_getsockopt,
996991 .addr2sockaddr = inet6_csk_addr2sockaddr,
997992 .sockaddr_len = sizeof(struct sockaddr_in6),
998
-#ifdef CONFIG_COMPAT
999
- .compat_setsockopt = compat_ipv6_setsockopt,
1000
- .compat_getsockopt = compat_ipv6_getsockopt,
1001
-#endif
1002993 };
994
+
995
+static void dccp_v6_sk_destruct(struct sock *sk)
996
+{
997
+ dccp_destruct_common(sk);
998
+ inet6_sock_destruct(sk);
999
+}
10031000
10041001 /* NOTE: A lot of things set to zero explicitly by call to
10051002 * sk_alloc() so need not be done here.
....@@ -1013,15 +1010,10 @@
10131010 if (unlikely(!dccp_v6_ctl_sock_initialized))
10141011 dccp_v6_ctl_sock_initialized = 1;
10151012 inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops;
1013
+ sk->sk_destruct = dccp_v6_sk_destruct;
10161014 }
10171015
10181016 return err;
1019
-}
1020
-
1021
-static void dccp_v6_destroy_sock(struct sock *sk)
1022
-{
1023
- dccp_destroy_sock(sk);
1024
- inet6_destroy_sock(sk);
10251017 }
10261018
10271019 static struct timewait_sock_ops dccp6_timewait_sock_ops = {
....@@ -1046,7 +1038,7 @@
10461038 .accept = inet_csk_accept,
10471039 .get_port = inet_csk_get_port,
10481040 .shutdown = dccp_shutdown,
1049
- .destroy = dccp_v6_destroy_sock,
1041
+ .destroy = dccp_destroy_sock,
10501042 .orphan_count = &dccp_orphan_count,
10511043 .max_header = MAX_DCCP_HEADER,
10521044 .obj_size = sizeof(struct dccp6_sock),
....@@ -1054,10 +1046,6 @@
10541046 .rsk_prot = &dccp6_request_sock_ops,
10551047 .twsk_prot = &dccp6_timewait_sock_ops,
10561048 .h.hashinfo = &dccp_hashinfo,
1057
-#ifdef CONFIG_COMPAT
1058
- .compat_setsockopt = compat_dccp_setsockopt,
1059
- .compat_getsockopt = compat_dccp_getsockopt,
1060
-#endif
10611049 };
10621050
10631051 static const struct inet6_protocol dccp_v6_protocol = {
....@@ -1077,6 +1065,7 @@
10771065 .getname = inet6_getname,
10781066 .poll = dccp_poll,
10791067 .ioctl = inet6_ioctl,
1068
+ .gettstamp = sock_gettstamp,
10801069 .listen = inet_dccp_listen,
10811070 .shutdown = inet_shutdown,
10821071 .setsockopt = sock_common_setsockopt,
....@@ -1086,8 +1075,7 @@
10861075 .mmap = sock_no_mmap,
10871076 .sendpage = sock_no_sendpage,
10881077 #ifdef CONFIG_COMPAT
1089
- .compat_setsockopt = compat_sock_common_setsockopt,
1090
- .compat_getsockopt = compat_sock_common_getsockopt,
1078
+ .compat_ioctl = inet6_compat_ioctl,
10911079 #endif
10921080 };
10931081