1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
4 *
5 * Development of this code funded by Astaro AG (http://www.astaro.com/)
6 */
7
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/module.h>
11 #include <linux/list.h>
12 #include <linux/rbtree.h>
13 #include <linux/bsearch.h>
14 #include <linux/netlink.h>
15 #include <linux/netfilter.h>
16 #include <linux/netfilter/nf_tables.h>
17 #include <net/netfilter/nf_tables_core.h>
18
19 struct nft_array_interval {
20 struct nft_set_ext *from;
21 struct nft_set_ext *to;
22 };
23
24 struct nft_array {
25 u32 max_intervals;
26 u32 num_intervals;
27 struct nft_array_interval *intervals;
28 struct rcu_head rcu_head;
29 };
30
31 struct nft_rbtree {
32 struct rb_root root;
33 rwlock_t lock;
34 struct nft_array __rcu *array;
35 struct nft_array *array_next;
36 unsigned long start_rbe_cookie;
37 unsigned long last_gc;
38 struct list_head expired;
39 u64 last_tstamp;
40 };
41
42 struct nft_rbtree_elem {
43 struct nft_elem_priv priv;
44 union {
45 struct rb_node node;
46 struct list_head list;
47 };
48 struct nft_set_ext ext;
49 };
50
nft_rbtree_interval_end(const struct nft_rbtree_elem * rbe)51 static bool nft_rbtree_interval_end(const struct nft_rbtree_elem *rbe)
52 {
53 return nft_set_ext_exists(&rbe->ext, NFT_SET_EXT_FLAGS) &&
54 (*nft_set_ext_flags(&rbe->ext) & NFT_SET_ELEM_INTERVAL_END);
55 }
56
nft_rbtree_interval_start(const struct nft_rbtree_elem * rbe)57 static bool nft_rbtree_interval_start(const struct nft_rbtree_elem *rbe)
58 {
59 return !nft_rbtree_interval_end(rbe);
60 }
61
nft_rbtree_interval_null(const struct nft_set * set,const struct nft_rbtree_elem * rbe)62 static bool nft_rbtree_interval_null(const struct nft_set *set,
63 const struct nft_rbtree_elem *rbe)
64 {
65 return (!memchr_inv(nft_set_ext_key(&rbe->ext), 0, set->klen) &&
66 nft_rbtree_interval_end(rbe));
67 }
68
nft_rbtree_cmp(const struct nft_set * set,const struct nft_rbtree_elem * e1,const struct nft_rbtree_elem * e2)69 static int nft_rbtree_cmp(const struct nft_set *set,
70 const struct nft_rbtree_elem *e1,
71 const struct nft_rbtree_elem *e2)
72 {
73 return memcmp(nft_set_ext_key(&e1->ext), nft_set_ext_key(&e2->ext),
74 set->klen);
75 }
76
77 struct nft_array_lookup_ctx {
78 const u32 *key;
79 u32 klen;
80 };
81
nft_array_lookup_cmp(const void * pkey,const void * entry)82 static int nft_array_lookup_cmp(const void *pkey, const void *entry)
83 {
84 const struct nft_array_interval *interval = entry;
85 const struct nft_array_lookup_ctx *ctx = pkey;
86 int a, b;
87
88 if (!interval->from)
89 return 1;
90
91 a = memcmp(ctx->key, nft_set_ext_key(interval->from), ctx->klen);
92 if (!interval->to)
93 b = -1;
94 else
95 b = memcmp(ctx->key, nft_set_ext_key(interval->to), ctx->klen);
96
97 if (a >= 0 && b < 0)
98 return 0;
99
100 if (a < 0)
101 return -1;
102
103 return 1;
104 }
105
106 INDIRECT_CALLABLE_SCOPE
107 const struct nft_set_ext *
nft_rbtree_lookup(const struct net * net,const struct nft_set * set,const u32 * key)108 nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
109 const u32 *key)
110 {
111 struct nft_rbtree *priv = nft_set_priv(set);
112 struct nft_array *array = rcu_dereference(priv->array);
113 const struct nft_array_interval *interval;
114 struct nft_array_lookup_ctx ctx = {
115 .key = key,
116 .klen = set->klen,
117 };
118
119 if (!array)
120 return NULL;
121
122 interval = bsearch(&ctx, array->intervals, array->num_intervals,
123 sizeof(struct nft_array_interval),
124 nft_array_lookup_cmp);
125 if (!interval || nft_set_elem_expired(interval->from))
126 return NULL;
127
128 return interval->from;
129 }
130
131 struct nft_array_get_ctx {
132 const u32 *key;
133 unsigned int flags;
134 u32 klen;
135 };
136
nft_array_get_cmp(const void * pkey,const void * entry)137 static int nft_array_get_cmp(const void *pkey, const void *entry)
138 {
139 const struct nft_array_interval *interval = entry;
140 const struct nft_array_get_ctx *ctx = pkey;
141 int a, b;
142
143 if (!interval->from)
144 return 1;
145
146 a = memcmp(ctx->key, nft_set_ext_key(interval->from), ctx->klen);
147 if (!interval->to)
148 b = -1;
149 else
150 b = memcmp(ctx->key, nft_set_ext_key(interval->to), ctx->klen);
151
152 if (a >= 0) {
153 if (ctx->flags & NFT_SET_ELEM_INTERVAL_END && b <= 0)
154 return 0;
155 else if (b < 0)
156 return 0;
157 }
158
159 if (a < 0)
160 return -1;
161
162 return 1;
163 }
164
165 static struct nft_elem_priv *
nft_rbtree_get(const struct net * net,const struct nft_set * set,const struct nft_set_elem * elem,unsigned int flags)166 nft_rbtree_get(const struct net *net, const struct nft_set *set,
167 const struct nft_set_elem *elem, unsigned int flags)
168 {
169 struct nft_rbtree *priv = nft_set_priv(set);
170 struct nft_array *array = rcu_dereference(priv->array);
171 const struct nft_array_interval *interval;
172 struct nft_array_get_ctx ctx = {
173 .key = (const u32 *)&elem->key.val,
174 .flags = flags,
175 .klen = set->klen,
176 };
177 struct nft_rbtree_elem *rbe;
178
179 if (!array)
180 return ERR_PTR(-ENOENT);
181
182 interval = bsearch(&ctx, array->intervals, array->num_intervals,
183 sizeof(struct nft_array_interval), nft_array_get_cmp);
184 if (!interval || nft_set_elem_expired(interval->from))
185 return ERR_PTR(-ENOENT);
186
187 if (flags & NFT_SET_ELEM_INTERVAL_END) {
188 if (!interval->to)
189 return NULL;
190
191 rbe = container_of(interval->to, struct nft_rbtree_elem, ext);
192 } else {
193 rbe = container_of(interval->from, struct nft_rbtree_elem, ext);
194 }
195
196 return &rbe->priv;
197 }
198
nft_rbtree_gc_elem_move(struct net * net,struct nft_set * set,struct nft_rbtree * priv,struct nft_rbtree_elem * rbe)199 static void nft_rbtree_gc_elem_move(struct net *net, struct nft_set *set,
200 struct nft_rbtree *priv,
201 struct nft_rbtree_elem *rbe)
202 {
203 lockdep_assert_held_write(&priv->lock);
204 nft_setelem_data_deactivate(net, set, &rbe->priv);
205 rb_erase(&rbe->node, &priv->root);
206
207 /* collected later on in commit callback */
208 list_add(&rbe->list, &priv->expired);
209 }
210
211 static const struct nft_rbtree_elem *
nft_rbtree_gc_elem(const struct nft_set * __set,struct nft_rbtree * priv,struct nft_rbtree_elem * rbe)212 nft_rbtree_gc_elem(const struct nft_set *__set, struct nft_rbtree *priv,
213 struct nft_rbtree_elem *rbe)
214 {
215 struct nft_set *set = (struct nft_set *)__set;
216 struct rb_node *prev = rb_prev(&rbe->node);
217 struct net *net = read_pnet(&set->net);
218 struct nft_rbtree_elem *rbe_prev;
219
220 /* search for end interval coming before this element.
221 * end intervals don't carry a timeout extension, they
222 * are coupled with the interval start element.
223 */
224 while (prev) {
225 rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node);
226 if (nft_rbtree_interval_end(rbe_prev) &&
227 nft_set_elem_active(&rbe_prev->ext, NFT_GENMASK_ANY))
228 break;
229
230 prev = rb_prev(prev);
231 }
232
233 rbe_prev = NULL;
234 if (prev) {
235 rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node);
236 nft_rbtree_gc_elem_move(net, set, priv, rbe_prev);
237 }
238
239 nft_rbtree_gc_elem_move(net, set, priv, rbe);
240
241 return rbe_prev;
242 }
243
nft_rbtree_update_first(const struct nft_set * set,struct nft_rbtree_elem * rbe,struct rb_node * first)244 static bool nft_rbtree_update_first(const struct nft_set *set,
245 struct nft_rbtree_elem *rbe,
246 struct rb_node *first)
247 {
248 struct nft_rbtree_elem *first_elem;
249
250 first_elem = rb_entry(first, struct nft_rbtree_elem, node);
251 /* this element is closest to where the new element is to be inserted:
252 * update the first element for the node list path.
253 */
254 if (nft_rbtree_cmp(set, rbe, first_elem) < 0)
255 return true;
256
257 return false;
258 }
259
260 /* Only for anonymous sets which do not allow updates, all element are active. */
nft_rbtree_prev_active(struct nft_rbtree_elem * rbe)261 static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
262 {
263 struct rb_node *node;
264
265 node = rb_prev(&rbe->node);
266 if (!node)
267 return NULL;
268
269 return rb_entry(node, struct nft_rbtree_elem, node);
270 }
271
272 static struct nft_rbtree_elem *
__nft_rbtree_next_active(struct rb_node * node,u8 genmask)273 __nft_rbtree_next_active(struct rb_node *node, u8 genmask)
274 {
275 struct nft_rbtree_elem *next_rbe;
276
277 while (node) {
278 next_rbe = rb_entry(node, struct nft_rbtree_elem, node);
279 if (!nft_set_elem_active(&next_rbe->ext, genmask)) {
280 node = rb_next(node);
281 continue;
282 }
283
284 return next_rbe;
285 }
286
287 return NULL;
288 }
289
290 static struct nft_rbtree_elem *
nft_rbtree_next_active(struct nft_rbtree_elem * rbe,u8 genmask)291 nft_rbtree_next_active(struct nft_rbtree_elem *rbe, u8 genmask)
292 {
293 return __nft_rbtree_next_active(rb_next(&rbe->node), genmask);
294 }
295
nft_rbtree_maybe_reset_start_cookie(struct nft_rbtree * priv,u64 tstamp)296 static void nft_rbtree_maybe_reset_start_cookie(struct nft_rbtree *priv,
297 u64 tstamp)
298 {
299 if (priv->last_tstamp != tstamp) {
300 priv->start_rbe_cookie = 0;
301 priv->last_tstamp = tstamp;
302 }
303 }
304
nft_rbtree_set_start_cookie(struct nft_rbtree * priv,const struct nft_rbtree_elem * rbe)305 static void nft_rbtree_set_start_cookie(struct nft_rbtree *priv,
306 const struct nft_rbtree_elem *rbe)
307 {
308 priv->start_rbe_cookie = (unsigned long)rbe;
309 }
310
nft_rbtree_cmp_start_cookie(struct nft_rbtree * priv,const struct nft_rbtree_elem * rbe)311 static bool nft_rbtree_cmp_start_cookie(struct nft_rbtree *priv,
312 const struct nft_rbtree_elem *rbe)
313 {
314 return priv->start_rbe_cookie == (unsigned long)rbe;
315 }
316
nft_rbtree_insert_same_interval(const struct net * net,struct nft_rbtree * priv,struct nft_rbtree_elem * rbe)317 static bool nft_rbtree_insert_same_interval(const struct net *net,
318 struct nft_rbtree *priv,
319 struct nft_rbtree_elem *rbe)
320 {
321 u8 genmask = nft_genmask_next(net);
322 struct nft_rbtree_elem *next_rbe;
323
324 if (!priv->start_rbe_cookie)
325 return true;
326
327 next_rbe = nft_rbtree_next_active(rbe, genmask);
328 if (next_rbe) {
329 /* Closest start element differs from last element added. */
330 if (nft_rbtree_interval_start(next_rbe) &&
331 nft_rbtree_cmp_start_cookie(priv, next_rbe)) {
332 priv->start_rbe_cookie = 0;
333 return true;
334 }
335 }
336
337 priv->start_rbe_cookie = 0;
338
339 return false;
340 }
341
__nft_rbtree_insert(const struct net * net,const struct nft_set * set,struct nft_rbtree_elem * new,struct nft_elem_priv ** elem_priv,u64 tstamp)342 static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
343 struct nft_rbtree_elem *new,
344 struct nft_elem_priv **elem_priv, u64 tstamp)
345 {
346 struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
347 struct rb_node *node, *next, *parent, **p, *first = NULL;
348 struct nft_rbtree *priv = nft_set_priv(set);
349 u8 cur_genmask = nft_genmask_cur(net);
350 u8 genmask = nft_genmask_next(net);
351 int d;
352
353 /* Descend the tree to search for an existing element greater than the
354 * key value to insert that is greater than the new element. This is the
355 * first element to walk the ordered elements to find possible overlap.
356 */
357 parent = NULL;
358 p = &priv->root.rb_node;
359 while (*p != NULL) {
360 parent = *p;
361 rbe = rb_entry(parent, struct nft_rbtree_elem, node);
362 d = nft_rbtree_cmp(set, rbe, new);
363
364 if (d < 0) {
365 p = &parent->rb_left;
366 } else if (d > 0) {
367 if (!first ||
368 nft_rbtree_update_first(set, rbe, first))
369 first = &rbe->node;
370
371 p = &parent->rb_right;
372 } else {
373 if (nft_rbtree_interval_end(rbe))
374 p = &parent->rb_left;
375 else
376 p = &parent->rb_right;
377 }
378 }
379
380 if (!first)
381 first = rb_first(&priv->root);
382
383 /* Detect overlap by going through the list of valid tree nodes.
384 * Values stored in the tree are in reversed order, starting from
385 * highest to lowest value.
386 */
387 for (node = first; node != NULL; node = next) {
388 next = rb_next(node);
389
390 rbe = rb_entry(node, struct nft_rbtree_elem, node);
391
392 if (!nft_set_elem_active(&rbe->ext, genmask))
393 continue;
394
395 /* perform garbage collection to avoid bogus overlap reports
396 * but skip new elements in this transaction.
397 */
398 if (__nft_set_elem_expired(&rbe->ext, tstamp) &&
399 nft_set_elem_active(&rbe->ext, cur_genmask)) {
400 const struct nft_rbtree_elem *removed_end;
401
402 removed_end = nft_rbtree_gc_elem(set, priv, rbe);
403 if (removed_end == rbe_le || removed_end == rbe_ge)
404 return -EAGAIN;
405
406 continue;
407 }
408
409 d = nft_rbtree_cmp(set, rbe, new);
410 if (d == 0) {
411 /* Matching end element: no need to look for an
412 * overlapping greater or equal element.
413 */
414 if (nft_rbtree_interval_end(rbe)) {
415 rbe_le = rbe;
416 break;
417 }
418
419 /* first element that is greater or equal to key value. */
420 if (!rbe_ge) {
421 rbe_ge = rbe;
422 continue;
423 }
424
425 /* this is a closer more or equal element, update it. */
426 if (nft_rbtree_cmp(set, rbe_ge, new) != 0) {
427 rbe_ge = rbe;
428 continue;
429 }
430
431 /* element is equal to key value, make sure flags are
432 * the same, an existing more or equal start element
433 * must not be replaced by more or equal end element.
434 */
435 if ((nft_rbtree_interval_start(new) &&
436 nft_rbtree_interval_start(rbe_ge)) ||
437 (nft_rbtree_interval_end(new) &&
438 nft_rbtree_interval_end(rbe_ge))) {
439 rbe_ge = rbe;
440 continue;
441 }
442 } else if (d > 0) {
443 /* annotate element greater than the new element. */
444 rbe_ge = rbe;
445 continue;
446 } else if (d < 0) {
447 /* annotate element less than the new element. */
448 rbe_le = rbe;
449 break;
450 }
451 }
452
453 if (nft_rbtree_interval_null(set, new))
454 priv->start_rbe_cookie = 0;
455 else if (nft_rbtree_interval_start(new) && priv->start_rbe_cookie)
456 priv->start_rbe_cookie = 0;
457
458 /* - new start element matching existing start element: full overlap
459 * reported as -EEXIST, cleared by caller if NLM_F_EXCL is not given.
460 */
461 if (rbe_ge && !nft_rbtree_cmp(set, new, rbe_ge) &&
462 nft_rbtree_interval_start(rbe_ge) == nft_rbtree_interval_start(new)) {
463 *elem_priv = &rbe_ge->priv;
464 nft_rbtree_set_start_cookie(priv, rbe_ge);
465 return -EEXIST;
466 }
467
468 /* - new end element matching existing end element: full overlap
469 * reported as -EEXIST, cleared by caller if NLM_F_EXCL is not given.
470 */
471 if (rbe_le && !nft_rbtree_cmp(set, new, rbe_le) &&
472 nft_rbtree_interval_end(rbe_le) == nft_rbtree_interval_end(new)) {
473 /* - ignore null interval, otherwise NLM_F_CREATE bogusly
474 * reports EEXIST.
475 */
476 if (nft_rbtree_interval_null(set, new))
477 return -ECANCELED;
478
479 *elem_priv = &rbe_le->priv;
480
481 /* - start and end element belong to the same interval. */
482 if (!nft_rbtree_insert_same_interval(net, priv, rbe_le))
483 return -ENOTEMPTY;
484
485 return -EEXIST;
486 }
487
488 /* - new start element with existing closest, less or equal key value
489 * being a start element: partial overlap, reported as -ENOTEMPTY.
490 * Anonymous sets allow for two consecutive start element since they
491 * are constant, but validate that this new start element does not
492 * sit in between an existing start and end elements: partial overlap,
493 * reported as -ENOTEMPTY.
494 */
495 if (rbe_le &&
496 nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
497 if (!nft_set_is_anonymous(set))
498 return -ENOTEMPTY;
499
500 rbe_prev = nft_rbtree_prev_active(rbe_le);
501 if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
502 return -ENOTEMPTY;
503 }
504
505 /* - new end element with existing closest, less or equal key value
506 * being a end element: partial overlap, reported as -ENOTEMPTY.
507 */
508 if (rbe_le &&
509 nft_rbtree_interval_end(rbe_le) && nft_rbtree_interval_end(new))
510 return -ENOTEMPTY;
511
512 /* - new end element with existing closest, greater or equal key value
513 * being an end element: partial overlap, reported as -ENOTEMPTY
514 */
515 if (rbe_ge &&
516 nft_rbtree_interval_end(rbe_ge) && nft_rbtree_interval_end(new))
517 return -ENOTEMPTY;
518
519 /* Accepted element: pick insertion point depending on key value */
520 parent = NULL;
521 p = &priv->root.rb_node;
522 while (*p != NULL) {
523 parent = *p;
524 rbe = rb_entry(parent, struct nft_rbtree_elem, node);
525 d = nft_rbtree_cmp(set, rbe, new);
526
527 if (d < 0)
528 p = &parent->rb_left;
529 else if (d > 0)
530 p = &parent->rb_right;
531 else if (nft_rbtree_interval_end(rbe))
532 p = &parent->rb_left;
533 else
534 p = &parent->rb_right;
535 }
536
537 rb_link_node_rcu(&new->node, parent, p);
538 rb_insert_color(&new->node, &priv->root);
539 return 0;
540 }
541
nft_array_intervals_alloc(struct nft_array * array,u32 max_intervals)542 static int nft_array_intervals_alloc(struct nft_array *array, u32 max_intervals)
543 {
544 struct nft_array_interval *intervals;
545
546 intervals = kvzalloc_objs(struct nft_array_interval, max_intervals,
547 GFP_KERNEL_ACCOUNT);
548 if (!intervals)
549 return -ENOMEM;
550
551 kvfree(array->intervals);
552
553 array->intervals = intervals;
554 array->max_intervals = max_intervals;
555
556 return 0;
557 }
558
nft_array_alloc(u32 max_intervals)559 static struct nft_array *nft_array_alloc(u32 max_intervals)
560 {
561 struct nft_array *array;
562
563 array = kzalloc_obj(*array, GFP_KERNEL_ACCOUNT);
564 if (!array)
565 return NULL;
566
567 if (nft_array_intervals_alloc(array, max_intervals) < 0) {
568 kfree(array);
569 return NULL;
570 }
571
572 return array;
573 }
574
575 /* Similar to nft_rbtree_{u,k}size to hide details to userspace, but consider
576 * packed representation coming from userspace for anonymous sets too.
577 */
nft_array_elems(const struct nft_set * set)578 static u32 nft_array_elems(const struct nft_set *set)
579 {
580 u32 nelems = atomic_read(&set->nelems) - set->ndeact;
581
582 /* Adjacent intervals are represented with a single start element in
583 * anonymous sets, use the current element counter as is.
584 */
585 if (nft_set_is_anonymous(set))
586 return nelems;
587
588 /* Add extra room for never matching interval at the beginning and open
589 * interval at the end which only use a single element to represent it.
590 * The conversion to array will compact intervals, this allows reduce
591 * memory consumption.
592 */
593 return (nelems / 2) + 2;
594 }
595
596 #define NFT_ARRAY_INITIAL_SIZE 1024
597 #define NFT_ARRAY_INITIAL_ANON_SIZE 16
598 #define NFT_ARRAY_INITIAL_ANON_THRESH (8192U / sizeof(struct nft_array_interval))
599
nft_array_may_resize(const struct nft_set * set,bool flush)600 static int nft_array_may_resize(const struct nft_set *set, bool flush)
601 {
602 u32 initial_intervals, max_intervals, new_max_intervals, delta;
603 u32 shrinked_max_intervals, nelems = nft_array_elems(set);
604 struct nft_rbtree *priv = nft_set_priv(set);
605 struct nft_array *array;
606
607 if (nft_set_is_anonymous(set))
608 initial_intervals = NFT_ARRAY_INITIAL_ANON_SIZE;
609 else
610 initial_intervals = NFT_ARRAY_INITIAL_SIZE;
611
612 if (priv->array_next) {
613 max_intervals = priv->array_next->max_intervals;
614 new_max_intervals = priv->array_next->max_intervals;
615 } else {
616 if (priv->array) {
617 max_intervals = priv->array->max_intervals;
618 new_max_intervals = priv->array->max_intervals;
619 } else {
620 max_intervals = 0;
621 new_max_intervals = initial_intervals;
622 }
623 }
624
625 if (nft_set_is_anonymous(set))
626 goto maybe_grow;
627
628 if (flush) {
629 /* Set flush just started, nelems still report elements.*/
630 nelems = 0;
631 new_max_intervals = NFT_ARRAY_INITIAL_SIZE;
632 goto realloc_array;
633 }
634
635 if (check_add_overflow(new_max_intervals, new_max_intervals,
636 &shrinked_max_intervals))
637 return -EOVERFLOW;
638
639 shrinked_max_intervals = DIV_ROUND_UP(shrinked_max_intervals, 3);
640
641 if (shrinked_max_intervals > NFT_ARRAY_INITIAL_SIZE &&
642 nelems < shrinked_max_intervals) {
643 new_max_intervals = shrinked_max_intervals;
644 goto realloc_array;
645 }
646 maybe_grow:
647 if (nelems > new_max_intervals) {
648 if (nft_set_is_anonymous(set) &&
649 new_max_intervals < NFT_ARRAY_INITIAL_ANON_THRESH) {
650 new_max_intervals <<= 1;
651 } else {
652 delta = new_max_intervals >> 1;
653 if (check_add_overflow(new_max_intervals, delta,
654 &new_max_intervals))
655 return -EOVERFLOW;
656 }
657 }
658
659 realloc_array:
660 if (unlikely(nelems > new_max_intervals)) {
661 DEBUG_NET_WARN_ON_ONCE(1);
662 return -ENOMEM;
663 }
664
665 if (priv->array_next) {
666 if (max_intervals == new_max_intervals)
667 return 0;
668
669 if (nft_array_intervals_alloc(priv->array_next, new_max_intervals) < 0)
670 return -ENOMEM;
671 } else {
672 array = nft_array_alloc(new_max_intervals);
673 if (!array)
674 return -ENOMEM;
675
676 priv->array_next = array;
677 }
678
679 return 0;
680 }
681
nft_rbtree_insert(const struct net * net,const struct nft_set * set,const struct nft_set_elem * elem,struct nft_elem_priv ** elem_priv)682 static int nft_rbtree_insert(const struct net *net, const struct nft_set *set,
683 const struct nft_set_elem *elem,
684 struct nft_elem_priv **elem_priv)
685 {
686 struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem->priv);
687 struct nft_rbtree *priv = nft_set_priv(set);
688 u64 tstamp = nft_net_tstamp(net);
689 int err;
690
691 nft_rbtree_maybe_reset_start_cookie(priv, tstamp);
692
693 if (nft_array_may_resize(set, false) < 0)
694 return -ENOMEM;
695
696 do {
697 if (fatal_signal_pending(current))
698 return -EINTR;
699
700 cond_resched();
701
702 write_lock(&priv->lock);
703 err = __nft_rbtree_insert(net, set, rbe, elem_priv, tstamp);
704 write_unlock(&priv->lock);
705 } while (err == -EAGAIN);
706
707 return err;
708 }
709
nft_rbtree_remove(const struct net * net,const struct nft_set * set,struct nft_elem_priv * elem_priv)710 static void nft_rbtree_remove(const struct net *net,
711 const struct nft_set *set,
712 struct nft_elem_priv *elem_priv)
713 {
714 struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem_priv);
715 struct nft_rbtree *priv = nft_set_priv(set);
716
717 write_lock(&priv->lock);
718 rb_erase(&rbe->node, &priv->root);
719 write_unlock(&priv->lock);
720 }
721
nft_rbtree_activate(const struct net * net,const struct nft_set * set,struct nft_elem_priv * elem_priv)722 static void nft_rbtree_activate(const struct net *net,
723 const struct nft_set *set,
724 struct nft_elem_priv *elem_priv)
725 {
726 struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem_priv);
727
728 nft_clear(net, &rbe->ext);
729 }
730
731 static struct nft_rbtree_elem *
nft_rbtree_next_inactive(struct nft_rbtree_elem * rbe,u8 genmask)732 nft_rbtree_next_inactive(struct nft_rbtree_elem *rbe, u8 genmask)
733 {
734 struct nft_rbtree_elem *next_rbe;
735 struct rb_node *node;
736
737 node = rb_next(&rbe->node);
738 if (node) {
739 next_rbe = rb_entry(node, struct nft_rbtree_elem, node);
740 if (nft_rbtree_interval_start(next_rbe) &&
741 !nft_set_elem_active(&next_rbe->ext, genmask))
742 return next_rbe;
743 }
744
745 return NULL;
746 }
747
nft_rbtree_deactivate_same_interval(const struct net * net,struct nft_rbtree * priv,struct nft_rbtree_elem * rbe)748 static bool nft_rbtree_deactivate_same_interval(const struct net *net,
749 struct nft_rbtree *priv,
750 struct nft_rbtree_elem *rbe)
751 {
752 u8 genmask = nft_genmask_next(net);
753 struct nft_rbtree_elem *next_rbe;
754
755 if (!priv->start_rbe_cookie)
756 return true;
757
758 next_rbe = nft_rbtree_next_inactive(rbe, genmask);
759 if (next_rbe) {
760 /* Closest start element differs from last element added. */
761 if (nft_rbtree_interval_start(next_rbe) &&
762 nft_rbtree_cmp_start_cookie(priv, next_rbe)) {
763 priv->start_rbe_cookie = 0;
764 return true;
765 }
766 }
767
768 priv->start_rbe_cookie = 0;
769
770 return false;
771 }
772
nft_rbtree_flush(const struct net * net,const struct nft_set * set,struct nft_elem_priv * elem_priv)773 static void nft_rbtree_flush(const struct net *net,
774 const struct nft_set *set,
775 struct nft_elem_priv *elem_priv)
776 {
777 struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem_priv);
778
779 nft_set_elem_change_active(net, set, &rbe->ext);
780 }
781
782 static struct nft_elem_priv *
nft_rbtree_deactivate(const struct net * net,const struct nft_set * set,const struct nft_set_elem * elem)783 nft_rbtree_deactivate(const struct net *net, const struct nft_set *set,
784 const struct nft_set_elem *elem)
785 {
786 struct nft_rbtree_elem *rbe, *this = nft_elem_priv_cast(elem->priv);
787 struct nft_rbtree *priv = nft_set_priv(set);
788 const struct rb_node *parent = priv->root.rb_node;
789 u8 genmask = nft_genmask_next(net);
790 u64 tstamp = nft_net_tstamp(net);
791 int d;
792
793 nft_rbtree_maybe_reset_start_cookie(priv, tstamp);
794
795 if (nft_rbtree_interval_start(this) ||
796 nft_rbtree_interval_null(set, this))
797 priv->start_rbe_cookie = 0;
798
799 if (nft_array_may_resize(set, false) < 0)
800 return NULL;
801
802 while (parent != NULL) {
803 rbe = rb_entry(parent, struct nft_rbtree_elem, node);
804
805 d = memcmp(nft_set_ext_key(&rbe->ext), &elem->key.val,
806 set->klen);
807 if (d < 0)
808 parent = parent->rb_left;
809 else if (d > 0)
810 parent = parent->rb_right;
811 else {
812 if (nft_rbtree_interval_end(rbe) &&
813 nft_rbtree_interval_start(this)) {
814 parent = parent->rb_left;
815 continue;
816 } else if (nft_rbtree_interval_start(rbe) &&
817 nft_rbtree_interval_end(this)) {
818 parent = parent->rb_right;
819 continue;
820 } else if (__nft_set_elem_expired(&rbe->ext, tstamp)) {
821 break;
822 } else if (!nft_set_elem_active(&rbe->ext, genmask)) {
823 parent = parent->rb_left;
824 continue;
825 }
826
827 if (nft_rbtree_interval_start(rbe))
828 nft_rbtree_set_start_cookie(priv, rbe);
829 else if (!nft_rbtree_deactivate_same_interval(net, priv, rbe))
830 return NULL;
831
832 nft_rbtree_flush(net, set, &rbe->priv);
833 return &rbe->priv;
834 }
835 }
836 return NULL;
837 }
838
nft_rbtree_do_walk(const struct nft_ctx * ctx,struct nft_set * set,struct nft_set_iter * iter)839 static void nft_rbtree_do_walk(const struct nft_ctx *ctx,
840 struct nft_set *set,
841 struct nft_set_iter *iter)
842 {
843 struct nft_rbtree *priv = nft_set_priv(set);
844 struct nft_rbtree_elem *rbe;
845 struct rb_node *node;
846
847 for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) {
848 rbe = rb_entry(node, struct nft_rbtree_elem, node);
849
850 if (iter->count < iter->skip)
851 goto cont;
852
853 iter->err = iter->fn(ctx, set, iter, &rbe->priv);
854 if (iter->err < 0)
855 return;
856 cont:
857 iter->count++;
858 }
859 }
860
nft_rbtree_walk(const struct nft_ctx * ctx,struct nft_set * set,struct nft_set_iter * iter)861 static void nft_rbtree_walk(const struct nft_ctx *ctx,
862 struct nft_set *set,
863 struct nft_set_iter *iter)
864 {
865 struct nft_rbtree *priv = nft_set_priv(set);
866
867 switch (iter->type) {
868 case NFT_ITER_UPDATE_CLONE:
869 if (nft_array_may_resize(set, true) < 0) {
870 iter->err = -ENOMEM;
871 break;
872 }
873 fallthrough;
874 case NFT_ITER_UPDATE:
875 lockdep_assert_held(&nft_pernet(ctx->net)->commit_mutex);
876
877 nft_rbtree_do_walk(ctx, set, iter);
878 break;
879 case NFT_ITER_READ:
880 read_lock(&priv->lock);
881 nft_rbtree_do_walk(ctx, set, iter);
882 read_unlock(&priv->lock);
883 break;
884 default:
885 iter->err = -EINVAL;
886 DEBUG_NET_WARN_ON_ONCE(1);
887 break;
888 }
889 }
890
nft_rbtree_gc_scan(struct nft_set * set)891 static void nft_rbtree_gc_scan(struct nft_set *set)
892 {
893 struct nft_rbtree *priv = nft_set_priv(set);
894 struct nft_rbtree_elem *rbe, *rbe_end = NULL;
895 struct net *net = read_pnet(&set->net);
896 u64 tstamp = nft_net_tstamp(net);
897 struct rb_node *node, *next;
898
899 for (node = rb_first(&priv->root); node ; node = next) {
900 next = rb_next(node);
901
902 rbe = rb_entry(node, struct nft_rbtree_elem, node);
903
904 /* elements are reversed in the rbtree for historical reasons,
905 * from highest to lowest value, that is why end element is
906 * always visited before the start element.
907 */
908 if (nft_rbtree_interval_end(rbe)) {
909 rbe_end = rbe;
910 continue;
911 }
912 if (!__nft_set_elem_expired(&rbe->ext, tstamp))
913 continue;
914
915 /* end element needs to be removed first, it has
916 * no timeout extension.
917 */
918 write_lock(&priv->lock);
919 if (rbe_end) {
920 nft_rbtree_gc_elem_move(net, set, priv, rbe_end);
921 rbe_end = NULL;
922 }
923
924 nft_rbtree_gc_elem_move(net, set, priv, rbe);
925 write_unlock(&priv->lock);
926 }
927
928 priv->last_gc = jiffies;
929 }
930
nft_rbtree_gc_queue(struct nft_set * set)931 static void nft_rbtree_gc_queue(struct nft_set *set)
932 {
933 struct nft_rbtree *priv = nft_set_priv(set);
934 struct nft_rbtree_elem *rbe, *rbe_end;
935 struct nft_trans_gc *gc;
936
937 if (list_empty(&priv->expired))
938 return;
939
940 gc = nft_trans_gc_alloc(set, 0, GFP_KERNEL);
941 if (!gc)
942 return;
943
944 list_for_each_entry_safe(rbe, rbe_end, &priv->expired, list) {
945 list_del(&rbe->list);
946 nft_trans_gc_elem_add(gc, rbe);
947
948 gc = nft_trans_gc_queue_sync(gc, GFP_KERNEL);
949 if (!gc)
950 return;
951 }
952
953 gc = nft_trans_gc_catchall_sync(gc);
954 nft_trans_gc_queue_sync_done(gc);
955 }
956
nft_rbtree_privsize(const struct nlattr * const nla[],const struct nft_set_desc * desc)957 static u64 nft_rbtree_privsize(const struct nlattr * const nla[],
958 const struct nft_set_desc *desc)
959 {
960 return sizeof(struct nft_rbtree);
961 }
962
nft_rbtree_init(const struct nft_set * set,const struct nft_set_desc * desc,const struct nlattr * const nla[])963 static int nft_rbtree_init(const struct nft_set *set,
964 const struct nft_set_desc *desc,
965 const struct nlattr * const nla[])
966 {
967 struct nft_rbtree *priv = nft_set_priv(set);
968
969 BUILD_BUG_ON(offsetof(struct nft_rbtree_elem, priv) != 0);
970
971 rwlock_init(&priv->lock);
972 priv->root = RB_ROOT;
973 INIT_LIST_HEAD(&priv->expired);
974
975 priv->array = NULL;
976 priv->array_next = NULL;
977
978 return 0;
979 }
980
__nft_array_free(struct nft_array * array)981 static void __nft_array_free(struct nft_array *array)
982 {
983 kvfree(array->intervals);
984 kfree(array);
985 }
986
nft_rbtree_destroy(const struct nft_ctx * ctx,const struct nft_set * set)987 static void nft_rbtree_destroy(const struct nft_ctx *ctx,
988 const struct nft_set *set)
989 {
990 struct nft_rbtree *priv = nft_set_priv(set);
991 struct nft_rbtree_elem *rbe, *next;
992 struct nft_array *array;
993 struct rb_node *node;
994
995 list_for_each_entry_safe(rbe, next, &priv->expired, list) {
996 list_del(&rbe->list);
997 nf_tables_set_elem_destroy(ctx, set, &rbe->priv);
998 }
999
1000 while ((node = priv->root.rb_node) != NULL) {
1001 rb_erase(node, &priv->root);
1002 rbe = rb_entry(node, struct nft_rbtree_elem, node);
1003 nf_tables_set_elem_destroy(ctx, set, &rbe->priv);
1004 }
1005
1006 array = rcu_dereference_protected(priv->array, true);
1007 if (array)
1008 __nft_array_free(array);
1009 if (priv->array_next)
1010 __nft_array_free(priv->array_next);
1011 }
1012
nft_rbtree_estimate(const struct nft_set_desc * desc,u32 features,struct nft_set_estimate * est)1013 static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features,
1014 struct nft_set_estimate *est)
1015 {
1016 if (desc->field_count > 1)
1017 return false;
1018
1019 if (desc->size)
1020 est->size = sizeof(struct nft_rbtree) +
1021 desc->size * sizeof(struct nft_rbtree_elem);
1022 else
1023 est->size = ~0;
1024
1025 est->lookup = NFT_SET_CLASS_O_LOG_N;
1026 est->space = NFT_SET_CLASS_O_N;
1027
1028 return true;
1029 }
1030
nft_array_free_rcu(struct rcu_head * rcu_head)1031 static void nft_array_free_rcu(struct rcu_head *rcu_head)
1032 {
1033 struct nft_array *array = container_of(rcu_head, struct nft_array, rcu_head);
1034
1035 __nft_array_free(array);
1036 }
1037
nft_rbtree_commit(struct nft_set * set)1038 static void nft_rbtree_commit(struct nft_set *set)
1039 {
1040 struct nft_rbtree *priv = nft_set_priv(set);
1041 struct nft_rbtree_elem *rbe, *prev_rbe;
1042 struct nft_array *old;
1043 u32 num_intervals = 0;
1044 struct rb_node *node;
1045
1046 /* No changes, skip, eg. elements updates only. */
1047 if (!priv->array_next)
1048 return;
1049
1050 /* GC can be performed if the binary search blob is going
1051 * to be rebuilt. It has to be done in two phases: first
1052 * scan tree and move all expired elements to the expired
1053 * list.
1054 *
1055 * Then, after blob has been re-built and published to other
1056 * CPUs, queue collected entries for freeing.
1057 */
1058 if (time_after_eq(jiffies, priv->last_gc + nft_set_gc_interval(set)))
1059 nft_rbtree_gc_scan(set);
1060
1061 /* Reverse walk to create an array from smaller to largest interval. */
1062 node = rb_last(&priv->root);
1063 if (node)
1064 prev_rbe = rb_entry(node, struct nft_rbtree_elem, node);
1065 else
1066 prev_rbe = NULL;
1067
1068 while (prev_rbe) {
1069 rbe = prev_rbe;
1070
1071 if (nft_rbtree_interval_start(rbe))
1072 priv->array_next->intervals[num_intervals].from = &rbe->ext;
1073 else if (nft_rbtree_interval_end(rbe))
1074 priv->array_next->intervals[num_intervals++].to = &rbe->ext;
1075
1076 if (num_intervals >= priv->array_next->max_intervals) {
1077 pr_warn_once("malformed interval set from userspace?");
1078 goto err_out;
1079 }
1080
1081 node = rb_prev(node);
1082 if (!node)
1083 break;
1084
1085 prev_rbe = rb_entry(node, struct nft_rbtree_elem, node);
1086
1087 /* For anonymous sets, when adjacent ranges are found,
1088 * the end element is not added to the set to pack the set
1089 * representation. Use next start element to complete this
1090 * interval.
1091 */
1092 if (nft_rbtree_interval_start(rbe) &&
1093 nft_rbtree_interval_start(prev_rbe) &&
1094 priv->array_next->intervals[num_intervals].from)
1095 priv->array_next->intervals[num_intervals++].to = &prev_rbe->ext;
1096
1097 if (num_intervals >= priv->array_next->max_intervals) {
1098 pr_warn_once("malformed interval set from userspace?");
1099 goto err_out;
1100 }
1101 }
1102
1103 if (priv->array_next->intervals[num_intervals].from)
1104 num_intervals++;
1105 err_out:
1106 priv->array_next->num_intervals = num_intervals;
1107 old = rcu_replace_pointer(priv->array, priv->array_next,
1108 lockdep_is_held(&nft_pernet(read_pnet(&set->net))->commit_mutex));
1109 priv->array_next = NULL;
1110 if (old)
1111 call_rcu(&old->rcu_head, nft_array_free_rcu);
1112
1113 /* New blob is public, queue collected entries for freeing.
1114 * call_rcu ensures elements stay around until readers are done.
1115 */
1116 nft_rbtree_gc_queue(set);
1117 }
1118
nft_rbtree_abort(const struct nft_set * set)1119 static void nft_rbtree_abort(const struct nft_set *set)
1120 {
1121 struct nft_rbtree *priv = nft_set_priv(set);
1122 struct nft_array *array_next;
1123
1124 if (!priv->array_next)
1125 return;
1126
1127 array_next = priv->array_next;
1128 priv->array_next = NULL;
1129 __nft_array_free(array_next);
1130 }
1131
nft_rbtree_gc_init(const struct nft_set * set)1132 static void nft_rbtree_gc_init(const struct nft_set *set)
1133 {
1134 struct nft_rbtree *priv = nft_set_priv(set);
1135
1136 priv->last_gc = jiffies;
1137 }
1138
1139 /* rbtree stores ranges as singleton elements, each range is composed of two
1140 * elements ...
1141 */
nft_rbtree_ksize(u32 size)1142 static u32 nft_rbtree_ksize(u32 size)
1143 {
1144 return size * 2;
1145 }
1146
1147 /* ... hide this detail to userspace. */
nft_rbtree_usize(u32 size)1148 static u32 nft_rbtree_usize(u32 size)
1149 {
1150 if (!size)
1151 return 0;
1152
1153 return size / 2;
1154 }
1155
nft_rbtree_adjust_maxsize(const struct nft_set * set)1156 static u32 nft_rbtree_adjust_maxsize(const struct nft_set *set)
1157 {
1158 struct nft_rbtree *priv = nft_set_priv(set);
1159 struct nft_rbtree_elem *rbe;
1160 struct rb_node *node;
1161 const void *key;
1162
1163 node = rb_last(&priv->root);
1164 if (!node)
1165 return 0;
1166
1167 rbe = rb_entry(node, struct nft_rbtree_elem, node);
1168 if (!nft_rbtree_interval_end(rbe))
1169 return 0;
1170
1171 key = nft_set_ext_key(&rbe->ext);
1172 if (memchr(key, 1, set->klen))
1173 return 0;
1174
1175 /* this is the all-zero no-match element. */
1176 return 1;
1177 }
1178
1179 const struct nft_set_type nft_set_rbtree_type = {
1180 .features = NFT_SET_INTERVAL | NFT_SET_MAP | NFT_SET_OBJECT | NFT_SET_TIMEOUT,
1181 .ops = {
1182 .privsize = nft_rbtree_privsize,
1183 .elemsize = offsetof(struct nft_rbtree_elem, ext),
1184 .estimate = nft_rbtree_estimate,
1185 .init = nft_rbtree_init,
1186 .destroy = nft_rbtree_destroy,
1187 .insert = nft_rbtree_insert,
1188 .remove = nft_rbtree_remove,
1189 .deactivate = nft_rbtree_deactivate,
1190 .flush = nft_rbtree_flush,
1191 .activate = nft_rbtree_activate,
1192 .commit = nft_rbtree_commit,
1193 .abort = nft_rbtree_abort,
1194 .gc_init = nft_rbtree_gc_init,
1195 .lookup = nft_rbtree_lookup,
1196 .walk = nft_rbtree_walk,
1197 .get = nft_rbtree_get,
1198 .ksize = nft_rbtree_ksize,
1199 .usize = nft_rbtree_usize,
1200 .adjust_maxsize = nft_rbtree_adjust_maxsize,
1201 },
1202 };
1203