hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/ipv6/raw.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * RAW sockets for IPv6
34 * Linux INET6 implementation
....@@ -11,11 +12,6 @@
1112 * Hideaki YOSHIFUJI : sin6_scope_id support
1213 * YOSHIFUJI,H.@USAGI : raw checksum (RFC2292(bis) compliance)
1314 * Kazunori MIYAZAWA @USAGI: change process style to use ip6_append_data
14
- *
15
- * This program is free software; you can redistribute it and/or
16
- * modify it under the terms of the GNU General Public License
17
- * as published by the Free Software Foundation; either version
18
- * 2 of the License, or (at your option) any later version.
1915 */
2016
2117 #include <linux/errno.h>
....@@ -86,9 +82,8 @@
8682 !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr))
8783 continue;
8884
89
- if (sk->sk_bound_dev_if &&
90
- sk->sk_bound_dev_if != dif &&
91
- sk->sk_bound_dev_if != sdif)
85
+ if (!raw_sk_bound_dev_eq(net, sk->sk_bound_dev_if,
86
+ dif, sdif))
9287 continue;
9388
9489 if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) {
....@@ -220,7 +215,7 @@
220215
221216 /* Not releasing hash table! */
222217 if (clone) {
223
- nf_reset(clone);
218
+ nf_reset_ct(clone);
224219 rawv6_rcv(sk, clone);
225220 }
226221 }
....@@ -544,6 +539,7 @@
544539 static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
545540 struct raw6_sock *rp)
546541 {
542
+ struct ipv6_txoptions *opt;
547543 struct sk_buff *skb;
548544 int err = 0;
549545 int offset;
....@@ -561,6 +557,9 @@
561557
562558 offset = rp->offset;
563559 total_len = inet_sk(sk)->cork.base.length;
560
+ opt = inet6_sk(sk)->cork.opt;
561
+ total_len -= opt ? opt->opt_flen : 0;
562
+
564563 if (offset >= total_len - 1) {
565564 err = -EINVAL;
566565 ip6_flush_pending_frames(sk);
....@@ -651,7 +650,7 @@
651650
652651 skb->protocol = htons(ETH_P_IPV6);
653652 skb->priority = sk->sk_priority;
654
- skb->mark = sk->sk_mark;
653
+ skb->mark = sockc->mark;
655654 skb->tstamp = sockc->transmit_time;
656655
657656 skb_put(skb, length);
....@@ -660,7 +659,7 @@
660659
661660 skb->ip_summed = CHECKSUM_NONE;
662661
663
- sock_tx_timestamp(sk, sockc->tsflags, &skb_shinfo(skb)->tx_flags);
662
+ skb_setup_tx_timestamp(skb, sockc->tsflags);
664663
665664 if (flags & MSG_CONFIRM)
666665 skb_set_dst_pending_confirm(skb, 1);
....@@ -751,7 +750,7 @@
751750 skb->csum = csum_block_add(
752751 skb->csum,
753752 csum_partial_copy_nocheck(rfv->c + offset,
754
- to, copy, 0),
753
+ to, copy),
755754 odd);
756755
757756 odd = 0;
....@@ -815,6 +814,7 @@
815814
816815 ipcm6_init(&ipc6);
817816 ipc6.sockc.tsflags = sk->sk_tsflags;
817
+ ipc6.sockc.mark = sk->sk_mark;
818818
819819 if (sin6) {
820820 if (addr_len < SIN6_LEN_RFC2133)
....@@ -828,7 +828,8 @@
828828
829829 if (!proto)
830830 proto = inet->inet_num;
831
- else if (proto != inet->inet_num)
831
+ else if (proto != inet->inet_num &&
832
+ inet->inet_num != IPPROTO_RAW)
832833 return -EINVAL;
833834
834835 if (proto > 255)
....@@ -839,7 +840,7 @@
839840 fl6.flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK;
840841 if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) {
841842 flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
842
- if (!flowlabel)
843
+ if (IS_ERR(flowlabel))
843844 return -EINVAL;
844845 }
845846 }
....@@ -881,7 +882,7 @@
881882 }
882883 if ((fl6.flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) {
883884 flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
884
- if (!flowlabel)
885
+ if (IS_ERR(flowlabel))
885886 return -EINVAL;
886887 }
887888 if (!(opt->opt_nflen|opt->opt_flen))
....@@ -896,6 +897,7 @@
896897 opt = ipv6_fixup_options(&opt_space, opt);
897898
898899 fl6.flowi6_proto = proto;
900
+ fl6.flowi6_mark = ipc6.sockc.mark;
899901
900902 if (!hdrincl) {
901903 rfv.msg = msg;
....@@ -918,7 +920,7 @@
918920 fl6.flowi6_oif = np->mcast_oif;
919921 else if (!fl6.flowi6_oif)
920922 fl6.flowi6_oif = np->ucast_oif;
921
- security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
923
+ security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6));
922924
923925 if (hdrincl)
924926 fl6.flowi6_flags |= FLOWI_FLAG_KNOWN_NH;
....@@ -975,13 +977,13 @@
975977 }
976978
977979 static int rawv6_seticmpfilter(struct sock *sk, int level, int optname,
978
- char __user *optval, int optlen)
980
+ sockptr_t optval, int optlen)
979981 {
980982 switch (optname) {
981983 case ICMPV6_FILTER:
982984 if (optlen > sizeof(struct icmp6_filter))
983985 optlen = sizeof(struct icmp6_filter);
984
- if (copy_from_user(&raw6_sk(sk)->filter, optval, optlen))
986
+ if (copy_from_sockptr(&raw6_sk(sk)->filter, optval, optlen))
985987 return -EFAULT;
986988 return 0;
987989 default:
....@@ -1018,12 +1020,15 @@
10181020
10191021
10201022 static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
1021
- char __user *optval, unsigned int optlen)
1023
+ sockptr_t optval, unsigned int optlen)
10221024 {
10231025 struct raw6_sock *rp = raw6_sk(sk);
10241026 int val;
10251027
1026
- if (get_user(val, (int __user *)optval))
1028
+ if (optlen < sizeof(val))
1029
+ return -EINVAL;
1030
+
1031
+ if (copy_from_sockptr(&val, optval, sizeof(val)))
10271032 return -EFAULT;
10281033
10291034 switch (optname) {
....@@ -1065,7 +1070,7 @@
10651070 }
10661071
10671072 static int rawv6_setsockopt(struct sock *sk, int level, int optname,
1068
- char __user *optval, unsigned int optlen)
1073
+ sockptr_t optval, unsigned int optlen)
10691074 {
10701075 switch (level) {
10711076 case SOL_RAW:
....@@ -1079,37 +1084,13 @@
10791084 if (optname == IPV6_CHECKSUM ||
10801085 optname == IPV6_HDRINCL)
10811086 break;
1082
- /* fall through */
1087
+ fallthrough;
10831088 default:
10841089 return ipv6_setsockopt(sk, level, optname, optval, optlen);
10851090 }
10861091
10871092 return do_rawv6_setsockopt(sk, level, optname, optval, optlen);
10881093 }
1089
-
1090
-#ifdef CONFIG_COMPAT
1091
-static int compat_rawv6_setsockopt(struct sock *sk, int level, int optname,
1092
- char __user *optval, unsigned int optlen)
1093
-{
1094
- switch (level) {
1095
- case SOL_RAW:
1096
- break;
1097
- case SOL_ICMPV6:
1098
- if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1099
- return -EOPNOTSUPP;
1100
- return rawv6_seticmpfilter(sk, level, optname, optval, optlen);
1101
- case SOL_IPV6:
1102
- if (optname == IPV6_CHECKSUM ||
1103
- optname == IPV6_HDRINCL)
1104
- break;
1105
- /* fall through */
1106
- default:
1107
- return compat_ipv6_setsockopt(sk, level, optname,
1108
- optval, optlen);
1109
- }
1110
- return do_rawv6_setsockopt(sk, level, optname, optval, optlen);
1111
-}
1112
-#endif
11131094
11141095 static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
11151096 char __user *optval, int __user *optlen)
....@@ -1164,37 +1145,13 @@
11641145 if (optname == IPV6_CHECKSUM ||
11651146 optname == IPV6_HDRINCL)
11661147 break;
1167
- /* fall through */
1148
+ fallthrough;
11681149 default:
11691150 return ipv6_getsockopt(sk, level, optname, optval, optlen);
11701151 }
11711152
11721153 return do_rawv6_getsockopt(sk, level, optname, optval, optlen);
11731154 }
1174
-
1175
-#ifdef CONFIG_COMPAT
1176
-static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname,
1177
- char __user *optval, int __user *optlen)
1178
-{
1179
- switch (level) {
1180
- case SOL_RAW:
1181
- break;
1182
- case SOL_ICMPV6:
1183
- if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1184
- return -EOPNOTSUPP;
1185
- return rawv6_geticmpfilter(sk, level, optname, optval, optlen);
1186
- case SOL_IPV6:
1187
- if (optname == IPV6_CHECKSUM ||
1188
- optname == IPV6_HDRINCL)
1189
- break;
1190
- /* fall through */
1191
- default:
1192
- return compat_ipv6_getsockopt(sk, level, optname,
1193
- optval, optlen);
1194
- }
1195
- return do_rawv6_getsockopt(sk, level, optname, optval, optlen);
1196
-}
1197
-#endif
11981155
11991156 static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
12001157 {
....@@ -1255,8 +1212,6 @@
12551212 lock_sock(sk);
12561213 ip6_flush_pending_frames(sk);
12571214 release_sock(sk);
1258
-
1259
- inet6_destroy_sock(sk);
12601215 }
12611216
12621217 static int rawv6_init_sk(struct sock *sk)
....@@ -1300,8 +1255,6 @@
13001255 .usersize = sizeof_field(struct raw6_sock, filter),
13011256 .h.raw_hash = &raw_v6_hashinfo,
13021257 #ifdef CONFIG_COMPAT
1303
- .compat_setsockopt = compat_rawv6_setsockopt,
1304
- .compat_getsockopt = compat_rawv6_getsockopt,
13051258 .compat_ioctl = compat_rawv6_ioctl,
13061259 #endif
13071260 .diag_destroy = raw_abort,
....@@ -1370,6 +1323,7 @@
13701323 .getname = inet6_getname,
13711324 .poll = datagram_poll, /* ok */
13721325 .ioctl = inet6_ioctl, /* must change */
1326
+ .gettstamp = sock_gettstamp,
13731327 .listen = sock_no_listen, /* ok */
13741328 .shutdown = inet_shutdown, /* ok */
13751329 .setsockopt = sock_common_setsockopt, /* ok */
....@@ -1379,8 +1333,7 @@
13791333 .mmap = sock_no_mmap,
13801334 .sendpage = sock_no_sendpage,
13811335 #ifdef CONFIG_COMPAT
1382
- .compat_setsockopt = compat_sock_common_setsockopt,
1383
- .compat_getsockopt = compat_sock_common_getsockopt,
1336
+ .compat_ioctl = inet6_compat_ioctl,
13841337 #endif
13851338 };
13861339