summaryrefslogtreecommitdiffstats
path: root/src/expression.c
Commit message (Collapse)AuthorAgeFilesLines
* expression: missing line in describe command with invalid expressionPablo Neira Ayuso2024-02-131-1/+3
| | | | | | | | | | | | | | | | Before: duh@testbed:~# nft describe blah symbol expression, datatype invalid (invalid)duh@testbed:# After: duh@testbed:~# nft describe blah symbol expression, datatype invalid (invalid) duh@testbed:# Fixes: 48aca2de80a7 ("iptopt: fix crash with invalid field/type combo") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: remove xfree() and use plain free()Thomas Haller2023-11-091-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | xmalloc() (and similar x-functions) are used for allocation. They wrap malloc()/realloc() but will abort the program on ENOMEM. The meaning of xmalloc() is that it wraps malloc() but aborts on failure. I don't think x-functions should have the notion, that this were potentially a different memory allocator that must be paired with a particular xfree(). Even if the original intent was that the allocator is abstracted (and possibly not backed by standard malloc()/free()), then that doesn't seem a good idea. Nowadays libc allocators are pretty good, and we would need a very special use cases to switch to something else. In other words, it will never happen that xmalloc() is not backed by malloc(). Also there were a few places, where a xmalloc() was already "wrongly" paired with free() (for example, iface_cache_release(), exit_cookie(), nft_run_cmd_from_buffer()). Or note how pid2name() returns an allocated string from fscanf(), which needs to be freed with free() (and not xfree()). This requirement bubbles up the callers portid2name() and name_by_portid(). This case was actually handled correctly and the buffer was freed with free(). But it shows that mixing different allocators is cumbersome to get right. Of course, we don't actually have different allocators and whether to use free() or xfree() makes no different. The point is that xfree() serves no actual purpose except raising irrelevant questions about whether x-functions are correctly paired with xfree(). Note that xfree() also used to accept const pointers. It is bad to unconditionally for all deallocations. Instead prefer to use plain free(). To free a const pointer use free_const() which obviously wraps free, as indicated by the name. Signed-off-by: Thomas Haller <thaller@redhat.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: add free_const() and use it instead of xfree()Thomas Haller2023-11-091-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Almost everywhere xmalloc() and friends is used instead of malloc(). This is almost everywhere paired with xfree(). xfree() has two problems. First, it brings the wrong notion that xmalloc() should be paired with xfree(), as if xmalloc() would not use the plain malloc() allocator. In practices, xfree() just wraps free(), and it wouldn't make sense any other way. xfree() should go away. This will be addressed in the next commit. The problem addressed by this commit is that xfree() accepts a const pointer. Paired with the practice of almost always using xfree() instead of free(), all our calls to xfree() cast away constness of the pointer, regardless whether that is necessary. Declaring a pointer as const should help us to catch wrong uses. If the xfree() function always casts aways const, the compiler doesn't help. There are many places that rightly cast away const during free. But not all of them. Add a free_const() macro, which is like free(), but accepts const pointers. We should always make an intentional choice whether to use free() or free_const(). Having a free_const() macro makes this very common choice clearer, instead of adding a (void*) cast at many places. Note that we now pair xmalloc() allocations with a free() call (instead of xfree(). That inconsistency will be resolved in the next commit. Signed-off-by: Thomas Haller <thaller@redhat.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* include: include <string.h> in <nft.h>Thomas Haller2023-09-281-1/+0
| | | | | | | | <string.h> provides strcmp(), as such it's very basic and used everywhere. Signed-off-by: Thomas Haller <thaller@redhat.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* expression: cleanup expr_ops_by_type() and handle u32 inputThomas Haller2023-09-251-11/+12
| | | | | | | | | | | | | | | | | | | | Make fewer assumptions about the underlying integer type of the enum. Instead, be clear about where we have an untrusted uint32_t from netlink and an enum. Rename expr_ops_by_type() to expr_ops_by_type_u32() to make this clearer. Later we might make the enum as packed, when this starts to matter more. Also, only the code path expr_ops() wants strict validation and assert against valid enum values. Move the assertion out of __expr_ops_by_type(). Then expr_ops_by_type_u32() does not need to duplicate the handling of EXPR_INVALID. We still need to duplicate the check against EXPR_MAX, to ensure that the uint32_t value can be cast to an enum value. [ Remove cast on EXPR_MAX. --pablo ] Signed-off-by: Thomas Haller <thaller@redhat.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* datatype: fix leak and cleanup reference counting for struct datatypeThomas Haller2023-09-141-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Test `./tests/shell/run-tests.sh -V tests/shell/testcases/maps/nat_addr_port` fails: ==118== 195 (112 direct, 83 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 3 ==118== at 0x484682C: calloc (vg_replace_malloc.c:1554) ==118== by 0x48A39DD: xmalloc (utils.c:37) ==118== by 0x48A39DD: xzalloc (utils.c:76) ==118== by 0x487BDFD: datatype_alloc (datatype.c:1205) ==118== by 0x487BDFD: concat_type_alloc (datatype.c:1288) ==118== by 0x488229D: stmt_evaluate_nat_map (evaluate.c:3786) ==118== by 0x488229D: stmt_evaluate_nat (evaluate.c:3892) ==118== by 0x488229D: stmt_evaluate (evaluate.c:4450) ==118== by 0x488328E: rule_evaluate (evaluate.c:4956) ==118== by 0x48ADC71: nft_evaluate (libnftables.c:552) ==118== by 0x48AEC29: nft_run_cmd_from_buffer (libnftables.c:595) ==118== by 0x402983: main (main.c:534) I think the reference handling for datatype is wrong. It was introduced by commit 01a13882bb59 ('src: add reference counter for dynamic datatypes'). We don't notice it most of the time, because instances are statically allocated, where datatype_get()/datatype_free() is a NOP. Fix and rework. - Commit 01a13882bb59 comments "The reference counter of any newly allocated datatype is set to zero". That seems not workable. Previously, functions like datatype_clone() would have returned the refcnt set to zero. Some callers would then then set the refcnt to one, but some wouldn't (set_datatype_alloc()). Calling datatype_free() with a refcnt of zero will overflow to UINT_MAX and leak: if (--dtype->refcnt > 0) return; While there could be schemes with such asymmetric counting that juggle the appropriate number of datatype_get() and datatype_free() calls, this is confusing and error prone. The common pattern is that every alloc/clone/get/ref is paired with exactly one unref/free. Let datatype_clone() return references with refcnt set 1 and in general be always clear about where we transfer ownership (take a reference) and where we need to release it. - set_datatype_alloc() needs to consistently return ownership to the reference. Previously, some code paths would and others wouldn't. - Replace datatype_set(key, set_datatype_alloc(dtype, key->byteorder)) with a __datatype_set() with takes ownership. Fixes: 01a13882bb59 ('src: add reference counter for dynamic datatypes') Signed-off-by: Thomas Haller <thaller@redhat.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* include: include <stdlib.h> in <nft.h>Thomas Haller2023-09-111-1/+0
| | | | | | | | | | | | | | It provides malloc()/free(), which is so basic that we need it everywhere. Include via <nft.h>. The ultimate purpose is to define more things in <nft.h>. While it has not corresponding C sources, <nft.h> can contain macros and static inline functions, and is a good place for things that we shall have everywhere. Since <stdlib.h> provides malloc()/free() and size_t, that is a very basic dependency, that will be needed for that. Signed-off-by: Thomas Haller <thaller@redhat.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* include: include <std{bool,int}.h> via <nft.h>Thomas Haller2023-08-251-1/+0
| | | | | | | | | | | | | | | | | | | | There is a minimum base that all our sources will end up needing. This is what <nft.h> provides. Add <stdbool.h> and <stdint.h> there. It's unlikely that we want to implement anything, without having "bool" and "uint32_t" types available. Yes, this means the internal headers are not self-contained, with respect to what <nft.h> provides. This is the exception to the rule, and our internal headers should rely to have <nft.h> included for them. They should not include <nft.h> themselves, because <nft.h> needs always be included as first. So when an internal header would include <nft.h> it would be unnecessary, because the header is *always* included already. Signed-off-by: Thomas Haller <thaller@redhat.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: add <nft.h> header and include it as firstThomas Haller2023-08-251-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | <config.h> is generated by the configure script. As it contains our feature detection, it want to use it everywhere. Likewise, in some of our sources, we define _GNU_SOURCE. This defines the C variant we want to use. Such a define need to come before anything else, and it would be confusing if different source files adhere to a different C variant. It would be good to use autoconf's AC_USE_SYSTEM_EXTENSIONS, in which case we would also need to ensure that <config.h> is always included as first. Instead of going through all source files and include <config.h> as first, add a new header "include/nft.h", which is supposed to be included in all our sources (and as first). This will also allow us later to prepare some common base, like include <stdbool.h> everywhere. We aim that headers are self-contained, so that they can be included in any order. Which, by the way, already didn't work because some headers define _GNU_SOURCE, which would only work if the header gets included as first. <nft.h> is however an exception to the rule: everything we compile shall rely on having <nft.h> header included as first. This applies to source files (which explicitly include <nft.h>) and to internal header files (which are only compiled indirectly, by being included from a source file). Note that <config.h> has no include guards, which is at least ugly to include multiple times. It doesn't cause problems in practice, because it only contains defines and the compiler doesn't warn about redefining a macro with the same value. Still, <nft.h> also ensures to include <config.h> exactly once. Signed-off-by: Thomas Haller <thaller@redhat.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* expression: define .clone for catchall set elementPablo Neira Ayuso2023-06-301-2/+13
| | | | | | | Otherwise reuse of catchall set element expression in variable triggers a null-pointer dereference. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: fix enum/integer mismatchesFlorian Westphal2023-04-291-1/+1
| | | | | | | | | | | | | | | | | | | gcc 13 complains about type confusion: cache.c:1178:5: warning: conflicting types for 'nft_cache_update' due to enum/integer mismatch; have 'int(struct nft_ctx *, unsigned int, struct list_head *, const struct nft_cache_filter *)' [-Wenum-int-mismatch] cache.h:74:5: note: previous declaration of 'nft_cache_update' with type 'int(struct nft_ctx *, enum cmd_ops, struct list_head *, const struct nft_cache_filter *)' Same for: rule.c:1915:13: warning: conflicting types for 'obj_type_name' due to enum/integer mismatch; have 'const char *(enum stmt_types)' [-Wenum-int-mismatch] 1915 | const char *obj_type_name(enum stmt_types type) | ^~~~~~~~~~~~~ expression.c:1543:24: warning: conflicting types for 'expr_ops_by_type' due to enum/integer mismatch; have 'const struct expr_ops *(uint32_t)' {aka 'const struct expr_ops *(unsigned int)'} [-Wenum-int-mismatch] 1543 | const struct expr_ops *expr_ops_by_type(uint32_t value) | ^~~~~~~~~~~~~~~~ Convert to the stricter type (enum) where possible. Signed-off-by: Florian Westphal <fw@strlen.de>
* src: add vxlan matching supportPablo Neira Ayuso2023-01-021-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch adds the initial infrastructure to support for inner header tunnel matching and its first user: vxlan. A new struct proto_desc field for payload and meta expression to specify that the expression refers to inner header matching is used. The existing codebase to generate bytecode is fully reused, allowing for reusing existing supported layer 2, 3 and 4 protocols. Syntax requires to specify vxlan before the inner protocol field: ... vxlan ip protocol udp ... vxlan ip saddr 1.2.3.0/24 This also works with concatenations and anonymous sets, eg. ... vxlan ip saddr . vxlan ip daddr { 1.2.3.4 . 4.3.2.1 } You have to restrict vxlan matching to udp traffic, otherwise it complains on missing transport protocol dependency, e.g. ... udp dport 4789 vxlan ip daddr 1.2.3.4 The bytecode that is generated uses the new inner expression: # nft --debug=netlink add rule netdev x y udp dport 4789 vxlan ip saddr 1.2.3.4 netdev x y [ meta load l4proto => reg 1 ] [ cmp eq reg 1 0x00000011 ] [ payload load 2b @ transport header + 2 => reg 1 ] [ cmp eq reg 1 0x0000b512 ] [ inner type 1 hdrsize 8 flags f [ meta load protocol => reg 1 ] ] [ cmp eq reg 1 0x00000008 ] [ inner type 1 hdrsize 8 flags f [ payload load 4b @ network header + 12 => reg 1 ] ] [ cmp eq reg 1 0x04030201 ] JSON support is not included in this patch. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: allow anon set concatenation with ether and vlanFlorian Westphal2022-08-051-2/+15
| | | | | | | | | | | | | | | | | | | | | | | vlan id uses integer type (which has a length of 0). Using it was possible, but listing would assert: python: mergesort.c:24: concat_expr_msort_value: Assertion `ilen > 0' failed. There are two reasons for this. First reason is that the udata/typeof information lacks the 'vlan id' part, because internally this is 'payload . binop(payload AND mask)'. binop lacks an udata store. It makes little sense to store it, 'typeof' keyword expects normal match syntax. So, when storing udata, store the left hand side of the binary operation, i.e. the load of the 2-byte key. With that resolved, delinerization could work, but concat_elem_expr() would splice 12 bits off the elements value, but it should be 16 (on a byte boundary). Signed-off-by: Florian Westphal <fw@strlen.de>
* src: restore interval sets work with string datatypesPablo Neira Ayuso2022-04-131-6/+2
| | | | | | | | | | | Switch byteorder of string datatypes to host byteorder. Partial revert of ("src: make interval sets work with string datatypes") otherwise new interval code complains with conflicting intervals. testcases/sets/sets_with_ifnames passes fine again. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: make interval sets work with string datatypesFlorian Westphal2022-04-131-2/+6
| | | | | | | | | | | | | | | | | | | Allows to interface names in interval sets: table inet filter { set s { type ifname flags interval elements = { eth*, foo } } Concatenations are not yet supported, also, listing is broken, those strings will not be printed back because the values will remain in big-endian order. Followup patch will extend segtree to translate this back to host byte order. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* evaluate: keep prefix expression lengthFlorian Westphal2022-04-131-0/+1
| | | | | | | | | | | | | Else, range_expr_value_high() will see a 0 length when doing: mpz_init_bitmask(tmp, expr->len - expr->prefix_len); This wasn't a problem so far because prefix expressions generated from "string*" were never passed down to the prefix->range conversion functions. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: allow to use typeof of raw expressions in set declarationPablo Neira Ayuso2022-03-291-2/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Use the dynamic datatype to allocate an instance of TYPE_INTEGER and set length and byteorder. Add missing information to the set userdata area for raw payload expressions which allows to rebuild the set typeof from the listing path. A few examples: - With anonymous sets: nft add rule x y ip saddr . @ih,32,32 { 1.1.1.1 . 0x14, 2.2.2.2 . 0x1e } - With named sets: table x { set y { typeof ip saddr . @ih,32,32 elements = { 1.1.1.1 . 0x14 } } } Incremental updates are also supported, eg. nft add element x y { 3.3.3.3 . 0x28 } expr_evaluate_concat() is used to evaluate both set key definitions and set key values, using two different function might help to simplify this code in the future. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* expression: typeof verdict needs verdict datatypePablo Neira Ayuso2022-03-291-0/+1
| | | | | | | | | | | | | | | | | Otherwise listing breaks showing [invalid type] notice. # nft list ruleset table inet x { map y { typeof ip saddr : verdict elements = { 1.1.1.1 : 0x1010101 [invalid type] } } } Update tests to cover this usecase. Fixes: 4ab1e5e60779 ("src: allow use of 'verdict' in typeof definitions") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: merge several selectors with different verdict into verdict mapPablo Neira Ayuso2022-01-151-2/+28
| | | | | | | | | | | | | Transform: ip saddr 1.1.1.1 ip daddr 2.2.2.2 accept ip saddr 2.2.2.2 ip daddr 3.3.3.3 drop into: ip saddr . ip daddr vmap { 1.1.1.1 . 2.2.2.2 : accept, 2.2.2.2 . 3.3.3.3 : drop } Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: remove '$' in symbol_expr_printPablo Neira Ayuso2022-01-151-2/+1
| | | | | | | This is used in --debug=eval mode to annotate symbols that have not yet been evaluated, remove it. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* iptopt: fix crash with invalid field/type comboFlorian Westphal2021-12-071-4/+4
| | | | | | | | | | | | | | | % nft describe ip option rr value segmentation fault after this fix, this exits with 'Error: unknown ip option type/field'. Problem is that 'rr' doesn't have a value template, so the template struct is all-zeroes, so we crash when trying to use tmpl->dtype (its NULL). Furthermore, expr_describe tries to print expr->identifier but expr is exthdr, not symbol: ->identifier contains garbage. Signed-off-by: Florian Westphal <fw@strlen.de>
* expression: missing != in flagcmp expression print functionPablo Neira Ayuso2021-07-271-1/+6
| | | | | | | Missing != when printing the expression. Fixes: c3d57114f119 ("parser_bison: add shortcut syntax for matching flags without binary operations") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* json: catchall element supportFlorian Westphal2021-06-021-0/+1
| | | | | | | Treat '*' as catchall element, not as a symbol. Also add missing json test cases for wildcard set support. Signed-off-by: Florian Westphal <fw@strlen.de>
* expression: display an error on unknown datatypePablo Neira Ayuso2021-05-241-1/+4
| | | | | | | | # nft describe foo datatype foo is invalid Fixes: 21cbab5b6ffe ("expression: extend 'nft describe' to allow listing data types") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* parser_bison: add shortcut syntax for matching flags without binary operationsPablo Neira Ayuso2021-05-161-0/+51
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch adds the following shortcut syntax: expression flags / flags instead of: expression and flags == flags For example: tcp flags syn,ack / syn,ack,fin,rst ^^^^^^^ ^^^^^^^^^^^^^^^ value mask instead of: tcp flags and (syn|ack|fin|rst) == syn|ack The second list of comma-separated flags represents the mask which are examined and the first list of comma-separated flags must be set. You can also use the != operator with this syntax: tcp flags != fin,rst / syn,ack,fin,rst This shortcut is based on the prefix notation, but it is also similar to the iptables tcp matching syntax. This patch introduces the flagcmp expression to print the tcp flags in this new notation. The delinearize path transforms the binary expression to this new flagcmp expression whenever possible. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: add set element catch-all supportPablo Neira Ayuso2021-05-111-0/+24
| | | | | | | | | | | | | | | | | | | | | | | | | Add a catchall expression (EXPR_SET_ELEM_CATCHALL). Use the asterisk (*) to represent the catch-all set element, e.g. table x { set y { type ipv4_addr counter elements = { 1.2.3.4 counter packets 0 bytes 0, * counter packets 0 bytes 0 } } } Special handling for segtree: zap the catch-all element from the set element list and re-add it after processing. Remove wildcard_expr deadcode in src/parser_bison.y This patch also adds several tests for the tests/py and tests/shell infrastructures. Acked-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: add datatype->describe()Pablo Neira Ayuso2021-03-251-0/+2
| | | | | | | | | | | | As an alternative to print the datatype values when no symbol table is available. Use it to print protocols available via getprotobynumber() which actually refers to /etc/protocols. Not very efficient, getprotobynumber() causes a series of open()/close() calls on /etc/protocols, but this is called from a non-critical path. Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1503 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* expression: memleak in verdict_expr_parse_udata()Pablo Neira Ayuso2021-03-051-1/+1
| | | | | | | Remove unnecessary verdict_expr_alloc() invocation. Fixes: 4ab1e5e60779 ("src: allow use of 'verdict' in typeof definitions") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: allow use of 'verdict' in typeof definitionsFlorian Westphal2021-02-221-0/+17
| | | | | | | | | | | | | | | 'verdict' cannot be used as part of a map typeof-based key definition, its a datatype and not an expression, e.g.: typeof iifname . ip protocol . th dport : verdic ... will fail. Make the parser convert a 'verdict' symbol to a verdict expression and allow to store its presence as part of the typeof key definition. Reported-by: Frank Myhr <fmyhr@fhmtech.com> Signed-off-by: Florian Westphal <fw@strlen.de>
* src: add negation match on singleton bitmask valuePablo Neira Ayuso2021-02-051-0/+1
| | | | | | | | | | | | | | | | | This patch provides a shortcut for: ct status and dnat == 0 which allows to check for the packet whose dnat bit is unset: # nft add rule x y ct status ! dnat counter This operation is only available for expression with a bitmask basetype, eg. # nft describe ct status ct expression, datatype ct_status (conntrack status) (basetype bitmask, integer), 32 bits Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: add set element multi-statement supportPablo Neira Ayuso2020-12-181-5/+13
| | | | | | | | Extend the set element infrastructure to support for several statements. This patch places the statements right after the key when printing it. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: context tracking for multiple transport protocolsPablo Neira Ayuso2020-09-151-3/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch extends the protocol context infrastructure to track multiple transport protocols when they are specified from sets. This removes errors like: "transport protocol mapping is only valid after transport protocol match" when invoking: # nft add rule x z meta l4proto { tcp, udp } dnat to 1.1.1.1:80 This patch also catches conflicts like: # nft add rule x z ip protocol { tcp, udp } tcp dport 20 dnat to 1.1.1.1:80 Error: conflicting protocols specified: udp vs. tcp add rule x z ip protocol { tcp, udp } tcp dport 20 dnat to 1.1.1.1:80 ^^^^^^^^^ and: # nft add rule x z meta l4proto { tcp, udp } tcp dport 20 dnat to 1.1.1.1:80 Error: conflicting protocols specified: udp vs. tcp add rule x z meta l4proto { tcp, udp } tcp dport 20 dnat to 1.1.1.1:80 ^^^^^^^^^ Note that: - the singleton protocol context tracker is left in place until the existing users are updated to use this new multiprotocol tracker. Moving forward, it would be good to consolidate things around this new multiprotocol context tracker infrastructure. - link and network layers are not updated to use this infrastructure yet. The code that deals with vlan conflicts relies on forcing protocol context updates to the singleton protocol base. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: use expression to store the log prefixPablo Neira Ayuso2020-07-081-0/+9
| | | | | | Intsead of using an array of char. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* datatype: fix double-free resulting in use-after-free in datatype_freeMichael Braun2020-05-011-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | nft list table bridge t table bridge t { set s4 { typeof ip saddr . ip daddr elements = { 1.0.0.1 . 2.0.0.2 } } } ================================================================= ==24334==ERROR: AddressSanitizer: heap-use-after-free on address 0x6080000000a8 at pc 0x7fe0e67df0ad bp 0x7ffff83e88c0 sp 0x7ffff83e88b8 READ of size 4 at 0x6080000000a8 thread T0 #0 0x7fe0e67df0ac in datatype_free nftables/src/datatype.c:1110 #1 0x7fe0e67e2092 in expr_free nftables/src/expression.c:89 #2 0x7fe0e67a855e in set_free nftables/src/rule.c:359 #3 0x7fe0e67b2f3e in table_free nftables/src/rule.c:1263 #4 0x7fe0e67a70ce in __cache_flush nftables/src/rule.c:299 #5 0x7fe0e67a71c7 in cache_release nftables/src/rule.c:305 #6 0x7fe0e68dbfa9 in nft_ctx_free nftables/src/libnftables.c:292 #7 0x55f00fbe0051 in main nftables/src/main.c:469 #8 0x7fe0e553309a in __libc_start_main ../csu/libc-start.c:308 #9 0x55f00fbdd429 in _start (nftables/src/.libs/nft+0x9429) 0x6080000000a8 is located 8 bytes inside of 96-byte region [0x6080000000a0,0x608000000100) freed by thread T0 here: #0 0x7fe0e6e70fb0 in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xe8fb0) #1 0x7fe0e68b8122 in xfree nftables/src/utils.c:29 #2 0x7fe0e67df2e5 in datatype_free nftables/src/datatype.c:1117 #3 0x7fe0e67e2092 in expr_free nftables/src/expression.c:89 #4 0x7fe0e67a83fe in set_free nftables/src/rule.c:356 #5 0x7fe0e67b2f3e in table_free nftables/src/rule.c:1263 #6 0x7fe0e67a70ce in __cache_flush nftables/src/rule.c:299 #7 0x7fe0e67a71c7 in cache_release nftables/src/rule.c:305 #8 0x7fe0e68dbfa9 in nft_ctx_free nftables/src/libnftables.c:292 #9 0x55f00fbe0051 in main nftables/src/main.c:469 #10 0x7fe0e553309a in __libc_start_main ../csu/libc-start.c:308 previously allocated by thread T0 here: #0 0x7fe0e6e71330 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xe9330) #1 0x7fe0e68b813d in xmalloc nftables/src/utils.c:36 #2 0x7fe0e68b8296 in xzalloc nftables/src/utils.c:65 #3 0x7fe0e67de7d5 in dtype_alloc nftables/src/datatype.c:1065 #4 0x7fe0e67df862 in concat_type_alloc nftables/src/datatype.c:1146 #5 0x7fe0e67ea852 in concat_expr_parse_udata nftables/src/expression.c:954 #6 0x7fe0e685dc94 in set_make_key nftables/src/netlink.c:718 #7 0x7fe0e685e177 in netlink_delinearize_set nftables/src/netlink.c:770 #8 0x7fe0e685f667 in list_set_cb nftables/src/netlink.c:895 #9 0x7fe0e4f95a03 in nftnl_set_list_foreach src/set.c:904 SUMMARY: AddressSanitizer: heap-use-after-free nftables/src/datatype.c:1110 in datatype_free Shadow bytes around the buggy address: 0x0c107fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c107fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c107fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c107fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c107fff8000: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd =>0x0c107fff8010: fa fa fa fa fd[fd]fd fd fd fd fd fd fd fd fd fd 0x0c107fff8020: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd 0x0c107fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c107fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c107fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c107fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==24334==ABORTING Signed-off-by: Michael Braun <michael-dev@fami-braun.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* concat: provide proper dtype when parsing typeof udataFlorian Westphal2020-04-011-5/+7
| | | | | | | | | | | | | | | | Pablo reports following list bug: table ip foo { map whitelist { typeof ip saddr . ip daddr : meta mark elements = { 0x0 [invalid type] . 0x0 [invalid type] : 0x00000001, 0x0 [invalid type] . 0x0 [invalid type] : 0x00000002 } } } Problem is that concat provided 'invalid' dtype. Reported-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
* expressions: concat: add typeof supportFlorian Westphal2020-02-261-0/+136
| | | | | | | | | | | | | | | | | | | | | Previous patches allow to pass concatenations as the mapped-to data type. This doesn't work with typeof() because the concat expression has no support to store the typeof data in the kernel, leading to: map t2 { typeof numgen inc mod 2 : ip daddr . tcp dport being shown as type 0 : ipv4_addr . inet_service ... which can't be parsed back by nft. This allows the concat expression to store the sub-expressions in set of nested attributes. Signed-off-by: Florian Westphal <fw@strlen.de>
* expression: use common code for expr_ops/expr_ops_by_typeFlorian Westphal2020-02-231-20/+15
| | | | | | | Useless duplication. Also, this avoids bloating expr_ops_by_type() when it needs to cope with more expressions. Signed-off-by: Florian Westphal <fw@strlen.de>
* xfrm: add parse and build userdata interfacePablo Neira Ayuso2019-12-171-0/+1
| | | | | | | Add support for meta userdata area. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
* fib: add parse and build userdata interfacePablo Neira Ayuso2019-12-171-0/+1
| | | | | | | Add support for meta userdata area. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
* rt: add parse and build userdata interfacePablo Neira Ayuso2019-12-171-0/+1
| | | | | | | Add support for meta userdata area. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
* hash: add parse and build userdata interfacePablo Neira Ayuso2019-12-171-0/+1
| | | | | | | Add support for meta userdata area. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
* numgen: add parse and build userdata interfacePablo Neira Ayuso2019-12-171-0/+1
| | | | | | | Add support for meta userdata area. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
* ct: add parse and build userdata interfacePablo Neira Ayuso2019-12-171-0/+1
| | | | | | | Add support for meta userdata area. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
* osf: add parse and build userdata interfacePablo Neira Ayuso2019-12-171-0/+1
| | | | | | | Add support for meta userdata area. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
* socket: add parse and build userdata interfacePablo Neira Ayuso2019-12-171-0/+1
| | | | | | | Add support for meta userdata area. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
* exthdr: add parse and build userdata interfacePablo Neira Ayuso2019-12-171-0/+1
| | | | | | | Add support for meta userdata area. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
* meta: add parse and build userdata interfacePablo Neira Ayuso2019-12-171-2/+2
| | | | | | | Add support for meta userdata area. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
* expr: add expr_ops_by_type()Pablo Neira Ayuso2019-12-161-0/+12
| | | | | | | Fetch expression operation from the expression type. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
* src: store expr, not dtype to track data in setsFlorian Westphal2019-12-161-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This will be needed once we add support for the 'typeof' keyword to handle maps that could e.g. store 'ct helper' "type" values. Instead of: set foo { type ipv4_addr . mark; this would allow set foo { typeof(ip saddr) . typeof(ct mark); (exact syntax TBD). This would be needed to allow sets that store variable-sized data types (string, integer and the like) that can't be used at at the moment. Adding special data types for everything is problematic due to the large amount of different types needed. For anonymous sets, e.g. "string" can be used because the needed size can be inferred from the statement, e.g. 'osf name { "Windows", "Linux }', but in case of named sets that won't work because 'type string' lacks the context needed to derive the size information. With 'typeof(osf name)' the context is there, but at the moment it won't help because the expression is discarded instantly and only the data type is retained. Signed-off-by: Florian Westphal <fw@strlen.de>
* src: add and use `set_is_meter` helperJeremy Sowden2019-11-061-7/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The sets constructed for meters are flagged as anonymous and dynamic. However, in some places there are only checks that they are dynamic, which can lead to normal sets being classified as meters. For example: # nft add table t # nft add set t s { type ipv4_addr; size 256; flags dynamic,timeout; } # nft add chain t c # nft add rule t c tcp dport 80 meter m size 128 { ip saddr limit rate 10/second } # nft list meters table ip t { set s { type ipv4_addr size 256 flags dynamic,timeout } meter m { type ipv4_addr size 128 flags dynamic } } # nft list meter t m table ip t { meter m { type ipv4_addr size 128 flags dynamic } } # nft list meter t s Error: No such file or directory list meter t s ^ Add a new helper `set_is_meter` and use it wherever there are checks for meters. Signed-off-by: Jeremy Sowden <jeremy@azazel.net> Signed-off-by: Florian Westphal <fw@strlen.de>