hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/sched/act_pedit.c
....@@ -1,10 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * net/sched/act_pedit.c Generic packet editor
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
6
- * as published by the Free Software Foundation; either version
7
- * 2 of the License, or (at your option) any later version.
84 *
95 * Authors: Jamal Hadi Salim (2002-4)
106 */
....@@ -23,12 +19,14 @@
2319 #include <linux/tc_act/tc_pedit.h>
2420 #include <net/tc_act/tc_pedit.h>
2521 #include <uapi/linux/tc_act/tc_pedit.h>
22
+#include <net/pkt_cls.h>
2623
2724 static unsigned int pedit_net_id;
2825 static struct tc_action_ops act_pedit_ops;
2926
3027 static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
3128 [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) },
29
+ [TCA_PEDIT_PARMS_EX] = { .len = sizeof(struct tc_pedit) },
3230 [TCA_PEDIT_KEYS_EX] = { .type = NLA_NESTED },
3331 };
3432
....@@ -69,8 +67,9 @@
6967 goto err_out;
7068 }
7169
72
- err = nla_parse_nested(tb, TCA_PEDIT_KEY_EX_MAX, ka,
73
- pedit_key_ex_policy, NULL);
70
+ err = nla_parse_nested_deprecated(tb, TCA_PEDIT_KEY_EX_MAX,
71
+ ka, pedit_key_ex_policy,
72
+ NULL);
7473 if (err)
7574 goto err_out;
7675
....@@ -107,14 +106,15 @@
107106 static int tcf_pedit_key_ex_dump(struct sk_buff *skb,
108107 struct tcf_pedit_key_ex *keys_ex, int n)
109108 {
110
- struct nlattr *keys_start = nla_nest_start(skb, TCA_PEDIT_KEYS_EX);
109
+ struct nlattr *keys_start = nla_nest_start_noflag(skb,
110
+ TCA_PEDIT_KEYS_EX);
111111
112112 if (!keys_start)
113113 goto nla_failure;
114114 for (; n > 0; n--) {
115115 struct nlattr *key_start;
116116
117
- key_start = nla_nest_start(skb, TCA_PEDIT_KEY_EX);
117
+ key_start = nla_nest_start_noflag(skb, TCA_PEDIT_KEY_EX);
118118 if (!key_start)
119119 goto nla_failure;
120120
....@@ -138,17 +138,19 @@
138138 static int tcf_pedit_init(struct net *net, struct nlattr *nla,
139139 struct nlattr *est, struct tc_action **a,
140140 int ovr, int bind, bool rtnl_held,
141
+ struct tcf_proto *tp, u32 flags,
141142 struct netlink_ext_ack *extack)
142143 {
143144 struct tc_action_net *tn = net_generic(net, pedit_net_id);
144145 struct nlattr *tb[TCA_PEDIT_MAX + 1];
146
+ struct tcf_chain *goto_ch = NULL;
145147 struct tc_pedit_key *keys = NULL;
146148 struct tcf_pedit_key_ex *keys_ex;
147149 struct tc_pedit *parm;
148150 struct nlattr *pattr;
149151 struct tcf_pedit *p;
150152 int ret = 0, err;
151
- int ksize;
153
+ int i, ksize;
152154 u32 index;
153155
154156 if (!nla) {
....@@ -156,7 +158,8 @@
156158 return -EINVAL;
157159 }
158160
159
- err = nla_parse_nested(tb, TCA_PEDIT_MAX, nla, pedit_policy, NULL);
161
+ err = nla_parse_nested_deprecated(tb, TCA_PEDIT_MAX, nla,
162
+ pedit_policy, NULL);
160163 if (err < 0)
161164 return err;
162165
....@@ -187,7 +190,7 @@
187190 err = tcf_idr_check_alloc(tn, &index, a, bind);
188191 if (!err) {
189192 ret = tcf_idr_create(tn, index, est, a,
190
- &act_pedit_ops, bind, false);
193
+ &act_pedit_ops, bind, false, flags);
191194 if (ret) {
192195 tcf_idr_cleanup(tn, index);
193196 goto out_free;
....@@ -205,6 +208,11 @@
205208 goto out_free;
206209 }
207210
211
+ err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
212
+ if (err < 0) {
213
+ ret = err;
214
+ goto out_release;
215
+ }
208216 p = to_pedit(*a);
209217 spin_lock_bh(&p->tcf_lock);
210218
....@@ -214,25 +222,44 @@
214222 if (!keys) {
215223 spin_unlock_bh(&p->tcf_lock);
216224 ret = -ENOMEM;
217
- goto out_release;
225
+ goto put_chain;
218226 }
219227 kfree(p->tcfp_keys);
220228 p->tcfp_keys = keys;
221229 p->tcfp_nkeys = parm->nkeys;
222230 }
223231 memcpy(p->tcfp_keys, parm->keys, ksize);
232
+ p->tcfp_off_max_hint = 0;
233
+ for (i = 0; i < p->tcfp_nkeys; ++i) {
234
+ u32 cur = p->tcfp_keys[i].off;
235
+
236
+ /* sanitize the shift value for any later use */
237
+ p->tcfp_keys[i].shift = min_t(size_t, BITS_PER_TYPE(int) - 1,
238
+ p->tcfp_keys[i].shift);
239
+
240
+ /* The AT option can read a single byte, we can bound the actual
241
+ * value with uchar max.
242
+ */
243
+ cur += (0xff & p->tcfp_keys[i].offmask) >> p->tcfp_keys[i].shift;
244
+
245
+ /* Each key touches 4 bytes starting from the computed offset */
246
+ p->tcfp_off_max_hint = max(p->tcfp_off_max_hint, cur + 4);
247
+ }
224248
225249 p->tcfp_flags = parm->flags;
226
- p->tcf_action = parm->action;
250
+ goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
227251
228252 kfree(p->tcfp_keys_ex);
229253 p->tcfp_keys_ex = keys_ex;
230254
231255 spin_unlock_bh(&p->tcf_lock);
232
- if (ret == ACT_P_CREATED)
233
- tcf_idr_insert(tn, *a);
256
+ if (goto_ch)
257
+ tcf_chain_put_by_act(goto_ch);
234258 return ret;
235259
260
+put_chain:
261
+ if (goto_ch)
262
+ tcf_chain_put_by_act(goto_ch);
236263 out_release:
237264 tcf_idr_release(*a, bind);
238265 out_free:
....@@ -298,12 +325,17 @@
298325 struct tcf_result *res)
299326 {
300327 struct tcf_pedit *p = to_pedit(a);
328
+ u32 max_offset;
301329 int i;
302330
303
- if (skb_unclone(skb, GFP_ATOMIC))
304
- return p->tcf_action;
305
-
306331 spin_lock(&p->tcf_lock);
332
+
333
+ max_offset = (skb_transport_header_was_set(skb) ?
334
+ skb_transport_offset(skb) :
335
+ skb_network_offset(skb)) +
336
+ p->tcfp_off_max_hint;
337
+ if (skb_ensure_writable(skb, min(skb->len, max_offset)))
338
+ goto unlock;
307339
308340 tcf_lastuse_update(&p->tcf_tm);
309341
....@@ -393,8 +425,19 @@
393425 p->tcf_qstats.overlimits++;
394426 done:
395427 bstats_update(&p->tcf_bstats, skb);
428
+unlock:
396429 spin_unlock(&p->tcf_lock);
397430 return p->tcf_action;
431
+}
432
+
433
+static void tcf_pedit_stats_update(struct tc_action *a, u64 bytes, u64 packets,
434
+ u64 drops, u64 lastuse, bool hw)
435
+{
436
+ struct tcf_pedit *d = to_pedit(a);
437
+ struct tcf_t *tm = &d->tcf_tm;
438
+
439
+ tcf_action_update_stats(a, bytes, packets, drops, hw);
440
+ tm->lastuse = max_t(u64, tm->lastuse, lastuse);
398441 }
399442
400443 static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
....@@ -406,7 +449,7 @@
406449 struct tcf_t t;
407450 int s;
408451
409
- s = sizeof(*opt) + p->tcfp_nkeys * sizeof(struct tc_pedit_key);
452
+ s = struct_size(opt, keys, p->tcfp_nkeys);
410453
411454 /* netlink spinlocks held above us - must use ATOMIC */
412455 opt = kzalloc(s, GFP_ATOMIC);
....@@ -414,8 +457,7 @@
414457 return -ENOBUFS;
415458
416459 spin_lock_bh(&p->tcf_lock);
417
- memcpy(opt->keys, p->tcfp_keys,
418
- p->tcfp_nkeys * sizeof(struct tc_pedit_key));
460
+ memcpy(opt->keys, p->tcfp_keys, flex_array_size(opt, keys, p->tcfp_nkeys));
419461 opt->index = p->tcf_index;
420462 opt->nkeys = p->tcfp_nkeys;
421463 opt->flags = p->tcfp_flags;
....@@ -461,8 +503,7 @@
461503 return tcf_generic_walker(tn, skb, cb, type, ops, extack);
462504 }
463505
464
-static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index,
465
- struct netlink_ext_ack *extack)
506
+static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index)
466507 {
467508 struct tc_action_net *tn = net_generic(net, pedit_net_id);
468509
....@@ -471,9 +512,10 @@
471512
472513 static struct tc_action_ops act_pedit_ops = {
473514 .kind = "pedit",
474
- .type = TCA_ACT_PEDIT,
515
+ .id = TCA_ID_PEDIT,
475516 .owner = THIS_MODULE,
476517 .act = tcf_pedit_act,
518
+ .stats_update = tcf_pedit_stats_update,
477519 .dump = tcf_pedit_dump,
478520 .cleanup = tcf_pedit_cleanup,
479521 .init = tcf_pedit_init,