hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/core/fib_rules.c
....@@ -1,9 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * net/core/fib_rules.c Generic Routing Rules
3
- *
4
- * This program is free software; you can redistribute it and/or
5
- * modify it under the terms of the GNU General Public License as
6
- * published by the Free Software Foundation, version 2.
74 *
85 * Authors: Thomas Graf <tgraf@suug.ch>
96 */
....@@ -17,6 +14,20 @@
1714 #include <net/sock.h>
1815 #include <net/fib_rules.h>
1916 #include <net/ip_tunnels.h>
17
+#include <linux/indirect_call_wrapper.h>
18
+
19
+#if defined(CONFIG_IPV6) && defined(CONFIG_IPV6_MULTIPLE_TABLES)
20
+#ifdef CONFIG_IP_MULTIPLE_TABLES
21
+#define INDIRECT_CALL_MT(f, f2, f1, ...) \
22
+ INDIRECT_CALL_INET(f, f2, f1, __VA_ARGS__)
23
+#else
24
+#define INDIRECT_CALL_MT(f, f2, f1, ...) INDIRECT_CALL_1(f, f2, __VA_ARGS__)
25
+#endif
26
+#elif defined(CONFIG_IP_MULTIPLE_TABLES)
27
+#define INDIRECT_CALL_MT(f, f2, f1, ...) INDIRECT_CALL_1(f, f1, __VA_ARGS__)
28
+#else
29
+#define INDIRECT_CALL_MT(f, f2, f1, ...) f(__VA_ARGS__)
30
+#endif
2031
2132 static const struct fib_kuid_range fib_kuid_range_unset = {
2233 KUIDT_INIT(0),
....@@ -270,7 +281,10 @@
270281 uid_gt(fl->flowi_uid, rule->uid_range.end))
271282 goto out;
272283
273
- ret = ops->match(rule, fl, flags);
284
+ ret = INDIRECT_CALL_MT(ops->match,
285
+ fib6_rule_match,
286
+ fib4_rule_match,
287
+ rule, fl, flags);
274288 out:
275289 return (rule->flags & FIB_RULE_INVERT) ? !ret : ret;
276290 }
....@@ -301,9 +315,15 @@
301315 } else if (rule->action == FR_ACT_NOP)
302316 continue;
303317 else
304
- err = ops->action(rule, fl, flags, arg);
318
+ err = INDIRECT_CALL_MT(ops->action,
319
+ fib6_rule_action,
320
+ fib4_rule_action,
321
+ rule, fl, flags, arg);
305322
306
- if (!err && ops->suppress && ops->suppress(rule, arg))
323
+ if (!err && ops->suppress && INDIRECT_CALL_MT(ops->suppress,
324
+ fib6_rule_suppress,
325
+ fib4_rule_suppress,
326
+ rule, flags, arg))
307327 continue;
308328
309329 if (err != -EAGAIN) {
....@@ -324,16 +344,18 @@
324344 }
325345 EXPORT_SYMBOL_GPL(fib_rules_lookup);
326346
327
-static int call_fib_rule_notifier(struct notifier_block *nb, struct net *net,
347
+static int call_fib_rule_notifier(struct notifier_block *nb,
328348 enum fib_event_type event_type,
329
- struct fib_rule *rule, int family)
349
+ struct fib_rule *rule, int family,
350
+ struct netlink_ext_ack *extack)
330351 {
331352 struct fib_rule_notifier_info info = {
332353 .info.family = family,
354
+ .info.extack = extack,
333355 .rule = rule,
334356 };
335357
336
- return call_fib_notifier(nb, net, event_type, &info.info);
358
+ return call_fib_notifier(nb, event_type, &info.info);
337359 }
338360
339361 static int call_fib_rule_notifiers(struct net *net,
....@@ -353,20 +375,25 @@
353375 }
354376
355377 /* Called with rcu_read_lock() */
356
-int fib_rules_dump(struct net *net, struct notifier_block *nb, int family)
378
+int fib_rules_dump(struct net *net, struct notifier_block *nb, int family,
379
+ struct netlink_ext_ack *extack)
357380 {
358381 struct fib_rules_ops *ops;
359382 struct fib_rule *rule;
383
+ int err = 0;
360384
361385 ops = lookup_rules_ops(net, family);
362386 if (!ops)
363387 return -EAFNOSUPPORT;
364
- list_for_each_entry_rcu(rule, &ops->rules_list, list)
365
- call_fib_rule_notifier(nb, net, FIB_EVENT_RULE_ADD, rule,
366
- family);
388
+ list_for_each_entry_rcu(rule, &ops->rules_list, list) {
389
+ err = call_fib_rule_notifier(nb, FIB_EVENT_RULE_ADD,
390
+ rule, family, extack);
391
+ if (err)
392
+ break;
393
+ }
367394 rules_ops_put(ops);
368395
369
- return 0;
396
+ return err;
370397 }
371398 EXPORT_SYMBOL_GPL(fib_rules_dump);
372399
....@@ -746,7 +773,8 @@
746773 goto errout;
747774 }
748775
749
- err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack);
776
+ err = nlmsg_parse_deprecated(nlh, sizeof(*frh), tb, FRA_MAX,
777
+ ops->policy, extack);
750778 if (err < 0) {
751779 NL_SET_ERR_MSG(extack, "Error parsing msg");
752780 goto errout;
....@@ -853,7 +881,8 @@
853881 goto errout;
854882 }
855883
856
- err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack);
884
+ err = nlmsg_parse_deprecated(nlh, sizeof(*frh), tb, FRA_MAX,
885
+ ops->policy, extack);
857886 if (err < 0) {
858887 NL_SET_ERR_MSG(extack, "Error parsing msg");
859888 goto errout;
....@@ -1063,13 +1092,47 @@
10631092 return err;
10641093 }
10651094
1095
+static int fib_valid_dumprule_req(const struct nlmsghdr *nlh,
1096
+ struct netlink_ext_ack *extack)
1097
+{
1098
+ struct fib_rule_hdr *frh;
1099
+
1100
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) {
1101
+ NL_SET_ERR_MSG(extack, "Invalid header for fib rule dump request");
1102
+ return -EINVAL;
1103
+ }
1104
+
1105
+ frh = nlmsg_data(nlh);
1106
+ if (frh->dst_len || frh->src_len || frh->tos || frh->table ||
1107
+ frh->res1 || frh->res2 || frh->action || frh->flags) {
1108
+ NL_SET_ERR_MSG(extack,
1109
+ "Invalid values in header for fib rule dump request");
1110
+ return -EINVAL;
1111
+ }
1112
+
1113
+ if (nlmsg_attrlen(nlh, sizeof(*frh))) {
1114
+ NL_SET_ERR_MSG(extack, "Invalid data after header in fib rule dump request");
1115
+ return -EINVAL;
1116
+ }
1117
+
1118
+ return 0;
1119
+}
1120
+
10661121 static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
10671122 {
1123
+ const struct nlmsghdr *nlh = cb->nlh;
10681124 struct net *net = sock_net(skb->sk);
10691125 struct fib_rules_ops *ops;
10701126 int idx = 0, family;
10711127
1072
- family = rtnl_msg_family(cb->nlh);
1128
+ if (cb->strict_check) {
1129
+ int err = fib_valid_dumprule_req(nlh, cb->extack);
1130
+
1131
+ if (err < 0)
1132
+ return err;
1133
+ }
1134
+
1135
+ family = rtnl_msg_family(nlh);
10731136 if (family != AF_UNSPEC) {
10741137 /* Protocol specific dump request */
10751138 ops = lookup_rules_ops(net, family);