hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/net/mpls/af_mpls.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 #include <linux/types.h>
23 #include <linux/skbuff.h>
34 #include <linux/socket.h>
....@@ -22,8 +23,8 @@
2223 #if IS_ENABLED(CONFIG_IPV6)
2324 #include <net/ipv6.h>
2425 #endif
25
-#include <net/addrconf.h>
26
-#include <net/nexthop.h>
26
+#include <net/ipv6_stubs.h>
27
+#include <net/rtnh.h>
2728 #include "internal.h"
2829
2930 /* max memory we will use for mpls_route */
....@@ -36,8 +37,6 @@
3637
3738 #define MPLS_NEIGH_TABLE_UNSPEC (NEIGH_LINK_TABLE + 1)
3839
39
-static int zero = 0;
40
-static int one = 1;
4140 static int label_limit = (1 << 20) - 1;
4241 static int ttl_max = 255;
4342
....@@ -1079,9 +1078,9 @@
10791078
10801079 p = per_cpu_ptr(mdev->stats, i);
10811080 do {
1082
- start = u64_stats_fetch_begin(&p->syncp);
1081
+ start = u64_stats_fetch_begin_irq(&p->syncp);
10831082 local = p->stats;
1084
- } while (u64_stats_fetch_retry(&p->syncp, start));
1083
+ } while (u64_stats_fetch_retry_irq(&p->syncp, start));
10851084
10861085 stats->rx_packets += local.rx_packets;
10871086 stats->rx_bytes += local.rx_bytes;
....@@ -1208,21 +1207,59 @@
12081207 [NETCONFA_IFINDEX] = { .len = sizeof(int) },
12091208 };
12101209
1210
+static int mpls_netconf_valid_get_req(struct sk_buff *skb,
1211
+ const struct nlmsghdr *nlh,
1212
+ struct nlattr **tb,
1213
+ struct netlink_ext_ack *extack)
1214
+{
1215
+ int i, err;
1216
+
1217
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(struct netconfmsg))) {
1218
+ NL_SET_ERR_MSG_MOD(extack,
1219
+ "Invalid header for netconf get request");
1220
+ return -EINVAL;
1221
+ }
1222
+
1223
+ if (!netlink_strict_get_check(skb))
1224
+ return nlmsg_parse_deprecated(nlh, sizeof(struct netconfmsg),
1225
+ tb, NETCONFA_MAX,
1226
+ devconf_mpls_policy, extack);
1227
+
1228
+ err = nlmsg_parse_deprecated_strict(nlh, sizeof(struct netconfmsg),
1229
+ tb, NETCONFA_MAX,
1230
+ devconf_mpls_policy, extack);
1231
+ if (err)
1232
+ return err;
1233
+
1234
+ for (i = 0; i <= NETCONFA_MAX; i++) {
1235
+ if (!tb[i])
1236
+ continue;
1237
+
1238
+ switch (i) {
1239
+ case NETCONFA_IFINDEX:
1240
+ break;
1241
+ default:
1242
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in netconf get request");
1243
+ return -EINVAL;
1244
+ }
1245
+ }
1246
+
1247
+ return 0;
1248
+}
1249
+
12111250 static int mpls_netconf_get_devconf(struct sk_buff *in_skb,
12121251 struct nlmsghdr *nlh,
12131252 struct netlink_ext_ack *extack)
12141253 {
12151254 struct net *net = sock_net(in_skb->sk);
12161255 struct nlattr *tb[NETCONFA_MAX + 1];
1217
- struct netconfmsg *ncm;
12181256 struct net_device *dev;
12191257 struct mpls_dev *mdev;
12201258 struct sk_buff *skb;
12211259 int ifindex;
12221260 int err;
12231261
1224
- err = nlmsg_parse(nlh, sizeof(*ncm), tb, NETCONFA_MAX,
1225
- devconf_mpls_policy, NULL);
1262
+ err = mpls_netconf_valid_get_req(in_skb, nlh, tb, extack);
12261263 if (err < 0)
12271264 goto errout;
12281265
....@@ -1262,12 +1299,28 @@
12621299 static int mpls_netconf_dump_devconf(struct sk_buff *skb,
12631300 struct netlink_callback *cb)
12641301 {
1302
+ const struct nlmsghdr *nlh = cb->nlh;
12651303 struct net *net = sock_net(skb->sk);
12661304 struct hlist_head *head;
12671305 struct net_device *dev;
12681306 struct mpls_dev *mdev;
12691307 int idx, s_idx;
12701308 int h, s_h;
1309
+
1310
+ if (cb->strict_check) {
1311
+ struct netlink_ext_ack *extack = cb->extack;
1312
+ struct netconfmsg *ncm;
1313
+
1314
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ncm))) {
1315
+ NL_SET_ERR_MSG_MOD(extack, "Invalid header for netconf dump request");
1316
+ return -EINVAL;
1317
+ }
1318
+
1319
+ if (nlmsg_attrlen(nlh, sizeof(*ncm))) {
1320
+ NL_SET_ERR_MSG_MOD(extack, "Invalid data after header in netconf dump request");
1321
+ return -EINVAL;
1322
+ }
1323
+ }
12711324
12721325 s_h = cb->args[0];
12731326 s_idx = idx = cb->args[1];
....@@ -1285,7 +1338,7 @@
12851338 goto cont;
12861339 if (mpls_netconf_fill_devconf(skb, mdev,
12871340 NETLINK_CB(cb->skb).portid,
1288
- cb->nlh->nlmsg_seq,
1341
+ nlh->nlmsg_seq,
12891342 RTM_NEWNETCONF,
12901343 NLM_F_MULTI,
12911344 NETCONFA_ALL) < 0) {
....@@ -1309,8 +1362,7 @@
13091362 (&((struct mpls_dev *)0)->field)
13101363
13111364 static int mpls_conf_proc(struct ctl_table *ctl, int write,
1312
- void __user *buffer,
1313
- size_t *lenp, loff_t *ppos)
1365
+ void *buffer, size_t *lenp, loff_t *ppos)
13141366 {
13151367 int oval = *(int *)ctl->data;
13161368 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
....@@ -1494,7 +1546,7 @@
14941546 case NETDEV_DOWN:
14951547 case NETDEV_UNREGISTER:
14961548 nh_flags |= RTNH_F_DEAD;
1497
- /* fall through */
1549
+ fallthrough;
14981550 case NETDEV_CHANGE:
14991551 nh_flags |= RTNH_F_LINKDOWN;
15001552 break;
....@@ -1561,20 +1613,10 @@
15611613 unsigned int flags;
15621614
15631615 if (event == NETDEV_REGISTER) {
1616
+ mdev = mpls_add_dev(dev);
1617
+ if (IS_ERR(mdev))
1618
+ return notifier_from_errno(PTR_ERR(mdev));
15641619
1565
- /* For now just support Ethernet, IPGRE, IP6GRE, SIT and
1566
- * IPIP devices
1567
- */
1568
- if (dev->type == ARPHRD_ETHER ||
1569
- dev->type == ARPHRD_LOOPBACK ||
1570
- dev->type == ARPHRD_IPGRE ||
1571
- dev->type == ARPHRD_IP6GRE ||
1572
- dev->type == ARPHRD_SIT ||
1573
- dev->type == ARPHRD_TUNNEL) {
1574
- mdev = mpls_add_dev(dev);
1575
- if (IS_ERR(mdev))
1576
- return notifier_from_errno(PTR_ERR(mdev));
1577
- }
15781620 return NOTIFY_OK;
15791621 }
15801622
....@@ -1771,8 +1813,8 @@
17711813 int index;
17721814 int err;
17731815
1774
- err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_mpls_policy,
1775
- extack);
1816
+ err = nlmsg_parse_deprecated(nlh, sizeof(*rtm), tb, RTA_MAX,
1817
+ rtm_mpls_policy, extack);
17761818 if (err < 0)
17771819 goto errout;
17781820
....@@ -2000,7 +2042,7 @@
20002042 u8 linkdown = 0;
20012043 u8 dead = 0;
20022044
2003
- mp = nla_nest_start(skb, RTA_MULTIPATH);
2045
+ mp = nla_nest_start_noflag(skb, RTA_MULTIPATH);
20042046 if (!mp)
20052047 goto nla_put_failure;
20062048
....@@ -2053,14 +2095,115 @@
20532095 return -EMSGSIZE;
20542096 }
20552097
2098
+#if IS_ENABLED(CONFIG_INET)
2099
+static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
2100
+ struct fib_dump_filter *filter,
2101
+ struct netlink_callback *cb)
2102
+{
2103
+ return ip_valid_fib_dump_req(net, nlh, filter, cb);
2104
+}
2105
+#else
2106
+static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
2107
+ struct fib_dump_filter *filter,
2108
+ struct netlink_callback *cb)
2109
+{
2110
+ struct netlink_ext_ack *extack = cb->extack;
2111
+ struct nlattr *tb[RTA_MAX + 1];
2112
+ struct rtmsg *rtm;
2113
+ int err, i;
2114
+
2115
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*rtm))) {
2116
+ NL_SET_ERR_MSG_MOD(extack, "Invalid header for FIB dump request");
2117
+ return -EINVAL;
2118
+ }
2119
+
2120
+ rtm = nlmsg_data(nlh);
2121
+ if (rtm->rtm_dst_len || rtm->rtm_src_len || rtm->rtm_tos ||
2122
+ rtm->rtm_table || rtm->rtm_scope || rtm->rtm_type ||
2123
+ rtm->rtm_flags) {
2124
+ NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for FIB dump request");
2125
+ return -EINVAL;
2126
+ }
2127
+
2128
+ if (rtm->rtm_protocol) {
2129
+ filter->protocol = rtm->rtm_protocol;
2130
+ filter->filter_set = 1;
2131
+ cb->answer_flags = NLM_F_DUMP_FILTERED;
2132
+ }
2133
+
2134
+ err = nlmsg_parse_deprecated_strict(nlh, sizeof(*rtm), tb, RTA_MAX,
2135
+ rtm_mpls_policy, extack);
2136
+ if (err < 0)
2137
+ return err;
2138
+
2139
+ for (i = 0; i <= RTA_MAX; ++i) {
2140
+ int ifindex;
2141
+
2142
+ if (i == RTA_OIF) {
2143
+ ifindex = nla_get_u32(tb[i]);
2144
+ filter->dev = __dev_get_by_index(net, ifindex);
2145
+ if (!filter->dev)
2146
+ return -ENODEV;
2147
+ filter->filter_set = 1;
2148
+ } else if (tb[i]) {
2149
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in dump request");
2150
+ return -EINVAL;
2151
+ }
2152
+ }
2153
+
2154
+ return 0;
2155
+}
2156
+#endif
2157
+
2158
+static bool mpls_rt_uses_dev(struct mpls_route *rt,
2159
+ const struct net_device *dev)
2160
+{
2161
+ struct net_device *nh_dev;
2162
+
2163
+ if (rt->rt_nhn == 1) {
2164
+ struct mpls_nh *nh = rt->rt_nh;
2165
+
2166
+ nh_dev = rtnl_dereference(nh->nh_dev);
2167
+ if (dev == nh_dev)
2168
+ return true;
2169
+ } else {
2170
+ for_nexthops(rt) {
2171
+ nh_dev = rtnl_dereference(nh->nh_dev);
2172
+ if (nh_dev == dev)
2173
+ return true;
2174
+ } endfor_nexthops(rt);
2175
+ }
2176
+
2177
+ return false;
2178
+}
2179
+
20562180 static int mpls_dump_routes(struct sk_buff *skb, struct netlink_callback *cb)
20572181 {
2182
+ const struct nlmsghdr *nlh = cb->nlh;
20582183 struct net *net = sock_net(skb->sk);
20592184 struct mpls_route __rcu **platform_label;
2185
+ struct fib_dump_filter filter = {};
2186
+ unsigned int flags = NLM_F_MULTI;
20602187 size_t platform_labels;
20612188 unsigned int index;
20622189
20632190 ASSERT_RTNL();
2191
+
2192
+ if (cb->strict_check) {
2193
+ int err;
2194
+
2195
+ err = mpls_valid_fib_dump_req(net, nlh, &filter, cb);
2196
+ if (err < 0)
2197
+ return err;
2198
+
2199
+ /* for MPLS, there is only 1 table with fixed type and flags.
2200
+ * If either are set in the filter then return nothing.
2201
+ */
2202
+ if ((filter.table_id && filter.table_id != RT_TABLE_MAIN) ||
2203
+ (filter.rt_type && filter.rt_type != RTN_UNICAST) ||
2204
+ filter.flags)
2205
+ return skb->len;
2206
+ }
20642207
20652208 index = cb->args[0];
20662209 if (index < MPLS_LABEL_FIRST_UNRESERVED)
....@@ -2068,15 +2211,24 @@
20682211
20692212 platform_label = rtnl_dereference(net->mpls.platform_label);
20702213 platform_labels = net->mpls.platform_labels;
2214
+
2215
+ if (filter.filter_set)
2216
+ flags |= NLM_F_DUMP_FILTERED;
2217
+
20712218 for (; index < platform_labels; index++) {
20722219 struct mpls_route *rt;
2220
+
20732221 rt = rtnl_dereference(platform_label[index]);
20742222 if (!rt)
20752223 continue;
20762224
2225
+ if ((filter.dev && !mpls_rt_uses_dev(rt, filter.dev)) ||
2226
+ (filter.protocol && rt->rt_protocol != filter.protocol))
2227
+ continue;
2228
+
20772229 if (mpls_dump_route(skb, NETLINK_CB(cb->skb).portid,
20782230 cb->nlh->nlmsg_seq, RTM_NEWROUTE,
2079
- index, rt, NLM_F_MULTI) < 0)
2231
+ index, rt, flags) < 0)
20802232 break;
20812233 }
20822234 cb->args[0] = index;
....@@ -2148,6 +2300,64 @@
21482300 rtnl_set_sk_err(net, RTNLGRP_MPLS_ROUTE, err);
21492301 }
21502302
2303
+static int mpls_valid_getroute_req(struct sk_buff *skb,
2304
+ const struct nlmsghdr *nlh,
2305
+ struct nlattr **tb,
2306
+ struct netlink_ext_ack *extack)
2307
+{
2308
+ struct rtmsg *rtm;
2309
+ int i, err;
2310
+
2311
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*rtm))) {
2312
+ NL_SET_ERR_MSG_MOD(extack,
2313
+ "Invalid header for get route request");
2314
+ return -EINVAL;
2315
+ }
2316
+
2317
+ if (!netlink_strict_get_check(skb))
2318
+ return nlmsg_parse_deprecated(nlh, sizeof(*rtm), tb, RTA_MAX,
2319
+ rtm_mpls_policy, extack);
2320
+
2321
+ rtm = nlmsg_data(nlh);
2322
+ if ((rtm->rtm_dst_len && rtm->rtm_dst_len != 20) ||
2323
+ rtm->rtm_src_len || rtm->rtm_tos || rtm->rtm_table ||
2324
+ rtm->rtm_protocol || rtm->rtm_scope || rtm->rtm_type) {
2325
+ NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for get route request");
2326
+ return -EINVAL;
2327
+ }
2328
+ if (rtm->rtm_flags & ~RTM_F_FIB_MATCH) {
2329
+ NL_SET_ERR_MSG_MOD(extack,
2330
+ "Invalid flags for get route request");
2331
+ return -EINVAL;
2332
+ }
2333
+
2334
+ err = nlmsg_parse_deprecated_strict(nlh, sizeof(*rtm), tb, RTA_MAX,
2335
+ rtm_mpls_policy, extack);
2336
+ if (err)
2337
+ return err;
2338
+
2339
+ if ((tb[RTA_DST] || tb[RTA_NEWDST]) && !rtm->rtm_dst_len) {
2340
+ NL_SET_ERR_MSG_MOD(extack, "rtm_dst_len must be 20 for MPLS");
2341
+ return -EINVAL;
2342
+ }
2343
+
2344
+ for (i = 0; i <= RTA_MAX; i++) {
2345
+ if (!tb[i])
2346
+ continue;
2347
+
2348
+ switch (i) {
2349
+ case RTA_DST:
2350
+ case RTA_NEWDST:
2351
+ break;
2352
+ default:
2353
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in get route request");
2354
+ return -EINVAL;
2355
+ }
2356
+ }
2357
+
2358
+ return 0;
2359
+}
2360
+
21512361 static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
21522362 struct netlink_ext_ack *extack)
21532363 {
....@@ -2167,8 +2377,7 @@
21672377 u8 n_labels;
21682378 int err;
21692379
2170
- err = nlmsg_parse(in_nlh, sizeof(*rtm), tb, RTA_MAX,
2171
- rtm_mpls_policy, extack);
2380
+ err = mpls_valid_getroute_req(in_skb, in_nlh, tb, extack);
21722381 if (err < 0)
21732382 goto errout;
21742383
....@@ -2410,7 +2619,7 @@
24102619 }
24112620
24122621 static int mpls_platform_labels(struct ctl_table *table, int write,
2413
- void __user *buffer, size_t *lenp, loff_t *ppos)
2622
+ void *buffer, size_t *lenp, loff_t *ppos)
24142623 {
24152624 struct net *net = table->data;
24162625 int platform_labels = net->mpls.platform_labels;
....@@ -2420,7 +2629,7 @@
24202629 .data = &platform_labels,
24212630 .maxlen = sizeof(int),
24222631 .mode = table->mode,
2423
- .extra1 = &zero,
2632
+ .extra1 = SYSCTL_ZERO,
24242633 .extra2 = &label_limit,
24252634 };
24262635
....@@ -2449,8 +2658,8 @@
24492658 .maxlen = sizeof(int),
24502659 .mode = 0644,
24512660 .proc_handler = proc_dointvec_minmax,
2452
- .extra1 = &zero,
2453
- .extra2 = &one,
2661
+ .extra1 = SYSCTL_ZERO,
2662
+ .extra2 = SYSCTL_ONE,
24542663 },
24552664 {
24562665 .procname = "default_ttl",
....@@ -2458,7 +2667,7 @@
24582667 .maxlen = sizeof(int),
24592668 .mode = 0644,
24602669 .proc_handler = proc_dointvec_minmax,
2461
- .extra1 = &one,
2670
+ .extra1 = SYSCTL_ONE,
24622671 .extra2 = &ttl_max,
24632672 },
24642673 { }