nftables-1.0.9-8.el9
* Wed Jul 22 2026 Phil Sutter <psutter@redhat.com> [1.0.9-8.el9]
- spec: Update expected test suite results (Phil Sutter) [RHEL-190549]
- tests: monitor: Fix for out-of-path call (Phil Sutter) [RHEL-190549]
- tests: monitor: Excercise all syntaxes and variants by default (Phil Sutter) [RHEL-190549]
- tests: monitor: Test JSON echo mode as well (Phil Sutter) [RHEL-190549]
- tests: monitor: Become $PWD agnostic (Phil Sutter) [RHEL-190549]
- tests: monitor: Run in own netns (Phil Sutter) [RHEL-190549]
- tests: monitor: Label diffs to help users (Phil Sutter) [RHEL-190549]
- tests: monitor: Extend testcases a bit (Phil Sutter) [RHEL-190549]
- tests: monitor: enclose device names in quotes (Phil Sutter) [RHEL-190549]
- json: Dump flowtable hook spec only if present (Phil Sutter) [RHEL-190549]
- tests: py: Fix some JSON equivalents (Phil Sutter) [RHEL-190549]
- rule: constify set_is_non_concat_range() (Phil Sutter) [RHEL-190549]
- datatype: don't return a const string from cgroupv2_get_path() (Phil Sutter) [RHEL-190549]
- tests: py: Fix --keep test runner option (Phil Sutter) [RHEL-190549]
- segtree: fix get element command with open intervals (Phil Sutter) [RHEL-190549]
- segtree: replace default case by specific types in get_set_intervals() (Phil Sutter) [RHEL-190549]
- src: remove EXPR_SET_ELEM in range_expr_value_{low,high}() (Phil Sutter) [RHEL-190549]
- segtree: rename set_elem_add() to set_elem_expr_add() (Phil Sutter) [RHEL-190549]
- parser_json: fix map/set type confusion crash in map statement parser (Phil Sutter) [RHEL-190549]
- cache: honor -c/--check for reset commands (Phil Sutter) [RHEL-190549]
- tests: py: osf is ip-only (Phil Sutter) [RHEL-190549]
- tests: py: print the file name as intended (Phil Sutter) [RHEL-190549]
- tests: py: don't use a fixed filename (Phil Sutter) [RHEL-190549]
- mnl: Fix ordering of hooks in 'list hooks' output (Phil Sutter) [RHEL-190549]
- segtree: Fix for variable-sized object may not be initialized (Phil Sutter) [RHEL-190549]
- cache: Filter for table when listing flowtables (Phil Sutter) [RHEL-190549]
- cache: Filter for table when listing sets or maps (Phil Sutter) [RHEL-190549]
- cache: Respect family in all list commands (Phil Sutter) [RHEL-190549]
- cache: Include chains, flowtables and objects in netlink debug output (Phil Sutter) [RHEL-190549]
- cache: Relax chain_cache_dump filter application (Phil Sutter) [RHEL-190549]
- parser_bison: add range check for synproxy wscale (Phil Sutter) [RHEL-190549]
- json: complete multi-statement set element support (Phil Sutter) [RHEL-190549]
- segtree: Fix range aggregation on Big Endian (Phil Sutter) [RHEL-190549]
- mergesort: Align concatenation sort order with Big Endian (Phil Sutter) [RHEL-190549]
- mergesort: Fix sorting of string values (Phil Sutter) [RHEL-190549]
- tests: py: any/tcpopt.t.json: Fix JSON equivalent (Phil Sutter) [RHEL-190549]
- expression: expr_build_udata_recurse should recurse (Phil Sutter) [RHEL-190549]
- expression: propagate key datatype for anonymous sets (Phil Sutter) [RHEL-190549]
- netlink_delinearize: also consider exthdr type when trimming binops (Phil Sutter) [RHEL-190549]
- tcpopt: add symbol table for mptcp suboptions (Phil Sutter) [RHEL-190549]
- monitor: fix memleak in setelem cb (Phil Sutter) [RHEL-190549]
- tests: json_echo: Drop rule handle before multi-add (Phil Sutter) [RHEL-190549]
- rule: skip CMD_OBJ_SETELEMS with no elements after set flush (Phil Sutter) [RHEL-190549]
- doc: libnftables-json: Describe RULESET object (Phil Sutter) [RHEL-190549]
- doc: don't suggest to disable GSO (Phil Sutter) [RHEL-190549]
- tests: py: Implement payload_record() (Phil Sutter) [RHEL-190549]
- tests: py: inet/osf.t: Fix element ordering in JSON equivalents (Phil Sutter) [RHEL-190549]
- tests: py: Do not rely upon '[end]' marker (Phil Sutter) [RHEL-190549]
- tests: py: Fix for using wrong payload path (Phil Sutter) [RHEL-190549]
- tests: py: any/ct.t.json.output: Drop leftover entry (Phil Sutter) [RHEL-190549]
- datatype: Fix boolean type on Big Endian (Phil Sutter) [RHEL-190549]
- optimize: Fix verdict expression comparison (Phil Sutter) [RHEL-190549]
- src: parser_json: fix format string bugs (Phil Sutter) [RHEL-190549]
- doc: fix tcpdump example (Phil Sutter) [RHEL-190549]
- tests: py: objects.t: must use input, not output (Phil Sutter) [RHEL-190549]
- fib: Fix for existence check on Big Endian (Phil Sutter) [RHEL-190549]
- tests: Prepare exit codes for automake (Phil Sutter) [RHEL-190549]
- monitor: Inform JSON printer when reporting an object delete event (Phil Sutter) [RHEL-190549]
- monitor: Recognize flowtable add/del events (Phil Sutter) [RHEL-190549]
- tests: monitor: Fix regex collecting expected echo output (Phil Sutter) [RHEL-190549]
- monitor: Quote device names in chain declarations, too (Phil Sutter) [RHEL-190549]
- mnl: continue on ENOBUFS errors when processing batch (Phil Sutter) [RHEL-190549]
- tests: monitor: Fix for flag arrays in JSON output (Phil Sutter) [RHEL-190549]
- mnl: silence compiler warning (Phil Sutter) [RHEL-190549]
- fib: restore JSON output for relational expressions (Phil Sutter) [RHEL-190549]
- src: ensure chain policy evaluation when specified (Phil Sutter) [RHEL-190549]
- segtree: incorrect type when aggregating concatenated set ranges (Phil Sutter) [RHEL-190549]
- json: Do not reduce single-item arrays on output (Phil Sutter) [RHEL-190549]
- tests: py: Fix tests added for 'icmpv6 taddr' support (Phil Sutter) [RHEL-190549]
- tests: py: Drop stale entry from ip/snat.t.payload (Phil Sutter) [RHEL-190549]
- tests: py: Drop stale entries from ip6/{ct,meta}.t.json (Phil Sutter) [RHEL-190549]
- tests: py: Drop stale entry from ip/snat.t.json (Phil Sutter) [RHEL-190549]
- tests: py: Drop duplicate test from inet/vxlan.t (Phil Sutter) [RHEL-190549]
- tests: py: Drop stale entry from inet/tcp.t.json (Phil Sutter) [RHEL-190549]
- tests: py: Drop duplicate test from inet/gretap.t (Phil Sutter) [RHEL-190549]
- tests: py: Drop duplicate test from inet/gre.t (Phil Sutter) [RHEL-190549]
- tests: py: Drop duplicate test from inet/geneve.t (Phil Sutter) [RHEL-190549]
- tests: py: Drop stale entries since redundant test case removal (Phil Sutter) [RHEL-190549]
- src: netlink: netlink_delinearize_table() may return NULL (Phil Sutter) [RHEL-190549]
- doc: nft.8: Minor NAT STATEMENTS section review (Phil Sutter) [RHEL-190549]
- mnl: Call mnl_attr_nest_end() just once (Phil Sutter) [RHEL-190549]
- evaluate: validate set expression type before accessing flags (Phil Sutter) [RHEL-190549]
- rule: print chain and flowtable devices in quotes (Phil Sutter) [RHEL-190549]
- tests: py: re-enables nft-test.py to load the local nftables.py (Phil Sutter) [RHEL-190549]
- fib: allow to use it in set statements (Phil Sutter) [RHEL-190549]
- fib: allow to check if route exists in maps (Phil Sutter) [RHEL-190549]
- tests: shell: Fix ifname_based_hooks feature check (Phil Sutter) [RHEL-190549]
- json: reject too long interface names (Phil Sutter) [RHEL-190549]
- tests/py: clean up set backend support fallout (Phil Sutter) [RHEL-190549]
- cache: assert name is non-nul when looking up (Phil Sutter) [RHEL-190549]
- parser_bison: only reset by name is supported by now (Phil Sutter) [RHEL-190549]
- rule: skip fuzzy lookup if object name is not available (Phil Sutter) [RHEL-190549]
- parser_bison: allow delete command with map via handle (Phil Sutter) [RHEL-190549]
- debug: include kernel set information on cache fill (Phil Sutter) [RHEL-190549]
- tests/py: prepare for set debug change (Phil Sutter) [RHEL-190549]
- src: BASECHAIN flag no longer implies presence of priority expression (Phil Sutter) [RHEL-190549]
- netlink: Avoid crash upon missing NFTNL_OBJ_CT_TIMEOUT_ARRAY attribute (Phil Sutter) [RHEL-190549]
- tests: py: Properly fix JSON equivalents for netdev/reject.t (Phil Sutter) [RHEL-190549]
- tests: shell: Adjust to ifname-based hooks (Phil Sutter) [RHEL-190549]
- tests: shell: combine dormant flag with netdevice removal (Phil Sutter) [RHEL-190549]
- tests: monitor: Fix for single flag array avoidance (Phil Sutter) [RHEL-190549]
- netlink: Do not allocate a bogus flowtable priority expr (Phil Sutter) [RHEL-190549]
- netlink: Fix for potential crash parsing a flowtable (Phil Sutter) [RHEL-190549]
- json: work around fuzzer-induced assert crashes (Phil Sutter) [RHEL-190549]
- json: prevent null deref if chain->policy is not set (Phil Sutter) [RHEL-190549]
- tests: py: fix json single-flag output for fib & synproxy (Phil Sutter) [RHEL-190549]
- tests: shell: check for features not available in 5.4 (Phil Sutter) [RHEL-190549]
- netlink: Avoid potential NULL-ptr deref parsing set elem expressions (Phil Sutter) [RHEL-190549]
- netlink: Catch unknown types when deserializing objects (Phil Sutter) [RHEL-190549]
- json: Introduce json_add_array_new() (Phil Sutter) [RHEL-190549]
- json: Fix for memleak in __binop_expr_json (Phil Sutter) [RHEL-190549]
- json: Accept more than two operands in binary expressions (Phil Sutter) [RHEL-190549]
- json: Print single fib flag as non-array (Phil Sutter) [RHEL-190549]
- tests: shell: Add test case for JSON 'flags' arrays (Phil Sutter) [RHEL-190549]
- json: Print single set flag as non-array (Phil Sutter) [RHEL-190549]
- json: Print single synproxy flags as non-array (Phil Sutter) [RHEL-190549]
- parser_json: Introduce parse_flags_array() (Phil Sutter) [RHEL-190549]
- doc: Fix typo in nat statement 'prefix' description (Phil Sutter) [RHEL-190549]
- netlink: bogus concatenated set ranges with netlink message overrun (Phil Sutter) [RHEL-190549]
- parser_bison: add selector_expr rule to restrict typeof_expr (Phil Sutter) [RHEL-190549]
- optimize: invalidate merge in case of duplicated key in set/map (Phil Sutter) [RHEL-190549]
- evaluate: bail out if ct saddr/daddr dependency cannot be inserted (Phil Sutter) [RHEL-190549]
- parser_json: bail out on malformed statement in set (Phil Sutter) [RHEL-190549]
- parser_json: reject empty jump/goto chain (Phil Sutter) [RHEL-190549]
- parser_json: allow statement stateful statement only in set elements (Phil Sutter) [RHEL-190549]
- cache: prevent possible crash rule filter is NULL (Phil Sutter) [RHEL-190549]
- optimize: expand expression list when merging into concatenation (Phil Sutter) [RHEL-190549]
- cache: don't crash when filter is NULL (Phil Sutter) [RHEL-190549]
- evaluate: only allow stateful statements in set and map definitions (Phil Sutter) [RHEL-190549]
- evaluate: compact STMT_F_STATEFUL checks (Phil Sutter) [RHEL-190549]
- json: don't BUG when asked to list synproxies (Phil Sutter) [RHEL-190549]
- optimize: incorrect comparison for reject statement (Phil Sutter) [RHEL-190549]
- optimize: compact bitmask matching in set/map (Phil Sutter) [RHEL-190549]
- tests: shell: missing ct count elements in new set_stmt test (Phil Sutter) [RHEL-190549]
- evaluate: don't update cache for anonymous chains (Phil Sutter) [RHEL-190549]
- json: make sure timeout list is initialised (Phil Sutter) [RHEL-190549]
- parser_bison: consolidate connlimit grammar rule for set elements (Phil Sutter) [RHEL-190549]
- parser_bison: consolidate last grammar rule for set elements (Phil Sutter) [RHEL-190549]
- parser_bison: consolidate quota grammar rule for set elements (Phil Sutter) [RHEL-190549]
- parser_bison: consolidate limit grammar rule for set elements (Phil Sutter) [RHEL-190549]
- parser_bison: consolidate counter grammar rule for set elements (Phil Sutter) [RHEL-190549]
- tests: shell: extend coverage for set element statements (Phil Sutter) [RHEL-190549]
- evaluate: fix assertion failure with malformed map definitions (Phil Sutter) [RHEL-190549]
- evaluate: don't allow nat map with specified protocol (Phil Sutter) [RHEL-190549]
- parser_bison: reject non-serializeable typeof expressions (Phil Sutter) [RHEL-190549]
- netlink: fix stack buffer overrun when emitting ranged expressions (Phil Sutter) [RHEL-190549]
- src: print set element with multi-word description in single one line (Phil Sutter) [RHEL-190549]
- tests: shell: detach synproxy test (Phil Sutter) [RHEL-190549]
- src: do not merge a set with a erroneous one (Phil Sutter) [RHEL-190549]
- segtree: incomplete output in get element command with maps (Phil Sutter) [RHEL-190549]
- evaluate: release existing datatype when evaluating unary expression (Phil Sutter) [RHEL-190549]
- segtree: fix string data initialisation (Phil Sutter) [RHEL-190549]
- payload: honor inner payload description in payload_expr_cmp() (Phil Sutter) [RHEL-190549]
- payload: return early if dependency is not a payload expression (Phil Sutter) [RHEL-190549]
- evaluate: optimize zero length range (Phil Sutter) [RHEL-190549]
- fib: Change data type of fib oifname to "ifname" (Phil Sutter) [RHEL-190549]
- evaluate: auto-merge is only available for singleton interval sets (Phil Sutter) [RHEL-190549]
- parser_bison: compact and simplify list and reset syntax (Phil Sutter) [RHEL-190549]
- parser_bison: turn redundant ip option type field match into boolean (Phil Sutter) [RHEL-190549]
- datatype: clamp boolean value to 0 and 1 (Phil Sutter) [RHEL-190549]
- tests: shell: delete netdev chain after test (Phil Sutter) [RHEL-190549]
- ipopt: use ipv4 address datatype for address field in ip options (Phil Sutter) [RHEL-190549]
- netlink_delinarize: fix bogus munging of mask value (Phil Sutter) [RHEL-190549]
- evaluate: remove variable shadowing (Phil Sutter) [RHEL-190549]
- intervals: do not merge intervals with different timeout (Phil Sutter) [RHEL-190549]
- src: add EXPR_RANGE_VALUE expression and use it (Phil Sutter) [RHEL-190549]
- intervals: add helper function to set previous element (Phil Sutter) [RHEL-190549]
- parser_bison: fix UaF when reporting table parse error (Phil Sutter) [RHEL-190549]
- intervals: set internal element location with the deletion trigger (Phil Sutter) [RHEL-190549]
- optimize: compare expression length (Phil Sutter) [RHEL-190549]
- tests: py: Fix for storing payload into missing file (Phil Sutter) [RHEL-190549]
- json: Support typeof in set and map types (Phil Sutter) [RHEL-190549]
- json: collapse set element commands from parser (Phil Sutter) [RHEL-190549]
- doc: extend description of fib expression (Phil Sutter) [RHEL-190549]
- tests: monitor: fix up test case breakage (Phil Sutter) [RHEL-190549]
- src: fix extended netlink error reporting with large set elements (Phil Sutter) [RHEL-190549]
- mnl: rename to mnl_seqnum_alloc() to mnl_seqnum_inc() (Phil Sutter) [RHEL-190549]
- mnl: update cmd_add_loc() to take struct nlmsghdr (Phil Sutter) [RHEL-190549]
- rule: netlink attribute offset is uint32_t for struct nlerr_loc (Phil Sutter) [RHEL-190549]
- src: collapse set element commands from parser (Phil Sutter) [RHEL-190549]
- libnftables-json: fix raw payload expression documentation (Phil Sutter) [RHEL-190549]
- cache: initialize filter when fetching implicit chains (Phil Sutter) [RHEL-190549]
- tests: py: fix up udp csum fixup output (Phil Sutter) [RHEL-190549]
- proto: use NFT_PAYLOAD_L4CSUM_PSEUDOHDR flag to mangle UDP checksum (Phil Sutter) [RHEL-190549]
- tests: shell: stabilize packetpath/payload (Phil Sutter) [RHEL-190549]
- libnftables: Zero ctx->vars after freeing it (Phil Sutter) [RHEL-190549]
- cache: position does not require full cache (Phil Sutter) [RHEL-190549]
- cache: relax requirement for replace rule command (Phil Sutter) [RHEL-190549]
- cache: remove full cache requirement when echo flag is set on (Phil Sutter) [RHEL-190549]
- cache: assert filter when calling nft_cache_evaluate() (Phil Sutter) [RHEL-190549]
- cache: consolidate reset command (Phil Sutter) [RHEL-190549]
- cache: add filtering support for objects (Phil Sutter) [RHEL-190549]
- cache: only dump rules for the given table (Phil Sutter) [RHEL-190549]
- cache: accumulate flags in batch (Phil Sutter) [RHEL-190549]
- cache: reset filter for each command (Phil Sutter) [RHEL-190549]
- parser_json: fix several expression memleaks from error path (Phil Sutter) [RHEL-190549]
- parser_json: release buffer returned by json_dumps (Phil Sutter) [RHEL-190549]
- json: Support maps with concatenated data (Phil Sutter) [RHEL-190549]
- parser_json: fix crash in json_parse_set_stmt_list (Phil Sutter) [RHEL-190549]
- parser_bison: allow 0 burst in limit rate byte mode (Phil Sutter) [RHEL-190549]
- datatype: improve error reporting when time unit is not correct (Phil Sutter) [RHEL-190549]
- cache: rule by index requires full cache (Phil Sutter) [RHEL-190549]
- datatype: reject rate in quota statement (Phil Sutter) [RHEL-190549]
- optimize: skip variables in nat statements (Phil Sutter) [RHEL-190549]
- parser_json: use stdin buffer if available (Phil Sutter) [RHEL-190549]
- libnftables: skip useable checks for /dev/stdin (Phil Sutter) [RHEL-190549]
- optimize: clone counter before insertion into set element (Phil Sutter) [RHEL-190549]
- segtree: set on EXPR_F_KERNEL flag for catchall elements in the cache (Phil Sutter) [RHEL-190549]
- evaluate: set on expr->len for catchall set elements (Phil Sutter) [RHEL-190549]
- parser_bison: recursive table declaration in deprecated meter statement (Phil Sutter) [RHEL-190549]
- intervals: fix element deletions with maps (Phil Sutter) [RHEL-190549]
- src: add string preprocessor and use it for log prefix string (Phil Sutter) [RHEL-190549]
- tests: shell: skip ip option tests if kernel does not support it (Phil Sutter) [RHEL-190549]
- cmd: skip variable set elements when collapsing commands (Phil Sutter) [RHEL-190549]
- cmd: provide better hint if chain is already declared with different type/hook/priority (Phil Sutter) [RHEL-190549]
- monitor: too large shift exponent displaying payload expression (Phil Sutter) [RHEL-190549]
- scanner: inet_pton() allows for broader IPv4-Mapped IPv6 addresses (Phil Sutter) [RHEL-190549]
- evaluate: Fix incorrect checking the `base` variable in case of IPV6 (Phil Sutter) [RHEL-190549]
- evaluate: bogus protocol conflicts in vlan with implicit dependencies (Phil Sutter) [RHEL-190549]
- cache: check for NFT_CACHE_REFRESH in current requested cache too (Phil Sutter) [RHEL-190549]
- doc: nft.8: Fix markup in ct expectation synopsis (Phil Sutter) [RHEL-190549]
- mergesort: Avoid accidental set element reordering (Phil Sutter) [RHEL-190549]
- doc: nft.8: Two minor synopsis fixups (Phil Sutter) [RHEL-190549]
- tests: shell: check for reset tcp options support (Phil Sutter) [RHEL-190549]
- tests: shell: payload matching requires egress support (Phil Sutter) [RHEL-190549]
- tests: py: complete icmp and icmpv6 update (Phil Sutter) [RHEL-190549]
- src: disentangle ICMP code types (Phil Sutter) [RHEL-190549]
- evaluate: display "Range negative size" error (Phil Sutter) [RHEL-190549]
- netlink_delinearize: restore binop syntax when listing ruleset for flags (Phil Sutter) [RHEL-190549]
- doc: libnftables-json: Drop invalid ops from match expression (Phil Sutter) [RHEL-190549]
- parser: json: Support for synproxy objects (Phil Sutter) [RHEL-190549]
- tests: py: add payload merging test cases (Phil Sutter) [RHEL-190549]
- nftables: do mot merge payloads on negation (Phil Sutter) [RHEL-190549]
- rule: fix ASAN errors in chain priority to textual names (Phil Sutter) [RHEL-190549]
- parser: compact type/typeof set rules (Phil Sutter) [RHEL-190549]
- parser: compact interval typeof rules (Phil Sutter) [RHEL-190549]
- src: improve error reporting for destroy command (Phil Sutter) [RHEL-190549]
- tests: shell: permit use of host-endian constant values in set lookup keys (Phil Sutter) [RHEL-190549]
- evaluate: permit use of host-endian constant values in set lookup keys (Phil Sutter) [RHEL-190549]
- expression: missing line in describe command with invalid expression (Phil Sutter) [RHEL-190549]
- netlink_delinearize: move concat and value postprocessing to helpers (Phil Sutter) [RHEL-190549]
- evaluate: skip byteorder conversion for selector smaller than 2 bytes (Phil Sutter) [RHEL-190549]
- cache: Optimize caching for 'list tables' command (Phil Sutter) [RHEL-190549]
- evaluate: fix check for unknown in cmd_op_to_name (Phil Sutter) [RHEL-190549]
- evaluate: don't assert on net/transport header conflict (Phil Sutter) [RHEL-190549]
- json: Support sets' auto-merge option (Phil Sutter) [RHEL-190549]
- rule: fix sym refcount assertion (Phil Sutter) [RHEL-190549]
- evaluate: error out when store needs more than one 128bit register of align fixup (Phil Sutter) [RHEL-190549]
- evaluate: do not fetch next expression on runaway number of concatenation components (Phil Sutter) [RHEL-190549]
- evaluate: skip anonymous set optimization for concatenations (Phil Sutter) [RHEL-190549]
- evaluate: add missing range checks for dup,fwd and payload statements (Phil Sutter) [RHEL-190549]
- doc: incorrect datatype description for icmpv6_type and icmpvx_code (Phil Sutter) [RHEL-190549]
- tests: shell: prefer project nft to system-wide nft (Phil Sutter) [RHEL-190549]
- parser_bison: ensure all timeout policy names are released (Phil Sutter) [RHEL-190549]
- netlink: fix stack overflow due to erroneous rounding (Phil Sutter) [RHEL-190549]
- parser_bison: error out on duplicated type/typeof/element keywords (Phil Sutter) [RHEL-190549]
- tests: shell: add test to cover payload transport match and mangle (Phil Sutter) [RHEL-190549]
- evaluate: fix stack overflow with huge priority string (Phil Sutter) [RHEL-190549]
- src: reject large raw payload and concat expressions (Phil Sutter) [RHEL-190549]
- evaluate: exthdr: statement arg must be not be a range (Phil Sutter) [RHEL-190549]
- meta: fix tc classid parsing out-of-bounds access (Phil Sutter) [RHEL-190549]
- parser_bison: close chain scope before chain release (Phil Sutter) [RHEL-190549]
- evaluate: fix bogus assertion failure with boolean datatype (Phil Sutter) [RHEL-190549]
- parser_bison: fix objref statement corruption (Phil Sutter) [RHEL-190549]
- tests: py: missing json output in meta.t with vlan mapping (Phil Sutter) [RHEL-190549]
- evaluate: reset statement length context before evaluating statement (Phil Sutter) [RHEL-190549]
- parser: tcpopt: fix tcp option parsing with NUM + length field (Phil Sutter) [RHEL-190549]
- evaluate: reject set definition with no key (Phil Sutter) [RHEL-190549]
- monitor: add support for concatenated set ranges (Phil Sutter) [RHEL-190549]
- evaluate: disable meta set with ranges (Phil Sutter) [RHEL-190549]
- evaluate: prevent assert when evaluating very large shift values (Phil Sutter) [RHEL-190549]
- evaluate: reject sets with no key (Phil Sutter) [RHEL-190549]
- evaluate: clone unary expression datatype to deal with dynamic datatype (Phil Sutter) [RHEL-190549]
- tests: shell: split nat inet tests (Phil Sutter) [RHEL-190549]
- evaluate: bogus error when adding devices to flowtable (Phil Sutter) [RHEL-190549]
- tests: shell: flush connlimit sets (Phil Sutter) [RHEL-190549]
- tests: shell: adjust add-after-delete flowtable for older kernels (Phil Sutter) [RHEL-190549]
- evaluate: fix rule replacement with anon sets (Phil Sutter) [RHEL-190549]
- tests: shell: skip if kernel does not support flowtable counter (Phil Sutter) [RHEL-190549]
- tests: shell: restore pipapo and chain binding coverage in standalone 30s-stress (Phil Sutter) [RHEL-190549]
- json: fix use after free in table_flags_json() (Phil Sutter) [RHEL-190549]
- src: expand create commands (Phil Sutter) [RHEL-190549]
- tests: shell: split set NAT interval test (Phil Sutter) [RHEL-190549]
- tests: shell: split merge nat optimization in two tests (Phil Sutter) [RHEL-190549]
- netlink: fix buffer size for user data in netlink_delinearize_chain() (Phil Sutter) [RHEL-190549]
- src: remove xfree() and use plain free() (Phil Sutter) [RHEL-190549]
- src: add free_const() and use it instead of xfree() (Phil Sutter) [RHEL-190549]
- evaluate: place byteorder conversion before rshift in payload expressions (Phil Sutter) [RHEL-190549]
- evaluate: reset statement length context only for set mappings (Phil Sutter) [RHEL-190549]
- meta: fix hour decoding when timezone offset is negative (Phil Sutter) [RHEL-190549]
- tproxy: Drop artificial port printing restriction (Phil Sutter) [RHEL-190549]
- tests/shell: fix mount command in "test-wrapper.sh" (Phil Sutter) [RHEL-190549]
- parser_bison: fix length check for ifname in ifname_expr_alloc() (Phil Sutter) [RHEL-190549]
- tests/shell: cover long interface name in "0042chain_variable_0" test (Phil Sutter) [RHEL-190549]
- tests/shell: add missing "elem_opts_compat_0.nodump" file (Phil Sutter) [RHEL-190549]
- parser_bison: Fix for broken compatibility with older dumps (Phil Sutter) [RHEL-190549]
Resolves: RHEL-190549
This commit is contained in:
parent
2eea6c6aeb
commit
92f5b031b7
@ -0,0 +1,83 @@
|
||||
From c13051bb51a4fcc1322faed773ee1dd6f81ed5f5 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:18 +0200
|
||||
Subject: [PATCH] parser_bison: Fix for broken compatibility with older dumps
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 22fab8681a50014174cdd02ace90f74b9e9eefe9
|
||||
|
||||
commit 22fab8681a50014174cdd02ace90f74b9e9eefe9
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Thu Oct 19 18:40:04 2023 +0200
|
||||
|
||||
parser_bison: Fix for broken compatibility with older dumps
|
||||
|
||||
Commit e6d1d0d611958 ("src: add set element multi-statement
|
||||
support") changed the order of expressions and other state attached to set
|
||||
elements are expected in input. This broke parsing of ruleset dumps
|
||||
created by nft commands prior to that commit.
|
||||
|
||||
Restore compatibility by also accepting the old ordering.
|
||||
|
||||
Fixes: e6d1d0d611958 ("src: add set element multi-statement support")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_bison.y | 6 ++++
|
||||
tests/shell/testcases/sets/elem_opts_compat_0 | 29 +++++++++++++++++++
|
||||
2 files changed, 35 insertions(+)
|
||||
create mode 100755 tests/shell/testcases/sets/elem_opts_compat_0
|
||||
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 5ced6e1..8eff50c 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -4532,6 +4532,12 @@ meter_key_expr_alloc : concat_expr
|
||||
|
||||
set_elem_expr : set_elem_expr_alloc
|
||||
| set_elem_expr_alloc set_elem_expr_options
|
||||
+ | set_elem_expr_alloc set_elem_expr_options set_elem_stmt_list
|
||||
+ {
|
||||
+ $$ = $1;
|
||||
+ list_splice_tail($3, &$$->stmt_list);
|
||||
+ xfree($3);
|
||||
+ }
|
||||
;
|
||||
|
||||
set_elem_key_expr : set_lhs_expr { $$ = $1; }
|
||||
diff --git a/tests/shell/testcases/sets/elem_opts_compat_0 b/tests/shell/testcases/sets/elem_opts_compat_0
|
||||
new file mode 100755
|
||||
index 0000000..e012953
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/sets/elem_opts_compat_0
|
||||
@@ -0,0 +1,29 @@
|
||||
+#!/bin/sh
|
||||
+
|
||||
+# ordering of element options and expressions has changed, make sure parser
|
||||
+# accepts both ways
|
||||
+
|
||||
+set -e
|
||||
+
|
||||
+$NFT -f - <<EOF
|
||||
+table t {
|
||||
+ set s {
|
||||
+ type inet_service
|
||||
+ counter;
|
||||
+ timeout 30s;
|
||||
+ }
|
||||
+}
|
||||
+EOF
|
||||
+
|
||||
+check() {
|
||||
+ out=$($NFT list ruleset)
|
||||
+ secs=$(sed -n 's/.*expires \([0-9]\+\)s.*/\1/p' <<< "$out")
|
||||
+ [[ $secs -lt 11 ]]
|
||||
+ grep -q 'counter packets 10 bytes 20' <<< "$out"
|
||||
+}
|
||||
+
|
||||
+$NFT add element t s '{ 23 counter packets 10 bytes 20 expires 10s }'
|
||||
+check
|
||||
+$NFT flush set t s
|
||||
+$NFT add element t s '{ 42 expires 10s counter packets 10 bytes 20 }'
|
||||
+check
|
||||
@ -0,0 +1,31 @@
|
||||
From 4bd9e30ecae19385b0e38fc1d5a82db87a351fb1 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:18 +0200
|
||||
Subject: [PATCH] tests/shell: add missing "elem_opts_compat_0.nodump" file
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit f65b2d12236174d477c55e96c4027cd51185ba5e
|
||||
|
||||
commit f65b2d12236174d477c55e96c4027cd51185ba5e
|
||||
Author: Thomas Haller <thaller@redhat.com>
|
||||
Date: Mon Oct 23 14:40:25 2023 +0200
|
||||
|
||||
tests/shell: add missing "elem_opts_compat_0.nodump" file
|
||||
|
||||
This is an inconsistency. The test should have either a .nft or a
|
||||
.nodump file. "./tools/check-tree.sh" enforces that and will in the
|
||||
future run by `make check`.
|
||||
|
||||
Fixes: 22fab8681a50 ("parser_bison: Fix for broken compatibility with older dumps")
|
||||
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
tests/shell/testcases/sets/dumps/elem_opts_compat_0.nodump | 0
|
||||
1 file changed, 0 insertions(+), 0 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/sets/dumps/elem_opts_compat_0.nodump
|
||||
|
||||
diff --git a/tests/shell/testcases/sets/dumps/elem_opts_compat_0.nodump b/tests/shell/testcases/sets/dumps/elem_opts_compat_0.nodump
|
||||
new file mode 100644
|
||||
index 0000000..e69de29
|
||||
126
0018-tests-shell-cover-long-interface-name-in-0042chain_v.patch
Normal file
126
0018-tests-shell-cover-long-interface-name-in-0042chain_v.patch
Normal file
@ -0,0 +1,126 @@
|
||||
From 7d88deb4054d71dcd038ea003484be65226d8f15 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:18 +0200
|
||||
Subject: [PATCH] tests/shell: cover long interface name in
|
||||
"0042chain_variable_0" test
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit f773041121d6d0d112fa9cb003fd791eacd6e43d
|
||||
|
||||
commit f773041121d6d0d112fa9cb003fd791eacd6e43d
|
||||
Author: Thomas Haller <thaller@redhat.com>
|
||||
Date: Mon Oct 23 19:00:46 2023 +0200
|
||||
|
||||
tests/shell: cover long interface name in "0042chain_variable_0" test
|
||||
|
||||
IFNAMSIZ is 16. Adjust "0042chain_variable_0" to use an interface name
|
||||
with the maximum allowed bytes length.
|
||||
|
||||
Instead of adding an entirely different test, adjust an existing one to
|
||||
use another interface name. The aspect for testing for a long interface
|
||||
name is not special enough, to warrant a separate test. We can cover it
|
||||
by extending an existing test.
|
||||
|
||||
Note that the length check in "parser_bison.y" is wrong. The test checks
|
||||
still for the wrong behavior and that "d23456789012345x" is accepted.
|
||||
|
||||
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
.../testcases/chains/0042chain_variable_0 | 36 ++++++++++++++++---
|
||||
.../chains/dumps/0042chain_variable_0.nft | 4 +--
|
||||
2 files changed, 34 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/tests/shell/testcases/chains/0042chain_variable_0 b/tests/shell/testcases/chains/0042chain_variable_0
|
||||
index 1ea44e8..739dc05 100755
|
||||
--- a/tests/shell/testcases/chains/0042chain_variable_0
|
||||
+++ b/tests/shell/testcases/chains/0042chain_variable_0
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
set -e
|
||||
|
||||
-ip link add name dummy0 type dummy
|
||||
+ip link add name d23456789012345 type dummy
|
||||
+
|
||||
|
||||
EXPECTED="define if_main = \"lo\"
|
||||
|
||||
@@ -14,22 +15,50 @@ table netdev filter1 {
|
||||
|
||||
$NFT -f - <<< $EXPECTED
|
||||
|
||||
+
|
||||
+EXPECTED="define if_main = \"lo\"
|
||||
+
|
||||
+table netdev filter2 {
|
||||
+ chain Main_Ingress2 {
|
||||
+ type filter hook ingress devices = { \$if_main, d23456789012345x } priority -500; policy accept;
|
||||
+ }
|
||||
+}"
|
||||
+
|
||||
+rc=0
|
||||
+$NFT -f - <<< $EXPECTED || rc=$?
|
||||
+test "$rc" = 0
|
||||
+cat <<EOF | $DIFF -u <($NFT list ruleset) -
|
||||
+table netdev filter1 {
|
||||
+ chain Main_Ingress1 {
|
||||
+ type filter hook ingress device "lo" priority -500; policy accept;
|
||||
+ }
|
||||
+}
|
||||
+table netdev filter2 {
|
||||
+ chain Main_Ingress2 {
|
||||
+ type filter hook ingress devices = { d23456789012345, lo } priority -500; policy accept;
|
||||
+ }
|
||||
+}
|
||||
+EOF
|
||||
+
|
||||
+
|
||||
EXPECTED="define if_main = \"lo\"
|
||||
|
||||
table netdev filter2 {
|
||||
chain Main_Ingress2 {
|
||||
- type filter hook ingress devices = { \$if_main, dummy0 } priority -500; policy accept;
|
||||
+ type filter hook ingress devices = { \$if_main, d23456789012345 } priority -500; policy accept;
|
||||
}
|
||||
}"
|
||||
|
||||
$NFT -f - <<< $EXPECTED
|
||||
|
||||
+
|
||||
if [ "$NFT_TEST_HAVE_netdev_egress" = n ] ; then
|
||||
echo "Skip parts of the test due to NFT_TEST_HAVE_netdev_egress=n"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
-EXPECTED="define if_main = { lo, dummy0 }
|
||||
+
|
||||
+EXPECTED="define if_main = { lo, d23456789012345 }
|
||||
define lan_interfaces = { lo }
|
||||
|
||||
table netdev filter3 {
|
||||
@@ -43,4 +72,3 @@ table netdev filter3 {
|
||||
|
||||
$NFT -f - <<< $EXPECTED
|
||||
|
||||
-
|
||||
diff --git a/tests/shell/testcases/chains/dumps/0042chain_variable_0.nft b/tests/shell/testcases/chains/dumps/0042chain_variable_0.nft
|
||||
index 5ec230d..84a908d 100644
|
||||
--- a/tests/shell/testcases/chains/dumps/0042chain_variable_0.nft
|
||||
+++ b/tests/shell/testcases/chains/dumps/0042chain_variable_0.nft
|
||||
@@ -5,12 +5,12 @@ table netdev filter1 {
|
||||
}
|
||||
table netdev filter2 {
|
||||
chain Main_Ingress2 {
|
||||
- type filter hook ingress devices = { dummy0, lo } priority -500; policy accept;
|
||||
+ type filter hook ingress devices = { d23456789012345, lo } priority -500; policy accept;
|
||||
}
|
||||
}
|
||||
table netdev filter3 {
|
||||
chain Main_Ingress3 {
|
||||
- type filter hook ingress devices = { dummy0, lo } priority -500; policy accept;
|
||||
+ type filter hook ingress devices = { d23456789012345, lo } priority -500; policy accept;
|
||||
}
|
||||
|
||||
chain Main_Egress3 {
|
||||
@ -0,0 +1,78 @@
|
||||
From 7f0483fec8d8fe12a8cb44f203f697f877e39b1a Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:18 +0200
|
||||
Subject: [PATCH] parser_bison: fix length check for ifname in
|
||||
ifname_expr_alloc()
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 122dce6b35205a3df419a5cae9acfd6e83e8725a
|
||||
|
||||
commit 122dce6b35205a3df419a5cae9acfd6e83e8725a
|
||||
Author: Thomas Haller <thaller@redhat.com>
|
||||
Date: Mon Oct 23 19:00:47 2023 +0200
|
||||
|
||||
parser_bison: fix length check for ifname in ifname_expr_alloc()
|
||||
|
||||
IFNAMSIZ is 16, and the allowed byte length of the name is one less than
|
||||
that. Fix the length check and adjust a test for covering the longest
|
||||
allowed interface name.
|
||||
|
||||
This is obviously a change in behavior, because previously interface
|
||||
names with length 16 were accepted and were silently truncated along the
|
||||
way. Now they are rejected as invalid.
|
||||
|
||||
Fixes: fa52bc225806 ("parser: reject zero-length interface names")
|
||||
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_bison.y | 3 ++-
|
||||
tests/shell/testcases/chains/0042chain_variable_0 | 7 +------
|
||||
2 files changed, 3 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 8eff50c..5c2d14b 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <syslog.h>
|
||||
+#include <net/if.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/if_ether.h>
|
||||
@@ -158,7 +159,7 @@ static struct expr *ifname_expr_alloc(const struct location *location,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- if (length > 16) {
|
||||
+ if (length >= IFNAMSIZ) {
|
||||
xfree(name);
|
||||
erec_queue(error(location, "interface name too long"), queue);
|
||||
return NULL;
|
||||
diff --git a/tests/shell/testcases/chains/0042chain_variable_0 b/tests/shell/testcases/chains/0042chain_variable_0
|
||||
index 739dc05..a4b929f 100755
|
||||
--- a/tests/shell/testcases/chains/0042chain_variable_0
|
||||
+++ b/tests/shell/testcases/chains/0042chain_variable_0
|
||||
@@ -26,18 +26,13 @@ table netdev filter2 {
|
||||
|
||||
rc=0
|
||||
$NFT -f - <<< $EXPECTED || rc=$?
|
||||
-test "$rc" = 0
|
||||
+test "$rc" = 1
|
||||
cat <<EOF | $DIFF -u <($NFT list ruleset) -
|
||||
table netdev filter1 {
|
||||
chain Main_Ingress1 {
|
||||
type filter hook ingress device "lo" priority -500; policy accept;
|
||||
}
|
||||
}
|
||||
-table netdev filter2 {
|
||||
- chain Main_Ingress2 {
|
||||
- type filter hook ingress devices = { d23456789012345, lo } priority -500; policy accept;
|
||||
- }
|
||||
-}
|
||||
EOF
|
||||
|
||||
|
||||
45
0020-tests-shell-fix-mount-command-in-test-wrapper.sh.patch
Normal file
45
0020-tests-shell-fix-mount-command-in-test-wrapper.sh.patch
Normal file
@ -0,0 +1,45 @@
|
||||
From 70989b95e0a340781eadd99af05f5bccbb36b028 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:18 +0200
|
||||
Subject: [PATCH] tests/shell: fix mount command in "test-wrapper.sh"
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 65d94af52f11a2c5a44d5ae8aa3891ccb648c666
|
||||
|
||||
commit 65d94af52f11a2c5a44d5ae8aa3891ccb648c666
|
||||
Author: Thomas Haller <thaller@redhat.com>
|
||||
Date: Thu Nov 2 09:15:41 2023 +0100
|
||||
|
||||
tests/shell: fix mount command in "test-wrapper.sh"
|
||||
|
||||
With Fedora 39 (util-linux-core-2.39.2-1.fc39), the mount command starts
|
||||
to fail. It was still working with Fedora 38 (util-linux-core-2.38.1-4.fc38).
|
||||
|
||||
$ unshare -f -p -m --mount-proc -U --map-root-user -n bash -c 'mount -t tmpfs --make-private /var/run && mount'
|
||||
mount: /run: mount failed: Invalid argument.
|
||||
|
||||
Not sure why this starts to fail. But arguably the command line
|
||||
arguments were wrong. Fix it, we need a pseudo name for the device.
|
||||
|
||||
Fixes: df6f1a3e0803 ("tests/shell: bind mount private /var/run/netns in test container")
|
||||
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
tests/shell/helpers/test-wrapper.sh | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tests/shell/helpers/test-wrapper.sh b/tests/shell/helpers/test-wrapper.sh
|
||||
index 13b918f..898dcce 100755
|
||||
--- a/tests/shell/helpers/test-wrapper.sh
|
||||
+++ b/tests/shell/helpers/test-wrapper.sh
|
||||
@@ -48,7 +48,7 @@ if [ "$NFT_TEST_HAS_UNSHARED_MOUNT" = y ] ; then
|
||||
# Note that this also hides everything that might reside in /var/run.
|
||||
# That is desirable, as tests should not depend on content there (or if
|
||||
# they do, we need to explicitly handle it as appropriate).
|
||||
- if mount -t tmpfs --make-private "/var/run" ; then
|
||||
+ if mount -t tmpfs --make-private tmpfs "/var/run" ; then
|
||||
CLEANUP_UMOUNT_VAR_RUN=y
|
||||
fi
|
||||
mkdir -p /var/run/netns
|
||||
119
0021-tproxy-Drop-artificial-port-printing-restriction.patch
Normal file
119
0021-tproxy-Drop-artificial-port-printing-restriction.patch
Normal file
@ -0,0 +1,119 @@
|
||||
From 2927e76b0fb5b64e1a57467151fb76c3d513fa3a Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:18 +0200
|
||||
Subject: [PATCH] tproxy: Drop artificial port printing restriction
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit e4c9f9f7e0d1f83be18f6c4a418da503e9021b24
|
||||
|
||||
commit e4c9f9f7e0d1f83be18f6c4a418da503e9021b24
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Thu Nov 2 14:48:10 2023 +0100
|
||||
|
||||
tproxy: Drop artificial port printing restriction
|
||||
|
||||
It does not make much sense to omit printing the port expression if it's
|
||||
not a value expression: On one hand, input allows for more advanced
|
||||
uses. On the other, if it is in-kernel, best nft can do is to try and
|
||||
print it no matter what. Just ignoring ruleset elements can't be
|
||||
correct.
|
||||
|
||||
Fixes: 2be1d52644cf7 ("src: Add tproxy support")
|
||||
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1721
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/statement.c | 2 +-
|
||||
tests/py/inet/tproxy.t | 2 ++
|
||||
tests/py/inet/tproxy.t.json | 35 ++++++++++++++++++++++++++++++++++
|
||||
tests/py/inet/tproxy.t.payload | 12 ++++++++++++
|
||||
4 files changed, 50 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/statement.c b/src/statement.c
|
||||
index 4756116..f5176e6 100644
|
||||
--- a/src/statement.c
|
||||
+++ b/src/statement.c
|
||||
@@ -989,7 +989,7 @@ static void tproxy_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
|
||||
expr_print(stmt->tproxy.addr, octx);
|
||||
}
|
||||
}
|
||||
- if (stmt->tproxy.port && stmt->tproxy.port->etype == EXPR_VALUE) {
|
||||
+ if (stmt->tproxy.port) {
|
||||
if (!stmt->tproxy.addr)
|
||||
nft_print(octx, " ");
|
||||
nft_print(octx, ":");
|
||||
diff --git a/tests/py/inet/tproxy.t b/tests/py/inet/tproxy.t
|
||||
index d23bbcb..9901df7 100644
|
||||
--- a/tests/py/inet/tproxy.t
|
||||
+++ b/tests/py/inet/tproxy.t
|
||||
@@ -19,3 +19,5 @@ meta l4proto 17 tproxy ip to :50080;ok
|
||||
meta l4proto 17 tproxy ip6 to :50080;ok
|
||||
meta l4proto 17 tproxy to :50080;ok
|
||||
ip daddr 0.0.0.0/0 meta l4proto 6 tproxy ip to :2000;ok
|
||||
+
|
||||
+meta l4proto 6 tproxy ip to 127.0.0.1:symhash mod 2 map { 0 : 23, 1 : 42 };ok
|
||||
diff --git a/tests/py/inet/tproxy.t.json b/tests/py/inet/tproxy.t.json
|
||||
index 7b3b11c..71b6fd2 100644
|
||||
--- a/tests/py/inet/tproxy.t.json
|
||||
+++ b/tests/py/inet/tproxy.t.json
|
||||
@@ -183,3 +183,38 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
+
|
||||
+# meta l4proto 6 tproxy ip to 127.0.0.1:symhash mod 2 map { 0 : 23, 1 : 42 }
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "meta": {
|
||||
+ "key": "l4proto"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": 6
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "tproxy": {
|
||||
+ "addr": "127.0.0.1",
|
||||
+ "family": "ip",
|
||||
+ "port": {
|
||||
+ "map": {
|
||||
+ "data": {
|
||||
+ "set": [
|
||||
+ [ 0, 23 ],
|
||||
+ [ 1, 42 ]
|
||||
+ ]
|
||||
+ },
|
||||
+ "key": {
|
||||
+ "symhash": { "mod": 2 }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
diff --git a/tests/py/inet/tproxy.t.payload b/tests/py/inet/tproxy.t.payload
|
||||
index 24bf8f6..2f41904 100644
|
||||
--- a/tests/py/inet/tproxy.t.payload
|
||||
+++ b/tests/py/inet/tproxy.t.payload
|
||||
@@ -61,3 +61,15 @@ inet x y
|
||||
[ immediate reg 1 0x0000d007 ]
|
||||
[ tproxy ip port reg 1 ]
|
||||
|
||||
+# meta l4proto 6 tproxy ip to 127.0.0.1:symhash mod 2 map { 0 : 23, 1 : 42 }
|
||||
+__map%d x b size 2
|
||||
+__map%d x 0
|
||||
+ element 00000000 : 00001700 0 [end] element 00000001 : 00002a00 0 [end]
|
||||
+inet x y
|
||||
+ [ meta load l4proto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ immediate reg 1 0x0100007f ]
|
||||
+ [ hash reg 2 = symhash() % mod 2 ]
|
||||
+ [ lookup reg 2 set __map%d dreg 2 ]
|
||||
+ [ tproxy ip addr reg 1 port reg 2 ]
|
||||
+
|
||||
126
0022-meta-fix-hour-decoding-when-timezone-offset-is-negat.patch
Normal file
126
0022-meta-fix-hour-decoding-when-timezone-offset-is-negat.patch
Normal file
@ -0,0 +1,126 @@
|
||||
From 2db221f432962517f777f225aadf4db1cf18e1e4 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:18 +0200
|
||||
Subject: [PATCH] meta: fix hour decoding when timezone offset is negative
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit d392ddf243dcbf8a34726c777d2c669b1e8bfa85
|
||||
|
||||
commit d392ddf243dcbf8a34726c777d2c669b1e8bfa85
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Thu Nov 2 15:34:13 2023 +0100
|
||||
|
||||
meta: fix hour decoding when timezone offset is negative
|
||||
|
||||
Brian Davidson says:
|
||||
|
||||
meta hour rules don't display properly after being created when the
|
||||
hour is on or after 00:00 UTC. The netlink debug looks correct for
|
||||
seconds past midnight UTC, but displaying the rules looks like an
|
||||
overflow or a byte order problem. I am in UTC-0400, so today, 20:00
|
||||
and later exhibits the problem, while 19:00 and earlier hours are
|
||||
fine.
|
||||
|
||||
meta.c only ever worked when the delta to UTC is positive.
|
||||
We need to add in case the second counter turns negative after
|
||||
offset adjustment.
|
||||
|
||||
Also add a test case for this.
|
||||
|
||||
Fixes: f8f32deda31d ("meta: Introduce new conditions 'time', 'day' and 'hour'")
|
||||
Reported-by: Brian Davidson <davidson.brian@gmail.com>
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/meta.c | 11 +++-
|
||||
.../testcases/listing/dumps/meta_time.nodump | 0
|
||||
tests/shell/testcases/listing/meta_time | 52 +++++++++++++++++++
|
||||
3 files changed, 61 insertions(+), 2 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/listing/dumps/meta_time.nodump
|
||||
create mode 100755 tests/shell/testcases/listing/meta_time
|
||||
|
||||
diff --git a/src/meta.c b/src/meta.c
|
||||
index b69dca2..1f1e33c 100644
|
||||
--- a/src/meta.c
|
||||
+++ b/src/meta.c
|
||||
@@ -495,9 +495,16 @@ static void hour_type_print(const struct expr *expr, struct output_ctx *octx)
|
||||
|
||||
/* Obtain current tm, so that we can add tm_gmtoff */
|
||||
ts = time(NULL);
|
||||
- if (ts != ((time_t) -1) && localtime_r(&ts, &cur_tm))
|
||||
- seconds = (seconds + cur_tm.tm_gmtoff) % SECONDS_PER_DAY;
|
||||
+ if (ts != ((time_t) -1) && localtime_r(&ts, &cur_tm)) {
|
||||
+ int32_t adj = seconds + cur_tm.tm_gmtoff;
|
||||
|
||||
+ if (adj < 0)
|
||||
+ adj += SECONDS_PER_DAY;
|
||||
+ else if (adj >= SECONDS_PER_DAY)
|
||||
+ adj -= SECONDS_PER_DAY;
|
||||
+
|
||||
+ seconds = adj;
|
||||
+ }
|
||||
minutes = seconds / 60;
|
||||
seconds %= 60;
|
||||
hours = minutes / 60;
|
||||
diff --git a/tests/shell/testcases/listing/dumps/meta_time.nodump b/tests/shell/testcases/listing/dumps/meta_time.nodump
|
||||
new file mode 100644
|
||||
index 0000000..e69de29
|
||||
diff --git a/tests/shell/testcases/listing/meta_time b/tests/shell/testcases/listing/meta_time
|
||||
new file mode 100755
|
||||
index 0000000..a976199
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/listing/meta_time
|
||||
@@ -0,0 +1,52 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+set -e
|
||||
+
|
||||
+TMP1=$(mktemp)
|
||||
+TMP2=$(mktemp)
|
||||
+
|
||||
+cleanup()
|
||||
+{
|
||||
+ rm -f "$TMP1"
|
||||
+ rm -f "$TMP2"
|
||||
+}
|
||||
+
|
||||
+check_decode()
|
||||
+{
|
||||
+ TZ=$1 $NFT list chain t c | grep meta > "$TMP2"
|
||||
+ diff -u "$TMP1" "$TMP2"
|
||||
+}
|
||||
+
|
||||
+trap cleanup EXIT
|
||||
+
|
||||
+$NFT -f - <<EOF
|
||||
+table t {
|
||||
+ chain c {
|
||||
+ }
|
||||
+}
|
||||
+EOF
|
||||
+
|
||||
+for i in $(seq -w 0 23); do
|
||||
+ TZ=UTC $NFT add rule t c meta hour "$i:00"-"$i:59"
|
||||
+done
|
||||
+
|
||||
+# Check decoding in UTC, this mirrors 1:1 what should have been added.
|
||||
+for i in $(seq 0 23); do
|
||||
+ printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" $i 0 $i 59 >> "$TMP1"
|
||||
+done
|
||||
+
|
||||
+check_decode UTC
|
||||
+
|
||||
+printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" 23 0 23 59 > "$TMP1"
|
||||
+for i in $(seq 0 22); do
|
||||
+ printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" $i 0 $i 59 >> "$TMP1"
|
||||
+done
|
||||
+check_decode UTC+1
|
||||
+
|
||||
+printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" 1 0 1 59 > "$TMP1"
|
||||
+for i in $(seq 2 23); do
|
||||
+ printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" $i 0 $i 59 >> "$TMP1"
|
||||
+done
|
||||
+printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" 0 0 0 59 >> "$TMP1"
|
||||
+
|
||||
+check_decode UTC-1
|
||||
218
0023-evaluate-reset-statement-length-context-only-for-set.patch
Normal file
218
0023-evaluate-reset-statement-length-context-only-for-set.patch
Normal file
@ -0,0 +1,218 @@
|
||||
From 3f363237125fded5adb4bc9ed8890e518a518286 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:18 +0200
|
||||
Subject: [PATCH] evaluate: reset statement length context only for set
|
||||
mappings
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 57f092a87fc4bc61e29cff31dfff976e1f2005ab
|
||||
|
||||
commit 57f092a87fc4bc61e29cff31dfff976e1f2005ab
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Sun Nov 5 18:33:14 2023 +0100
|
||||
|
||||
evaluate: reset statement length context only for set mappings
|
||||
|
||||
map expression (which is used a key to look up for the mapping) needs to
|
||||
consider the statement length context, otherwise incorrect bytecode is
|
||||
generated when {ct,meta} statement is generated.
|
||||
|
||||
# nft -f - <<EOF
|
||||
add table ip6 t
|
||||
add chain ip6 t c
|
||||
add map ip6 t mapv6 { typeof ip6 dscp : meta mark; }
|
||||
EOF
|
||||
|
||||
# nft -d netlink add rule ip6 t c meta mark set ip6 dscp map @mapv6
|
||||
ip6 t c
|
||||
[ payload load 2b @ network header + 0 => reg 1 ]
|
||||
[ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
|
||||
... missing byteorder conversion here before shift ...
|
||||
[ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
|
||||
[ lookup reg 1 set mapv6 dreg 1 ]
|
||||
[ meta set mark with reg 1 ]
|
||||
|
||||
Reset statement length context only for the mapping side for the
|
||||
elements in the set.
|
||||
|
||||
Fixes: edecd58755a8 ("evaluate: support shifts larger than the width of the left operand")
|
||||
Reported-by: Brian Davidson <davidson.brian@gmail.com>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 2 +-
|
||||
tests/py/ip6/ip6.t | 5 +++
|
||||
tests/py/ip6/ip6.t.json | 58 +++++++++++++++++++++++++++++++++
|
||||
tests/py/ip6/ip6.t.payload.inet | 23 +++++++++++++
|
||||
tests/py/ip6/ip6.t.payload.ip6 | 19 +++++++++++
|
||||
5 files changed, 106 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 711990a..1850043 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -1913,13 +1913,13 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
|
||||
}
|
||||
|
||||
expr_set_context(&ctx->ectx, NULL, 0);
|
||||
- ctx->stmt_len = 0;
|
||||
if (expr_evaluate(ctx, &map->map) < 0)
|
||||
return -1;
|
||||
if (expr_is_constant(map->map))
|
||||
return expr_error(ctx->msgs, map->map,
|
||||
"Map expression can not be constant");
|
||||
|
||||
+ ctx->stmt_len = 0;
|
||||
mappings = map->mappings;
|
||||
mappings->set_flags |= NFT_SET_MAP;
|
||||
|
||||
diff --git a/tests/py/ip6/ip6.t b/tests/py/ip6/ip6.t
|
||||
index 2ffe318..60ea223 100644
|
||||
--- a/tests/py/ip6/ip6.t
|
||||
+++ b/tests/py/ip6/ip6.t
|
||||
@@ -17,6 +17,11 @@ ip6 dscp != 0x20;ok;ip6 dscp != cs4
|
||||
ip6 dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef};ok
|
||||
ip6 dscp vmap { 0x04 : accept, 0x3f : continue } counter;ok
|
||||
|
||||
+!map1 type dscp : mark;ok
|
||||
+meta mark set ip6 dscp map @map1;ok
|
||||
+!map2 type dscp . ipv6_addr : mark;ok
|
||||
+meta mark set ip6 dscp . ip6 daddr map @map2;ok
|
||||
+
|
||||
ip6 flowlabel 22;ok
|
||||
ip6 flowlabel != 233;ok
|
||||
- ip6 flowlabel 33-45;ok
|
||||
diff --git a/tests/py/ip6/ip6.t.json b/tests/py/ip6/ip6.t.json
|
||||
index cf80217..5411190 100644
|
||||
--- a/tests/py/ip6/ip6.t.json
|
||||
+++ b/tests/py/ip6/ip6.t.json
|
||||
@@ -135,6 +135,64 @@
|
||||
}
|
||||
]
|
||||
|
||||
+# meta mark set ip6 dscp map @map1
|
||||
+[
|
||||
+ {
|
||||
+ "mangle": {
|
||||
+ "key": {
|
||||
+ "meta": {
|
||||
+ "key": "mark"
|
||||
+ }
|
||||
+ },
|
||||
+ "value": {
|
||||
+ "map": {
|
||||
+ "data": "@map1",
|
||||
+ "key": {
|
||||
+ "payload": {
|
||||
+ "field": "dscp",
|
||||
+ "protocol": "ip6"
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# meta mark set ip6 dscp . ip6 daddr map @map2
|
||||
+[
|
||||
+ {
|
||||
+ "mangle": {
|
||||
+ "key": {
|
||||
+ "meta": {
|
||||
+ "key": "mark"
|
||||
+ }
|
||||
+ },
|
||||
+ "value": {
|
||||
+ "map": {
|
||||
+ "data": "@map2",
|
||||
+ "key": {
|
||||
+ "concat": [
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "dscp",
|
||||
+ "protocol": "ip6"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "daddr",
|
||||
+ "protocol": "ip6"
|
||||
+ }
|
||||
+ }
|
||||
+ ]
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
# ip6 flowlabel 22
|
||||
[
|
||||
{
|
||||
diff --git a/tests/py/ip6/ip6.t.payload.inet b/tests/py/ip6/ip6.t.payload.inet
|
||||
index 20dfe54..214a0ed 100644
|
||||
--- a/tests/py/ip6/ip6.t.payload.inet
|
||||
+++ b/tests/py/ip6/ip6.t.payload.inet
|
||||
@@ -53,6 +53,29 @@ ip6 test-ip6 input
|
||||
[ lookup reg 1 set __map%d dreg 0 ]
|
||||
[ counter pkts 0 bytes 0 ]
|
||||
|
||||
+# meta mark set ip6 dscp map @map1
|
||||
+inet test-inet input
|
||||
+ [ meta load nfproto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0000000a ]
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
|
||||
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
|
||||
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
|
||||
+ [ lookup reg 1 set map1 dreg 1 ]
|
||||
+ [ meta set mark with reg 1 ]
|
||||
+
|
||||
+# meta mark set ip6 dscp . ip6 daddr map @map2
|
||||
+inet test-inet input
|
||||
+ [ meta load nfproto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0000000a ]
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
|
||||
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
|
||||
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
|
||||
+ [ payload load 16b @ network header + 24 => reg 9 ]
|
||||
+ [ lookup reg 1 set map2 dreg 1 ]
|
||||
+ [ meta set mark with reg 1 ]
|
||||
+
|
||||
# ip6 flowlabel 22
|
||||
inet test-inet input
|
||||
[ meta load nfproto => reg 1 ]
|
||||
diff --git a/tests/py/ip6/ip6.t.payload.ip6 b/tests/py/ip6/ip6.t.payload.ip6
|
||||
index f8e3ca3..428b8ea 100644
|
||||
--- a/tests/py/ip6/ip6.t.payload.ip6
|
||||
+++ b/tests/py/ip6/ip6.t.payload.ip6
|
||||
@@ -41,6 +41,25 @@ ip6 test-ip6 input
|
||||
[ lookup reg 1 set __map%d dreg 0 ]
|
||||
[ counter pkts 0 bytes 0 ]
|
||||
|
||||
+# meta mark set ip6 dscp map @map1
|
||||
+ip6 test-ip6 input
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
|
||||
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
|
||||
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
|
||||
+ [ lookup reg 1 set map1 dreg 1 ]
|
||||
+ [ meta set mark with reg 1 ]
|
||||
+
|
||||
+# meta mark set ip6 dscp . ip6 daddr map @map2
|
||||
+ip6 test-ip6 input
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
|
||||
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
|
||||
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
|
||||
+ [ payload load 16b @ network header + 24 => reg 9 ]
|
||||
+ [ lookup reg 1 set map2 dreg 1 ]
|
||||
+ [ meta set mark with reg 1 ]
|
||||
+
|
||||
# ip6 flowlabel 22
|
||||
ip6 test-ip6 input
|
||||
[ payload load 3b @ network header + 1 => reg 1 ]
|
||||
238
0024-evaluate-place-byteorder-conversion-before-rshift-in.patch
Normal file
238
0024-evaluate-place-byteorder-conversion-before-rshift-in.patch
Normal file
@ -0,0 +1,238 @@
|
||||
From 2d5e3d1d7241a86d1555b3edfb020f20fc95748d Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:18 +0200
|
||||
Subject: [PATCH] evaluate: place byteorder conversion before rshift in payload
|
||||
expressions
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit cb9b72a43c5684379c027908d9f332170bf8dd15
|
||||
|
||||
commit cb9b72a43c5684379c027908d9f332170bf8dd15
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Sun Nov 5 21:54:25 2023 +0100
|
||||
|
||||
evaluate: place byteorder conversion before rshift in payload expressions
|
||||
|
||||
Use the key from the evaluation context to perform the byteorder
|
||||
conversion in case that this expression is used for lookups and updates
|
||||
on explicit sets.
|
||||
|
||||
# nft --debug=netlink add rule ip6 t output ip6 dscp @mapv6
|
||||
ip6 t output
|
||||
[ payload load 2b @ network header + 0 => reg 1 ]
|
||||
[ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
|
||||
[ byteorder reg 1 = ntoh(reg 1, 2, 2) ] <-------------- this was missing!
|
||||
[ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
|
||||
[ lookup reg 1 set mapv6 ]
|
||||
|
||||
Also with set statements (updates from packet path):
|
||||
|
||||
# nft --debug=netlink add rule ip6 t output update @mapv6 { ip6 dscp }
|
||||
ip6 t output
|
||||
[ payload load 2b @ network header + 0 => reg 1 ]
|
||||
[ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
|
||||
[ byteorder reg 1 = ntoh(reg 1, 2, 2) ] <------------- also here!
|
||||
[ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
|
||||
[ dynset update reg_key 1 set mapv6 ]
|
||||
|
||||
Simple matches on values and implicit sets rely on the binary transfer
|
||||
mechanism to propagate the shift to the constant, no explicit byteorder
|
||||
is required in such case.
|
||||
|
||||
Fixes: 668c18f67203 ("evaluate: place byteorder conversion before rshift in payload statement")
|
||||
Reported-by: Florian Westphal <fw@strlen.de>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 10 +++++++-
|
||||
tests/py/ip6/ip6.t | 4 ++++
|
||||
tests/py/ip6/ip6.t.json | 42 +++++++++++++++++++++++++++++++++
|
||||
tests/py/ip6/ip6.t.payload.inet | 21 +++++++++++++++++
|
||||
tests/py/ip6/ip6.t.payload.ip6 | 17 +++++++++++++
|
||||
5 files changed, 93 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 1850043..303e36c 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -545,7 +545,8 @@ static void expr_evaluate_bits(struct eval_ctx *ctx, struct expr **exprp)
|
||||
and->len = masklen;
|
||||
|
||||
if (shift) {
|
||||
- if (ctx->stmt_len > 0 && div_round_up(masklen, BITS_PER_BYTE) > 1) {
|
||||
+ if ((ctx->ectx.key || ctx->stmt_len > 0) &&
|
||||
+ div_round_up(masklen, BITS_PER_BYTE) > 1) {
|
||||
int op = byteorder_conversion_op(expr, BYTEORDER_HOST_ENDIAN);
|
||||
and = unary_expr_alloc(&expr->location, op, and);
|
||||
and->len = masklen;
|
||||
@@ -574,6 +575,7 @@ static void expr_evaluate_bits(struct eval_ctx *ctx, struct expr **exprp)
|
||||
|
||||
static int __expr_evaluate_exthdr(struct eval_ctx *ctx, struct expr **exprp)
|
||||
{
|
||||
+ const struct expr *key = ctx->ectx.key;
|
||||
struct expr *expr = *exprp;
|
||||
|
||||
if (expr->exthdr.flags & NFT_EXTHDR_F_PRESENT)
|
||||
@@ -582,6 +584,8 @@ static int __expr_evaluate_exthdr(struct eval_ctx *ctx, struct expr **exprp)
|
||||
if (expr_evaluate_primary(ctx, exprp) < 0)
|
||||
return -1;
|
||||
|
||||
+ ctx->ectx.key = key;
|
||||
+
|
||||
if (expr->exthdr.offset % BITS_PER_BYTE != 0 ||
|
||||
expr->len % BITS_PER_BYTE != 0)
|
||||
expr_evaluate_bits(ctx, exprp);
|
||||
@@ -878,6 +882,7 @@ static bool payload_needs_adjustment(const struct expr *expr)
|
||||
|
||||
static int expr_evaluate_payload(struct eval_ctx *ctx, struct expr **exprp)
|
||||
{
|
||||
+ const struct expr *key = ctx->ectx.key;
|
||||
struct expr *expr = *exprp;
|
||||
|
||||
if (expr->payload.evaluated)
|
||||
@@ -889,6 +894,8 @@ static int expr_evaluate_payload(struct eval_ctx *ctx, struct expr **exprp)
|
||||
if (expr_evaluate_primary(ctx, exprp) < 0)
|
||||
return -1;
|
||||
|
||||
+ ctx->ectx.key = key;
|
||||
+
|
||||
if (payload_needs_adjustment(expr))
|
||||
expr_evaluate_bits(ctx, exprp);
|
||||
|
||||
@@ -1508,6 +1515,7 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
|
||||
}
|
||||
|
||||
__expr_set_context(&ctx->ectx, tmp, bo, dsize, 0);
|
||||
+ ctx->ectx.key = i;
|
||||
|
||||
if (list_member_evaluate(ctx, &i) < 0)
|
||||
return -1;
|
||||
diff --git a/tests/py/ip6/ip6.t b/tests/py/ip6/ip6.t
|
||||
index 60ea223..430dd57 100644
|
||||
--- a/tests/py/ip6/ip6.t
|
||||
+++ b/tests/py/ip6/ip6.t
|
||||
@@ -21,6 +21,10 @@ ip6 dscp vmap { 0x04 : accept, 0x3f : continue } counter;ok
|
||||
meta mark set ip6 dscp map @map1;ok
|
||||
!map2 type dscp . ipv6_addr : mark;ok
|
||||
meta mark set ip6 dscp . ip6 daddr map @map2;ok
|
||||
+!map3 type dscp : mark;ok
|
||||
+ip6 dscp @map3;ok
|
||||
+!map4 type dscp . ipv6_addr : mark;ok
|
||||
+ip6 dscp . ip6 daddr @map4;ok
|
||||
|
||||
ip6 flowlabel 22;ok
|
||||
ip6 flowlabel != 233;ok
|
||||
diff --git a/tests/py/ip6/ip6.t.json b/tests/py/ip6/ip6.t.json
|
||||
index 5411190..49e5a2d 100644
|
||||
--- a/tests/py/ip6/ip6.t.json
|
||||
+++ b/tests/py/ip6/ip6.t.json
|
||||
@@ -193,6 +193,48 @@
|
||||
}
|
||||
]
|
||||
|
||||
+# ip6 dscp @map3
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "dscp",
|
||||
+ "protocol": "ip6"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": "@map3"
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# ip6 dscp . ip6 daddr @map4
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "concat": [
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "dscp",
|
||||
+ "protocol": "ip6"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "daddr",
|
||||
+ "protocol": "ip6"
|
||||
+ }
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": "@map4"
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
# ip6 flowlabel 22
|
||||
[
|
||||
{
|
||||
diff --git a/tests/py/ip6/ip6.t.payload.inet b/tests/py/ip6/ip6.t.payload.inet
|
||||
index 214a0ed..dbb430a 100644
|
||||
--- a/tests/py/ip6/ip6.t.payload.inet
|
||||
+++ b/tests/py/ip6/ip6.t.payload.inet
|
||||
@@ -76,6 +76,27 @@ inet test-inet input
|
||||
[ lookup reg 1 set map2 dreg 1 ]
|
||||
[ meta set mark with reg 1 ]
|
||||
|
||||
+# ip6 dscp @map3
|
||||
+inet test-inet input
|
||||
+ [ meta load nfproto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0000000a ]
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
|
||||
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
|
||||
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
|
||||
+ [ lookup reg 1 set map3 ]
|
||||
+
|
||||
+# ip6 dscp . ip6 daddr @map4
|
||||
+inet test-inet input
|
||||
+ [ meta load nfproto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0000000a ]
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
|
||||
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
|
||||
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
|
||||
+ [ payload load 16b @ network header + 24 => reg 9 ]
|
||||
+ [ lookup reg 1 set map4 ]
|
||||
+
|
||||
# ip6 flowlabel 22
|
||||
inet test-inet input
|
||||
[ meta load nfproto => reg 1 ]
|
||||
diff --git a/tests/py/ip6/ip6.t.payload.ip6 b/tests/py/ip6/ip6.t.payload.ip6
|
||||
index 428b8ea..b128923 100644
|
||||
--- a/tests/py/ip6/ip6.t.payload.ip6
|
||||
+++ b/tests/py/ip6/ip6.t.payload.ip6
|
||||
@@ -60,6 +60,23 @@ ip6 test-ip6 input
|
||||
[ lookup reg 1 set map2 dreg 1 ]
|
||||
[ meta set mark with reg 1 ]
|
||||
|
||||
+# ip6 dscp @map3
|
||||
+ip6 test-ip6 input
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
|
||||
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
|
||||
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
|
||||
+ [ lookup reg 1 set map3 ]
|
||||
+
|
||||
+# ip6 dscp . ip6 daddr @map4
|
||||
+ip6 test-ip6 input
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
|
||||
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
|
||||
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
|
||||
+ [ payload load 16b @ network header + 24 => reg 9 ]
|
||||
+ [ lookup reg 1 set map4 ]
|
||||
+
|
||||
# ip6 flowlabel 22
|
||||
ip6 test-ip6 input
|
||||
[ payload load 3b @ network header + 1 => reg 1 ]
|
||||
992
0025-src-add-free_const-and-use-it-instead-of-xfree.patch
Normal file
992
0025-src-add-free_const-and-use-it-instead-of-xfree.patch
Normal file
@ -0,0 +1,992 @@
|
||||
From 612339e3a96884fa9436ec56cfae355356a745e8 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:18 +0200
|
||||
Subject: [PATCH] src: add free_const() and use it instead of xfree()
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit ffd6b4790a728bd879cc8e4532b54150febb58fa
|
||||
Conflicts: One chunk omitted due to previous backport of commit
|
||||
4955ae1a81b73 ("Add support for table's persist flag")
|
||||
|
||||
commit ffd6b4790a728bd879cc8e4532b54150febb58fa
|
||||
Author: Thomas Haller <thaller@redhat.com>
|
||||
Date: Tue Oct 24 11:57:09 2023 +0200
|
||||
|
||||
src: add free_const() and use it instead of xfree()
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
include/nft.h | 6 ++
|
||||
src/ct.c | 2 +-
|
||||
src/datatype.c | 8 +--
|
||||
src/evaluate.c | 8 +--
|
||||
src/expression.c | 4 +-
|
||||
src/libnftables.c | 12 ++--
|
||||
src/mnl.c | 12 ++--
|
||||
src/optimize.c | 2 +-
|
||||
src/parser_bison.y | 138 ++++++++++++++++++++++-----------------------
|
||||
src/rule.c | 36 ++++++------
|
||||
src/scanner.l | 4 +-
|
||||
src/statement.c | 2 +-
|
||||
src/xt.c | 2 +-
|
||||
13 files changed, 121 insertions(+), 115 deletions(-)
|
||||
|
||||
diff --git a/include/nft.h b/include/nft.h
|
||||
index 3c894e5..a2d62db 100644
|
||||
--- a/include/nft.h
|
||||
+++ b/include/nft.h
|
||||
@@ -9,4 +9,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
+/* Just free(), but casts to a (void*). This is for places where
|
||||
+ * we have a const pointer that we know we want to free. We could just
|
||||
+ * do the (void*) cast, but free_const() makes it clear that this is
|
||||
+ * something we frequently need to do and it's intentional. */
|
||||
+#define free_const(ptr) free((void *)(ptr))
|
||||
+
|
||||
#endif /* NFTABLES_NFT_H */
|
||||
diff --git a/src/ct.c b/src/ct.c
|
||||
index 1dda799..ebfd90a 100644
|
||||
--- a/src/ct.c
|
||||
+++ b/src/ct.c
|
||||
@@ -570,7 +570,7 @@ static void flow_offload_stmt_print(const struct stmt *stmt,
|
||||
|
||||
static void flow_offload_stmt_destroy(struct stmt *stmt)
|
||||
{
|
||||
- xfree(stmt->flow.table_name);
|
||||
+ free_const(stmt->flow.table_name);
|
||||
}
|
||||
|
||||
static const struct stmt_ops flow_offload_stmt_ops = {
|
||||
diff --git a/src/datatype.c b/src/datatype.c
|
||||
index 9530ae7..9353ff2 100644
|
||||
--- a/src/datatype.c
|
||||
+++ b/src/datatype.c
|
||||
@@ -938,8 +938,8 @@ void rt_symbol_table_free(const struct symbol_table *tbl)
|
||||
const struct symbolic_constant *s;
|
||||
|
||||
for (s = tbl->symbols; s->identifier != NULL; s++)
|
||||
- xfree(s->identifier);
|
||||
- xfree(tbl);
|
||||
+ free_const(s->identifier);
|
||||
+ free_const(tbl);
|
||||
}
|
||||
|
||||
void mark_table_init(struct nft_ctx *ctx)
|
||||
@@ -1296,8 +1296,8 @@ void datatype_free(const struct datatype *ptr)
|
||||
if (--dtype->refcnt > 0)
|
||||
return;
|
||||
|
||||
- xfree(dtype->name);
|
||||
- xfree(dtype->desc);
|
||||
+ free_const(dtype->name);
|
||||
+ free_const(dtype->desc);
|
||||
xfree(dtype);
|
||||
}
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 303e36c..c41210b 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -4022,7 +4022,7 @@ static int stmt_evaluate_chain(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
memset(&h, 0, sizeof(h));
|
||||
handle_merge(&h, &chain->handle);
|
||||
h.family = ctx->rule->handle.family;
|
||||
- xfree(h.table.name);
|
||||
+ free_const(h.table.name);
|
||||
h.table.name = xstrdup(ctx->rule->handle.table.name);
|
||||
h.chain.location = stmt->location;
|
||||
h.chain_id = chain->handle.chain_id;
|
||||
@@ -4042,9 +4042,9 @@ static int stmt_evaluate_chain(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
struct handle h2 = {};
|
||||
|
||||
handle_merge(&rule->handle, &ctx->rule->handle);
|
||||
- xfree(rule->handle.table.name);
|
||||
+ free_const(rule->handle.table.name);
|
||||
rule->handle.table.name = xstrdup(ctx->rule->handle.table.name);
|
||||
- xfree(rule->handle.chain.name);
|
||||
+ free_const(rule->handle.chain.name);
|
||||
rule->handle.chain.name = NULL;
|
||||
rule->handle.chain_id = chain->handle.chain_id;
|
||||
if (rule_evaluate(&rule_ctx, rule, CMD_INVALID) < 0)
|
||||
@@ -5147,7 +5147,7 @@ static int ct_timeout_evaluate(struct eval_ctx *ctx, struct obj *obj)
|
||||
|
||||
ct->timeout[ts->timeout_index] = ts->timeout_value;
|
||||
list_del(&ts->head);
|
||||
- xfree(ts->timeout_str);
|
||||
+ free_const(ts->timeout_str);
|
||||
xfree(ts);
|
||||
}
|
||||
|
||||
diff --git a/src/expression.c b/src/expression.c
|
||||
index a21dfec..0b4a537 100644
|
||||
--- a/src/expression.c
|
||||
+++ b/src/expression.c
|
||||
@@ -314,7 +314,7 @@ static void symbol_expr_clone(struct expr *new, const struct expr *expr)
|
||||
|
||||
static void symbol_expr_destroy(struct expr *expr)
|
||||
{
|
||||
- xfree(expr->identifier);
|
||||
+ free_const(expr->identifier);
|
||||
}
|
||||
|
||||
static const struct expr_ops symbol_expr_ops = {
|
||||
@@ -1335,7 +1335,7 @@ static void set_elem_expr_destroy(struct expr *expr)
|
||||
{
|
||||
struct stmt *stmt, *next;
|
||||
|
||||
- xfree(expr->comment);
|
||||
+ free_const(expr->comment);
|
||||
expr_free(expr->key);
|
||||
list_for_each_entry_safe(stmt, next, &expr->stmt_list, list)
|
||||
stmt_free(stmt);
|
||||
diff --git a/src/libnftables.c b/src/libnftables.c
|
||||
index 41f54c0..866b5c6 100644
|
||||
--- a/src/libnftables.c
|
||||
+++ b/src/libnftables.c
|
||||
@@ -154,8 +154,8 @@ void nft_ctx_clear_vars(struct nft_ctx *ctx)
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ctx->num_vars; i++) {
|
||||
- xfree(ctx->vars[i].key);
|
||||
- xfree(ctx->vars[i].value);
|
||||
+ free_const(ctx->vars[i].key);
|
||||
+ free_const(ctx->vars[i].value);
|
||||
}
|
||||
ctx->num_vars = 0;
|
||||
xfree(ctx->vars);
|
||||
@@ -743,12 +743,12 @@ err:
|
||||
|
||||
list_for_each_entry_safe(indesc, next, &nft->vars_ctx.indesc_list, list) {
|
||||
if (indesc->name)
|
||||
- xfree(indesc->name);
|
||||
+ free_const(indesc->name);
|
||||
|
||||
xfree(indesc);
|
||||
}
|
||||
}
|
||||
- xfree(nft->vars_ctx.buf);
|
||||
+ free_const(nft->vars_ctx.buf);
|
||||
|
||||
if (!rc &&
|
||||
nft_output_json(&nft->output) &&
|
||||
@@ -799,12 +799,12 @@ int nft_run_cmd_from_filename(struct nft_ctx *nft, const char *filename)
|
||||
|
||||
if (nft->optimize_flags) {
|
||||
ret = nft_run_optimized_file(nft, filename);
|
||||
- xfree(nft->stdin_buf);
|
||||
+ free_const(nft->stdin_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __nft_run_cmd_from_filename(nft, filename);
|
||||
- xfree(nft->stdin_buf);
|
||||
+ free_const(nft->stdin_buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
diff --git a/src/mnl.c b/src/mnl.c
|
||||
index 0fb36bd..0158924 100644
|
||||
--- a/src/mnl.c
|
||||
+++ b/src/mnl.c
|
||||
@@ -776,9 +776,9 @@ static void nft_dev_array_free(const struct nft_dev *dev_array)
|
||||
int i = 0;
|
||||
|
||||
while (dev_array[i].ifname != NULL)
|
||||
- xfree(dev_array[i++].ifname);
|
||||
+ free_const(dev_array[i++].ifname);
|
||||
|
||||
- xfree(dev_array);
|
||||
+ free_const(dev_array);
|
||||
}
|
||||
|
||||
static void mnl_nft_chain_devs_build(struct nlmsghdr *nlh, struct cmd *cmd)
|
||||
@@ -2175,10 +2175,10 @@ static struct basehook *basehook_alloc(void)
|
||||
static void basehook_free(struct basehook *b)
|
||||
{
|
||||
list_del(&b->list);
|
||||
- xfree(b->module_name);
|
||||
- xfree(b->hookfn);
|
||||
- xfree(b->chain);
|
||||
- xfree(b->table);
|
||||
+ free_const(b->module_name);
|
||||
+ free_const(b->hookfn);
|
||||
+ free_const(b->chain);
|
||||
+ free_const(b->table);
|
||||
xfree(b);
|
||||
}
|
||||
|
||||
diff --git a/src/optimize.c b/src/optimize.c
|
||||
index 27e0ffe..9ae9283 100644
|
||||
--- a/src/optimize.c
|
||||
+++ b/src/optimize.c
|
||||
@@ -1194,7 +1194,7 @@ static void merge_rules(const struct optimize_ctx *ctx,
|
||||
}
|
||||
|
||||
if (ctx->rule[from]->comment) {
|
||||
- xfree(ctx->rule[from]->comment);
|
||||
+ free_const(ctx->rule[from]->comment);
|
||||
ctx->rule[from]->comment = NULL;
|
||||
}
|
||||
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 5c2d14b..b485a48 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -154,13 +154,13 @@ static struct expr *ifname_expr_alloc(const struct location *location,
|
||||
struct expr *expr;
|
||||
|
||||
if (length == 0) {
|
||||
- xfree(name);
|
||||
+ free_const(name);
|
||||
erec_queue(error(location, "empty interface name"), queue);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (length >= IFNAMSIZ) {
|
||||
- xfree(name);
|
||||
+ free_const(name);
|
||||
erec_queue(error(location, "interface name too long"), queue);
|
||||
return NULL;
|
||||
}
|
||||
@@ -168,7 +168,7 @@ static struct expr *ifname_expr_alloc(const struct location *location,
|
||||
expr = constant_expr_alloc(location, &ifname_type, BYTEORDER_HOST_ENDIAN,
|
||||
length * BITS_PER_BYTE, name);
|
||||
|
||||
- xfree(name);
|
||||
+ free_const(name);
|
||||
|
||||
return expr;
|
||||
}
|
||||
@@ -358,7 +358,7 @@ int nft_lex(void *, void *, void *);
|
||||
%token <string> STRING "string"
|
||||
%token <string> QUOTED_STRING "quoted string"
|
||||
%token <string> ASTERISK_STRING "string with a trailing asterisk"
|
||||
-%destructor { xfree($$); } STRING QUOTED_STRING ASTERISK_STRING
|
||||
+%destructor { free_const($$); } STRING QUOTED_STRING ASTERISK_STRING
|
||||
|
||||
%token LL_HDR "ll"
|
||||
%token NETWORK_HDR "nh"
|
||||
@@ -674,7 +674,7 @@ int nft_lex(void *, void *, void *);
|
||||
%type <limit_rate> limit_rate_bytes
|
||||
|
||||
%type <string> identifier type_identifier string comment_spec
|
||||
-%destructor { xfree($$); } identifier type_identifier string comment_spec
|
||||
+%destructor { free_const($$); } identifier type_identifier string comment_spec
|
||||
|
||||
%type <val> time_spec time_spec_or_num_s quota_used
|
||||
|
||||
@@ -709,7 +709,7 @@ int nft_lex(void *, void *, void *);
|
||||
%type <val32> int_num chain_policy
|
||||
%type <prio_spec> extended_prio_spec prio_spec
|
||||
%type <string> extended_prio_name quota_unit basehook_device_name
|
||||
-%destructor { xfree($$); } extended_prio_name quota_unit basehook_device_name
|
||||
+%destructor { free_const($$); } extended_prio_name quota_unit basehook_device_name
|
||||
|
||||
%type <expr> dev_spec
|
||||
%destructor { xfree($$); } dev_spec
|
||||
@@ -930,7 +930,7 @@ int nft_lex(void *, void *, void *);
|
||||
|
||||
%type <val> markup_format
|
||||
%type <string> monitor_event
|
||||
-%destructor { xfree($$); } monitor_event
|
||||
+%destructor { free_const($$); } monitor_event
|
||||
%type <val> monitor_object monitor_format
|
||||
|
||||
%type <val> synproxy_ts synproxy_sack
|
||||
@@ -1055,10 +1055,10 @@ close_scope_xt : { scanner_pop_start_cond(nft->scanner, PARSER_SC_XT); }
|
||||
common_block : INCLUDE QUOTED_STRING stmt_separator
|
||||
{
|
||||
if (scanner_include_file(nft, scanner, $2, &@$) < 0) {
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
}
|
||||
| DEFINE identifier '=' initializer_expr stmt_separator
|
||||
{
|
||||
@@ -1068,19 +1068,19 @@ common_block : INCLUDE QUOTED_STRING stmt_separator
|
||||
erec_queue(error(&@2, "redefinition of symbol '%s'", $2),
|
||||
state->msgs);
|
||||
expr_free($4);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
|
||||
symbol_bind(scope, $2, $4);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
}
|
||||
| REDEFINE identifier '=' initializer_expr stmt_separator
|
||||
{
|
||||
struct scope *scope = current_scope(state);
|
||||
|
||||
symbol_bind(scope, $2, $4);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
}
|
||||
| UNDEFINE identifier stmt_separator
|
||||
{
|
||||
@@ -1089,10 +1089,10 @@ common_block : INCLUDE QUOTED_STRING stmt_separator
|
||||
if (symbol_unbind(scope, $2) < 0) {
|
||||
erec_queue(error(&@2, "undefined symbol '%s'", $2),
|
||||
state->msgs);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
}
|
||||
| error stmt_separator
|
||||
{
|
||||
@@ -1884,7 +1884,7 @@ table_options : FLAGS table_flags
|
||||
| comment_spec
|
||||
{
|
||||
if (already_set($<table>0->comment, &@$, state)) {
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
YYERROR;
|
||||
}
|
||||
$<table>0->comment = $1;
|
||||
@@ -2073,7 +2073,7 @@ chain_block : /* empty */ { $$ = $<chain>-1; }
|
||||
| chain_block comment_spec stmt_separator
|
||||
{
|
||||
if (already_set($1->comment, &@2, state)) {
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
$1->comment = $2;
|
||||
@@ -2199,7 +2199,7 @@ set_block : /* empty */ { $$ = $<set>-1; }
|
||||
| set_block comment_spec stmt_separator
|
||||
{
|
||||
if (already_set($1->comment, &@2, state)) {
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
$1->comment = $2;
|
||||
@@ -2316,7 +2316,7 @@ map_block : /* empty */ { $$ = $<set>-1; }
|
||||
| map_block comment_spec stmt_separator
|
||||
{
|
||||
if (already_set($1->comment, &@2, state)) {
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
$1->comment = $2;
|
||||
@@ -2355,10 +2355,10 @@ flowtable_block : /* empty */ { $$ = $<flowtable>-1; }
|
||||
if ($$->hook.name == NULL) {
|
||||
erec_queue(error(&@3, "unknown chain hook"),
|
||||
state->msgs);
|
||||
- xfree($3);
|
||||
+ free_const($3);
|
||||
YYERROR;
|
||||
}
|
||||
- xfree($3);
|
||||
+ free_const($3);
|
||||
|
||||
$$->priority = $4;
|
||||
}
|
||||
@@ -2432,12 +2432,12 @@ data_type_atom_expr : type_identifier
|
||||
if (dtype == NULL) {
|
||||
erec_queue(error(&@1, "unknown datatype %s", $1),
|
||||
state->msgs);
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
YYERROR;
|
||||
}
|
||||
$$ = constant_expr_alloc(&@1, dtype, dtype->byteorder,
|
||||
dtype->size, NULL);
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
}
|
||||
| TIME
|
||||
{
|
||||
@@ -2474,7 +2474,7 @@ counter_block : /* empty */ { $$ = $<obj>-1; }
|
||||
| counter_block comment_spec
|
||||
{
|
||||
if (already_set($<obj>1->comment, &@2, state)) {
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
$<obj>1->comment = $2;
|
||||
@@ -2491,7 +2491,7 @@ quota_block : /* empty */ { $$ = $<obj>-1; }
|
||||
| quota_block comment_spec
|
||||
{
|
||||
if (already_set($<obj>1->comment, &@2, state)) {
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
$<obj>1->comment = $2;
|
||||
@@ -2508,7 +2508,7 @@ ct_helper_block : /* empty */ { $$ = $<obj>-1; }
|
||||
| ct_helper_block comment_spec
|
||||
{
|
||||
if (already_set($<obj>1->comment, &@2, state)) {
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
$<obj>1->comment = $2;
|
||||
@@ -2529,7 +2529,7 @@ ct_timeout_block : /*empty */
|
||||
| ct_timeout_block comment_spec
|
||||
{
|
||||
if (already_set($<obj>1->comment, &@2, state)) {
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
$<obj>1->comment = $2;
|
||||
@@ -2546,7 +2546,7 @@ ct_expect_block : /*empty */ { $$ = $<obj>-1; }
|
||||
| ct_expect_block comment_spec
|
||||
{
|
||||
if (already_set($<obj>1->comment, &@2, state)) {
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
$<obj>1->comment = $2;
|
||||
@@ -2563,7 +2563,7 @@ limit_block : /* empty */ { $$ = $<obj>-1; }
|
||||
| limit_block comment_spec
|
||||
{
|
||||
if (already_set($<obj>1->comment, &@2, state)) {
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
$<obj>1->comment = $2;
|
||||
@@ -2580,7 +2580,7 @@ secmark_block : /* empty */ { $$ = $<obj>-1; }
|
||||
| secmark_block comment_spec
|
||||
{
|
||||
if (already_set($<obj>1->comment, &@2, state)) {
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
$<obj>1->comment = $2;
|
||||
@@ -2597,7 +2597,7 @@ synproxy_block : /* empty */ { $$ = $<obj>-1; }
|
||||
| synproxy_block comment_spec
|
||||
{
|
||||
if (already_set($<obj>1->comment, &@2, state)) {
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
$<obj>1->comment = $2;
|
||||
@@ -2618,12 +2618,12 @@ hook_spec : TYPE close_scope_type STRING HOOK STRING dev_spec prio_spec
|
||||
if (chain_type == NULL) {
|
||||
erec_queue(error(&@3, "unknown chain type"),
|
||||
state->msgs);
|
||||
- xfree($3);
|
||||
+ free_const($3);
|
||||
YYERROR;
|
||||
}
|
||||
$<chain>0->type.loc = @3;
|
||||
$<chain>0->type.str = xstrdup(chain_type);
|
||||
- xfree($3);
|
||||
+ free_const($3);
|
||||
|
||||
$<chain>0->loc = @$;
|
||||
$<chain>0->hook.loc = @5;
|
||||
@@ -2631,10 +2631,10 @@ hook_spec : TYPE close_scope_type STRING HOOK STRING dev_spec prio_spec
|
||||
if ($<chain>0->hook.name == NULL) {
|
||||
erec_queue(error(&@5, "unknown chain hook"),
|
||||
state->msgs);
|
||||
- xfree($5);
|
||||
+ free_const($5);
|
||||
YYERROR;
|
||||
}
|
||||
- xfree($5);
|
||||
+ free_const($5);
|
||||
|
||||
$<chain>0->dev_expr = $6;
|
||||
$<chain>0->priority = $7;
|
||||
@@ -2681,7 +2681,7 @@ extended_prio_spec : int_num
|
||||
BYTEORDER_HOST_ENDIAN,
|
||||
strlen($1) * BITS_PER_BYTE,
|
||||
$1);
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
$$ = spec;
|
||||
}
|
||||
| extended_prio_name PLUS NUM
|
||||
@@ -2694,7 +2694,7 @@ extended_prio_spec : int_num
|
||||
BYTEORDER_HOST_ENDIAN,
|
||||
strlen(str) * BITS_PER_BYTE,
|
||||
str);
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
$$ = spec;
|
||||
}
|
||||
| extended_prio_name DASH NUM
|
||||
@@ -2707,7 +2707,7 @@ extended_prio_spec : int_num
|
||||
BYTEORDER_HOST_ENDIAN,
|
||||
strlen(str) * BITS_PER_BYTE,
|
||||
str);
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
$$ = spec;
|
||||
}
|
||||
;
|
||||
@@ -2792,7 +2792,7 @@ time_spec : STRING
|
||||
uint64_t res;
|
||||
|
||||
erec = time_parse(&@1, $1, &res);
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
if (erec != NULL) {
|
||||
erec_queue(erec, state->msgs);
|
||||
YYERROR;
|
||||
@@ -2993,7 +2993,7 @@ comment_spec : COMMENT string
|
||||
erec_queue(error(&@2, "comment too long, %d characters maximum allowed",
|
||||
NFTNL_UDATA_COMMENT_MAXLEN),
|
||||
state->msgs);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
$$ = $2;
|
||||
@@ -3094,8 +3094,8 @@ stmt : verdict_stmt
|
||||
xt_stmt : XT STRING string
|
||||
{
|
||||
$$ = NULL;
|
||||
- xfree($2);
|
||||
- xfree($3);
|
||||
+ free_const($2);
|
||||
+ free_const($3);
|
||||
erec_queue(error(&@$, "unsupported xtables compat expression, use iptables-nft with this ruleset"),
|
||||
state->msgs);
|
||||
YYERROR;
|
||||
@@ -3253,7 +3253,7 @@ log_arg : PREFIX string
|
||||
expr = constant_expr_alloc(&@$, &string_type,
|
||||
BYTEORDER_HOST_ENDIAN,
|
||||
(strlen($2) + 1) * BITS_PER_BYTE, $2);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
$<stmt>0->log.prefix = expr;
|
||||
$<stmt>0->log.flags |= STMT_LOG_PREFIX;
|
||||
break;
|
||||
@@ -3327,7 +3327,7 @@ log_arg : PREFIX string
|
||||
state->msgs);
|
||||
}
|
||||
expr_free(expr);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
item = variable_expr_alloc(&@$, scope, sym);
|
||||
@@ -3357,7 +3357,7 @@ log_arg : PREFIX string
|
||||
}
|
||||
}
|
||||
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
$<stmt>0->log.prefix = expr;
|
||||
$<stmt>0->log.flags |= STMT_LOG_PREFIX;
|
||||
}
|
||||
@@ -3410,10 +3410,10 @@ level_type : string
|
||||
else {
|
||||
erec_queue(error(&@1, "invalid log level"),
|
||||
state->msgs);
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
YYERROR;
|
||||
}
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -3503,7 +3503,7 @@ quota_used : /* empty */ { $$ = 0; }
|
||||
uint64_t rate;
|
||||
|
||||
erec = data_unit_parse(&@$, $3, &rate);
|
||||
- xfree($3);
|
||||
+ free_const($3);
|
||||
if (erec != NULL) {
|
||||
erec_queue(erec, state->msgs);
|
||||
YYERROR;
|
||||
@@ -3518,7 +3518,7 @@ quota_stmt : QUOTA quota_mode NUM quota_unit quota_used close_scope_quota
|
||||
uint64_t rate;
|
||||
|
||||
erec = data_unit_parse(&@$, $4, &rate);
|
||||
- xfree($4);
|
||||
+ free_const($4);
|
||||
if (erec != NULL) {
|
||||
erec_queue(erec, state->msgs);
|
||||
YYERROR;
|
||||
@@ -3562,7 +3562,7 @@ limit_rate_bytes : NUM STRING
|
||||
uint64_t rate, unit;
|
||||
|
||||
erec = rate_parse(&@$, $2, &rate, &unit);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
if (erec != NULL) {
|
||||
erec_queue(erec, state->msgs);
|
||||
YYERROR;
|
||||
@@ -3584,7 +3584,7 @@ limit_bytes : NUM BYTES { $$ = $1; }
|
||||
uint64_t rate;
|
||||
|
||||
erec = data_unit_parse(&@$, $2, &rate);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
if (erec != NULL) {
|
||||
erec_queue(erec, state->msgs);
|
||||
YYERROR;
|
||||
@@ -3613,7 +3613,7 @@ reject_with_expr : STRING
|
||||
{
|
||||
$$ = symbol_expr_alloc(&@$, SYMBOL_VALUE,
|
||||
current_scope(state), $1);
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
}
|
||||
| integer_expr { $$ = $1; }
|
||||
;
|
||||
@@ -4277,12 +4277,12 @@ variable_expr : '$' identifier
|
||||
erec_queue(error(&@2, "unknown identifier '%s'", $2),
|
||||
state->msgs);
|
||||
}
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
|
||||
$$ = variable_expr_alloc(&@$, scope, sym);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -4292,7 +4292,7 @@ symbol_expr : variable_expr
|
||||
$$ = symbol_expr_alloc(&@$, SYMBOL_VALUE,
|
||||
current_scope(state),
|
||||
$1);
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -4305,7 +4305,7 @@ set_ref_symbol_expr : AT identifier close_scope_at
|
||||
$$ = symbol_expr_alloc(&@$, SYMBOL_SET,
|
||||
current_scope(state),
|
||||
$2);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -4402,10 +4402,10 @@ osf_ttl : /* empty */
|
||||
else {
|
||||
erec_queue(error(&@2, "invalid ttl option"),
|
||||
state->msgs);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
YYERROR;
|
||||
}
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -4575,7 +4575,7 @@ set_elem_option : TIMEOUT time_spec
|
||||
| comment_spec
|
||||
{
|
||||
if (already_set($<expr>0->comment, &@1, state)) {
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
YYERROR;
|
||||
}
|
||||
$<expr>0->comment = $1;
|
||||
@@ -4657,7 +4657,7 @@ set_elem_stmt : COUNTER close_scope_counter
|
||||
uint64_t rate;
|
||||
|
||||
erec = data_unit_parse(&@$, $4, &rate);
|
||||
- xfree($4);
|
||||
+ free_const($4);
|
||||
if (erec != NULL) {
|
||||
erec_queue(erec, state->msgs);
|
||||
YYERROR;
|
||||
@@ -4690,7 +4690,7 @@ set_elem_expr_option : TIMEOUT time_spec
|
||||
| comment_spec
|
||||
{
|
||||
if (already_set($<expr>0->comment, &@1, state)) {
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
YYERROR;
|
||||
}
|
||||
$<expr>0->comment = $1;
|
||||
@@ -4742,7 +4742,7 @@ quota_config : quota_mode NUM quota_unit quota_used
|
||||
uint64_t rate;
|
||||
|
||||
erec = data_unit_parse(&@$, $3, &rate);
|
||||
- xfree($3);
|
||||
+ free_const($3);
|
||||
if (erec != NULL) {
|
||||
erec_queue(erec, state->msgs);
|
||||
YYERROR;
|
||||
@@ -4771,10 +4771,10 @@ secmark_config : string
|
||||
ret = snprintf(secmark->ctx, sizeof(secmark->ctx), "%s", $1);
|
||||
if (ret <= 0 || ret >= (int)sizeof(secmark->ctx)) {
|
||||
erec_queue(error(&@1, "invalid context '%s', max length is %u\n", $1, (int)sizeof(secmark->ctx)), state->msgs);
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
YYERROR;
|
||||
}
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -4811,7 +4811,7 @@ ct_helper_config : TYPE QUOTED_STRING PROTOCOL ct_l4protoname stmt_separator cl
|
||||
erec_queue(error(&@2, "invalid name '%s', max length is %u\n", $2, (int)sizeof(ct->name)), state->msgs);
|
||||
YYERROR;
|
||||
}
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
|
||||
ct->l4proto = $4;
|
||||
}
|
||||
@@ -5206,7 +5206,7 @@ chain_expr : variable_expr
|
||||
BYTEORDER_HOST_ENDIAN,
|
||||
strlen($1) * BITS_PER_BYTE,
|
||||
$1);
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -5224,7 +5224,7 @@ meta_expr : META meta_key close_scope_meta
|
||||
unsigned int key;
|
||||
|
||||
erec = meta_key_parse(&@$, $2, &key);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
if (erec != NULL) {
|
||||
erec_queue(erec, state->msgs);
|
||||
YYERROR;
|
||||
@@ -5301,7 +5301,7 @@ meta_stmt : META meta_key SET stmt_expr close_scope_meta
|
||||
unsigned int key;
|
||||
|
||||
erec = meta_key_parse(&@$, $2, &key);
|
||||
- xfree($2);
|
||||
+ free_const($2);
|
||||
if (erec != NULL) {
|
||||
erec_queue(erec, state->msgs);
|
||||
YYERROR;
|
||||
@@ -5612,10 +5612,10 @@ payload_base_spec : LL_HDR { $$ = PROTO_BASE_LL_HDR; }
|
||||
$$ = PROTO_BASE_INNER_HDR;
|
||||
} else {
|
||||
erec_queue(error(&@1, "unknown raw payload base"), state->msgs);
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
YYERROR;
|
||||
}
|
||||
- xfree($1);
|
||||
+ free_const($1);
|
||||
}
|
||||
;
|
||||
|
||||
diff --git a/src/rule.c b/src/rule.c
|
||||
index a0e151d..76cd58c 100644
|
||||
--- a/src/rule.c
|
||||
+++ b/src/rule.c
|
||||
@@ -104,11 +104,11 @@ int timeout_str2num(uint16_t l4proto, struct timeout_state *ts)
|
||||
|
||||
void handle_free(struct handle *h)
|
||||
{
|
||||
- xfree(h->table.name);
|
||||
- xfree(h->chain.name);
|
||||
- xfree(h->set.name);
|
||||
- xfree(h->flowtable.name);
|
||||
- xfree(h->obj.name);
|
||||
+ free_const(h->table.name);
|
||||
+ free_const(h->chain.name);
|
||||
+ free_const(h->set.name);
|
||||
+ free_const(h->flowtable.name);
|
||||
+ free_const(h->obj.name);
|
||||
}
|
||||
|
||||
void handle_merge(struct handle *dst, const struct handle *src)
|
||||
@@ -194,7 +194,7 @@ void set_free(struct set *set)
|
||||
|
||||
expr_free(set->init);
|
||||
if (set->comment)
|
||||
- xfree(set->comment);
|
||||
+ free_const(set->comment);
|
||||
handle_free(&set->handle);
|
||||
list_for_each_entry_safe(stmt, next, &set->stmt_list, list)
|
||||
stmt_free(stmt);
|
||||
@@ -479,7 +479,7 @@ void rule_free(struct rule *rule)
|
||||
return;
|
||||
stmt_list_free(&rule->stmts);
|
||||
handle_free(&rule->handle);
|
||||
- xfree(rule->comment);
|
||||
+ free_const(rule->comment);
|
||||
xfree(rule);
|
||||
}
|
||||
|
||||
@@ -557,7 +557,7 @@ void scope_release(const struct scope *scope)
|
||||
list_for_each_entry_safe(sym, next, &scope->symbols, list) {
|
||||
assert(sym->refcnt == 1);
|
||||
list_del(&sym->list);
|
||||
- xfree(sym->identifier);
|
||||
+ free_const(sym->identifier);
|
||||
expr_free(sym->expr);
|
||||
xfree(sym);
|
||||
}
|
||||
@@ -597,7 +597,7 @@ struct symbol *symbol_get(const struct scope *scope, const char *identifier)
|
||||
static void symbol_put(struct symbol *sym)
|
||||
{
|
||||
if (--sym->refcnt == 0) {
|
||||
- xfree(sym->identifier);
|
||||
+ free_const(sym->identifier);
|
||||
expr_free(sym->expr);
|
||||
xfree(sym);
|
||||
}
|
||||
@@ -730,14 +730,14 @@ void chain_free(struct chain *chain)
|
||||
rule_free(rule);
|
||||
handle_free(&chain->handle);
|
||||
scope_release(&chain->scope);
|
||||
- xfree(chain->type.str);
|
||||
+ free_const(chain->type.str);
|
||||
expr_free(chain->dev_expr);
|
||||
for (i = 0; i < chain->dev_array_len; i++)
|
||||
- xfree(chain->dev_array[i]);
|
||||
+ free_const(chain->dev_array[i]);
|
||||
xfree(chain->dev_array);
|
||||
expr_free(chain->priority.expr);
|
||||
expr_free(chain->policy);
|
||||
- xfree(chain->comment);
|
||||
+ free_const(chain->comment);
|
||||
xfree(chain);
|
||||
}
|
||||
|
||||
@@ -1151,7 +1151,7 @@ void table_free(struct table *table)
|
||||
if (--table->refcnt > 0)
|
||||
return;
|
||||
if (table->comment)
|
||||
- xfree(table->comment);
|
||||
+ free_const(table->comment);
|
||||
list_for_each_entry_safe(chain, next, &table->chains, list)
|
||||
chain_free(chain);
|
||||
list_for_each_entry_safe(chain, next, &table->chain_bindings, cache.list)
|
||||
@@ -1360,7 +1360,7 @@ struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event)
|
||||
|
||||
void monitor_free(struct monitor *m)
|
||||
{
|
||||
- xfree(m->event);
|
||||
+ free_const(m->event);
|
||||
xfree(m);
|
||||
}
|
||||
|
||||
@@ -1416,7 +1416,7 @@ void cmd_free(struct cmd *cmd)
|
||||
}
|
||||
}
|
||||
xfree(cmd->attr);
|
||||
- xfree(cmd->arg);
|
||||
+ free_const(cmd->arg);
|
||||
xfree(cmd);
|
||||
}
|
||||
|
||||
@@ -1654,14 +1654,14 @@ void obj_free(struct obj *obj)
|
||||
{
|
||||
if (--obj->refcnt > 0)
|
||||
return;
|
||||
- xfree(obj->comment);
|
||||
+ free_const(obj->comment);
|
||||
handle_free(&obj->handle);
|
||||
if (obj->type == NFT_OBJECT_CT_TIMEOUT) {
|
||||
struct timeout_state *ts, *next;
|
||||
|
||||
list_for_each_entry_safe(ts, next, &obj->ct_timeout.timeout_list, head) {
|
||||
list_del(&ts->head);
|
||||
- xfree(ts->timeout_str);
|
||||
+ free_const(ts->timeout_str);
|
||||
xfree(ts);
|
||||
}
|
||||
}
|
||||
@@ -2074,7 +2074,7 @@ void flowtable_free(struct flowtable *flowtable)
|
||||
|
||||
if (flowtable->dev_array != NULL) {
|
||||
for (i = 0; i < flowtable->dev_array_len; i++)
|
||||
- xfree(flowtable->dev_array[i]);
|
||||
+ free_const(flowtable->dev_array[i]);
|
||||
xfree(flowtable->dev_array);
|
||||
}
|
||||
xfree(flowtable);
|
||||
diff --git a/src/scanner.l b/src/scanner.l
|
||||
index 88376b7..93a31f2 100644
|
||||
--- a/src/scanner.l
|
||||
+++ b/src/scanner.l
|
||||
@@ -1261,8 +1261,8 @@ void *scanner_init(struct parser_state *state)
|
||||
static void input_descriptor_destroy(const struct input_descriptor *indesc)
|
||||
{
|
||||
if (indesc->name)
|
||||
- xfree(indesc->name);
|
||||
- xfree(indesc);
|
||||
+ free_const(indesc->name);
|
||||
+ free_const(indesc);
|
||||
}
|
||||
|
||||
static void input_descriptor_list_destroy(struct parser_state *state)
|
||||
diff --git a/src/statement.c b/src/statement.c
|
||||
index f5176e6..994b522 100644
|
||||
--- a/src/statement.c
|
||||
+++ b/src/statement.c
|
||||
@@ -183,7 +183,7 @@ static void meter_stmt_destroy(struct stmt *stmt)
|
||||
expr_free(stmt->meter.key);
|
||||
expr_free(stmt->meter.set);
|
||||
stmt_free(stmt->meter.stmt);
|
||||
- xfree(stmt->meter.name);
|
||||
+ free_const(stmt->meter.name);
|
||||
}
|
||||
|
||||
static const struct stmt_ops meter_stmt_ops = {
|
||||
diff --git a/src/xt.c b/src/xt.c
|
||||
index 3cb5f02..48b2873 100644
|
||||
--- a/src/xt.c
|
||||
+++ b/src/xt.c
|
||||
@@ -124,7 +124,7 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx)
|
||||
|
||||
void xt_stmt_destroy(struct stmt *stmt)
|
||||
{
|
||||
- xfree(stmt->xt.name);
|
||||
+ free_const(stmt->xt.name);
|
||||
xfree(stmt->xt.info);
|
||||
}
|
||||
|
||||
635
0026-src-remove-xfree-and-use-plain-free.patch
Normal file
635
0026-src-remove-xfree-and-use-plain-free.patch
Normal file
@ -0,0 +1,635 @@
|
||||
From 91824e5e97716d8d433ea8c064bd7eb701e006f6 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:40 +0200
|
||||
Subject: [PATCH] src: remove xfree() and use plain free()
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit d7af8ab26d62e602b73e1017183f899923d8d5ae
|
||||
|
||||
commit d7af8ab26d62e602b73e1017183f899923d8d5ae
|
||||
Author: Thomas Haller <thaller@redhat.com>
|
||||
Date: Tue Oct 24 11:57:10 2023 +0200
|
||||
|
||||
src: remove xfree() and use plain free()
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
include/utils.h | 1 -
|
||||
src/cache.c | 6 +++---
|
||||
src/datatype.c | 4 ++--
|
||||
src/erec.c | 6 +++---
|
||||
src/evaluate.c | 4 ++--
|
||||
src/expression.c | 2 +-
|
||||
src/json.c | 2 +-
|
||||
src/libnftables.c | 12 ++++++------
|
||||
src/meta.c | 4 ++--
|
||||
src/misspell.c | 2 +-
|
||||
src/mnl.c | 4 ++--
|
||||
src/netlink_linearize.c | 4 ++--
|
||||
src/optimize.c | 10 +++++-----
|
||||
src/parser_bison.y | 14 +++++++-------
|
||||
src/rule.c | 32 ++++++++++++++++----------------
|
||||
src/scanner.l | 2 +-
|
||||
src/segtree.c | 4 ++--
|
||||
src/statement.c | 2 +-
|
||||
src/utils.c | 5 -----
|
||||
src/xt.c | 8 ++++----
|
||||
20 files changed, 61 insertions(+), 67 deletions(-)
|
||||
|
||||
diff --git a/include/utils.h b/include/utils.h
|
||||
index 36a28f8..e18fabe 100644
|
||||
--- a/include/utils.h
|
||||
+++ b/include/utils.h
|
||||
@@ -142,7 +142,6 @@ extern void __memory_allocation_error(const char *filename, uint32_t line) __nor
|
||||
#define memory_allocation_error() \
|
||||
__memory_allocation_error(__FILE__, __LINE__);
|
||||
|
||||
-extern void xfree(const void *ptr);
|
||||
extern void *xmalloc(size_t size);
|
||||
extern void *xmalloc_array(size_t nmemb, size_t size);
|
||||
extern void *xrealloc(void *ptr, size_t size);
|
||||
diff --git a/src/cache.c b/src/cache.c
|
||||
index 0ac0f7c..a3cd795 100644
|
||||
--- a/src/cache.c
|
||||
+++ b/src/cache.c
|
||||
@@ -126,9 +126,9 @@ void nft_cache_filter_fini(struct nft_cache_filter *filter)
|
||||
struct nft_filter_obj *obj, *next;
|
||||
|
||||
list_for_each_entry_safe(obj, next, &filter->obj[i].head, list)
|
||||
- xfree(obj);
|
||||
+ free(obj);
|
||||
}
|
||||
- xfree(filter);
|
||||
+ free(filter);
|
||||
}
|
||||
|
||||
static void cache_filter_add(struct nft_cache_filter *filter,
|
||||
@@ -1275,7 +1275,7 @@ void cache_init(struct cache *cache)
|
||||
|
||||
void cache_free(struct cache *cache)
|
||||
{
|
||||
- xfree(cache->ht);
|
||||
+ free(cache->ht);
|
||||
}
|
||||
|
||||
void cache_add(struct cache_item *item, struct cache *cache, uint32_t hash)
|
||||
diff --git a/src/datatype.c b/src/datatype.c
|
||||
index 9353ff2..a92f41d 100644
|
||||
--- a/src/datatype.c
|
||||
+++ b/src/datatype.c
|
||||
@@ -1298,7 +1298,7 @@ void datatype_free(const struct datatype *ptr)
|
||||
|
||||
free_const(dtype->name);
|
||||
free_const(dtype->desc);
|
||||
- xfree(dtype);
|
||||
+ free(dtype);
|
||||
}
|
||||
|
||||
const struct datatype *concat_type_alloc(uint32_t type)
|
||||
@@ -1545,7 +1545,7 @@ static void cgroupv2_type_print(const struct expr *expr,
|
||||
else
|
||||
nft_print(octx, "%" PRIu64, id);
|
||||
|
||||
- xfree(cgroup_path);
|
||||
+ free(cgroup_path);
|
||||
}
|
||||
|
||||
static struct error_record *cgroupv2_type_parse(struct parse_ctx *ctx,
|
||||
diff --git a/src/erec.c b/src/erec.c
|
||||
index cd9f62b..fe66abb 100644
|
||||
--- a/src/erec.c
|
||||
+++ b/src/erec.c
|
||||
@@ -43,8 +43,8 @@ void erec_add_location(struct error_record *erec, const struct location *loc)
|
||||
|
||||
void erec_destroy(struct error_record *erec)
|
||||
{
|
||||
- xfree(erec->msg);
|
||||
- xfree(erec);
|
||||
+ free(erec->msg);
|
||||
+ free(erec);
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 3, 0)))
|
||||
@@ -203,7 +203,7 @@ void erec_print(struct output_ctx *octx, const struct error_record *erec,
|
||||
}
|
||||
pbuf[end] = '\0';
|
||||
fprintf(f, "%s", pbuf);
|
||||
- xfree(pbuf);
|
||||
+ free(pbuf);
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index c41210b..27ecaa2 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -3249,7 +3249,7 @@ static int stmt_reject_gen_dependency(struct eval_ctx *ctx, struct stmt *stmt,
|
||||
*/
|
||||
list_add(&nstmt->list, &ctx->rule->stmts);
|
||||
out:
|
||||
- xfree(payload);
|
||||
+ free(payload);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -5148,7 +5148,7 @@ static int ct_timeout_evaluate(struct eval_ctx *ctx, struct obj *obj)
|
||||
ct->timeout[ts->timeout_index] = ts->timeout_value;
|
||||
list_del(&ts->head);
|
||||
free_const(ts->timeout_str);
|
||||
- xfree(ts);
|
||||
+ free(ts);
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/src/expression.c b/src/expression.c
|
||||
index 0b4a537..dde48b6 100644
|
||||
--- a/src/expression.c
|
||||
+++ b/src/expression.c
|
||||
@@ -94,7 +94,7 @@ void expr_free(struct expr *expr)
|
||||
*/
|
||||
if (expr->etype != EXPR_INVALID)
|
||||
expr_destroy(expr);
|
||||
- xfree(expr);
|
||||
+ free(expr);
|
||||
}
|
||||
|
||||
void expr_print(const struct expr *expr, struct output_ctx *octx)
|
||||
diff --git a/src/json.c b/src/json.c
|
||||
index dad93e5..98fa026 100644
|
||||
--- a/src/json.c
|
||||
+++ b/src/json.c
|
||||
@@ -83,7 +83,7 @@ static json_t *set_dtype_json(const struct expr *key)
|
||||
json_array_append_new(root, jtok);
|
||||
tok = strtok_r(NULL, " .", &tok_safe);
|
||||
}
|
||||
- xfree(namedup);
|
||||
+ free(namedup);
|
||||
return root;
|
||||
}
|
||||
|
||||
diff --git a/src/libnftables.c b/src/libnftables.c
|
||||
index 866b5c6..ec90200 100644
|
||||
--- a/src/libnftables.c
|
||||
+++ b/src/libnftables.c
|
||||
@@ -158,7 +158,7 @@ void nft_ctx_clear_vars(struct nft_ctx *ctx)
|
||||
free_const(ctx->vars[i].value);
|
||||
}
|
||||
ctx->num_vars = 0;
|
||||
- xfree(ctx->vars);
|
||||
+ free(ctx->vars);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(nft_ctx_add_include_path);
|
||||
@@ -182,9 +182,9 @@ EXPORT_SYMBOL(nft_ctx_clear_include_paths);
|
||||
void nft_ctx_clear_include_paths(struct nft_ctx *ctx)
|
||||
{
|
||||
while (ctx->num_include_paths)
|
||||
- xfree(ctx->include_paths[--ctx->num_include_paths]);
|
||||
+ free(ctx->include_paths[--ctx->num_include_paths]);
|
||||
|
||||
- xfree(ctx->include_paths);
|
||||
+ free(ctx->include_paths);
|
||||
ctx->include_paths = NULL;
|
||||
}
|
||||
|
||||
@@ -343,9 +343,9 @@ void nft_ctx_free(struct nft_ctx *ctx)
|
||||
nft_ctx_clear_vars(ctx);
|
||||
nft_ctx_clear_include_paths(ctx);
|
||||
scope_free(ctx->top_scope);
|
||||
- xfree(ctx->state);
|
||||
+ free(ctx->state);
|
||||
nft_exit(ctx);
|
||||
- xfree(ctx);
|
||||
+ free(ctx);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(nft_ctx_set_output);
|
||||
@@ -745,7 +745,7 @@ err:
|
||||
if (indesc->name)
|
||||
free_const(indesc->name);
|
||||
|
||||
- xfree(indesc);
|
||||
+ free(indesc);
|
||||
}
|
||||
}
|
||||
free_const(nft->vars_ctx.buf);
|
||||
diff --git a/src/meta.c b/src/meta.c
|
||||
index 1f1e33c..4e55e00 100644
|
||||
--- a/src/meta.c
|
||||
+++ b/src/meta.c
|
||||
@@ -99,13 +99,13 @@ static struct error_record *tchandle_type_parse(struct parse_ctx *ctx,
|
||||
handle = strtoull(sym->identifier, NULL, 0);
|
||||
}
|
||||
out:
|
||||
- xfree(str);
|
||||
+ free(str);
|
||||
*res = constant_expr_alloc(&sym->location, sym->dtype,
|
||||
BYTEORDER_HOST_ENDIAN,
|
||||
sizeof(handle) * BITS_PER_BYTE, &handle);
|
||||
return NULL;
|
||||
err:
|
||||
- xfree(str);
|
||||
+ free(str);
|
||||
return error(&sym->location, "Could not parse %s", sym->dtype->desc);
|
||||
}
|
||||
|
||||
diff --git a/src/misspell.c b/src/misspell.c
|
||||
index c1e58a0..f5354fa 100644
|
||||
--- a/src/misspell.c
|
||||
+++ b/src/misspell.c
|
||||
@@ -72,7 +72,7 @@ static unsigned int string_distance(const char *a, const char *b)
|
||||
|
||||
ret = DISTANCE(len_a, len_b);
|
||||
|
||||
- xfree(distance);
|
||||
+ free(distance);
|
||||
|
||||
return ret;
|
||||
}
|
||||
diff --git a/src/mnl.c b/src/mnl.c
|
||||
index 0158924..9e4bfcd 100644
|
||||
--- a/src/mnl.c
|
||||
+++ b/src/mnl.c
|
||||
@@ -242,7 +242,7 @@ static void mnl_err_list_node_add(struct list_head *err_list, int error,
|
||||
void mnl_err_list_free(struct mnl_err *err)
|
||||
{
|
||||
list_del(&err->head);
|
||||
- xfree(err);
|
||||
+ free(err);
|
||||
}
|
||||
|
||||
static void mnl_set_sndbuffer(struct netlink_ctx *ctx)
|
||||
@@ -2179,7 +2179,7 @@ static void basehook_free(struct basehook *b)
|
||||
free_const(b->hookfn);
|
||||
free_const(b->chain);
|
||||
free_const(b->table);
|
||||
- xfree(b);
|
||||
+ free(b);
|
||||
}
|
||||
|
||||
static void basehook_list_add_tail(struct basehook *b, struct list_head *head)
|
||||
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
|
||||
index 0c62341..df395ba 100644
|
||||
--- a/src/netlink_linearize.c
|
||||
+++ b/src/netlink_linearize.c
|
||||
@@ -1743,9 +1743,9 @@ void netlink_linearize_fini(struct netlink_linearize_ctx *lctx)
|
||||
|
||||
for (i = 0; i < NFT_EXPR_LOC_HSIZE; i++) {
|
||||
list_for_each_entry_safe(eloc, next, &lctx->expr_loc_htable[i], hlist)
|
||||
- xfree(eloc);
|
||||
+ free(eloc);
|
||||
}
|
||||
- xfree(lctx->expr_loc_htable);
|
||||
+ free(lctx->expr_loc_htable);
|
||||
}
|
||||
|
||||
void netlink_linearize_rule(struct netlink_ctx *ctx,
|
||||
diff --git a/src/optimize.c b/src/optimize.c
|
||||
index 9ae9283..b90dd99 100644
|
||||
--- a/src/optimize.c
|
||||
+++ b/src/optimize.c
|
||||
@@ -1347,16 +1347,16 @@ static int chain_optimize(struct nft_ctx *nft, struct list_head *rules)
|
||||
}
|
||||
ret = 0;
|
||||
for (i = 0; i < ctx->num_rules; i++)
|
||||
- xfree(ctx->stmt_matrix[i]);
|
||||
+ free(ctx->stmt_matrix[i]);
|
||||
|
||||
- xfree(ctx->stmt_matrix);
|
||||
- xfree(merge);
|
||||
+ free(ctx->stmt_matrix);
|
||||
+ free(merge);
|
||||
err:
|
||||
for (i = 0; i < ctx->num_stmts; i++)
|
||||
stmt_free(ctx->stmt[i]);
|
||||
|
||||
- xfree(ctx->rule);
|
||||
- xfree(ctx);
|
||||
+ free(ctx->rule);
|
||||
+ free(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index b485a48..751b3e1 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -712,7 +712,7 @@ int nft_lex(void *, void *, void *);
|
||||
%destructor { free_const($$); } extended_prio_name quota_unit basehook_device_name
|
||||
|
||||
%type <expr> dev_spec
|
||||
-%destructor { xfree($$); } dev_spec
|
||||
+%destructor { free($$); } dev_spec
|
||||
|
||||
%type <table> table_block_alloc table_block
|
||||
%destructor { close_scope(state); table_free($$); } table_block_alloc
|
||||
@@ -741,7 +741,7 @@ int nft_lex(void *, void *, void *);
|
||||
%destructor { obj_free($$); } obj_block_alloc
|
||||
|
||||
%type <list> stmt_list stateful_stmt_list set_elem_stmt_list
|
||||
-%destructor { stmt_list_free($$); xfree($$); } stmt_list stateful_stmt_list set_elem_stmt_list
|
||||
+%destructor { stmt_list_free($$); free($$); } stmt_list stateful_stmt_list set_elem_stmt_list
|
||||
%type <stmt> stmt match_stmt verdict_stmt set_elem_stmt
|
||||
%destructor { stmt_free($$); } stmt match_stmt verdict_stmt set_elem_stmt
|
||||
%type <stmt> counter_stmt counter_stmt_alloc stateful_stmt last_stmt
|
||||
@@ -967,7 +967,7 @@ int nft_lex(void *, void *, void *);
|
||||
%type <val> ct_l4protoname ct_obj_type ct_cmd_type
|
||||
|
||||
%type <list> timeout_states timeout_state
|
||||
-%destructor { xfree($$); } timeout_states timeout_state
|
||||
+%destructor { free($$); } timeout_states timeout_state
|
||||
|
||||
%type <val> xfrm_state_key xfrm_state_proto_key xfrm_dir xfrm_spnum
|
||||
%type <expr> xfrm_expr
|
||||
@@ -3030,7 +3030,7 @@ rule_alloc : stmt_list
|
||||
list_for_each_entry(i, $1, list)
|
||||
$$->num_stmts++;
|
||||
list_splice_tail($1, &$$->stmts);
|
||||
- xfree($1);
|
||||
+ free($1);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -4537,7 +4537,7 @@ set_elem_expr : set_elem_expr_alloc
|
||||
{
|
||||
$$ = $1;
|
||||
list_splice_tail($3, &$$->stmt_list);
|
||||
- xfree($3);
|
||||
+ free($3);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -4549,7 +4549,7 @@ set_elem_expr_alloc : set_elem_key_expr set_elem_stmt_list
|
||||
{
|
||||
$$ = set_elem_expr_alloc(&@1, $1);
|
||||
list_splice_tail($2, &$$->stmt_list);
|
||||
- xfree($2);
|
||||
+ free($2);
|
||||
}
|
||||
| set_elem_key_expr
|
||||
{
|
||||
@@ -4861,7 +4861,7 @@ ct_timeout_config : PROTOCOL ct_l4protoname stmt_separator
|
||||
|
||||
ct = &$<obj>0->ct_timeout;
|
||||
list_splice_tail($4, &ct->timeout_list);
|
||||
- xfree($4);
|
||||
+ free($4);
|
||||
}
|
||||
| L3PROTOCOL family_spec_explicit stmt_separator
|
||||
{
|
||||
diff --git a/src/rule.c b/src/rule.c
|
||||
index 76cd58c..633fae7 100644
|
||||
--- a/src/rule.c
|
||||
+++ b/src/rule.c
|
||||
@@ -200,7 +200,7 @@ void set_free(struct set *set)
|
||||
stmt_free(stmt);
|
||||
expr_free(set->key);
|
||||
expr_free(set->data);
|
||||
- xfree(set);
|
||||
+ free(set);
|
||||
}
|
||||
|
||||
struct set *set_lookup_fuzzy(const char *set_name,
|
||||
@@ -480,7 +480,7 @@ void rule_free(struct rule *rule)
|
||||
stmt_list_free(&rule->stmts);
|
||||
handle_free(&rule->handle);
|
||||
free_const(rule->comment);
|
||||
- xfree(rule);
|
||||
+ free(rule);
|
||||
}
|
||||
|
||||
void rule_print(const struct rule *rule, struct output_ctx *octx)
|
||||
@@ -559,14 +559,14 @@ void scope_release(const struct scope *scope)
|
||||
list_del(&sym->list);
|
||||
free_const(sym->identifier);
|
||||
expr_free(sym->expr);
|
||||
- xfree(sym);
|
||||
+ free(sym);
|
||||
}
|
||||
}
|
||||
|
||||
void scope_free(struct scope *scope)
|
||||
{
|
||||
scope_release(scope);
|
||||
- xfree(scope);
|
||||
+ free(scope);
|
||||
}
|
||||
|
||||
void symbol_bind(struct scope *scope, const char *identifier, struct expr *expr)
|
||||
@@ -599,7 +599,7 @@ static void symbol_put(struct symbol *sym)
|
||||
if (--sym->refcnt == 0) {
|
||||
free_const(sym->identifier);
|
||||
expr_free(sym->expr);
|
||||
- xfree(sym);
|
||||
+ free(sym);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -734,11 +734,11 @@ void chain_free(struct chain *chain)
|
||||
expr_free(chain->dev_expr);
|
||||
for (i = 0; i < chain->dev_array_len; i++)
|
||||
free_const(chain->dev_array[i]);
|
||||
- xfree(chain->dev_array);
|
||||
+ free(chain->dev_array);
|
||||
expr_free(chain->priority.expr);
|
||||
expr_free(chain->policy);
|
||||
free_const(chain->comment);
|
||||
- xfree(chain);
|
||||
+ free(chain);
|
||||
}
|
||||
|
||||
struct chain *chain_binding_lookup(const struct table *table,
|
||||
@@ -1181,7 +1181,7 @@ void table_free(struct table *table)
|
||||
cache_free(&table->set_cache);
|
||||
cache_free(&table->obj_cache);
|
||||
cache_free(&table->ft_cache);
|
||||
- xfree(table);
|
||||
+ free(table);
|
||||
}
|
||||
|
||||
struct table *table_get(struct table *table)
|
||||
@@ -1342,7 +1342,7 @@ struct markup *markup_alloc(uint32_t format)
|
||||
|
||||
void markup_free(struct markup *m)
|
||||
{
|
||||
- xfree(m);
|
||||
+ free(m);
|
||||
}
|
||||
|
||||
struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event)
|
||||
@@ -1361,7 +1361,7 @@ struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event)
|
||||
void monitor_free(struct monitor *m)
|
||||
{
|
||||
free_const(m->event);
|
||||
- xfree(m);
|
||||
+ free(m);
|
||||
}
|
||||
|
||||
void cmd_free(struct cmd *cmd)
|
||||
@@ -1415,9 +1415,9 @@ void cmd_free(struct cmd *cmd)
|
||||
BUG("invalid command object type %u\n", cmd->obj);
|
||||
}
|
||||
}
|
||||
- xfree(cmd->attr);
|
||||
+ free(cmd->attr);
|
||||
free_const(cmd->arg);
|
||||
- xfree(cmd);
|
||||
+ free(cmd);
|
||||
}
|
||||
|
||||
#include <netlink.h>
|
||||
@@ -1662,10 +1662,10 @@ void obj_free(struct obj *obj)
|
||||
list_for_each_entry_safe(ts, next, &obj->ct_timeout.timeout_list, head) {
|
||||
list_del(&ts->head);
|
||||
free_const(ts->timeout_str);
|
||||
- xfree(ts);
|
||||
+ free(ts);
|
||||
}
|
||||
}
|
||||
- xfree(obj);
|
||||
+ free(obj);
|
||||
}
|
||||
|
||||
struct obj *obj_lookup_fuzzy(const char *obj_name,
|
||||
@@ -2075,9 +2075,9 @@ void flowtable_free(struct flowtable *flowtable)
|
||||
if (flowtable->dev_array != NULL) {
|
||||
for (i = 0; i < flowtable->dev_array_len; i++)
|
||||
free_const(flowtable->dev_array[i]);
|
||||
- xfree(flowtable->dev_array);
|
||||
+ free(flowtable->dev_array);
|
||||
}
|
||||
- xfree(flowtable);
|
||||
+ free(flowtable);
|
||||
}
|
||||
|
||||
static void flowtable_print_declaration(const struct flowtable *flowtable,
|
||||
diff --git a/src/scanner.l b/src/scanner.l
|
||||
index 93a31f2..00a0948 100644
|
||||
--- a/src/scanner.l
|
||||
+++ b/src/scanner.l
|
||||
@@ -1284,7 +1284,7 @@ void scanner_destroy(struct nft_ctx *nft)
|
||||
struct parser_state *state = yyget_extra(nft->scanner);
|
||||
|
||||
input_descriptor_list_destroy(state);
|
||||
- xfree(state->startcond_active);
|
||||
+ free(state->startcond_active);
|
||||
|
||||
yylex_destroy(nft->scanner);
|
||||
}
|
||||
diff --git a/src/segtree.c b/src/segtree.c
|
||||
index c4029f9..7d246de 100644
|
||||
--- a/src/segtree.c
|
||||
+++ b/src/segtree.c
|
||||
@@ -656,6 +656,6 @@ out:
|
||||
if (catchall)
|
||||
compound_expr_add(set, catchall);
|
||||
|
||||
- xfree(ranges);
|
||||
- xfree(elements);
|
||||
+ free(ranges);
|
||||
+ free(elements);
|
||||
}
|
||||
diff --git a/src/statement.c b/src/statement.c
|
||||
index 994b522..ab144d6 100644
|
||||
--- a/src/statement.c
|
||||
+++ b/src/statement.c
|
||||
@@ -51,7 +51,7 @@ void stmt_free(struct stmt *stmt)
|
||||
return;
|
||||
if (stmt->ops->destroy)
|
||||
stmt->ops->destroy(stmt);
|
||||
- xfree(stmt);
|
||||
+ free(stmt);
|
||||
}
|
||||
|
||||
void stmt_list_free(struct list_head *list)
|
||||
diff --git a/src/utils.c b/src/utils.c
|
||||
index e6ad8b8..2aa1eb4 100644
|
||||
--- a/src/utils.c
|
||||
+++ b/src/utils.c
|
||||
@@ -24,11 +24,6 @@ void __noreturn __memory_allocation_error(const char *filename, uint32_t line)
|
||||
exit(NFT_EXIT_NOMEM);
|
||||
}
|
||||
|
||||
-void xfree(const void *ptr)
|
||||
-{
|
||||
- free((void *)ptr);
|
||||
-}
|
||||
-
|
||||
void *xmalloc(size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
diff --git a/src/xt.c b/src/xt.c
|
||||
index 48b2873..f7bee21 100644
|
||||
--- a/src/xt.c
|
||||
+++ b/src/xt.c
|
||||
@@ -78,7 +78,7 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx)
|
||||
|
||||
rc = mt->xlate(xl, ¶ms);
|
||||
}
|
||||
- xfree(m);
|
||||
+ free(m);
|
||||
break;
|
||||
case NFT_XT_WATCHER:
|
||||
case NFT_XT_TARGET:
|
||||
@@ -108,14 +108,14 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx)
|
||||
|
||||
rc = tg->xlate(xl, ¶ms);
|
||||
}
|
||||
- xfree(t);
|
||||
+ free(t);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc == 1)
|
||||
nft_print(octx, "%s", xt_xlate_get(xl));
|
||||
xt_xlate_free(xl);
|
||||
- xfree(entry);
|
||||
+ free(entry);
|
||||
#endif
|
||||
if (!rc)
|
||||
nft_print(octx, "xt %s \"%s\"",
|
||||
@@ -125,7 +125,7 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx)
|
||||
void xt_stmt_destroy(struct stmt *stmt)
|
||||
{
|
||||
free_const(stmt->xt.name);
|
||||
- xfree(stmt->xt.info);
|
||||
+ free(stmt->xt.info);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBXTABLES
|
||||
@ -0,0 +1,41 @@
|
||||
From 643ad1a2a68d58fd7fbbaefd1af83c60f229ef0b Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:40 +0200
|
||||
Subject: [PATCH] netlink: fix buffer size for user data in
|
||||
netlink_delinearize_chain()
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 505a6794422238f9f1d590fe8c1ee3ea7fd46579
|
||||
|
||||
commit 505a6794422238f9f1d590fe8c1ee3ea7fd46579
|
||||
Author: Thomas Haller <thaller@redhat.com>
|
||||
Date: Wed Nov 8 19:22:20 2023 +0100
|
||||
|
||||
netlink: fix buffer size for user data in netlink_delinearize_chain()
|
||||
|
||||
The correct define is NFTNL_UDATA_CHAIN_MAX and not NFTNL_UDATA_OBJ_MAX.
|
||||
In current libnftnl, they both are defined as 1, so (with current libnftnl)
|
||||
there is no difference.
|
||||
|
||||
Fixes: 702ac2b72c0e ("src: add comment support for chains")
|
||||
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/netlink.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/netlink.c b/src/netlink.c
|
||||
index 04bba59..a366758 100644
|
||||
--- a/src/netlink.c
|
||||
+++ b/src/netlink.c
|
||||
@@ -617,7 +617,7 @@ static int qsort_device_cmp(const void *a, const void *b)
|
||||
struct chain *netlink_delinearize_chain(struct netlink_ctx *ctx,
|
||||
const struct nftnl_chain *nlc)
|
||||
{
|
||||
- const struct nftnl_udata *ud[NFTNL_UDATA_OBJ_MAX + 1] = {};
|
||||
+ const struct nftnl_udata *ud[NFTNL_UDATA_CHAIN_MAX + 1] = {};
|
||||
int priority, policy, len = 0, i;
|
||||
const char * const *dev_array;
|
||||
struct chain *chain;
|
||||
110
0028-tests-shell-split-merge-nat-optimization-in-two-test.patch
Normal file
110
0028-tests-shell-split-merge-nat-optimization-in-two-test.patch
Normal file
@ -0,0 +1,110 @@
|
||||
From 800e92dac205e2f7684414528e3605abb93861f7 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:40 +0200
|
||||
Subject: [PATCH] tests: shell: split merge nat optimization in two tests
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 0f89958eefd5318f594a653b78b47cefec9e87e9
|
||||
|
||||
commit 0f89958eefd5318f594a653b78b47cefec9e87e9
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Nov 7 13:03:56 2023 +0100
|
||||
|
||||
tests: shell: split merge nat optimization in two tests
|
||||
|
||||
One without pipapo support and another with not to harm existing
|
||||
coverage.
|
||||
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
.../optimizations/dumps/merge_nat.nft | 8 --------
|
||||
.../optimizations/dumps/merge_nat_concat.nft | 8 ++++++++
|
||||
tests/shell/testcases/optimizations/merge_nat | 13 -------------
|
||||
.../testcases/optimizations/merge_nat_concat | 18 ++++++++++++++++++
|
||||
4 files changed, 26 insertions(+), 21 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/optimizations/dumps/merge_nat_concat.nft
|
||||
create mode 100755 tests/shell/testcases/optimizations/merge_nat_concat
|
||||
|
||||
diff --git a/tests/shell/testcases/optimizations/dumps/merge_nat.nft b/tests/shell/testcases/optimizations/dumps/merge_nat.nft
|
||||
index 48d18a6..61feb27 100644
|
||||
--- a/tests/shell/testcases/optimizations/dumps/merge_nat.nft
|
||||
+++ b/tests/shell/testcases/optimizations/dumps/merge_nat.nft
|
||||
@@ -11,14 +11,6 @@ table ip test2 {
|
||||
ip saddr { 10.141.11.0/24, 10.141.13.0/24 } masquerade
|
||||
}
|
||||
}
|
||||
-table ip test3 {
|
||||
- chain y {
|
||||
- oif "lo" accept
|
||||
- snat to ip saddr . tcp sport map { 1.1.1.1 . 1024-65535 : 3.3.3.3, 2.2.2.2 . 1024-65535 : 4.4.4.4 }
|
||||
- oifname "enp2s0" snat ip to ip saddr map { 10.1.1.0/24 : 72.2.3.66-72.2.3.78 }
|
||||
- tcp dport { 8888, 9999 } redirect
|
||||
- }
|
||||
-}
|
||||
table ip test4 {
|
||||
chain y {
|
||||
oif "lo" accept
|
||||
diff --git a/tests/shell/testcases/optimizations/dumps/merge_nat_concat.nft b/tests/shell/testcases/optimizations/dumps/merge_nat_concat.nft
|
||||
new file mode 100644
|
||||
index 0000000..0faddfd
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/optimizations/dumps/merge_nat_concat.nft
|
||||
@@ -0,0 +1,8 @@
|
||||
+table ip test3 {
|
||||
+ chain y {
|
||||
+ oif "lo" accept
|
||||
+ snat to ip saddr . tcp sport map { 1.1.1.1 . 1024-65535 : 3.3.3.3, 2.2.2.2 . 1024-65535 : 4.4.4.4 }
|
||||
+ oifname "enp2s0" snat ip to ip saddr map { 10.1.1.0/24 : 72.2.3.66-72.2.3.78 }
|
||||
+ tcp dport { 8888, 9999 } redirect
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/optimizations/merge_nat b/tests/shell/testcases/optimizations/merge_nat
|
||||
index 3a57d94..bfe9787 100755
|
||||
--- a/tests/shell/testcases/optimizations/merge_nat
|
||||
+++ b/tests/shell/testcases/optimizations/merge_nat
|
||||
@@ -24,19 +24,6 @@ RULESET="table ip test2 {
|
||||
|
||||
$NFT -o -f - <<< $RULESET
|
||||
|
||||
-RULESET="table ip test3 {
|
||||
- chain y {
|
||||
- oif lo accept
|
||||
- ip saddr 1.1.1.1 tcp sport 1024-65535 snat to 3.3.3.3
|
||||
- ip saddr 2.2.2.2 tcp sport 1024-65535 snat to 4.4.4.4
|
||||
- oifname enp2s0 snat ip to ip saddr map { 10.1.1.0/24 : 72.2.3.66-72.2.3.78 }
|
||||
- tcp dport 8888 redirect
|
||||
- tcp dport 9999 redirect
|
||||
- }
|
||||
-}"
|
||||
-
|
||||
-$NFT -o -f - <<< $RULESET
|
||||
-
|
||||
RULESET="table ip test4 {
|
||||
chain y {
|
||||
oif lo accept
|
||||
diff --git a/tests/shell/testcases/optimizations/merge_nat_concat b/tests/shell/testcases/optimizations/merge_nat_concat
|
||||
new file mode 100755
|
||||
index 0000000..2e0a91a
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/optimizations/merge_nat_concat
|
||||
@@ -0,0 +1,18 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
|
||||
+
|
||||
+set -e
|
||||
+
|
||||
+RULESET="table ip test3 {
|
||||
+ chain y {
|
||||
+ oif lo accept
|
||||
+ ip saddr 1.1.1.1 tcp sport 1024-65535 snat to 3.3.3.3
|
||||
+ ip saddr 2.2.2.2 tcp sport 1024-65535 snat to 4.4.4.4
|
||||
+ oifname enp2s0 snat ip to ip saddr map { 10.1.1.0/24 : 72.2.3.66-72.2.3.78 }
|
||||
+ tcp dport 8888 redirect
|
||||
+ tcp dport 9999 redirect
|
||||
+ }
|
||||
+}"
|
||||
+
|
||||
+$NFT -o -f - <<< $RULESET
|
||||
123
0029-tests-shell-split-set-NAT-interval-test.patch
Normal file
123
0029-tests-shell-split-set-NAT-interval-test.patch
Normal file
@ -0,0 +1,123 @@
|
||||
From 20b2a43a27321b052fb9d626b13eb6de3668a9c8 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:40 +0200
|
||||
Subject: [PATCH] tests: shell: split set NAT interval test
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit b95bbe966bd2431fee7b19aa0902aba10f9be696
|
||||
|
||||
commit b95bbe966bd2431fee7b19aa0902aba10f9be696
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Nov 7 11:41:19 2023 +0100
|
||||
|
||||
tests: shell: split set NAT interval test
|
||||
|
||||
Split test in two, one for interval sets and another with concatenation
|
||||
+ intervals, so at least intervals are tested in older kernels with no
|
||||
pipapo support.
|
||||
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
.../testcases/sets/0067nat_concat_interval_0 | 17 ++---------------
|
||||
tests/shell/testcases/sets/0067nat_interval_0 | 18 ++++++++++++++++++
|
||||
.../sets/dumps/0067nat_concat_interval_0.nft | 7 -------
|
||||
.../sets/dumps/0067nat_interval_0.nft | 12 ++++++++++++
|
||||
4 files changed, 32 insertions(+), 22 deletions(-)
|
||||
create mode 100755 tests/shell/testcases/sets/0067nat_interval_0
|
||||
create mode 100644 tests/shell/testcases/sets/dumps/0067nat_interval_0.nft
|
||||
|
||||
diff --git a/tests/shell/testcases/sets/0067nat_concat_interval_0 b/tests/shell/testcases/sets/0067nat_concat_interval_0
|
||||
index 55cc0d4..8162195 100755
|
||||
--- a/tests/shell/testcases/sets/0067nat_concat_interval_0
|
||||
+++ b/tests/shell/testcases/sets/0067nat_concat_interval_0
|
||||
@@ -1,21 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
-set -e
|
||||
-
|
||||
-EXPECTED="table ip nat {
|
||||
- map ipportmap {
|
||||
- type ipv4_addr : interval ipv4_addr . inet_service
|
||||
- flags interval
|
||||
- elements = { 192.168.1.2 : 10.141.10.1-10.141.10.3 . 8888-8999 }
|
||||
- }
|
||||
- chain prerouting {
|
||||
- type nat hook prerouting priority dstnat; policy accept;
|
||||
- ip protocol tcp dnat ip to ip saddr map @ipportmap
|
||||
- }
|
||||
-}"
|
||||
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
|
||||
|
||||
-$NFT -f - <<< $EXPECTED
|
||||
-$NFT add element ip nat ipportmap { 192.168.2.0/24 : 10.141.11.5-10.141.11.20 . 8888-8999 }
|
||||
+set -e
|
||||
|
||||
EXPECTED="table ip nat {
|
||||
map ipportmap2 {
|
||||
diff --git a/tests/shell/testcases/sets/0067nat_interval_0 b/tests/shell/testcases/sets/0067nat_interval_0
|
||||
new file mode 100755
|
||||
index 0000000..c90203d
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/sets/0067nat_interval_0
|
||||
@@ -0,0 +1,18 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+set -e
|
||||
+
|
||||
+EXPECTED="table ip nat {
|
||||
+ map ipportmap {
|
||||
+ type ipv4_addr : interval ipv4_addr . inet_service
|
||||
+ flags interval
|
||||
+ elements = { 192.168.1.2 : 10.141.10.1-10.141.10.3 . 8888-8999 }
|
||||
+ }
|
||||
+ chain prerouting {
|
||||
+ type nat hook prerouting priority dstnat; policy accept;
|
||||
+ ip protocol tcp dnat ip to ip saddr map @ipportmap
|
||||
+ }
|
||||
+}"
|
||||
+
|
||||
+$NFT -f - <<< $EXPECTED
|
||||
+$NFT add element ip nat ipportmap { 192.168.2.0/24 : 10.141.11.5-10.141.11.20 . 8888-8999 }
|
||||
diff --git a/tests/shell/testcases/sets/dumps/0067nat_concat_interval_0.nft b/tests/shell/testcases/sets/dumps/0067nat_concat_interval_0.nft
|
||||
index 0215691..9ac3774 100644
|
||||
--- a/tests/shell/testcases/sets/dumps/0067nat_concat_interval_0.nft
|
||||
+++ b/tests/shell/testcases/sets/dumps/0067nat_concat_interval_0.nft
|
||||
@@ -1,10 +1,4 @@
|
||||
table ip nat {
|
||||
- map ipportmap {
|
||||
- type ipv4_addr : interval ipv4_addr . inet_service
|
||||
- flags interval
|
||||
- elements = { 192.168.1.2 : 10.141.10.1-10.141.10.3 . 8888-8999, 192.168.2.0/24 : 10.141.11.5-10.141.11.20 . 8888-8999 }
|
||||
- }
|
||||
-
|
||||
map ipportmap2 {
|
||||
type ipv4_addr . ipv4_addr : interval ipv4_addr . inet_service
|
||||
flags interval
|
||||
@@ -33,7 +27,6 @@ table ip nat {
|
||||
|
||||
chain prerouting {
|
||||
type nat hook prerouting priority dstnat; policy accept;
|
||||
- ip protocol tcp dnat ip to ip saddr map @ipportmap
|
||||
ip protocol tcp dnat ip to ip saddr . ip daddr map @ipportmap2
|
||||
meta l4proto { tcp, udp } dnat ip to ip daddr . th dport map @fwdtoip_th
|
||||
dnat ip to iifname . ip saddr map @ipportmap4
|
||||
diff --git a/tests/shell/testcases/sets/dumps/0067nat_interval_0.nft b/tests/shell/testcases/sets/dumps/0067nat_interval_0.nft
|
||||
new file mode 100644
|
||||
index 0000000..b6d07fc
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/sets/dumps/0067nat_interval_0.nft
|
||||
@@ -0,0 +1,12 @@
|
||||
+table ip nat {
|
||||
+ map ipportmap {
|
||||
+ type ipv4_addr : interval ipv4_addr . inet_service
|
||||
+ flags interval
|
||||
+ elements = { 192.168.1.2 : 10.141.10.1-10.141.10.3 . 8888-8999, 192.168.2.0/24 : 10.141.11.5-10.141.11.20 . 8888-8999 }
|
||||
+ }
|
||||
+
|
||||
+ chain prerouting {
|
||||
+ type nat hook prerouting priority dstnat; policy accept;
|
||||
+ ip protocol tcp dnat ip to ip saddr map @ipportmap
|
||||
+ }
|
||||
+}
|
||||
132
0030-src-expand-create-commands.patch
Normal file
132
0030-src-expand-create-commands.patch
Normal file
@ -0,0 +1,132 @@
|
||||
From 6d277e247b5022f59f733acbbe74f609937d5b9d Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:40 +0200
|
||||
Subject: [PATCH] src: expand create commands
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 04a1ddc2012964c0a00350973328f5954887cedb
|
||||
|
||||
commit 04a1ddc2012964c0a00350973328f5954887cedb
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Mon Nov 13 14:39:23 2023 +0100
|
||||
|
||||
src: expand create commands
|
||||
|
||||
create commands also need to be expanded, otherwise elements are never
|
||||
evaluated:
|
||||
|
||||
# cat ruleset.nft
|
||||
define ip-block-4 = { 1.1.1.1 }
|
||||
create set netdev filter ip-block-4-test {
|
||||
type ipv4_addr
|
||||
flags interval
|
||||
auto-merge
|
||||
elements = $ip-block-4
|
||||
}
|
||||
# nft -f ruleset.nft
|
||||
BUG: unhandled expression type 0
|
||||
nft: src/intervals.c:211: interval_expr_key: Assertion `0' failed.
|
||||
Aborted
|
||||
|
||||
Same applies to chains in the form of:
|
||||
|
||||
create chain x y {
|
||||
counter
|
||||
}
|
||||
|
||||
which is also accepted by the parser.
|
||||
|
||||
Update tests/shell to improve coverage for these use cases.
|
||||
|
||||
Fixes: 56c90a2dd2eb ("evaluate: expand sets and maps before evaluation")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/libnftables.c | 3 ++-
|
||||
tests/shell/testcases/include/0020include_chain_0 | 7 +++++++
|
||||
.../testcases/include/dumps/0020include_chain_0.nft | 5 +++++
|
||||
tests/shell/testcases/sets/0049set_define_0 | 12 ++++++++++++
|
||||
.../shell/testcases/sets/dumps/0049set_define_0.nft | 7 +++++++
|
||||
5 files changed, 33 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/libnftables.c b/src/libnftables.c
|
||||
index ec90200..0dee1ba 100644
|
||||
--- a/src/libnftables.c
|
||||
+++ b/src/libnftables.c
|
||||
@@ -532,7 +532,8 @@ static int nft_evaluate(struct nft_ctx *nft, struct list_head *msgs,
|
||||
collapsed = true;
|
||||
|
||||
list_for_each_entry(cmd, cmds, list) {
|
||||
- if (cmd->op != CMD_ADD)
|
||||
+ if (cmd->op != CMD_ADD &&
|
||||
+ cmd->op != CMD_CREATE)
|
||||
continue;
|
||||
|
||||
nft_cmd_expand(cmd);
|
||||
diff --git a/tests/shell/testcases/include/0020include_chain_0 b/tests/shell/testcases/include/0020include_chain_0
|
||||
index 8f78e8c..49b6f76 100755
|
||||
--- a/tests/shell/testcases/include/0020include_chain_0
|
||||
+++ b/tests/shell/testcases/include/0020include_chain_0
|
||||
@@ -20,4 +20,11 @@ RULESET2="chain inet filter input2 {
|
||||
|
||||
echo "$RULESET2" > $tmpfile1
|
||||
|
||||
+RULESET3="create chain inet filter output2 {
|
||||
+ type filter hook output priority filter; policy accept;
|
||||
+ ip daddr 1.2.3.4 tcp dport { 22, 443, 123 } drop
|
||||
+}"
|
||||
+
|
||||
+echo "$RULESET3" >> $tmpfile1
|
||||
+
|
||||
$NFT -o -f - <<< $RULESET
|
||||
diff --git a/tests/shell/testcases/include/dumps/0020include_chain_0.nft b/tests/shell/testcases/include/dumps/0020include_chain_0.nft
|
||||
index 3ad6db1..bf596ff 100644
|
||||
--- a/tests/shell/testcases/include/dumps/0020include_chain_0.nft
|
||||
+++ b/tests/shell/testcases/include/dumps/0020include_chain_0.nft
|
||||
@@ -3,4 +3,9 @@ table inet filter {
|
||||
type filter hook input priority filter; policy accept;
|
||||
ip saddr 1.2.3.4 tcp dport { 22, 123, 443 } drop
|
||||
}
|
||||
+
|
||||
+ chain output2 {
|
||||
+ type filter hook output priority filter; policy accept;
|
||||
+ ip daddr 1.2.3.4 tcp dport { 22, 123, 443 } drop
|
||||
+ }
|
||||
}
|
||||
diff --git a/tests/shell/testcases/sets/0049set_define_0 b/tests/shell/testcases/sets/0049set_define_0
|
||||
index 1d512f7..756afdc 100755
|
||||
--- a/tests/shell/testcases/sets/0049set_define_0
|
||||
+++ b/tests/shell/testcases/sets/0049set_define_0
|
||||
@@ -14,3 +14,15 @@ table inet filter {
|
||||
"
|
||||
|
||||
$NFT -f - <<< "$EXPECTED"
|
||||
+
|
||||
+EXPECTED="define ip-block-4 = { 1.1.1.1 }
|
||||
+
|
||||
+ create set inet filter ip-block-4-test {
|
||||
+ type ipv4_addr
|
||||
+ flags interval
|
||||
+ auto-merge
|
||||
+ elements = \$ip-block-4
|
||||
+ }
|
||||
+"
|
||||
+
|
||||
+$NFT -f - <<< "$EXPECTED"
|
||||
diff --git a/tests/shell/testcases/sets/dumps/0049set_define_0.nft b/tests/shell/testcases/sets/dumps/0049set_define_0.nft
|
||||
index 998b387..d654420 100644
|
||||
--- a/tests/shell/testcases/sets/dumps/0049set_define_0.nft
|
||||
+++ b/tests/shell/testcases/sets/dumps/0049set_define_0.nft
|
||||
@@ -1,4 +1,11 @@
|
||||
table inet filter {
|
||||
+ set ip-block-4-test {
|
||||
+ type ipv4_addr
|
||||
+ flags interval
|
||||
+ auto-merge
|
||||
+ elements = { 1.1.1.1 }
|
||||
+ }
|
||||
+
|
||||
chain input {
|
||||
type filter hook input priority filter; policy drop;
|
||||
tcp dport { 22, 80, 443 } ct state new counter packets 0 bytes 0 accept
|
||||
57
0031-json-fix-use-after-free-in-table_flags_json.patch
Normal file
57
0031-json-fix-use-after-free-in-table_flags_json.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From d5019748ad5b02980c7ff7349d6e55245c831a7c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:40 +0200
|
||||
Subject: [PATCH] json: fix use after free in table_flags_json()
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit b04512cf30de1ba6657facba5ebe2321e17c2727
|
||||
|
||||
commit b04512cf30de1ba6657facba5ebe2321e17c2727
|
||||
Author: Thomas Haller <thaller@redhat.com>
|
||||
Date: Tue Nov 14 16:29:25 2023 +0100
|
||||
|
||||
json: fix use after free in table_flags_json()
|
||||
|
||||
Add `$NFT -j list ruleset` to the end of "tests/shell/testcases/transactions/table_onoff".
|
||||
Then valgrind will find this issue:
|
||||
|
||||
$ make -j && ./tests/shell/run-tests.sh tests/shell/testcases/transactions/table_onoff -V
|
||||
|
||||
Gives:
|
||||
|
||||
==286== Invalid read of size 4
|
||||
==286== at 0x49B0261: do_dump (dump.c:211)
|
||||
==286== by 0x49B08B8: do_dump (dump.c:378)
|
||||
==286== by 0x49B08B8: do_dump (dump.c:378)
|
||||
==286== by 0x49B04F7: do_dump (dump.c:273)
|
||||
==286== by 0x49B08B8: do_dump (dump.c:378)
|
||||
==286== by 0x49B0E84: json_dump_callback (dump.c:465)
|
||||
==286== by 0x48AF22A: do_command_list_json (json.c:2016)
|
||||
==286== by 0x48732F1: do_command_list (rule.c:2335)
|
||||
==286== by 0x48737F5: do_command (rule.c:2605)
|
||||
==286== by 0x48A867D: nft_netlink (libnftables.c:42)
|
||||
==286== by 0x48A92B1: nft_run_cmd_from_buffer (libnftables.c:597)
|
||||
==286== by 0x402CBA: main (main.c:533)
|
||||
|
||||
Fixes: e70354f53e9f ("libnftables: Implement JSON output support")
|
||||
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/json.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/json.c b/src/json.c
|
||||
index 98fa026..6809cd5 100644
|
||||
--- a/src/json.c
|
||||
+++ b/src/json.c
|
||||
@@ -497,7 +497,7 @@ static json_t *table_flags_json(const struct table *table)
|
||||
json_decref(root);
|
||||
return NULL;
|
||||
case 1:
|
||||
- json_unpack(root, "[o]", &tmp);
|
||||
+ json_unpack(root, "[O]", &tmp);
|
||||
json_decref(root);
|
||||
root = tmp;
|
||||
break;
|
||||
@ -0,0 +1,56 @@
|
||||
From dd1a258c4dd517dd4b89a8913fd4e1ae47dc0c34 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:40 +0200
|
||||
Subject: [PATCH] tests: shell: restore pipapo and chain binding coverage in
|
||||
standalone 30s-stress
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 110f73023497720d4161263c03d8d7cc062af7ab
|
||||
|
||||
commit 110f73023497720d4161263c03d8d7cc062af7ab
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Nov 14 20:16:08 2023 +0100
|
||||
|
||||
tests: shell: restore pipapo and chain binding coverage in standalone 30s-stress
|
||||
|
||||
Do not disable pipapo and chain binding coverage for standalone runs by
|
||||
default. Instead, turn them on by default and allow users to disable them
|
||||
through:
|
||||
|
||||
# export NFT_TEST_HAVE_chain_binding=n; bash tests/shell/testcases/transactions/30s-stress 3600
|
||||
...
|
||||
running standalone with:
|
||||
NFT_TEST_HAVE_chain_binding=n
|
||||
NFT_TEST_HAVE_pipapo=y
|
||||
|
||||
given feature detection is not available in this case, thus, user has to
|
||||
provide an explicit hint on what this kernel supports.
|
||||
|
||||
Fixes: c5b5b1044fdd ("tests/shell: add feature probing via "features/*.nft" files")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
tests/shell/testcases/transactions/30s-stress | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/tests/shell/testcases/transactions/30s-stress b/tests/shell/testcases/transactions/30s-stress
|
||||
index 4c3c6a2..544eef1 100755
|
||||
--- a/tests/shell/testcases/transactions/30s-stress
|
||||
+++ b/tests/shell/testcases/transactions/30s-stress
|
||||
@@ -6,6 +6,15 @@ runtime=30
|
||||
|
||||
# allow stand-alone execution as well, e.g. '$0 3600'
|
||||
if [ x"$1" != "x" ] ;then
|
||||
+ if [ -z "${NFT_TEST_HAVE_chain_binding+x}" ]; then
|
||||
+ NFT_TEST_HAVE_chain_binding=y
|
||||
+ fi
|
||||
+ if [ -z "${NFT_TEST_HAVE_pipapo+x}" ]; then
|
||||
+ NFT_TEST_HAVE_pipapo=y
|
||||
+ fi
|
||||
+ echo "running standalone with:"
|
||||
+ echo "NFT_TEST_HAVE_chain_binding="$NFT_TEST_HAVE_chain_binding
|
||||
+ echo "NFT_TEST_HAVE_pipapo="$NFT_TEST_HAVE_pipapo
|
||||
if [ $1 -ge 0 ]; then
|
||||
runtime="$1"
|
||||
else
|
||||
@ -0,0 +1,61 @@
|
||||
From 0a8f8baff7bdfe2001f63429de7d8317bf72f4fc Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:40 +0200
|
||||
Subject: [PATCH] tests: shell: skip if kernel does not support flowtable
|
||||
counter
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 279654904d5186430588b475501b2ca0d3ab6517
|
||||
|
||||
commit 279654904d5186430588b475501b2ca0d3ab6517
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Nov 14 16:57:22 2023 +0100
|
||||
|
||||
tests: shell: skip if kernel does not support flowtable counter
|
||||
|
||||
Check if kernel provides flowtable counter supports which is available
|
||||
since 53c2b2899af7 ("netfilter: flowtable: add counter support").
|
||||
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
tests/shell/features/flowtable_counter.sh | 16 ++++++++++++++++
|
||||
.../testcases/flowtable/0012flowtable_variable_0 | 2 ++
|
||||
2 files changed, 18 insertions(+)
|
||||
create mode 100755 tests/shell/features/flowtable_counter.sh
|
||||
|
||||
diff --git a/tests/shell/features/flowtable_counter.sh b/tests/shell/features/flowtable_counter.sh
|
||||
new file mode 100755
|
||||
index 0000000..a4c4c62
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/features/flowtable_counter.sh
|
||||
@@ -0,0 +1,16 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+# 53c2b2899af7 ("netfilter: flowtable: add counter support")
|
||||
+# v5.7-rc1~146^2~12^2~16
|
||||
+
|
||||
+EXPECTED="table ip filter2 {
|
||||
+ flowtable main_ft2 {
|
||||
+ hook ingress priority filter
|
||||
+ devices = { lo }
|
||||
+ counter
|
||||
+ }
|
||||
+}"
|
||||
+
|
||||
+$NFT -f - <<< $EXPECTED
|
||||
+
|
||||
+diff -u <($NFT list ruleset) - <<<"$EXPECTED"
|
||||
diff --git a/tests/shell/testcases/flowtable/0012flowtable_variable_0 b/tests/shell/testcases/flowtable/0012flowtable_variable_0
|
||||
index 080059d..9c03820 100755
|
||||
--- a/tests/shell/testcases/flowtable/0012flowtable_variable_0
|
||||
+++ b/tests/shell/testcases/flowtable/0012flowtable_variable_0
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_flowtable_counter)
|
||||
+
|
||||
set -e
|
||||
|
||||
iface_cleanup() {
|
||||
39
0034-evaluate-fix-rule-replacement-with-anon-sets.patch
Normal file
39
0034-evaluate-fix-rule-replacement-with-anon-sets.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From ecd609b492cbc755529e75a6af8fd9c06b89135b Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:40 +0200
|
||||
Subject: [PATCH] evaluate: fix rule replacement with anon sets
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 256904b1ded6314974dddc75726149f7b19d33f4
|
||||
|
||||
commit 256904b1ded6314974dddc75726149f7b19d33f4
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Sun Nov 19 13:05:55 2023 +0100
|
||||
|
||||
evaluate: fix rule replacement with anon sets
|
||||
|
||||
nft replace rule t c handle 3 'jhash ip protocol . ip saddr mod 170 vmap { 0-94 : goto wan1, 95-169 : goto wan2, 170-269 }"'
|
||||
BUG: unhandled op 2
|
||||
nft: src/evaluate.c:1748: interval_set_eval: Assertion `0' failed.
|
||||
|
||||
Fixes: 81e36530fcac ("src: replace interval segment tree overlap and automerge")
|
||||
Reported-by: Tino Reichardt <milky-netfilter@mcmilk.de>
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 27ecaa2..30190ac 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -1723,6 +1723,7 @@ static int interval_set_eval(struct eval_ctx *ctx, struct set *set,
|
||||
switch (ctx->cmd->op) {
|
||||
case CMD_CREATE:
|
||||
case CMD_ADD:
|
||||
+ case CMD_REPLACE:
|
||||
case CMD_INSERT:
|
||||
if (set->automerge) {
|
||||
ret = set_automerge(ctx->msgs, ctx->cmd, set, init,
|
||||
@ -0,0 +1,74 @@
|
||||
From 29629b90e74c3228434c4fc27e97c39c0761ed7e Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:40 +0200
|
||||
Subject: [PATCH] tests: shell: adjust add-after-delete flowtable for older
|
||||
kernels
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 566182cd8259cfc22f9fd949e9ad3c15ed6a7945
|
||||
|
||||
commit 566182cd8259cfc22f9fd949e9ad3c15ed6a7945
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Mon Nov 20 13:54:03 2023 +0100
|
||||
|
||||
tests: shell: adjust add-after-delete flowtable for older kernels
|
||||
|
||||
Remove counter from flowtable, older kernels (<=5.4) do not support this
|
||||
in testcases/flowtable/0013addafterdelete_0 so this bug is still
|
||||
covered.
|
||||
|
||||
Skip testcases/flowtable/0014addafterdelete_0 if flowtable counter
|
||||
support is not available.
|
||||
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
tests/shell/testcases/flowtable/0013addafterdelete_0 | 2 --
|
||||
tests/shell/testcases/flowtable/0014addafterdelete_0 | 2 ++
|
||||
tests/shell/testcases/flowtable/dumps/0013addafterdelete_0.nft | 1 -
|
||||
3 files changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/tests/shell/testcases/flowtable/0013addafterdelete_0 b/tests/shell/testcases/flowtable/0013addafterdelete_0
|
||||
index b23ab97..56c9834 100755
|
||||
--- a/tests/shell/testcases/flowtable/0013addafterdelete_0
|
||||
+++ b/tests/shell/testcases/flowtable/0013addafterdelete_0
|
||||
@@ -7,7 +7,6 @@ RULESET='table inet filter {
|
||||
flowtable f {
|
||||
hook ingress priority filter - 1
|
||||
devices = { lo }
|
||||
- counter
|
||||
}
|
||||
}'
|
||||
|
||||
@@ -20,7 +19,6 @@ table inet filter {
|
||||
flowtable f {
|
||||
hook ingress priority filter - 1
|
||||
devices = { lo }
|
||||
- counter
|
||||
}
|
||||
}'
|
||||
|
||||
diff --git a/tests/shell/testcases/flowtable/0014addafterdelete_0 b/tests/shell/testcases/flowtable/0014addafterdelete_0
|
||||
index 6a24c4b..1ac6510 100755
|
||||
--- a/tests/shell/testcases/flowtable/0014addafterdelete_0
|
||||
+++ b/tests/shell/testcases/flowtable/0014addafterdelete_0
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_flowtable_counter)
|
||||
+
|
||||
set -e
|
||||
|
||||
RULESET='table inet filter {
|
||||
diff --git a/tests/shell/testcases/flowtable/dumps/0013addafterdelete_0.nft b/tests/shell/testcases/flowtable/dumps/0013addafterdelete_0.nft
|
||||
index 83fdd5d..67db7d0 100644
|
||||
--- a/tests/shell/testcases/flowtable/dumps/0013addafterdelete_0.nft
|
||||
+++ b/tests/shell/testcases/flowtable/dumps/0013addafterdelete_0.nft
|
||||
@@ -2,6 +2,5 @@ table inet filter {
|
||||
flowtable f {
|
||||
hook ingress priority filter - 1
|
||||
devices = { lo }
|
||||
- counter
|
||||
}
|
||||
}
|
||||
59
0036-tests-shell-flush-connlimit-sets.patch
Normal file
59
0036-tests-shell-flush-connlimit-sets.patch
Normal file
@ -0,0 +1,59 @@
|
||||
From 93fe20fda0915183e19c513515d3f98e2d2c2df3 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:40 +0200
|
||||
Subject: [PATCH] tests: shell: flush connlimit sets
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit bab3ede002da778e18fa5f30ac7b05c4de5e1de8
|
||||
|
||||
commit bab3ede002da778e18fa5f30ac7b05c4de5e1de8
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Nov 21 16:33:17 2023 +0100
|
||||
|
||||
tests: shell: flush connlimit sets
|
||||
|
||||
Restored elements via set declaration are removed almost inmediately by
|
||||
GC, this is causing spurious failures in test runs.
|
||||
|
||||
Flush sets to ensure dump is always consistent. Still, cover that
|
||||
restoring a set with connlimit elements do not.
|
||||
|
||||
Fixes: 95d348d55a9e ("tests: shell: extend connlimit test")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
tests/shell/testcases/sets/0062set_connlimit_0 | 3 +++
|
||||
tests/shell/testcases/sets/dumps/0062set_connlimit_0.nft | 2 --
|
||||
2 files changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tests/shell/testcases/sets/0062set_connlimit_0 b/tests/shell/testcases/sets/0062set_connlimit_0
|
||||
index 48d589f..dab1da0 100755
|
||||
--- a/tests/shell/testcases/sets/0062set_connlimit_0
|
||||
+++ b/tests/shell/testcases/sets/0062set_connlimit_0
|
||||
@@ -24,3 +24,6 @@ RULESET="table ip x {
|
||||
}"
|
||||
|
||||
$NFT -f - <<< $RULESET
|
||||
+
|
||||
+$NFT flush set ip x est-connlimit
|
||||
+$NFT flush set ip x new-connlimit
|
||||
diff --git a/tests/shell/testcases/sets/dumps/0062set_connlimit_0.nft b/tests/shell/testcases/sets/dumps/0062set_connlimit_0.nft
|
||||
index 080d675..13bbb95 100644
|
||||
--- a/tests/shell/testcases/sets/dumps/0062set_connlimit_0.nft
|
||||
+++ b/tests/shell/testcases/sets/dumps/0062set_connlimit_0.nft
|
||||
@@ -3,7 +3,6 @@ table ip x {
|
||||
type ipv4_addr
|
||||
size 65535
|
||||
flags dynamic
|
||||
- elements = { 84.245.120.167 ct count over 20 }
|
||||
}
|
||||
|
||||
set new-connlimit {
|
||||
@@ -11,6 +10,5 @@ table ip x {
|
||||
size 65535
|
||||
flags dynamic
|
||||
ct count over 20
|
||||
- elements = { 84.245.120.167 ct count over 20 }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
From 65c523bdd547ea90488adebefcba672f0e676aca Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:40 +0200
|
||||
Subject: [PATCH] evaluate: bogus error when adding devices to flowtable
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 59d304f47a121afda867d792c709bc2c81946979
|
||||
|
||||
commit 59d304f47a121afda867d792c709bc2c81946979
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Wed Nov 22 09:43:04 2023 +0100
|
||||
|
||||
evaluate: bogus error when adding devices to flowtable
|
||||
|
||||
Bail out if flowtable declaration is missing and no devices are
|
||||
specified.
|
||||
|
||||
Otherwise, this reports a bogus error when adding new devices to an
|
||||
existing flowtable.
|
||||
|
||||
# nft -v
|
||||
nftables v1.0.9 (Old Doc Yak #3)
|
||||
# ip link add dummy1 type dummy
|
||||
# ip link set dummy1 up
|
||||
# nft 'create flowtable inet filter f1 { hook ingress priority 0; counter }'
|
||||
# nft 'add flowtable inet filter f1 { devices = { dummy1 } ; }'
|
||||
Error: missing hook and priority in flowtable declaration
|
||||
add flowtable inet filter f1 { devices = { dummy1 } ; }
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Fixes: 5ad475fce5a1 ("evaluate: bail out if new flowtable does not specify hook and priority")
|
||||
Reported-by: Martin Gignac <martin.gignac@gmail.com>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 2 +-
|
||||
tests/shell/testcases/flowtable/0015destroy_0 | 8 ++++++++
|
||||
2 files changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 30190ac..d204d3e 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -4862,7 +4862,7 @@ static int flowtable_evaluate(struct eval_ctx *ctx, struct flowtable *ft)
|
||||
return table_not_found(ctx);
|
||||
|
||||
if (!ft_cache_find(table, ft->handle.flowtable.name)) {
|
||||
- if (!ft->hook.name)
|
||||
+ if (!ft->hook.name && !ft->dev_expr)
|
||||
return chain_error(ctx, ft, "missing hook and priority in flowtable declaration");
|
||||
|
||||
ft_cache_add(flowtable_get(ft), table);
|
||||
diff --git a/tests/shell/testcases/flowtable/0015destroy_0 b/tests/shell/testcases/flowtable/0015destroy_0
|
||||
index d2a87da..cea3352 100755
|
||||
--- a/tests/shell/testcases/flowtable/0015destroy_0
|
||||
+++ b/tests/shell/testcases/flowtable/0015destroy_0
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
# NFT_TEST_REQUIRES(NFT_TEST_HAVE_destroy)
|
||||
|
||||
+trap "ip link del dummy1" EXIT
|
||||
+
|
||||
+ip link add dummy1 type dummy
|
||||
+ip link set dummy1 up
|
||||
+
|
||||
$NFT add table t
|
||||
|
||||
# pass for non-existent flowtable
|
||||
@@ -9,4 +14,7 @@ $NFT destroy flowtable t f
|
||||
|
||||
# successfully delete existing flowtable
|
||||
$NFT add flowtable t f '{ hook ingress priority 10; devices = { lo }; }'
|
||||
+
|
||||
+$NFT 'add flowtable t f { devices = { dummy1 } ; }'
|
||||
+
|
||||
$NFT destroy flowtable t f
|
||||
115
0038-tests-shell-split-nat-inet-tests.patch
Normal file
115
0038-tests-shell-split-nat-inet-tests.patch
Normal file
@ -0,0 +1,115 @@
|
||||
From 2c05e5e6b0c3aedcefbe73dbab6ac7b4f1b13138 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] tests: shell: split nat inet tests
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit b975de80bd1dbf0a04c6cb7a42e46c323c865de8
|
||||
|
||||
commit b975de80bd1dbf0a04c6cb7a42e46c323c865de8
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Nov 21 20:45:48 2023 +0100
|
||||
|
||||
tests: shell: split nat inet tests
|
||||
|
||||
Detach nat inet from existing tests not to reduce test coverage.
|
||||
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
.../optimizations/dumps/merge_nat.nft | 11 ----------
|
||||
.../optimizations/dumps/merge_nat_inet.nft | 11 ++++++++++
|
||||
tests/shell/testcases/optimizations/merge_nat | 16 --------------
|
||||
.../testcases/optimizations/merge_nat_inet | 21 +++++++++++++++++++
|
||||
4 files changed, 32 insertions(+), 27 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/optimizations/dumps/merge_nat_inet.nft
|
||||
create mode 100755 tests/shell/testcases/optimizations/merge_nat_inet
|
||||
|
||||
diff --git a/tests/shell/testcases/optimizations/dumps/merge_nat.nft b/tests/shell/testcases/optimizations/dumps/merge_nat.nft
|
||||
index 61feb27..f6c119e 100644
|
||||
--- a/tests/shell/testcases/optimizations/dumps/merge_nat.nft
|
||||
+++ b/tests/shell/testcases/optimizations/dumps/merge_nat.nft
|
||||
@@ -19,14 +19,3 @@ table ip test4 {
|
||||
tcp dport 85 redirect
|
||||
}
|
||||
}
|
||||
-table inet nat {
|
||||
- chain prerouting {
|
||||
- oif "lo" accept
|
||||
- dnat ip to iifname . ip daddr . tcp dport map { "enp2s0" . 72.2.3.70 . 80 : 10.1.1.52 . 80, "enp2s0" . 72.2.3.66 . 53122 : 10.1.1.10 . 22, "enp2s0" . 72.2.3.66 . 443 : 10.1.1.52 . 443 }
|
||||
- }
|
||||
-
|
||||
- chain postrouting {
|
||||
- oif "lo" accept
|
||||
- snat ip to ip daddr map { 72.2.3.66 : 10.2.2.2, 72.2.3.67 : 10.2.3.3 }
|
||||
- }
|
||||
-}
|
||||
diff --git a/tests/shell/testcases/optimizations/dumps/merge_nat_inet.nft b/tests/shell/testcases/optimizations/dumps/merge_nat_inet.nft
|
||||
new file mode 100644
|
||||
index 0000000..a1a1135
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/optimizations/dumps/merge_nat_inet.nft
|
||||
@@ -0,0 +1,11 @@
|
||||
+table inet nat {
|
||||
+ chain prerouting {
|
||||
+ oif "lo" accept
|
||||
+ dnat ip to iifname . ip daddr . tcp dport map { "enp2s0" . 72.2.3.70 . 80 : 10.1.1.52 . 80, "enp2s0" . 72.2.3.66 . 53122 : 10.1.1.10 . 22, "enp2s0" . 72.2.3.66 . 443 : 10.1.1.52 . 443 }
|
||||
+ }
|
||||
+
|
||||
+ chain postrouting {
|
||||
+ oif "lo" accept
|
||||
+ snat ip to ip daddr map { 72.2.3.66 : 10.2.2.2, 72.2.3.67 : 10.2.3.3 }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/optimizations/merge_nat b/tests/shell/testcases/optimizations/merge_nat
|
||||
index bfe9787..3ffcbd5 100755
|
||||
--- a/tests/shell/testcases/optimizations/merge_nat
|
||||
+++ b/tests/shell/testcases/optimizations/merge_nat
|
||||
@@ -36,19 +36,3 @@ RULESET="table ip test4 {
|
||||
}"
|
||||
|
||||
$NFT -o -f - <<< $RULESET
|
||||
-
|
||||
-RULESET="table inet nat {
|
||||
- chain prerouting {
|
||||
- oif lo accept
|
||||
- iifname enp2s0 ip daddr 72.2.3.66 tcp dport 53122 dnat to 10.1.1.10:22
|
||||
- iifname enp2s0 ip daddr 72.2.3.66 tcp dport 443 dnat to 10.1.1.52:443
|
||||
- iifname enp2s0 ip daddr 72.2.3.70 tcp dport 80 dnat to 10.1.1.52:80
|
||||
- }
|
||||
- chain postrouting {
|
||||
- oif lo accept
|
||||
- ip daddr 72.2.3.66 snat to 10.2.2.2
|
||||
- ip daddr 72.2.3.67 snat to 10.2.3.3
|
||||
- }
|
||||
-}"
|
||||
-
|
||||
-$NFT -o -f - <<< $RULESET
|
||||
diff --git a/tests/shell/testcases/optimizations/merge_nat_inet b/tests/shell/testcases/optimizations/merge_nat_inet
|
||||
new file mode 100755
|
||||
index 0000000..ff1916d
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/optimizations/merge_nat_inet
|
||||
@@ -0,0 +1,21 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_inet_nat)
|
||||
+
|
||||
+set -e
|
||||
+
|
||||
+RULESET="table inet nat {
|
||||
+ chain prerouting {
|
||||
+ oif lo accept
|
||||
+ iifname enp2s0 ip daddr 72.2.3.66 tcp dport 53122 dnat to 10.1.1.10:22
|
||||
+ iifname enp2s0 ip daddr 72.2.3.66 tcp dport 443 dnat to 10.1.1.52:443
|
||||
+ iifname enp2s0 ip daddr 72.2.3.70 tcp dport 80 dnat to 10.1.1.52:80
|
||||
+ }
|
||||
+ chain postrouting {
|
||||
+ oif lo accept
|
||||
+ ip daddr 72.2.3.66 snat to 10.2.2.2
|
||||
+ ip daddr 72.2.3.67 snat to 10.2.3.3
|
||||
+ }
|
||||
+}"
|
||||
+
|
||||
+$NFT -o -f - <<< $RULESET
|
||||
@ -0,0 +1,83 @@
|
||||
From bf752ee621e61026a40f050ac9d8a1eda351b81c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] evaluate: clone unary expression datatype to deal with
|
||||
dynamic datatype
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit faa6908fad6053ae9549c45b88d0402cc69cf1ed
|
||||
|
||||
commit faa6908fad6053ae9549c45b88d0402cc69cf1ed
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Wed Nov 22 20:35:07 2023 +0100
|
||||
|
||||
evaluate: clone unary expression datatype to deal with dynamic datatype
|
||||
|
||||
When allocating a unary expression, clone the datatype to deal with
|
||||
dynamic datatypes.
|
||||
|
||||
Fixes: 6b01bb9ff798 ("datatype: concat expression only releases dynamically allocated datatype")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 2 +-
|
||||
tests/shell/testcases/maps/dumps/vmap_unary.nft | 11 +++++++++++
|
||||
tests/shell/testcases/maps/vmap_unary | 17 +++++++++++++++++
|
||||
3 files changed, 29 insertions(+), 1 deletion(-)
|
||||
create mode 100644 tests/shell/testcases/maps/dumps/vmap_unary.nft
|
||||
create mode 100755 tests/shell/testcases/maps/vmap_unary
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index d204d3e..6f0fba6 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -1245,7 +1245,7 @@ static int expr_evaluate_unary(struct eval_ctx *ctx, struct expr **expr)
|
||||
BUG("invalid unary operation %u\n", unary->op);
|
||||
}
|
||||
|
||||
- unary->dtype = arg->dtype;
|
||||
+ unary->dtype = datatype_clone(arg->dtype);
|
||||
unary->byteorder = byteorder;
|
||||
unary->len = arg->len;
|
||||
return 0;
|
||||
diff --git a/tests/shell/testcases/maps/dumps/vmap_unary.nft b/tests/shell/testcases/maps/dumps/vmap_unary.nft
|
||||
new file mode 100644
|
||||
index 0000000..46c538b
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/maps/dumps/vmap_unary.nft
|
||||
@@ -0,0 +1,11 @@
|
||||
+table ip filter {
|
||||
+ map ipsec_in {
|
||||
+ typeof ipsec in reqid . iif : verdict
|
||||
+ flags interval
|
||||
+ }
|
||||
+
|
||||
+ chain INPUT {
|
||||
+ type filter hook input priority filter; policy drop;
|
||||
+ ipsec in reqid . iif vmap @ipsec_in
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/maps/vmap_unary b/tests/shell/testcases/maps/vmap_unary
|
||||
new file mode 100755
|
||||
index 0000000..4038d1c
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/maps/vmap_unary
|
||||
@@ -0,0 +1,17 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+set -e
|
||||
+
|
||||
+RULESET="table ip filter {
|
||||
+ map ipsec_in {
|
||||
+ typeof ipsec in reqid . iif : verdict
|
||||
+ flags interval
|
||||
+ }
|
||||
+
|
||||
+ chain INPUT {
|
||||
+ type filter hook input priority 0; policy drop
|
||||
+ ipsec in reqid . iif vmap @ipsec_in
|
||||
+ }
|
||||
+}"
|
||||
+
|
||||
+$NFT -f - <<< $RULESET
|
||||
65
0040-evaluate-reject-sets-with-no-key.patch
Normal file
65
0040-evaluate-reject-sets-with-no-key.patch
Normal file
@ -0,0 +1,65 @@
|
||||
From e0b42568ea971334ca2177f5275bfab4e8312e8c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] evaluate: reject sets with no key
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 09c573053ff03ad0a2eeb12c2957881648062f50
|
||||
|
||||
commit 09c573053ff03ad0a2eeb12c2957881648062f50
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Thu Nov 30 21:29:52 2023 +0100
|
||||
|
||||
evaluate: reject sets with no key
|
||||
|
||||
nft --check -f tests/shell/testcases/bogons/nft-f/set_without_key
|
||||
Segmentation fault (core dumped)
|
||||
|
||||
Fixes: 56c90a2dd2eb ("evaluate: expand sets and maps before evaluation")
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 3 +++
|
||||
tests/shell/testcases/bogons/nft-f/map_without_key | 5 +++++
|
||||
tests/shell/testcases/bogons/nft-f/set_without_key | 5 +++++
|
||||
3 files changed, 13 insertions(+)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/map_without_key
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/set_without_key
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 6f0fba6..2955ac5 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -4616,6 +4616,9 @@ static int elems_evaluate(struct eval_ctx *ctx, struct set *set)
|
||||
{
|
||||
ctx->set = set;
|
||||
if (set->init != NULL) {
|
||||
+ if (set->key == NULL)
|
||||
+ return set_error(ctx, set, "set definition does not specify key");
|
||||
+
|
||||
__expr_set_context(&ctx->ectx, set->key->dtype,
|
||||
set->key->byteorder, set->key->len, 0);
|
||||
if (expr_evaluate(ctx, &set->init) < 0)
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/map_without_key b/tests/shell/testcases/bogons/nft-f/map_without_key
|
||||
new file mode 100644
|
||||
index 0000000..78f16b2
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/map_without_key
|
||||
@@ -0,0 +1,5 @@
|
||||
+table t {
|
||||
+ map m {
|
||||
+ elements = { 0x00000023 : 0x00001337 }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/set_without_key b/tests/shell/testcases/bogons/nft-f/set_without_key
|
||||
new file mode 100644
|
||||
index 0000000..f194afb
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/set_without_key
|
||||
@@ -0,0 +1,5 @@
|
||||
+table ip t {
|
||||
+ set s {
|
||||
+ elements = { 0x00000023-0x00000142, 0x00001337 }
|
||||
+ }
|
||||
+}
|
||||
@ -0,0 +1,59 @@
|
||||
From 8523567b0fc4d2c0f978ee43234d984d5e75795c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] evaluate: prevent assert when evaluating very large shift
|
||||
values
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 26723202e600604ab7cf48915507cfcb7a313620
|
||||
|
||||
commit 26723202e600604ab7cf48915507cfcb7a313620
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Fri Dec 1 14:16:14 2023 +0100
|
||||
|
||||
evaluate: prevent assert when evaluating very large shift values
|
||||
|
||||
Error out instead of 'nft: gmputil.c:67: mpz_get_uint32: Assertion `cnt <= 1' failed.'.
|
||||
|
||||
Fixes: edecd58755a8 ("evaluate: support shifts larger than the width of the left operand")
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 9 +++++++--
|
||||
tests/shell/testcases/bogons/nft-f/huge_shift_assert | 5 +++++
|
||||
2 files changed, 12 insertions(+), 2 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/huge_shift_assert
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 2955ac5..1d13db1 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -1312,9 +1312,14 @@ static int constant_binop_simplify(struct eval_ctx *ctx, struct expr **expr)
|
||||
static int expr_evaluate_shift(struct eval_ctx *ctx, struct expr **expr)
|
||||
{
|
||||
struct expr *op = *expr, *left = op->left, *right = op->right;
|
||||
- unsigned int shift = mpz_get_uint32(right->value);
|
||||
- unsigned int max_shift_len;
|
||||
+ unsigned int shift, max_shift_len;
|
||||
|
||||
+ /* mpz_get_uint32 has assert() for huge values */
|
||||
+ if (mpz_cmp_ui(right->value, UINT_MAX) > 0)
|
||||
+ return expr_binary_error(ctx->msgs, right, left,
|
||||
+ "shifts exceeding %u bits are not supported", UINT_MAX);
|
||||
+
|
||||
+ shift = mpz_get_uint32(right->value);
|
||||
if (ctx->stmt_len > left->len)
|
||||
max_shift_len = ctx->stmt_len;
|
||||
else
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/huge_shift_assert b/tests/shell/testcases/bogons/nft-f/huge_shift_assert
|
||||
new file mode 100644
|
||||
index 0000000..7599f85
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/huge_shift_assert
|
||||
@@ -0,0 +1,5 @@
|
||||
+table ip t {
|
||||
+ chain c {
|
||||
+ counter name meta mark >> 88888888888888888888
|
||||
+ }
|
||||
+}
|
||||
70
0042-evaluate-disable-meta-set-with-ranges.patch
Normal file
70
0042-evaluate-disable-meta-set-with-ranges.patch
Normal file
@ -0,0 +1,70 @@
|
||||
From 04adeaaab4d640f4bb50e783db835909df9959d4 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] evaluate: disable meta set with ranges
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit d99b44adc5cfc455fdafd9b4bdabd413edf9a38a
|
||||
|
||||
commit d99b44adc5cfc455fdafd9b4bdabd413edf9a38a
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Mon Dec 4 19:04:58 2023 +0100
|
||||
|
||||
evaluate: disable meta set with ranges
|
||||
|
||||
... this will cause an assertion in netlink linearization, catch this
|
||||
at eval stage instead.
|
||||
|
||||
before:
|
||||
BUG: unknown expression type range
|
||||
nft: netlink_linearize.c:908: netlink_gen_expr: Assertion `0' failed.
|
||||
|
||||
after:
|
||||
/unknown_expr_type_range_assert:3:31-40: Error: Meta expression cannot be a range
|
||||
meta mark set 0x001-3434
|
||||
^^^^^^^^^^
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 13 +++++++++++++
|
||||
.../bogons/nft-f/unknown_expr_type_range_assert | 5 +++++
|
||||
2 files changed, 18 insertions(+)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/unknown_expr_type_range_assert
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 1d13db1..9de71d7 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -3148,6 +3148,19 @@ static int stmt_evaluate_meta(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
&stmt->meta.expr);
|
||||
ctx->stmt_len = 0;
|
||||
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ switch (stmt->meta.expr->etype) {
|
||||
+ case EXPR_RANGE:
|
||||
+ ret = expr_error(ctx->msgs, stmt->meta.expr,
|
||||
+ "Meta expression cannot be a range");
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+
|
||||
+ }
|
||||
+
|
||||
return ret;
|
||||
}
|
||||
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/unknown_expr_type_range_assert b/tests/shell/testcases/bogons/nft-f/unknown_expr_type_range_assert
|
||||
new file mode 100644
|
||||
index 0000000..234dd62
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/unknown_expr_type_range_assert
|
||||
@@ -0,0 +1,5 @@
|
||||
+table ip x {
|
||||
+ chain k {
|
||||
+ meta mark set 0x001-3434
|
||||
+ }
|
||||
+}
|
||||
78
0043-monitor-add-support-for-concatenated-set-ranges.patch
Normal file
78
0043-monitor-add-support-for-concatenated-set-ranges.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From 4559a6cc20f887f7763153790f01449da18bf1cd Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] monitor: add support for concatenated set ranges
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 0d9392eef5f2c79ac7c19f59754a0aee574b5617
|
||||
|
||||
commit 0d9392eef5f2c79ac7c19f59754a0aee574b5617
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Dec 5 17:20:05 2023 +0100
|
||||
|
||||
monitor: add support for concatenated set ranges
|
||||
|
||||
monitor is missing concatenated set ranges support.
|
||||
|
||||
Fixes: 8ac2f3b2fca3 ("src: Add support for concatenated set ranges")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/monitor.c | 11 +++++++++--
|
||||
tests/monitor/testcases/set-concat-interval.t | 12 ++++++++++++
|
||||
2 files changed, 21 insertions(+), 2 deletions(-)
|
||||
create mode 100644 tests/monitor/testcases/set-concat-interval.t
|
||||
|
||||
diff --git a/src/monitor.c b/src/monitor.c
|
||||
index 82762a0..2fc16d6 100644
|
||||
--- a/src/monitor.c
|
||||
+++ b/src/monitor.c
|
||||
@@ -390,13 +390,19 @@ static bool netlink_event_range_cache(struct set *cached_set,
|
||||
|
||||
/* don't cache half-open range elements */
|
||||
elem = list_entry(dummyset->init->expressions.prev, struct expr, list);
|
||||
- if (!set_elem_is_open_interval(elem)) {
|
||||
+ if (!set_elem_is_open_interval(elem) &&
|
||||
+ dummyset->desc.field_count <= 1) {
|
||||
cached_set->rg_cache = expr_clone(elem);
|
||||
return true;
|
||||
}
|
||||
|
||||
out_decompose:
|
||||
- interval_map_decompose(dummyset->init);
|
||||
+ if (dummyset->flags & NFT_SET_INTERVAL &&
|
||||
+ dummyset->desc.field_count > 1)
|
||||
+ concat_range_aggregate(dummyset->init);
|
||||
+ else
|
||||
+ interval_map_decompose(dummyset->init);
|
||||
+
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -437,6 +443,7 @@ static int netlink_events_setelem_cb(const struct nlmsghdr *nlh, int type,
|
||||
dummyset->data = expr_clone(set->data);
|
||||
dummyset->flags = set->flags;
|
||||
dummyset->init = set_expr_alloc(monh->loc, set);
|
||||
+ dummyset->desc.field_count = set->desc.field_count;
|
||||
|
||||
nlsei = nftnl_set_elems_iter_create(nls);
|
||||
if (nlsei == NULL)
|
||||
diff --git a/tests/monitor/testcases/set-concat-interval.t b/tests/monitor/testcases/set-concat-interval.t
|
||||
new file mode 100644
|
||||
index 0000000..763dc31
|
||||
--- /dev/null
|
||||
+++ b/tests/monitor/testcases/set-concat-interval.t
|
||||
@@ -0,0 +1,12 @@
|
||||
+# setup first
|
||||
+I add table ip t
|
||||
+I add chain ip t c
|
||||
+O -
|
||||
+J {"add": {"table": {"family": "ip", "name": "t", "handle": 0}}}
|
||||
+J {"add": {"chain": {"family": "ip", "table": "t", "name": "c", "handle": 0}}}
|
||||
+
|
||||
+# add set with elements, monitor output expectedly differs
|
||||
+I add map ip t s { typeof udp length . @ih,32,32 : verdict; flags interval; elements = { 20-80 . 0x14 : accept, 1-10 . 0xa : drop }; }
|
||||
+O add map ip t s { typeof udp length . @ih,32,32 : verdict; flags interval; }
|
||||
+O add element ip t s { 20-80 . 0x14 : accept }
|
||||
+O add element ip t s { 1-10 . 0xa : drop }
|
||||
55
0044-evaluate-reject-set-definition-with-no-key.patch
Normal file
55
0044-evaluate-reject-set-definition-with-no-key.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From 1ccb4065209aef5be9e922c8702317636ca67745 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] evaluate: reject set definition with no key
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 1949a63215b423b914d3a7a9de7511cb48af3c09
|
||||
|
||||
commit 1949a63215b423b914d3a7a9de7511cb48af3c09
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Wed Dec 6 13:40:22 2023 +0100
|
||||
|
||||
evaluate: reject set definition with no key
|
||||
|
||||
tests/shell/testcases/bogons/nft-f/set_definition_with_no_key_assert
|
||||
BUG: unhandled key type 2
|
||||
nft: src/intervals.c:59: setelem_expr_to_range: Assertion `0' failed.
|
||||
|
||||
This patch adds a new unit tests/shell courtesy of Florian Westphal.
|
||||
|
||||
Fixes: 3975430b12d9 ("src: expand table command before evaluation")
|
||||
Reported-by: Florian Westphal <fw@strlen.de>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 9de71d7..c2a7a41 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -4664,6 +4664,12 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
|
||||
struct stmt *stmt;
|
||||
const char *type;
|
||||
|
||||
+ type = set_is_map(set->flags) ? "map" : "set";
|
||||
+
|
||||
+ if (set->key == NULL)
|
||||
+ return set_error(ctx, set, "%s definition does not specify key",
|
||||
+ type);
|
||||
+
|
||||
if (!set_is_anonymous(set->flags)) {
|
||||
table = table_cache_find(&ctx->nft->cache.table_cache,
|
||||
set->handle.table.name,
|
||||
@@ -4687,8 +4693,6 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
|
||||
if (!(set->flags & NFT_SET_INTERVAL) && set->automerge)
|
||||
return set_error(ctx, set, "auto-merge only works with interval sets");
|
||||
|
||||
- type = set_is_map(set->flags) ? "map" : "set";
|
||||
-
|
||||
if (set->key == NULL)
|
||||
return set_error(ctx, set, "%s definition does not specify key",
|
||||
type);
|
||||
210
0045-parser-tcpopt-fix-tcp-option-parsing-with-NUM-length.patch
Normal file
210
0045-parser-tcpopt-fix-tcp-option-parsing-with-NUM-length.patch
Normal file
@ -0,0 +1,210 @@
|
||||
From 039d41bcd5dc8728690f5e9a6cf7c1b68bd05905 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] parser: tcpopt: fix tcp option parsing with NUM + length
|
||||
field
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 59a33d08ab3a75b2ae370b6816942793f49fa8db
|
||||
|
||||
commit 59a33d08ab3a75b2ae370b6816942793f49fa8db
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Tue Dec 5 12:56:08 2023 +0100
|
||||
|
||||
parser: tcpopt: fix tcp option parsing with NUM + length field
|
||||
|
||||
tcp option 254 length ge 4
|
||||
|
||||
... will segfault.
|
||||
The crash bug is that tcpopt_expr_alloc() can return NULL if we cannot
|
||||
find a suitable template for the requested kind + field combination,
|
||||
so add the needed error handling in the bison parser.
|
||||
|
||||
However, we can handle this. NOP and EOL have templates, all other
|
||||
options (known or unknown) must also have a length field.
|
||||
|
||||
So also add a fallback template to handle both kind and length, even
|
||||
if only a numeric option is given that nft doesn't recognize.
|
||||
|
||||
Don't bother with output, above will be printed via raw syntax, i.e.
|
||||
tcp option @254,8,8 >= 4.
|
||||
|
||||
Fixes: 24d8da308342 ("tcpopt: allow to check for presence of any tcp option")
|
||||
Reported-by: Maciej Żenczykowski <zenczykowski@gmail.com>
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_bison.y | 4 ++
|
||||
src/tcpopt.c | 44 +++++++++++----
|
||||
.../packetpath/dumps/tcp_options.nodump | 0
|
||||
tests/shell/testcases/packetpath/tcp_options | 55 +++++++++++++++++++
|
||||
4 files changed, 93 insertions(+), 10 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/packetpath/dumps/tcp_options.nodump
|
||||
create mode 100755 tests/shell/testcases/packetpath/tcp_options
|
||||
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 751b3e1..9386a9c 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -5837,6 +5837,10 @@ tcp_hdr_expr : TCP tcp_hdr_field
|
||||
| TCP OPTION tcp_hdr_option_kind_and_field
|
||||
{
|
||||
$$ = tcpopt_expr_alloc(&@$, $3.kind, $3.field);
|
||||
+ if ($$ == NULL) {
|
||||
+ erec_queue(error(&@1, "Could not find a tcp option template"), state->msgs);
|
||||
+ YYERROR;
|
||||
+ }
|
||||
}
|
||||
| TCP OPTION AT close_scope_at tcp_hdr_option_type COMMA NUM COMMA NUM
|
||||
{
|
||||
diff --git a/src/tcpopt.c b/src/tcpopt.c
|
||||
index 3fcb273..8111a50 100644
|
||||
--- a/src/tcpopt.c
|
||||
+++ b/src/tcpopt.c
|
||||
@@ -118,6 +118,13 @@ static const struct exthdr_desc tcpopt_mptcp = {
|
||||
[TCPOPT_MPTCP_SUBTYPE] = PHT("subtype", 16, 4),
|
||||
},
|
||||
};
|
||||
+
|
||||
+static const struct exthdr_desc tcpopt_fallback = {
|
||||
+ .templates = {
|
||||
+ [TCPOPT_COMMON_KIND] = PHT("kind", 0, 8),
|
||||
+ [TCPOPT_COMMON_LENGTH] = PHT("length", 8, 8),
|
||||
+ },
|
||||
+};
|
||||
#undef PHT
|
||||
|
||||
const struct exthdr_desc *tcpopt_protocols[] = {
|
||||
@@ -133,6 +140,17 @@ const struct exthdr_desc *tcpopt_protocols[] = {
|
||||
[TCPOPT_KIND_FASTOPEN] = &tcpopt_fastopen,
|
||||
};
|
||||
|
||||
+static void tcpopt_assign_tmpl(struct expr *expr,
|
||||
+ const struct proto_hdr_template *tmpl,
|
||||
+ const struct exthdr_desc *desc)
|
||||
+{
|
||||
+ expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT;
|
||||
+
|
||||
+ expr->exthdr.desc = desc;
|
||||
+ expr->exthdr.tmpl = tmpl;
|
||||
+ expr->exthdr.offset = tmpl->offset;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* tcpopt_expr_alloc - allocate tcp option extension expression
|
||||
*
|
||||
@@ -182,18 +200,26 @@ struct expr *tcpopt_expr_alloc(const struct location *loc,
|
||||
desc = tcpopt_protocols[kind];
|
||||
|
||||
if (!desc) {
|
||||
- if (field != TCPOPT_COMMON_KIND || kind > 255)
|
||||
+ if (kind > 255)
|
||||
return NULL;
|
||||
|
||||
+ desc = &tcpopt_fallback;
|
||||
+
|
||||
+ switch (field) {
|
||||
+ case TCPOPT_COMMON_KIND:
|
||||
+ case TCPOPT_COMMON_LENGTH:
|
||||
+ tmpl = &desc->templates[field];
|
||||
+ break;
|
||||
+ default:
|
||||
+ tmpl = &tcpopt_unknown_template;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
expr = expr_alloc(loc, EXPR_EXTHDR, &integer_type,
|
||||
BYTEORDER_BIG_ENDIAN, 8);
|
||||
|
||||
- desc = tcpopt_protocols[TCPOPT_NOP];
|
||||
- tmpl = &desc->templates[field];
|
||||
- expr->exthdr.desc = desc;
|
||||
- expr->exthdr.tmpl = tmpl;
|
||||
- expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT;
|
||||
expr->exthdr.raw_type = kind;
|
||||
+ tcpopt_assign_tmpl(expr, tmpl, desc);
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -203,11 +229,9 @@ struct expr *tcpopt_expr_alloc(const struct location *loc,
|
||||
|
||||
expr = expr_alloc(loc, EXPR_EXTHDR, tmpl->dtype,
|
||||
BYTEORDER_BIG_ENDIAN, tmpl->len);
|
||||
- expr->exthdr.desc = desc;
|
||||
- expr->exthdr.tmpl = tmpl;
|
||||
- expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT;
|
||||
+
|
||||
expr->exthdr.raw_type = desc->type;
|
||||
- expr->exthdr.offset = tmpl->offset;
|
||||
+ tcpopt_assign_tmpl(expr, tmpl, desc);
|
||||
|
||||
return expr;
|
||||
}
|
||||
diff --git a/tests/shell/testcases/packetpath/dumps/tcp_options.nodump b/tests/shell/testcases/packetpath/dumps/tcp_options.nodump
|
||||
new file mode 100644
|
||||
index 0000000..e69de29
|
||||
diff --git a/tests/shell/testcases/packetpath/tcp_options b/tests/shell/testcases/packetpath/tcp_options
|
||||
new file mode 100755
|
||||
index 0000000..1c9ee53
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/packetpath/tcp_options
|
||||
@@ -0,0 +1,55 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+have_socat="no"
|
||||
+socat -h > /dev/null && have_socat="yes"
|
||||
+
|
||||
+ip link set lo up
|
||||
+
|
||||
+$NFT -f /dev/stdin <<EOF
|
||||
+table inet t {
|
||||
+ counter nomatchc {}
|
||||
+ counter sackpermc {}
|
||||
+ counter maxsegc {}
|
||||
+ counter nopc {}
|
||||
+
|
||||
+ chain c {
|
||||
+ type filter hook output priority 0;
|
||||
+ tcp dport != 22345 accept
|
||||
+ tcp flags syn / fin,syn,rst,ack tcp option 254 length ge 4 counter name nomatchc drop
|
||||
+ tcp flags syn / fin,syn,rst,ack tcp option fastopen length ge 2 reset tcp option fastopen counter name nomatchc
|
||||
+ tcp flags syn / fin,syn,rst,ack tcp option sack-perm missing counter name nomatchc
|
||||
+ tcp flags syn / fin,syn,rst,ack tcp option sack-perm exists counter name sackpermc
|
||||
+ tcp flags syn / fin,syn,rst,ack tcp option maxseg size gt 1400 counter name maxsegc
|
||||
+ tcp flags syn / fin,syn,rst,ack tcp option nop missing counter name nomatchc
|
||||
+ tcp flags syn / fin,syn,rst,ack tcp option nop exists counter name nopc
|
||||
+ tcp flags syn / fin,syn,rst,ack drop
|
||||
+ }
|
||||
+}
|
||||
+EOF
|
||||
+
|
||||
+if [ $? -ne 0 ]; then
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+if [ $have_socat != "yes" ]; then
|
||||
+ echo "Ran partial test, socat not available (skipped)"
|
||||
+ exit 77
|
||||
+fi
|
||||
+
|
||||
+# This will fail (drop in output -> connect fails with eperm)
|
||||
+socat -u STDIN TCP:127.0.0.1:22345,connect-timeout=1 < /dev/null > /dev/null
|
||||
+
|
||||
+# can't validate via dump file, syn rexmit can cause counters to be > 1 in rare cases.
|
||||
+
|
||||
+$NFT list counter inet t nomatchc
|
||||
+
|
||||
+# nomatchc must be 0.
|
||||
+$NFT list counter inet t nomatchc | grep -q "packets 0" || exit 1
|
||||
+
|
||||
+# these counters must not be 0.
|
||||
+for nz in sackpermc maxsegc nopc; do
|
||||
+ $NFT list counter inet t $nz
|
||||
+ $NFT list counter inet t $nz | grep -q "packets 0" && exit 1
|
||||
+done
|
||||
+
|
||||
+exit 0
|
||||
344
0046-evaluate-reset-statement-length-context-before-evalu.patch
Normal file
344
0046-evaluate-reset-statement-length-context-before-evalu.patch
Normal file
@ -0,0 +1,344 @@
|
||||
From dca8ddacdacbad26f92b7cd665dd150a341ced26 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] evaluate: reset statement length context before evaluating
|
||||
statement
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 8d3de823b622136e1d05a6fed11ff2dc0e804f8a
|
||||
|
||||
commit 8d3de823b622136e1d05a6fed11ff2dc0e804f8a
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Wed Dec 6 18:48:29 2023 +0100
|
||||
|
||||
evaluate: reset statement length context before evaluating statement
|
||||
|
||||
This patch consolidates ctx->stmt_len reset in stmt_evaluate() to avoid
|
||||
this problem. Note that stmt_evaluate_meta() and stmt_evaluate_ct()
|
||||
already reset it after the statement evaluation.
|
||||
|
||||
Moreover, statement dependency can be generated while evaluating a meta
|
||||
and ct statement. Payload statement dependency already manually stashes
|
||||
this before calling stmt_evaluate(). Add a new stmt_dependency_evaluate()
|
||||
function to stash statement length context when evaluating a new statement
|
||||
dependency and use it for all of the existing statement dependencies.
|
||||
|
||||
Florian also says:
|
||||
|
||||
'meta mark set vlan id map { 1 : 0x00000001, 4095 : 0x00004095 }' will
|
||||
crash. Reason is that the l2 dependency generated here is errounously
|
||||
expanded to a 32bit-one, so the evaluation path won't recognize this
|
||||
as a L2 dependency. Therefore, pctx->stacked_ll_count is 0 and
|
||||
__expr_evaluate_payload() crashes with a null deref when
|
||||
dereferencing pctx->stacked_ll[0].
|
||||
|
||||
nft-test.py gains a fugly hack to tolerate '!map typeof vlan id : meta mark'.
|
||||
For more generic support we should find something more acceptable, e.g.
|
||||
|
||||
!map typeof( everything here is a key or data ) timeout ...
|
||||
|
||||
tests/py update and assert(pctx->stacked_ll_count) by Florian Westphal.
|
||||
|
||||
Fixes: edecd58755a8 ("evaluate: support shifts larger than the width of the left operand")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
include/statement.h | 1 +
|
||||
src/evaluate.c | 26 ++++++++++++++++++--------
|
||||
src/payload.c | 29 +++++++----------------------
|
||||
tests/py/any/meta.t | 4 ++++
|
||||
tests/py/any/meta.t.payload | 25 +++++++++++++++++++++++++
|
||||
tests/py/any/meta.t.payload.bridge | 20 ++++++++++++++++++++
|
||||
tests/py/nft-test.py | 17 +++++++++++++----
|
||||
7 files changed, 88 insertions(+), 34 deletions(-)
|
||||
create mode 100644 tests/py/any/meta.t.payload.bridge
|
||||
|
||||
diff --git a/include/statement.h b/include/statement.h
|
||||
index 720a6ac..662f99d 100644
|
||||
--- a/include/statement.h
|
||||
+++ b/include/statement.h
|
||||
@@ -416,6 +416,7 @@ struct stmt {
|
||||
extern struct stmt *stmt_alloc(const struct location *loc,
|
||||
const struct stmt_ops *ops);
|
||||
int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt);
|
||||
+int stmt_dependency_evaluate(struct eval_ctx *ctx, struct stmt *stmt);
|
||||
extern void stmt_free(struct stmt *stmt);
|
||||
extern void stmt_list_free(struct list_head *list);
|
||||
extern void stmt_print(const struct stmt *stmt, struct output_ctx *octx);
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index c2a7a41..cfdc6c0 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -454,6 +454,18 @@ static int expr_evaluate_primary(struct eval_ctx *ctx, struct expr **expr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int stmt_dependency_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
+{
|
||||
+ uint32_t stmt_len = ctx->stmt_len;
|
||||
+
|
||||
+ if (stmt_evaluate(ctx, stmt) < 0)
|
||||
+ return stmt_error(ctx, stmt, "dependency statement is invalid");
|
||||
+
|
||||
+ ctx->stmt_len = stmt_len;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
conflict_resolution_gen_dependency(struct eval_ctx *ctx, int protocol,
|
||||
const struct expr *expr,
|
||||
@@ -479,7 +491,7 @@ conflict_resolution_gen_dependency(struct eval_ctx *ctx, int protocol,
|
||||
|
||||
dep = relational_expr_alloc(&expr->location, OP_EQ, left, right);
|
||||
stmt = expr_stmt_alloc(&dep->location, dep);
|
||||
- if (stmt_evaluate(ctx, stmt) < 0)
|
||||
+ if (stmt_dependency_evaluate(ctx, stmt) < 0)
|
||||
return expr_error(ctx->msgs, expr,
|
||||
"dependency statement is invalid");
|
||||
|
||||
@@ -696,9 +708,8 @@ static int meta_iiftype_gen_dependency(struct eval_ctx *ctx,
|
||||
"for this family");
|
||||
|
||||
nstmt = meta_stmt_meta_iiftype(&payload->location, type);
|
||||
- if (stmt_evaluate(ctx, nstmt) < 0)
|
||||
- return expr_error(ctx->msgs, payload,
|
||||
- "dependency statement is invalid");
|
||||
+ if (stmt_dependency_evaluate(ctx, nstmt) < 0)
|
||||
+ return -1;
|
||||
|
||||
if (ctx->inner_desc)
|
||||
nstmt->expr->left->meta.inner_desc = ctx->inner_desc;
|
||||
@@ -809,6 +820,7 @@ static int __expr_evaluate_payload(struct eval_ctx *ctx, struct expr *expr)
|
||||
desc->name,
|
||||
payload->payload.desc->name);
|
||||
|
||||
+ assert(pctx->stacked_ll_count);
|
||||
payload->payload.offset += pctx->stacked_ll[0]->length;
|
||||
rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
|
||||
return 1;
|
||||
@@ -3146,8 +3158,6 @@ static int stmt_evaluate_meta(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
stmt->meta.tmpl->len,
|
||||
stmt->meta.tmpl->byteorder,
|
||||
&stmt->meta.expr);
|
||||
- ctx->stmt_len = 0;
|
||||
-
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -3175,8 +3185,6 @@ static int stmt_evaluate_ct(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
stmt->ct.tmpl->len,
|
||||
stmt->ct.tmpl->byteorder,
|
||||
&stmt->ct.expr);
|
||||
- ctx->stmt_len = 0;
|
||||
-
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
@@ -4468,6 +4476,8 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
erec_destroy(erec);
|
||||
}
|
||||
|
||||
+ ctx->stmt_len = 0;
|
||||
+
|
||||
switch (stmt->ops->type) {
|
||||
case STMT_CONNLIMIT:
|
||||
case STMT_COUNTER:
|
||||
diff --git a/src/payload.c b/src/payload.c
|
||||
index 140ca50..5de3d32 100644
|
||||
--- a/src/payload.c
|
||||
+++ b/src/payload.c
|
||||
@@ -407,7 +407,6 @@ static int payload_add_dependency(struct eval_ctx *ctx,
|
||||
const struct proto_hdr_template *tmpl;
|
||||
struct expr *dep, *left, *right;
|
||||
struct proto_ctx *pctx;
|
||||
- unsigned int stmt_len;
|
||||
struct stmt *stmt;
|
||||
int protocol;
|
||||
|
||||
@@ -429,15 +428,9 @@ static int payload_add_dependency(struct eval_ctx *ctx,
|
||||
|
||||
dep = relational_expr_alloc(&expr->location, OP_EQ, left, right);
|
||||
|
||||
- stmt_len = ctx->stmt_len;
|
||||
- ctx->stmt_len = 0;
|
||||
-
|
||||
stmt = expr_stmt_alloc(&dep->location, dep);
|
||||
- if (stmt_evaluate(ctx, stmt) < 0) {
|
||||
- return expr_error(ctx->msgs, expr,
|
||||
- "dependency statement is invalid");
|
||||
- }
|
||||
- ctx->stmt_len = stmt_len;
|
||||
+ if (stmt_dependency_evaluate(ctx, stmt) < 0)
|
||||
+ return -1;
|
||||
|
||||
if (ctx->inner_desc) {
|
||||
if (tmpl->meta_key)
|
||||
@@ -547,7 +540,6 @@ int payload_gen_dependency(struct eval_ctx *ctx, const struct expr *expr,
|
||||
const struct hook_proto_desc *h;
|
||||
const struct proto_desc *desc;
|
||||
struct proto_ctx *pctx;
|
||||
- unsigned int stmt_len;
|
||||
struct stmt *stmt;
|
||||
uint16_t type;
|
||||
|
||||
@@ -564,17 +556,11 @@ int payload_gen_dependency(struct eval_ctx *ctx, const struct expr *expr,
|
||||
"protocol specification is invalid "
|
||||
"for this family");
|
||||
|
||||
- stmt_len = ctx->stmt_len;
|
||||
- ctx->stmt_len = 0;
|
||||
-
|
||||
stmt = meta_stmt_meta_iiftype(&expr->location, type);
|
||||
- if (stmt_evaluate(ctx, stmt) < 0) {
|
||||
- return expr_error(ctx->msgs, expr,
|
||||
- "dependency statement is invalid");
|
||||
- }
|
||||
- *res = stmt;
|
||||
+ if (stmt_dependency_evaluate(ctx, stmt) < 0)
|
||||
+ return -1;
|
||||
|
||||
- ctx->stmt_len = stmt_len;
|
||||
+ *res = stmt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1442,9 +1428,8 @@ int payload_gen_icmp_dependency(struct eval_ctx *ctx, const struct expr *expr,
|
||||
|
||||
pctx->th_dep.icmp.type = type;
|
||||
|
||||
- if (stmt_evaluate(ctx, stmt) < 0)
|
||||
- return expr_error(ctx->msgs, expr,
|
||||
- "icmp dependency statement is invalid");
|
||||
+ if (stmt_dependency_evaluate(ctx, stmt) < 0)
|
||||
+ return -1;
|
||||
done:
|
||||
*res = stmt;
|
||||
return 0;
|
||||
diff --git a/tests/py/any/meta.t b/tests/py/any/meta.t
|
||||
index 12fabb7..718c7ad 100644
|
||||
--- a/tests/py/any/meta.t
|
||||
+++ b/tests/py/any/meta.t
|
||||
@@ -224,3 +224,7 @@ time > "2022-07-01 11:00:00" accept;ok;meta time > "2022-07-01 11:00:00" accept
|
||||
meta time "meh";fail
|
||||
meta hour "24:00" drop;fail
|
||||
meta day 7 drop;fail
|
||||
+
|
||||
+meta mark set vlan id map { 1 : 0x00000001, 4095 : 0x00004095 };ok
|
||||
+!map1 typeof vlan id : meta mark;ok
|
||||
+meta mark set vlan id map @map1;ok
|
||||
diff --git a/tests/py/any/meta.t.payload b/tests/py/any/meta.t.payload
|
||||
index 16dc121..49dd729 100644
|
||||
--- a/tests/py/any/meta.t.payload
|
||||
+++ b/tests/py/any/meta.t.payload
|
||||
@@ -1072,3 +1072,28 @@ ip test-ip4 input
|
||||
[ byteorder reg 1 = hton(reg 1, 8, 8) ]
|
||||
[ cmp gt reg 1 0xf3a8fd16 0x00a07719 ]
|
||||
[ immediate reg 0 accept ]
|
||||
+
|
||||
+# meta mark set vlan id map { 1 : 0x00000001, 4095 : 0x00004095 }
|
||||
+__map%d test-ip4 b size 2
|
||||
+__map%d test-ip4 0
|
||||
+ element 00000100 : 00000001 0 [end] element 0000ff0f : 00004095 0 [end]
|
||||
+ip test-ip4 input
|
||||
+ [ meta load iiftype => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000001 ]
|
||||
+ [ payload load 2b @ link header + 12 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000081 ]
|
||||
+ [ payload load 2b @ link header + 14 => reg 1 ]
|
||||
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
|
||||
+ [ lookup reg 1 set __map%d dreg 1 ]
|
||||
+ [ meta set mark with reg 1 ]
|
||||
+
|
||||
+# meta mark set vlan id map @map1
|
||||
+ip test-ip4 input
|
||||
+ [ meta load iiftype => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000001 ]
|
||||
+ [ payload load 2b @ link header + 12 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000081 ]
|
||||
+ [ payload load 2b @ link header + 14 => reg 1 ]
|
||||
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
|
||||
+ [ lookup reg 1 set map1 dreg 1 ]
|
||||
+ [ meta set mark with reg 1 ]
|
||||
diff --git a/tests/py/any/meta.t.payload.bridge b/tests/py/any/meta.t.payload.bridge
|
||||
new file mode 100644
|
||||
index 0000000..5997ccc
|
||||
--- /dev/null
|
||||
+++ b/tests/py/any/meta.t.payload.bridge
|
||||
@@ -0,0 +1,20 @@
|
||||
+# meta mark set vlan id map { 1 : 0x00000001, 4095 : 0x00004095 }
|
||||
+__map%d test-bridge b size 2
|
||||
+__map%d test-bridge 0
|
||||
+ element 00000100 : 00000001 0 [end] element 0000ff0f : 00004095 0 [end]
|
||||
+bridge test-bridge input
|
||||
+ [ payload load 2b @ link header + 12 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000081 ]
|
||||
+ [ payload load 2b @ link header + 14 => reg 1 ]
|
||||
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
|
||||
+ [ lookup reg 1 set __map%d dreg 1 ]
|
||||
+ [ meta set mark with reg 1 ]
|
||||
+
|
||||
+# meta mark set vlan id map @map1
|
||||
+bridge test-bridge input
|
||||
+ [ payload load 2b @ link header + 12 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000081 ]
|
||||
+ [ payload load 2b @ link header + 14 => reg 1 ]
|
||||
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
|
||||
+ [ lookup reg 1 set map1 dreg 1 ]
|
||||
+ [ meta set mark with reg 1 ]
|
||||
diff --git a/tests/py/nft-test.py b/tests/py/nft-test.py
|
||||
index 9a25503..a7d27c2 100755
|
||||
--- a/tests/py/nft-test.py
|
||||
+++ b/tests/py/nft-test.py
|
||||
@@ -368,9 +368,9 @@ def set_add(s, test_result, filename, lineno):
|
||||
flags = "flags %s; " % flags
|
||||
|
||||
if s.data == "":
|
||||
- cmd = "add set %s %s { type %s;%s %s}" % (table, s.name, s.type, s.timeout, flags)
|
||||
+ cmd = "add set %s %s { %s;%s %s}" % (table, s.name, s.type, s.timeout, flags)
|
||||
else:
|
||||
- cmd = "add map %s %s { type %s : %s;%s %s}" % (table, s.name, s.type, s.data, s.timeout, flags)
|
||||
+ cmd = "add map %s %s { %s : %s;%s %s}" % (table, s.name, s.type, s.data, s.timeout, flags)
|
||||
|
||||
ret = execute_cmd(cmd, filename, lineno)
|
||||
|
||||
@@ -410,7 +410,7 @@ def map_add(s, test_result, filename, lineno):
|
||||
if flags != "":
|
||||
flags = "flags %s; " % flags
|
||||
|
||||
- cmd = "add map %s %s { type %s : %s;%s %s}" % (table, s.name, s.type, s.data, s.timeout, flags)
|
||||
+ cmd = "add map %s %s { %s : %s;%s %s}" % (table, s.name, s.type, s.data, s.timeout, flags)
|
||||
|
||||
ret = execute_cmd(cmd, filename, lineno)
|
||||
|
||||
@@ -1144,11 +1144,16 @@ def set_process(set_line, filename, lineno):
|
||||
|
||||
tokens = set_line[0].split(" ")
|
||||
set_name = tokens[0]
|
||||
- set_type = tokens[2]
|
||||
+ parse_typeof = tokens[1] == "typeof"
|
||||
+ set_type = tokens[1] + " " + tokens[2]
|
||||
set_data = ""
|
||||
set_flags = ""
|
||||
|
||||
i = 3
|
||||
+ if parse_typeof and tokens[i] == "id":
|
||||
+ set_type += " " + tokens[i]
|
||||
+ i += 1;
|
||||
+
|
||||
while len(tokens) > i and tokens[i] == ".":
|
||||
set_type += " . " + tokens[i+1]
|
||||
i += 2
|
||||
@@ -1157,6 +1162,10 @@ def set_process(set_line, filename, lineno):
|
||||
set_data = tokens[i+1]
|
||||
i += 2
|
||||
|
||||
+ if parse_typeof and tokens[i] == "mark":
|
||||
+ set_data += " " + tokens[i]
|
||||
+ i += 1;
|
||||
+
|
||||
if len(tokens) == i+2 and tokens[i] == "timeout":
|
||||
timeout = "timeout " + tokens[i+1] + ";"
|
||||
i += 2
|
||||
@ -0,0 +1,95 @@
|
||||
From 6b25abca848fe00a46536c61bd6770d219f965c8 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] tests: py: missing json output in meta.t with vlan mapping
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 5fec559727ffd2c6c8958748beab782096385758
|
||||
|
||||
commit 5fec559727ffd2c6c8958748beab782096385758
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Mon Dec 11 12:54:35 2023 +0100
|
||||
|
||||
tests: py: missing json output in meta.t with vlan mapping
|
||||
|
||||
Fix this warning due to missing coverage:
|
||||
|
||||
tests/py/any/meta.t.json.got: WARNING: line 2: Wrote JSON equivalent for rule meta mark set vlan id map { 1 : 0x00000001, 4095 : 0x00004095 }
|
||||
ERROR: did not find JSON equivalent for rule 'meta mark set vlan id map @map1
|
||||
|
||||
Fixes: 8d3de823b622 ("evaluate: reset statement length context before evaluating statement")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
tests/py/any/meta.t.json | 60 ++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 60 insertions(+)
|
||||
|
||||
diff --git a/tests/py/any/meta.t.json b/tests/py/any/meta.t.json
|
||||
index 4734bbf..d50272d 100644
|
||||
--- a/tests/py/any/meta.t.json
|
||||
+++ b/tests/py/any/meta.t.json
|
||||
@@ -2758,3 +2758,63 @@
|
||||
"accept": null
|
||||
}
|
||||
]
|
||||
+
|
||||
+# meta mark set vlan id map { 1 : 0x00000001, 4095 : 0x00004095 }
|
||||
+[
|
||||
+ {
|
||||
+ "mangle": {
|
||||
+ "key": {
|
||||
+ "meta": {
|
||||
+ "key": "mark"
|
||||
+ }
|
||||
+ },
|
||||
+ "value": {
|
||||
+ "map": {
|
||||
+ "data": {
|
||||
+ "set": [
|
||||
+ [
|
||||
+ 1,
|
||||
+ 1
|
||||
+ ],
|
||||
+ [
|
||||
+ 4095,
|
||||
+ 16533
|
||||
+ ]
|
||||
+ ]
|
||||
+ },
|
||||
+ "key": {
|
||||
+ "payload": {
|
||||
+ "field": "id",
|
||||
+ "protocol": "vlan"
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# meta mark set vlan id map @map1
|
||||
+[
|
||||
+ {
|
||||
+ "mangle": {
|
||||
+ "key": {
|
||||
+ "meta": {
|
||||
+ "key": "mark"
|
||||
+ }
|
||||
+ },
|
||||
+ "value": {
|
||||
+ "map": {
|
||||
+ "data": "@map1",
|
||||
+ "key": {
|
||||
+ "payload": {
|
||||
+ "field": "id",
|
||||
+ "protocol": "vlan"
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
271
0048-parser_bison-fix-objref-statement-corruption.patch
Normal file
271
0048-parser_bison-fix-objref-statement-corruption.patch
Normal file
@ -0,0 +1,271 @@
|
||||
From fdf39fe2cf3f15cbea9c26b1c5951f207cda6ea8 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] parser_bison: fix objref statement corruption
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 78dffb470fcf7b1c0b1b3d6f43fcc056c337a808
|
||||
|
||||
commit 78dffb470fcf7b1c0b1b3d6f43fcc056c337a808
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Fri Dec 8 19:41:39 2023 +0100
|
||||
|
||||
parser_bison: fix objref statement corruption
|
||||
|
||||
Consider this:
|
||||
|
||||
counter_stmt : counter_stmt_alloc
|
||||
| counter_stmt_alloc counter_args
|
||||
|
||||
counter_stmt_alloc : COUNTER { $$ = counter_stmt_alloc(&@$); }
|
||||
| COUNTER NAME stmt_expr
|
||||
{
|
||||
$$ = objref_stmt_alloc(&@$);
|
||||
$$->objref.type = NFT_OBJECT_COUNTER;
|
||||
$$->objref.expr = $3;
|
||||
}
|
||||
;
|
||||
|
||||
counter_args : counter_arg { $<stmt>$ = $<stmt>0; }
|
||||
| counter_args counter_arg
|
||||
;
|
||||
|
||||
counter_arg : PACKETS NUM { $<stmt>0->counter.packets = $2; }
|
||||
|
||||
[..]
|
||||
|
||||
This has 'counter_stmt_alloc' EITHER return counter or objref statement.
|
||||
Both are the same structure but with different (union'd) trailer content.
|
||||
|
||||
counter_stmt permits the 'packet' and 'byte' argument.
|
||||
|
||||
But the 'counter_arg' directive only works with a statement
|
||||
coming from counter_stmt_alloc().
|
||||
|
||||
afl++ came up with following input:
|
||||
|
||||
table inet x {
|
||||
chain y {
|
||||
counter name ip saddr bytes 1.1.1. 1024
|
||||
}
|
||||
}
|
||||
|
||||
This clobbers $<stmt>->objref.expr pointer, we then crash when
|
||||
calling expr_evaluate() on it.
|
||||
|
||||
Split the objref related statements into their own directive.
|
||||
|
||||
After this, the input will fail with:
|
||||
"syntax error, unexpected bytes, expecting newline or semicolon".
|
||||
|
||||
Also split most of the other objref statements into their own blocks.
|
||||
synproxy seems to have same problem, limit and quota appeared to be ok.
|
||||
|
||||
v1 added objref_stmt to stateful_stmt list, this is wrong, we will
|
||||
assert when generating the 'counter' statement.
|
||||
Place it in the normal statement list so netlink_gen_stmt_stateful_assert
|
||||
throws the expected parser error.
|
||||
|
||||
Fixes: dccab4f646b4 ("parser_bison: consolidate stmt_expr rule")
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_bison.y | 97 ++++++++++++-------
|
||||
.../bogons/nft-f/counter_objref_crash | 5 +
|
||||
.../nft-f/netlink_gen_stmt_stateful_assert | 6 ++
|
||||
3 files changed, 71 insertions(+), 37 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/counter_objref_crash
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/netlink_gen_stmt_stateful_assert
|
||||
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 9386a9c..2c829f9 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -746,6 +746,9 @@ int nft_lex(void *, void *, void *);
|
||||
%destructor { stmt_free($$); } stmt match_stmt verdict_stmt set_elem_stmt
|
||||
%type <stmt> counter_stmt counter_stmt_alloc stateful_stmt last_stmt
|
||||
%destructor { stmt_free($$); } counter_stmt counter_stmt_alloc stateful_stmt last_stmt
|
||||
+%type <stmt> objref_stmt objref_stmt_counter objref_stmt_limit objref_stmt_quota objref_stmt_ct objref_stmt_synproxy
|
||||
+%destructor { stmt_free($$); } objref_stmt objref_stmt_counter objref_stmt_limit objref_stmt_quota objref_stmt_ct objref_stmt_synproxy
|
||||
+
|
||||
%type <stmt> payload_stmt
|
||||
%destructor { stmt_free($$); } payload_stmt
|
||||
%type <stmt> ct_stmt
|
||||
@@ -3060,6 +3063,60 @@ stateful_stmt_list : stateful_stmt
|
||||
}
|
||||
;
|
||||
|
||||
+objref_stmt_counter : COUNTER NAME stmt_expr close_scope_counter
|
||||
+ {
|
||||
+ $$ = objref_stmt_alloc(&@$);
|
||||
+ $$->objref.type = NFT_OBJECT_COUNTER;
|
||||
+ $$->objref.expr = $3;
|
||||
+ }
|
||||
+ ;
|
||||
+
|
||||
+objref_stmt_limit : LIMIT NAME stmt_expr close_scope_limit
|
||||
+ {
|
||||
+ $$ = objref_stmt_alloc(&@$);
|
||||
+ $$->objref.type = NFT_OBJECT_LIMIT;
|
||||
+ $$->objref.expr = $3;
|
||||
+ }
|
||||
+ ;
|
||||
+
|
||||
+objref_stmt_quota : QUOTA NAME stmt_expr close_scope_quota
|
||||
+ {
|
||||
+ $$ = objref_stmt_alloc(&@$);
|
||||
+ $$->objref.type = NFT_OBJECT_QUOTA;
|
||||
+ $$->objref.expr = $3;
|
||||
+ }
|
||||
+ ;
|
||||
+
|
||||
+objref_stmt_synproxy : SYNPROXY NAME stmt_expr close_scope_synproxy
|
||||
+ {
|
||||
+ $$ = objref_stmt_alloc(&@$);
|
||||
+ $$->objref.type = NFT_OBJECT_SYNPROXY;
|
||||
+ $$->objref.expr = $3;
|
||||
+ }
|
||||
+ ;
|
||||
+
|
||||
+objref_stmt_ct : CT TIMEOUT SET stmt_expr close_scope_ct
|
||||
+ {
|
||||
+ $$ = objref_stmt_alloc(&@$);
|
||||
+ $$->objref.type = NFT_OBJECT_CT_TIMEOUT;
|
||||
+ $$->objref.expr = $4;
|
||||
+
|
||||
+ }
|
||||
+ | CT EXPECTATION SET stmt_expr close_scope_ct
|
||||
+ {
|
||||
+ $$ = objref_stmt_alloc(&@$);
|
||||
+ $$->objref.type = NFT_OBJECT_CT_EXPECT;
|
||||
+ $$->objref.expr = $4;
|
||||
+ }
|
||||
+ ;
|
||||
+
|
||||
+objref_stmt : objref_stmt_counter
|
||||
+ | objref_stmt_limit
|
||||
+ | objref_stmt_quota
|
||||
+ | objref_stmt_synproxy
|
||||
+ | objref_stmt_ct
|
||||
+ ;
|
||||
+
|
||||
stateful_stmt : counter_stmt close_scope_counter
|
||||
| limit_stmt
|
||||
| quota_stmt
|
||||
@@ -3089,6 +3146,7 @@ stmt : verdict_stmt
|
||||
| chain_stmt
|
||||
| optstrip_stmt
|
||||
| xt_stmt close_scope_xt
|
||||
+ | objref_stmt
|
||||
;
|
||||
|
||||
xt_stmt : XT STRING string
|
||||
@@ -3178,12 +3236,6 @@ counter_stmt_alloc : COUNTER
|
||||
{
|
||||
$$ = counter_stmt_alloc(&@$);
|
||||
}
|
||||
- | COUNTER NAME stmt_expr
|
||||
- {
|
||||
- $$ = objref_stmt_alloc(&@$);
|
||||
- $$->objref.type = NFT_OBJECT_COUNTER;
|
||||
- $$->objref.expr = $3;
|
||||
- }
|
||||
;
|
||||
|
||||
counter_args : counter_arg
|
||||
@@ -3195,10 +3247,12 @@ counter_args : counter_arg
|
||||
|
||||
counter_arg : PACKETS NUM
|
||||
{
|
||||
+ assert($<stmt>0->ops->type == STMT_COUNTER);
|
||||
$<stmt>0->counter.packets = $2;
|
||||
}
|
||||
| BYTES NUM
|
||||
{
|
||||
+ assert($<stmt>0->ops->type == STMT_COUNTER);
|
||||
$<stmt>0->counter.bytes = $2;
|
||||
}
|
||||
;
|
||||
@@ -3479,12 +3533,6 @@ limit_stmt : LIMIT RATE limit_mode limit_rate_pkts limit_burst_pkts close_scope
|
||||
$$->limit.type = NFT_LIMIT_PKT_BYTES;
|
||||
$$->limit.flags = $3;
|
||||
}
|
||||
- | LIMIT NAME stmt_expr close_scope_limit
|
||||
- {
|
||||
- $$ = objref_stmt_alloc(&@$);
|
||||
- $$->objref.type = NFT_OBJECT_LIMIT;
|
||||
- $$->objref.expr = $3;
|
||||
- }
|
||||
;
|
||||
|
||||
quota_mode : OVER { $$ = NFT_QUOTA_F_INV; }
|
||||
@@ -3528,12 +3576,6 @@ quota_stmt : QUOTA quota_mode NUM quota_unit quota_used close_scope_quota
|
||||
$$->quota.used = $5;
|
||||
$$->quota.flags = $2;
|
||||
}
|
||||
- | QUOTA NAME stmt_expr close_scope_quota
|
||||
- {
|
||||
- $$ = objref_stmt_alloc(&@$);
|
||||
- $$->objref.type = NFT_OBJECT_QUOTA;
|
||||
- $$->objref.expr = $3;
|
||||
- }
|
||||
;
|
||||
|
||||
limit_mode : OVER { $$ = NFT_LIMIT_F_INV; }
|
||||
@@ -3724,12 +3766,6 @@ synproxy_stmt_alloc : SYNPROXY
|
||||
{
|
||||
$$ = synproxy_stmt_alloc(&@$);
|
||||
}
|
||||
- | SYNPROXY NAME stmt_expr
|
||||
- {
|
||||
- $$ = objref_stmt_alloc(&@$);
|
||||
- $$->objref.type = NFT_OBJECT_SYNPROXY;
|
||||
- $$->objref.expr = $3;
|
||||
- }
|
||||
;
|
||||
|
||||
synproxy_args : synproxy_arg
|
||||
@@ -5542,19 +5578,6 @@ ct_stmt : CT ct_key SET stmt_expr close_scope_ct
|
||||
break;
|
||||
}
|
||||
}
|
||||
- | CT TIMEOUT SET stmt_expr close_scope_ct
|
||||
- {
|
||||
- $$ = objref_stmt_alloc(&@$);
|
||||
- $$->objref.type = NFT_OBJECT_CT_TIMEOUT;
|
||||
- $$->objref.expr = $4;
|
||||
-
|
||||
- }
|
||||
- | CT EXPECTATION SET stmt_expr close_scope_ct
|
||||
- {
|
||||
- $$ = objref_stmt_alloc(&@$);
|
||||
- $$->objref.type = NFT_OBJECT_CT_EXPECT;
|
||||
- $$->objref.expr = $4;
|
||||
- }
|
||||
| CT ct_dir ct_key_dir_optional SET stmt_expr close_scope_ct
|
||||
{
|
||||
$$ = ct_stmt_alloc(&@$, $3, $2, $5);
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/counter_objref_crash b/tests/shell/testcases/bogons/nft-f/counter_objref_crash
|
||||
new file mode 100644
|
||||
index 0000000..3a4b981
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/counter_objref_crash
|
||||
@@ -0,0 +1,5 @@
|
||||
+table inet x {
|
||||
+ chain y {
|
||||
+ counter name ip saddr bytes 1.1.1. 1024
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/netlink_gen_stmt_stateful_assert b/tests/shell/testcases/bogons/nft-f/netlink_gen_stmt_stateful_assert
|
||||
new file mode 100644
|
||||
index 0000000..547b937
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/netlink_gen_stmt_stateful_assert
|
||||
@@ -0,0 +1,6 @@
|
||||
+table ip x {
|
||||
+ map sctm_o1 {
|
||||
+ type mark : counter
|
||||
+ counter name meta mark
|
||||
+ }
|
||||
+}
|
||||
128
0049-evaluate-fix-bogus-assertion-failure-with-boolean-da.patch
Normal file
128
0049-evaluate-fix-bogus-assertion-failure-with-boolean-da.patch
Normal file
@ -0,0 +1,128 @@
|
||||
From 62be3f747b22309adff113b95d6cadc2d7a0a470 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] evaluate: fix bogus assertion failure with boolean datatype
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 567937b5560fbcc7f6b74fb43c52e1cab2ac425a
|
||||
|
||||
commit 567937b5560fbcc7f6b74fb43c52e1cab2ac425a
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Fri Dec 8 19:38:33 2023 +0100
|
||||
|
||||
evaluate: fix bogus assertion failure with boolean datatype
|
||||
|
||||
The assertion is too strict, as found by afl++:
|
||||
|
||||
typeof iifname . ip saddr . meta ipsec
|
||||
elements = { "eth0" . 10.1.1.2 . 1 }
|
||||
|
||||
meta ipsec is boolean (1 bit), but datasize of 1 is set at 8 bit.
|
||||
|
||||
Fixes: 22b750aa6dc9 ("src: allow use of base integer types as set keys in concatenations")
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 7 ++++---
|
||||
.../testcases/sets/dumps/typeof_sets_0.nft | 9 +++++++++
|
||||
tests/shell/testcases/sets/typeof_sets_0 | 17 +++++++++++++++++
|
||||
3 files changed, 30 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index cfdc6c0..fa3512b 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -4618,14 +4618,15 @@ static int set_expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
|
||||
"expressions",
|
||||
i->dtype->name);
|
||||
|
||||
- if (i->dtype->size)
|
||||
- assert(i->len == i->dtype->size);
|
||||
-
|
||||
flags &= i->flags;
|
||||
|
||||
ntype = concat_subtype_add(ntype, i->dtype->type);
|
||||
|
||||
dsize_bytes = div_round_up(i->len, BITS_PER_BYTE);
|
||||
+
|
||||
+ if (i->dtype->size)
|
||||
+ assert(dsize_bytes == div_round_up(i->dtype->size, BITS_PER_BYTE));
|
||||
+
|
||||
(*expr)->field_len[(*expr)->field_count++] = dsize_bytes;
|
||||
size += netlink_padded_len(i->len);
|
||||
}
|
||||
diff --git a/tests/shell/testcases/sets/dumps/typeof_sets_0.nft b/tests/shell/testcases/sets/dumps/typeof_sets_0.nft
|
||||
index 6f5b83a..63fc5b1 100644
|
||||
--- a/tests/shell/testcases/sets/dumps/typeof_sets_0.nft
|
||||
+++ b/tests/shell/testcases/sets/dumps/typeof_sets_0.nft
|
||||
@@ -55,6 +55,11 @@ table inet t {
|
||||
elements = { 3567 . 1.2.3.4 }
|
||||
}
|
||||
|
||||
+ set s12 {
|
||||
+ typeof iifname . ip saddr . meta ipsec
|
||||
+ elements = { "eth0" . 10.1.1.2 . exists }
|
||||
+ }
|
||||
+
|
||||
chain c1 {
|
||||
osf name @s1 accept
|
||||
}
|
||||
@@ -94,4 +99,8 @@ table inet t {
|
||||
chain c11 {
|
||||
vlan id . ip saddr @s11 accept
|
||||
}
|
||||
+
|
||||
+ chain c12 {
|
||||
+ iifname . ip saddr . meta ipsec @s12 accept
|
||||
+ }
|
||||
}
|
||||
diff --git a/tests/shell/testcases/sets/typeof_sets_0 b/tests/shell/testcases/sets/typeof_sets_0
|
||||
index 35c572c..943c9c2 100755
|
||||
--- a/tests/shell/testcases/sets/typeof_sets_0
|
||||
+++ b/tests/shell/testcases/sets/typeof_sets_0
|
||||
@@ -92,6 +92,10 @@ INPUT="table inet t {$INPUT_OSF_SET
|
||||
typeof vlan id . ip saddr
|
||||
elements = { 3567 . 1.2.3.4 }
|
||||
}
|
||||
+ set s12 {
|
||||
+ typeof meta iifname . ip saddr . meta ipsec
|
||||
+ elements = { \"eth0\" . 10.1.1.2 . 1 }
|
||||
+ }
|
||||
$INPUT_OSF_CHAIN
|
||||
chain c2 {
|
||||
ether type vlan vlan id @s2 accept
|
||||
@@ -124,6 +128,10 @@ $INPUT_SCTP_CHAIN
|
||||
chain c11 {
|
||||
ether type vlan vlan id . ip saddr @s11 accept
|
||||
}
|
||||
+
|
||||
+ chain c12 {
|
||||
+ meta iifname . ip saddr . meta ipsec @s12 accept
|
||||
+ }
|
||||
}"
|
||||
|
||||
EXPECTED="table inet t {$INPUT_OSF_SET
|
||||
@@ -177,6 +185,11 @@ EXPECTED="table inet t {$INPUT_OSF_SET
|
||||
typeof vlan id . ip saddr
|
||||
elements = { 3567 . 1.2.3.4 }
|
||||
}
|
||||
+
|
||||
+ set s12 {
|
||||
+ typeof iifname . ip saddr . meta ipsec
|
||||
+ elements = { \"eth0\" . 10.1.1.2 . exists }
|
||||
+ }
|
||||
$INPUT_OSF_CHAIN
|
||||
chain c2 {
|
||||
vlan id @s2 accept
|
||||
@@ -209,6 +222,10 @@ $INPUT_SCTP_CHAIN
|
||||
chain c11 {
|
||||
vlan id . ip saddr @s11 accept
|
||||
}
|
||||
+
|
||||
+ chain c12 {
|
||||
+ iifname . ip saddr . meta ipsec @s12 accept
|
||||
+ }
|
||||
}"
|
||||
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
From fdb03b033c3efcb28b4c51c469d3e93559d7bdb8 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] parser_bison: close chain scope before chain release
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 28b3bbec5a97aaa57f7138fee8b2f22ff0e5b960
|
||||
|
||||
commit 28b3bbec5a97aaa57f7138fee8b2f22ff0e5b960
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Wed Dec 13 11:09:58 2023 +0100
|
||||
|
||||
parser_bison: close chain scope before chain release
|
||||
|
||||
cmd_alloc() will free the chain, so we must close the scope opened
|
||||
in chain_block_alloc beforehand.
|
||||
|
||||
The included test file will cause a use-after-free because nft attempts
|
||||
to search for an identifier in a scope that has been freed:
|
||||
|
||||
AddressSanitizer: heap-use-after-free on address 0x618000000368 at pc 0x7f1cbc0e6959 bp 0x7ffd3ccb7850 sp 0x7ffd3ccb7840
|
||||
#0 0x7f1cbc0e6958 in symbol_lookup src/rule.c:629
|
||||
#1 0x7f1cbc0e66a1 in symbol_get src/rule.c:588
|
||||
#2 0x7f1cbc120d67 in nft_parse src/parser_bison.y:4325
|
||||
|
||||
Fixes: a66b5ad9540d ("src: allow for updating devices on existing netdev chain")
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_bison.y | 1 +
|
||||
.../testcases/bogons/nft-f/use_after_free_on_chain_removal | 5 +++++
|
||||
2 files changed, 6 insertions(+)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/use_after_free_on_chain_removal
|
||||
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 2c829f9..83302fd 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -1397,6 +1397,7 @@ delete_cmd : TABLE table_or_id_spec
|
||||
{
|
||||
$5->location = @5;
|
||||
handle_merge(&$3->handle, &$2);
|
||||
+ close_scope(state);
|
||||
$$ = cmd_alloc(CMD_DELETE, CMD_OBJ_CHAIN, &$2, &@$, $5);
|
||||
}
|
||||
| RULE ruleid_spec
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/use_after_free_on_chain_removal b/tests/shell/testcases/bogons/nft-f/use_after_free_on_chain_removal
|
||||
new file mode 100644
|
||||
index 0000000..bb9632b
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/use_after_free_on_chain_removal
|
||||
@@ -0,0 +1,5 @@
|
||||
+delete chain d iUi {
|
||||
+}}
|
||||
+delete chain d hUi {
|
||||
+delete chain o
|
||||
+c b icmpv6 id$i
|
||||
112
0051-meta-fix-tc-classid-parsing-out-of-bounds-access.patch
Normal file
112
0051-meta-fix-tc-classid-parsing-out-of-bounds-access.patch
Normal file
@ -0,0 +1,112 @@
|
||||
From ae85b206060f420d4eb8f2ba0a61bb6c6813b908 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] meta: fix tc classid parsing out-of-bounds access
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 7008b1200fb4988b7cd7ee1c5399cae071688d50
|
||||
|
||||
commit 7008b1200fb4988b7cd7ee1c5399cae071688d50
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Wed Dec 13 17:37:11 2023 +0100
|
||||
|
||||
meta: fix tc classid parsing out-of-bounds access
|
||||
|
||||
AddressSanitizer: heap-buffer-overflow on address 0x6020000003af ...
|
||||
#0 0x7f9a83cbb402 in tchandle_type_parse src/meta.c:89
|
||||
#1 0x7f9a83c6753f in symbol_parse src/datatype.c:138
|
||||
|
||||
strlen() - 1 can underflow if length was 0.
|
||||
|
||||
Simplify the function, there is no need to duplicate the string
|
||||
while scanning it.
|
||||
|
||||
Expect the first strtol to stop at ':', scan for the minor number next.
|
||||
The second scan is required to stop at '\0'.
|
||||
|
||||
Fixes: 6f2eb8548e0d ("src: meta priority support using tc classid")
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/meta.c | 29 ++++++-------------
|
||||
.../nft-f/tchandle_type_parse_heap_overflow | 6 ++++
|
||||
2 files changed, 15 insertions(+), 20 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/tchandle_type_parse_heap_overflow
|
||||
|
||||
diff --git a/src/meta.c b/src/meta.c
|
||||
index 4e55e00..6f76f00 100644
|
||||
--- a/src/meta.c
|
||||
+++ b/src/meta.c
|
||||
@@ -62,50 +62,39 @@ static struct error_record *tchandle_type_parse(struct parse_ctx *ctx,
|
||||
struct expr **res)
|
||||
{
|
||||
uint32_t handle;
|
||||
- char *str = NULL;
|
||||
|
||||
if (strcmp(sym->identifier, "root") == 0)
|
||||
handle = TC_H_ROOT;
|
||||
else if (strcmp(sym->identifier, "none") == 0)
|
||||
handle = TC_H_UNSPEC;
|
||||
else if (strchr(sym->identifier, ':')) {
|
||||
+ char *colon, *end;
|
||||
uint32_t tmp;
|
||||
- char *colon;
|
||||
-
|
||||
- str = xstrdup(sym->identifier);
|
||||
-
|
||||
- colon = strchr(str, ':');
|
||||
- if (!colon)
|
||||
- goto err;
|
||||
-
|
||||
- *colon = '\0';
|
||||
|
||||
errno = 0;
|
||||
- tmp = strtoull(str, NULL, 16);
|
||||
- if (errno != 0)
|
||||
+ tmp = strtoul(sym->identifier, &colon, 16);
|
||||
+ if (errno != 0 || sym->identifier == colon)
|
||||
goto err;
|
||||
|
||||
- handle = (tmp << 16);
|
||||
- if (str[strlen(str) - 1] == ':')
|
||||
- goto out;
|
||||
+ if (*colon != ':')
|
||||
+ goto err;
|
||||
|
||||
+ handle = tmp << 16;
|
||||
errno = 0;
|
||||
- tmp = strtoull(colon + 1, NULL, 16);
|
||||
- if (errno != 0)
|
||||
+ tmp = strtoul(colon + 1, &end, 16);
|
||||
+ if (errno != 0 || *end)
|
||||
goto err;
|
||||
|
||||
handle |= tmp;
|
||||
} else {
|
||||
handle = strtoull(sym->identifier, NULL, 0);
|
||||
}
|
||||
-out:
|
||||
- free(str);
|
||||
+
|
||||
*res = constant_expr_alloc(&sym->location, sym->dtype,
|
||||
BYTEORDER_HOST_ENDIAN,
|
||||
sizeof(handle) * BITS_PER_BYTE, &handle);
|
||||
return NULL;
|
||||
err:
|
||||
- free(str);
|
||||
return error(&sym->location, "Could not parse %s", sym->dtype->desc);
|
||||
}
|
||||
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/tchandle_type_parse_heap_overflow b/tests/shell/testcases/bogons/nft-f/tchandle_type_parse_heap_overflow
|
||||
new file mode 100644
|
||||
index 0000000..ea7186b
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/tchandle_type_parse_heap_overflow
|
||||
@@ -0,0 +1,6 @@
|
||||
+table t {
|
||||
+map m {
|
||||
+ type ipv4_addr : classid
|
||||
+ elements = { 1.1.26.3 : ::a }
|
||||
+}
|
||||
+}
|
||||
@ -0,0 +1,69 @@
|
||||
From 9f755eed0849227f88d69b5efeb2809a8fc311a7 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] evaluate: exthdr: statement arg must be not be a range
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 8eeedce89d8bf0ad58da398782c2ca8a91d83a32
|
||||
|
||||
commit 8eeedce89d8bf0ad58da398782c2ca8a91d83a32
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Thu Dec 14 17:56:59 2023 +0100
|
||||
|
||||
evaluate: exthdr: statement arg must be not be a range
|
||||
|
||||
Else we get:
|
||||
BUG: unknown expression type range
|
||||
nft: src/netlink_linearize.c:909: netlink_gen_expr: Assertion `0' failed.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 19 ++++++++++++++++---
|
||||
.../bogons/nft-f/exthdr_with_range_bug | 1 +
|
||||
2 files changed, 17 insertions(+), 3 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/exthdr_with_range_bug
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index fa3512b..78a5d10 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -2964,14 +2964,27 @@ static bool stmt_evaluate_payload_need_csum(const struct expr *payload)
|
||||
static int stmt_evaluate_exthdr(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
{
|
||||
struct expr *exthdr;
|
||||
+ int ret;
|
||||
|
||||
if (__expr_evaluate_exthdr(ctx, &stmt->exthdr.expr) < 0)
|
||||
return -1;
|
||||
|
||||
exthdr = stmt->exthdr.expr;
|
||||
- return stmt_evaluate_arg(ctx, stmt, exthdr->dtype, exthdr->len,
|
||||
- BYTEORDER_BIG_ENDIAN,
|
||||
- &stmt->exthdr.val);
|
||||
+ ret = stmt_evaluate_arg(ctx, stmt, exthdr->dtype, exthdr->len,
|
||||
+ BYTEORDER_BIG_ENDIAN,
|
||||
+ &stmt->exthdr.val);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ switch (stmt->exthdr.val->etype) {
|
||||
+ case EXPR_RANGE:
|
||||
+ return expr_error(ctx->msgs, stmt->exthdr.val,
|
||||
+ "cannot be a range");
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int stmt_evaluate_payload(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/exthdr_with_range_bug b/tests/shell/testcases/bogons/nft-f/exthdr_with_range_bug
|
||||
new file mode 100644
|
||||
index 0000000..e307e7c
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/exthdr_with_range_bug
|
||||
@@ -0,0 +1 @@
|
||||
+add rule t c ip option ra set 0-1
|
||||
121
0053-src-reject-large-raw-payload-and-concat-expressions.patch
Normal file
121
0053-src-reject-large-raw-payload-and-concat-expressions.patch
Normal file
@ -0,0 +1,121 @@
|
||||
From 15e1ec4b465ba529675998d6da5d90ba2020f087 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] src: reject large raw payload and concat expressions
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit ef10d65db278d77208e960d210a1f4f532ebb552
|
||||
|
||||
commit ef10d65db278d77208e960d210a1f4f532ebb552
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Tue Dec 12 19:13:14 2023 +0100
|
||||
|
||||
src: reject large raw payload and concat expressions
|
||||
|
||||
The kernel will reject this too, but unfortunately nft may try
|
||||
to cram the data into the underlying libnftnl expr.
|
||||
|
||||
This causes heap corruption or
|
||||
BUG: nld buffer overflow: want to copy 132, max 64
|
||||
|
||||
After:
|
||||
|
||||
Error: Concatenation of size 544 exceeds maximum size of 512
|
||||
udp length . @th,0,512 . @th,512,512 { 47-63 . 0xe373135363130 . 0x33131303735353203 }
|
||||
^^^^^^^^^
|
||||
|
||||
resp. same warning for an over-sized raw expression.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
include/expression.h | 3 +++
|
||||
src/evaluate.c | 8 ++++++++
|
||||
src/parser_bison.y | 7 +++++++
|
||||
.../bogons/nft-f/stack_overflow_via_large_concat_expr | 5 +++++
|
||||
.../bogons/nft-f/stack_overflow_via_large_raw_expr | 5 +++++
|
||||
5 files changed, 28 insertions(+)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/stack_overflow_via_large_concat_expr
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/stack_overflow_via_large_raw_expr
|
||||
|
||||
diff --git a/include/expression.h b/include/expression.h
|
||||
index aede223..809089c 100644
|
||||
--- a/include/expression.h
|
||||
+++ b/include/expression.h
|
||||
@@ -11,6 +11,9 @@
|
||||
#include <json.h>
|
||||
#include <libnftnl/udata.h>
|
||||
|
||||
+#define NFT_MAX_EXPR_LEN_BYTES (NFT_REG32_COUNT * sizeof(uint32_t))
|
||||
+#define NFT_MAX_EXPR_LEN_BITS (NFT_MAX_EXPR_LEN_BYTES * BITS_PER_BYTE)
|
||||
+
|
||||
/**
|
||||
* enum expr_types
|
||||
*
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 78a5d10..1a8c815 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -1569,6 +1569,10 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
|
||||
}
|
||||
|
||||
ctx->inner_desc = NULL;
|
||||
+
|
||||
+ if (size > NFT_MAX_EXPR_LEN_BITS)
|
||||
+ return expr_error(ctx->msgs, i, "Concatenation of size %u exceeds maximum size of %u",
|
||||
+ size, NFT_MAX_EXPR_LEN_BITS);
|
||||
}
|
||||
|
||||
(*expr)->flags |= flags;
|
||||
@@ -4642,6 +4646,10 @@ static int set_expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
|
||||
|
||||
(*expr)->field_len[(*expr)->field_count++] = dsize_bytes;
|
||||
size += netlink_padded_len(i->len);
|
||||
+
|
||||
+ if (size > NFT_MAX_EXPR_LEN_BITS)
|
||||
+ return expr_error(ctx->msgs, i, "Concatenation of size %u exceeds maximum size of %u",
|
||||
+ size, NFT_MAX_EXPR_LEN_BITS);
|
||||
}
|
||||
|
||||
(*expr)->flags |= flags;
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 83302fd..fa59207 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -5620,6 +5620,13 @@ payload_expr : payload_raw_expr
|
||||
|
||||
payload_raw_expr : AT payload_base_spec COMMA NUM COMMA NUM close_scope_at
|
||||
{
|
||||
+ if ($6 > NFT_MAX_EXPR_LEN_BITS) {
|
||||
+ erec_queue(error(&@1, "raw payload length %u exceeds upper limit of %u",
|
||||
+ $6, NFT_MAX_EXPR_LEN_BITS),
|
||||
+ state->msgs);
|
||||
+ YYERROR;
|
||||
+ }
|
||||
+
|
||||
$$ = payload_expr_alloc(&@$, NULL, 0);
|
||||
payload_init_raw($$, $2, $4, $6);
|
||||
$$->byteorder = BYTEORDER_BIG_ENDIAN;
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/stack_overflow_via_large_concat_expr b/tests/shell/testcases/bogons/nft-f/stack_overflow_via_large_concat_expr
|
||||
new file mode 100644
|
||||
index 0000000..8b0d274
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/stack_overflow_via_large_concat_expr
|
||||
@@ -0,0 +1,5 @@
|
||||
+table t {
|
||||
+ chain c {
|
||||
+ udp length . @th,0,512 . @th,512,512 { 47-63 . 0xe373135363130 . 0x33131303735353203 }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/stack_overflow_via_large_raw_expr b/tests/shell/testcases/bogons/nft-f/stack_overflow_via_large_raw_expr
|
||||
new file mode 100644
|
||||
index 0000000..66bd6bf
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/stack_overflow_via_large_raw_expr
|
||||
@@ -0,0 +1,5 @@
|
||||
+table t {
|
||||
+ chain c {
|
||||
+ @th,160,1272 gt 0
|
||||
+ }
|
||||
+}
|
||||
@ -0,0 +1,51 @@
|
||||
From 23a5147a32733f75548526e9b8769cd1157b34f8 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] evaluate: fix stack overflow with huge priority string
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit b626c86abaf294fcf1ec788f722071dc90da68c4
|
||||
|
||||
commit b626c86abaf294fcf1ec788f722071dc90da68c4
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Fri Dec 15 10:19:02 2023 +0100
|
||||
|
||||
evaluate: fix stack overflow with huge priority string
|
||||
|
||||
Alternative would be to refactor this and move this into the parsers
|
||||
(bison, json) instead of this hidden re-parsing.
|
||||
|
||||
Fixes: 627c451b2351 ("src: allow variables in the chain priority specification")
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 2 +-
|
||||
tests/shell/testcases/bogons/nft-f/huge_chain_prio | 5 +++++
|
||||
2 files changed, 6 insertions(+), 1 deletion(-)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/huge_chain_prio
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 1a8c815..c655e3a 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -4820,7 +4820,7 @@ static bool evaluate_priority(struct eval_ctx *ctx, struct prio_spec *prio,
|
||||
NFT_NAME_MAXLEN);
|
||||
loc = prio->expr->location;
|
||||
|
||||
- if (sscanf(prio_str, "%s %c %d", prio_fst, &op, &prio_snd) < 3) {
|
||||
+ if (sscanf(prio_str, "%255s %c %d", prio_fst, &op, &prio_snd) < 3) {
|
||||
priority = std_prio_lookup(prio_str, family, hook);
|
||||
if (priority == NF_IP_PRI_LAST)
|
||||
return false;
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/huge_chain_prio b/tests/shell/testcases/bogons/nft-f/huge_chain_prio
|
||||
new file mode 100644
|
||||
index 0000000..41f8061
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/huge_chain_prio
|
||||
@@ -0,0 +1,5 @@
|
||||
+table t {
|
||||
+ chain c {
|
||||
+ type filter hook input priority srcnDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD#DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; policy accept;
|
||||
+ }
|
||||
+}
|
||||
220
0055-tests-shell-add-test-to-cover-payload-transport-matc.patch
Normal file
220
0055-tests-shell-add-test-to-cover-payload-transport-matc.patch
Normal file
@ -0,0 +1,220 @@
|
||||
From dcd92e16a863ba062ff9792dd304b0eb958fb60c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] tests: shell: add test to cover payload transport match and
|
||||
mangle
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 84da729e067a68bd50be8c0791d16901360be5ad
|
||||
|
||||
commit 84da729e067a68bd50be8c0791d16901360be5ad
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Sun Dec 17 00:15:08 2023 +0100
|
||||
|
||||
tests: shell: add test to cover payload transport match and mangle
|
||||
|
||||
Exercise payload transport match and mangle for inet, bridge and netdev
|
||||
families with IPv4 and IPv6 packets.
|
||||
|
||||
To cover kernel patch ("netfilter: nf_tables: set transport offset from
|
||||
mac header for netdev/egress").
|
||||
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
.../testcases/packetpath/dumps/payload.nodump | 0
|
||||
tests/shell/testcases/packetpath/payload | 180 ++++++++++++++++++
|
||||
2 files changed, 180 insertions(+)
|
||||
create mode 100644 tests/shell/testcases/packetpath/dumps/payload.nodump
|
||||
create mode 100755 tests/shell/testcases/packetpath/payload
|
||||
|
||||
diff --git a/tests/shell/testcases/packetpath/dumps/payload.nodump b/tests/shell/testcases/packetpath/dumps/payload.nodump
|
||||
new file mode 100644
|
||||
index 0000000..e69de29
|
||||
diff --git a/tests/shell/testcases/packetpath/payload b/tests/shell/testcases/packetpath/payload
|
||||
new file mode 100755
|
||||
index 0000000..1a89d85
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/packetpath/payload
|
||||
@@ -0,0 +1,180 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+rnd=$(mktemp -u XXXXXXXX)
|
||||
+ns1="nft1payload-$rnd"
|
||||
+ns2="nft2payload-$rnd"
|
||||
+
|
||||
+cleanup()
|
||||
+{
|
||||
+ ip netns del "$ns1"
|
||||
+ ip netns del "$ns2"
|
||||
+}
|
||||
+
|
||||
+trap cleanup EXIT
|
||||
+
|
||||
+run_test()
|
||||
+{
|
||||
+ ns1_addr=$2
|
||||
+ ns2_addr=$3
|
||||
+ cidr=$4
|
||||
+
|
||||
+ # socat needs square brackets, ie. [abcd::2]
|
||||
+ if [ $1 -eq 6 ]; then
|
||||
+ nsx1_addr="["$ns1_addr"]"
|
||||
+ nsx2_addr="["$ns2_addr"]"
|
||||
+ else
|
||||
+ nsx1_addr="$ns1_addr"
|
||||
+ nsx2_addr="$ns2_addr"
|
||||
+ fi
|
||||
+
|
||||
+ ip netns add "$ns1" || exit 111
|
||||
+ ip netns add "$ns2" || exit 111
|
||||
+
|
||||
+ ip -net "$ns1" link set lo up
|
||||
+ ip -net "$ns2" link set lo up
|
||||
+
|
||||
+ ip link add veth0 netns $ns1 type veth peer name veth0 netns $ns2
|
||||
+
|
||||
+ ip -net "$ns1" link set veth0 up
|
||||
+ ip -net "$ns2" link set veth0 up
|
||||
+ ip -net "$ns1" addr add $ns1_addr/$cidr dev veth0
|
||||
+ ip -net "$ns2" addr add $ns2_addr/$cidr dev veth0
|
||||
+
|
||||
+RULESET="table netdev payload_netdev {
|
||||
+ counter ingress {}
|
||||
+ counter egress {}
|
||||
+ counter mangle_ingress {}
|
||||
+ counter mangle_egress {}
|
||||
+ counter mangle_ingress_match {}
|
||||
+ counter mangle_egress_match {}
|
||||
+
|
||||
+ chain ingress {
|
||||
+ type filter hook ingress device veth0 priority 0;
|
||||
+ tcp dport 7777 counter name ingress
|
||||
+ tcp dport 7778 tcp dport set 7779 counter name mangle_ingress
|
||||
+ tcp dport 7779 counter name mangle_ingress_match
|
||||
+ }
|
||||
+
|
||||
+ chain egress {
|
||||
+ type filter hook egress device veth0 priority 0;
|
||||
+ tcp dport 8887 counter name egress
|
||||
+ tcp dport 8888 tcp dport set 8889 counter name mangle_egress
|
||||
+ tcp dport 8889 counter name mangle_egress_match
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+table inet payload_inet {
|
||||
+ counter input {}
|
||||
+ counter output {}
|
||||
+ counter mangle_input {}
|
||||
+ counter mangle_output {}
|
||||
+ counter mangle_input_match {}
|
||||
+ counter mangle_output_match {}
|
||||
+
|
||||
+ chain in {
|
||||
+ type filter hook input priority 0;
|
||||
+ tcp dport 7770 counter name input
|
||||
+ tcp dport 7771 tcp dport set 7772 counter name mangle_input
|
||||
+ tcp dport 7772 counter name mangle_input_match
|
||||
+ }
|
||||
+
|
||||
+ chain out {
|
||||
+ type filter hook output priority 0;
|
||||
+ tcp dport 8880 counter name output
|
||||
+ tcp dport 8881 tcp dport set 8882 counter name mangle_output
|
||||
+ tcp dport 8882 counter name mangle_output_match
|
||||
+ }
|
||||
+}"
|
||||
+
|
||||
+ ip netns exec "$ns1" $NFT -f - <<< "$RULESET" || exit 1
|
||||
+
|
||||
+ ip netns exec "$ns1" socat -u STDIN TCP:$nsx2_addr:8887,connect-timeout=2 < /dev/null > /dev/null
|
||||
+ ip netns exec "$ns1" socat -u STDIN TCP:$nsx2_addr:8888,connect-timeout=2 < /dev/null > /dev/null
|
||||
+
|
||||
+ ip netns exec "$ns1" socat -u STDIN TCP:$nsx2_addr:8880,connect-timeout=2 < /dev/null > /dev/null
|
||||
+ ip netns exec "$ns1" socat -u STDIN TCP:$nsx2_addr:8881,connect-timeout=2 < /dev/null > /dev/null
|
||||
+
|
||||
+ ip netns exec "$ns2" socat -u STDIN TCP:$nsx1_addr:7777,connect-timeout=2 < /dev/null > /dev/null
|
||||
+ ip netns exec "$ns2" socat -u STDIN TCP:$nsx1_addr:7778,connect-timeout=2 < /dev/null > /dev/null
|
||||
+
|
||||
+ ip netns exec "$ns2" socat -u STDIN TCP:$nsx1_addr:7770,connect-timeout=2 < /dev/null > /dev/null
|
||||
+ ip netns exec "$ns2" socat -u STDIN TCP:$nsx1_addr:7771,connect-timeout=2 < /dev/null > /dev/null
|
||||
+
|
||||
+ ip netns exec "$ns1" $NFT list ruleset
|
||||
+
|
||||
+ ip netns exec "$ns1" nft list counter netdev payload_netdev ingress | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter netdev payload_netdev mangle_ingress | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter netdev payload_netdev mangle_ingress_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter netdev payload_netdev egress | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter netdev payload_netdev mangle_egress | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter netdev payload_netdev mangle_egress_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
+
|
||||
+ ip netns exec "$ns1" nft list counter inet payload_inet input | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter inet payload_inet mangle_input | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter inet payload_inet mangle_input_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter inet payload_inet output | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter inet payload_inet mangle_output | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter inet payload_inet mangle_output_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
+
|
||||
+ #
|
||||
+ # ... next stage
|
||||
+ #
|
||||
+
|
||||
+ ip netns exec "$ns1" $NFT flush ruleset
|
||||
+
|
||||
+ #
|
||||
+ # bridge
|
||||
+ #
|
||||
+
|
||||
+ ip -net "$ns1" addr del $ns1_addr/$cidr dev veth0
|
||||
+
|
||||
+ ip -net "$ns1" link add name br0 type bridge
|
||||
+ ip -net "$ns1" link set veth0 master br0
|
||||
+ ip -net "$ns1" addr add $ns1_addr/$cidr dev br0
|
||||
+ ip -net "$ns1" link set up dev br0
|
||||
+
|
||||
+RULESET="table bridge payload_bridge {
|
||||
+ counter input {}
|
||||
+ counter output {}
|
||||
+ counter mangle_input {}
|
||||
+ counter mangle_output {}
|
||||
+ counter mangle_input_match {}
|
||||
+ counter mangle_output_match {}
|
||||
+
|
||||
+ chain in {
|
||||
+ type filter hook input priority 0;
|
||||
+ tcp dport 7770 counter name input
|
||||
+ tcp dport 7771 tcp dport set 7772 counter name mangle_input
|
||||
+ tcp dport 7772 counter name mangle_input_match
|
||||
+ }
|
||||
+
|
||||
+ chain out {
|
||||
+ type filter hook output priority 0;
|
||||
+ tcp dport 8880 counter name output
|
||||
+ tcp dport 8881 tcp dport set 8882 counter name mangle_output
|
||||
+ tcp dport 8882 counter name mangle_output_match
|
||||
+ }
|
||||
+}"
|
||||
+
|
||||
+ ip netns exec "$ns1" $NFT -f - <<< "$RULESET" || exit 1
|
||||
+
|
||||
+ ip netns exec "$ns1" socat -u STDIN TCP:$nsx2_addr:8880,connect-timeout=2 < /dev/null > /dev/null
|
||||
+ ip netns exec "$ns1" socat -u STDIN TCP:$nsx2_addr:8881,connect-timeout=2 < /dev/null > /dev/null
|
||||
+
|
||||
+ ip netns exec "$ns2" socat -u STDIN TCP:$nsx1_addr:7770,connect-timeout=2 < /dev/null > /dev/null
|
||||
+ ip netns exec "$ns2" socat -u STDIN TCP:$nsx1_addr:7771,connect-timeout=2 < /dev/null > /dev/null
|
||||
+
|
||||
+ ip netns exec "$ns1" $NFT list ruleset
|
||||
+
|
||||
+ ip netns exec "$ns1" nft list counter bridge payload_bridge input | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter bridge payload_bridge mangle_input | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter bridge payload_bridge mangle_input_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter bridge payload_bridge output | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter bridge payload_bridge mangle_output | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" nft list counter bridge payload_bridge mangle_output_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
+}
|
||||
+
|
||||
+run_test "4" "10.141.10.2" "10.141.10.3" "24"
|
||||
+cleanup
|
||||
+run_test 6 "abcd::2" "abcd::3" "64"
|
||||
+# trap calls cleanup
|
||||
120
0056-parser_bison-error-out-on-duplicated-type-typeof-ele.patch
Normal file
120
0056-parser_bison-error-out-on-duplicated-type-typeof-ele.patch
Normal file
@ -0,0 +1,120 @@
|
||||
From e1c01c2858d276e16b8fea5c42014799d00258c9 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] parser_bison: error out on duplicated type/typeof/element
|
||||
keywords
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 6c04e5ceb95068bb459b07307ecc3629d97a2043
|
||||
|
||||
commit 6c04e5ceb95068bb459b07307ecc3629d97a2043
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Tue Dec 19 16:22:32 2023 +0100
|
||||
|
||||
parser_bison: error out on duplicated type/typeof/element keywords
|
||||
|
||||
Otherwise nft will leak the previous definition (expressions).
|
||||
Also remove the nonsensical
|
||||
|
||||
datatype_set($1->key, $3->dtype);
|
||||
|
||||
This is a no-op, at this point: $1->key and $3 are identical.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_bison.y | 38 ++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 36 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index fa59207..0ab9dec 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -2159,11 +2159,20 @@ set_block : /* empty */ { $$ = $<set>-1; }
|
||||
| set_block stmt_separator
|
||||
| set_block TYPE data_type_expr stmt_separator close_scope_type
|
||||
{
|
||||
+ if (already_set($1->key, &@2, state)) {
|
||||
+ expr_free($3);
|
||||
+ YYERROR;
|
||||
+ }
|
||||
+
|
||||
$1->key = $3;
|
||||
$$ = $1;
|
||||
}
|
||||
| set_block TYPEOF typeof_expr stmt_separator
|
||||
{
|
||||
+ if (already_set($1->key, &@2, state)) {
|
||||
+ expr_free($3);
|
||||
+ YYERROR;
|
||||
+ }
|
||||
$1->key = $3;
|
||||
datatype_set($1->key, $3->dtype);
|
||||
$$ = $1;
|
||||
@@ -2191,6 +2200,10 @@ set_block : /* empty */ { $$ = $<set>-1; }
|
||||
}
|
||||
| set_block ELEMENTS '=' set_block_expr
|
||||
{
|
||||
+ if (already_set($1->init, &@2, state)) {
|
||||
+ expr_free($4);
|
||||
+ YYERROR;
|
||||
+ }
|
||||
$1->init = $4;
|
||||
$$ = $1;
|
||||
}
|
||||
@@ -2262,6 +2275,12 @@ map_block : /* empty */ { $$ = $<set>-1; }
|
||||
data_type_expr COLON map_block_data_interval data_type_expr
|
||||
stmt_separator close_scope_type
|
||||
{
|
||||
+ if (already_set($1->key, &@2, state)) {
|
||||
+ expr_free($3);
|
||||
+ expr_free($6);
|
||||
+ YYERROR;
|
||||
+ }
|
||||
+
|
||||
$1->key = $3;
|
||||
$1->data = $6;
|
||||
$1->data->flags |= $5;
|
||||
@@ -2273,8 +2292,13 @@ map_block : /* empty */ { $$ = $<set>-1; }
|
||||
typeof_expr COLON typeof_data_expr
|
||||
stmt_separator
|
||||
{
|
||||
+ if (already_set($1->key, &@2, state)) {
|
||||
+ expr_free($3);
|
||||
+ expr_free($5);
|
||||
+ YYERROR;
|
||||
+ }
|
||||
+
|
||||
$1->key = $3;
|
||||
- datatype_set($1->key, $3->dtype);
|
||||
$1->data = $5;
|
||||
|
||||
$1->flags |= NFT_SET_MAP;
|
||||
@@ -2284,8 +2308,13 @@ map_block : /* empty */ { $$ = $<set>-1; }
|
||||
typeof_expr COLON INTERVAL typeof_expr
|
||||
stmt_separator
|
||||
{
|
||||
+ if (already_set($1->key, &@2, state)) {
|
||||
+ expr_free($3);
|
||||
+ expr_free($6);
|
||||
+ YYERROR;
|
||||
+ }
|
||||
+
|
||||
$1->key = $3;
|
||||
- datatype_set($1->key, $3->dtype);
|
||||
$1->data = $6;
|
||||
$1->data->flags |= EXPR_F_INTERVAL;
|
||||
|
||||
@@ -2296,6 +2325,11 @@ map_block : /* empty */ { $$ = $<set>-1; }
|
||||
data_type_expr COLON map_block_obj_type
|
||||
stmt_separator close_scope_type
|
||||
{
|
||||
+ if (already_set($1->key, &@2, state)) {
|
||||
+ expr_free($3);
|
||||
+ YYERROR;
|
||||
+ }
|
||||
+
|
||||
$1->key = $3;
|
||||
$1->objtype = $5;
|
||||
$1->flags |= NFT_SET_OBJECT;
|
||||
@ -0,0 +1,81 @@
|
||||
From 0ef6256eae2581795a6aa9070876ae4d909c7f50 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] netlink: fix stack overflow due to erroneous rounding
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit b9e19cc396347df8c7f8cf5d14ba1d6172040f16
|
||||
|
||||
commit b9e19cc396347df8c7f8cf5d14ba1d6172040f16
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Wed Dec 20 15:40:54 2023 +0100
|
||||
|
||||
netlink: fix stack overflow due to erroneous rounding
|
||||
|
||||
Byteorder switch in this function may undersize the conversion
|
||||
buffer by one byte, this needs to use div_round_up().
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/netlink.c | 11 ++++++++---
|
||||
.../bogons/nft-f/byteorder_switch_stack_overflow | 6 ++++++
|
||||
2 files changed, 14 insertions(+), 3 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/byteorder_switch_stack_overflow
|
||||
|
||||
diff --git a/src/netlink.c b/src/netlink.c
|
||||
index a366758..8637186 100644
|
||||
--- a/src/netlink.c
|
||||
+++ b/src/netlink.c
|
||||
@@ -254,6 +254,11 @@ static int netlink_export_pad(unsigned char *data, const mpz_t v,
|
||||
return netlink_padded_len(i->len) / BITS_PER_BYTE;
|
||||
}
|
||||
|
||||
+static void byteorder_switch_expr_value(mpz_t v, const struct expr *e)
|
||||
+{
|
||||
+ mpz_switch_byteorder(v, div_round_up(e->len, BITS_PER_BYTE));
|
||||
+}
|
||||
+
|
||||
static int __netlink_gen_concat_key(uint32_t flags, const struct expr *i,
|
||||
unsigned char *data)
|
||||
{
|
||||
@@ -268,7 +273,7 @@ static int __netlink_gen_concat_key(uint32_t flags, const struct expr *i,
|
||||
|
||||
if (expr_basetype(expr)->type == TYPE_INTEGER &&
|
||||
expr->byteorder == BYTEORDER_HOST_ENDIAN)
|
||||
- mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE);
|
||||
+ byteorder_switch_expr_value(expr->value, expr);
|
||||
|
||||
i = expr;
|
||||
break;
|
||||
@@ -280,7 +285,7 @@ static int __netlink_gen_concat_key(uint32_t flags, const struct expr *i,
|
||||
mpz_init_bitmask(v, i->len - i->prefix_len);
|
||||
|
||||
if (i->byteorder == BYTEORDER_HOST_ENDIAN)
|
||||
- mpz_switch_byteorder(v, i->len / BITS_PER_BYTE);
|
||||
+ byteorder_switch_expr_value(v, i);
|
||||
|
||||
mpz_add(v, i->prefix->value, v);
|
||||
count = netlink_export_pad(data, v, i);
|
||||
@@ -298,7 +303,7 @@ static int __netlink_gen_concat_key(uint32_t flags, const struct expr *i,
|
||||
expr = (struct expr *)i;
|
||||
if (expr_basetype(expr)->type == TYPE_INTEGER &&
|
||||
expr->byteorder == BYTEORDER_HOST_ENDIAN)
|
||||
- mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE);
|
||||
+ byteorder_switch_expr_value(expr->value, expr);
|
||||
break;
|
||||
default:
|
||||
BUG("invalid expression type '%s' in set", expr_ops(i)->name);
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/byteorder_switch_stack_overflow b/tests/shell/testcases/bogons/nft-f/byteorder_switch_stack_overflow
|
||||
new file mode 100644
|
||||
index 0000000..0164052
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/byteorder_switch_stack_overflow
|
||||
@@ -0,0 +1,6 @@
|
||||
+table inet x {
|
||||
+ chain nat_dns_acme {
|
||||
+ udp length . @th,260,118 vmap { 47-63 . 0xe373135363130333131303735353203 : goto nat_dns_dnstc, }
|
||||
+ drop
|
||||
+ }
|
||||
+}
|
||||
125
0058-parser_bison-ensure-all-timeout-policy-names-are-rel.patch
Normal file
125
0058-parser_bison-ensure-all-timeout-policy-names-are-rel.patch
Normal file
@ -0,0 +1,125 @@
|
||||
From 023ceb40acf7fd6dad65c149243b2dbc16838f87 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] parser_bison: ensure all timeout policy names are released
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 86a496928420046e9d32317f09db050e8351b10e
|
||||
|
||||
commit 86a496928420046e9d32317f09db050e8351b10e
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Tue Dec 12 13:32:24 2023 +0100
|
||||
|
||||
parser_bison: ensure all timeout policy names are released
|
||||
|
||||
We need to add a custom destructor for this structure, it
|
||||
contains the dynamically allocated names.
|
||||
|
||||
a:5:55-55: Error: syntax error, unexpected '}', expecting string
|
||||
policy = { estabQisheestablished : 2m3s, cd : 2m3s, }
|
||||
|
||||
==562373==ERROR: LeakSanitizer: detected memory leaks
|
||||
|
||||
Indirect leak of 160 byte(s) in 2 object(s) allocated from:
|
||||
#1 0x5a565b in xmalloc src/utils.c:31:8
|
||||
#2 0x5a565b in xzalloc src/utils.c:70:8
|
||||
#3 0x3d9352 in nft_parse_bison_filename src/libnftables.c:520:8
|
||||
[..]
|
||||
|
||||
Fixes: c7c94802679c ("src: add ct timeout support")
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_bison.y | 32 ++++++++++++++++---
|
||||
.../testcases/bogons/nft-f/ct_timeout_memleak | 7 ++++
|
||||
2 files changed, 34 insertions(+), 5 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/ct_timeout_memleak
|
||||
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 0ab9dec..e81336f 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -173,6 +173,24 @@ static struct expr *ifname_expr_alloc(const struct location *location,
|
||||
return expr;
|
||||
}
|
||||
|
||||
+static void timeout_state_free(struct timeout_state *s)
|
||||
+{
|
||||
+ free_const(s->timeout_str);
|
||||
+ free(s);
|
||||
+}
|
||||
+
|
||||
+static void timeout_states_free(struct list_head *list)
|
||||
+{
|
||||
+ struct timeout_state *ts, *next;
|
||||
+
|
||||
+ list_for_each_entry_safe(ts, next, list, head) {
|
||||
+ list_del(&ts->head);
|
||||
+ timeout_state_free(ts);
|
||||
+ }
|
||||
+
|
||||
+ free(list);
|
||||
+}
|
||||
+
|
||||
#define YYLLOC_DEFAULT(Current, Rhs, N) location_update(&Current, Rhs, N)
|
||||
|
||||
#define symbol_value(loc, str) \
|
||||
@@ -230,6 +248,7 @@ int nft_lex(void *, void *, void *);
|
||||
uint16_t kind; /* must allow > 255 for SACK1, 2.. hack */
|
||||
uint8_t field;
|
||||
} tcp_kind_field;
|
||||
+ struct timeout_state *timeout_state;
|
||||
}
|
||||
|
||||
%token TOKEN_EOF 0 "end of file"
|
||||
@@ -969,8 +988,11 @@ int nft_lex(void *, void *, void *);
|
||||
|
||||
%type <val> ct_l4protoname ct_obj_type ct_cmd_type
|
||||
|
||||
-%type <list> timeout_states timeout_state
|
||||
-%destructor { free($$); } timeout_states timeout_state
|
||||
+%type <timeout_state> timeout_state
|
||||
+%destructor { timeout_state_free($$); } timeout_state
|
||||
+
|
||||
+%type <list> timeout_states
|
||||
+%destructor { timeout_states_free($$); } timeout_states
|
||||
|
||||
%type <val> xfrm_state_key xfrm_state_proto_key xfrm_dir xfrm_spnum
|
||||
%type <expr> xfrm_expr
|
||||
@@ -4896,11 +4918,11 @@ timeout_states : timeout_state
|
||||
{
|
||||
$$ = xmalloc(sizeof(*$$));
|
||||
init_list_head($$);
|
||||
- list_add_tail($1, $$);
|
||||
+ list_add_tail(&$1->head, $$);
|
||||
}
|
||||
| timeout_states COMMA timeout_state
|
||||
{
|
||||
- list_add_tail($3, $1);
|
||||
+ list_add_tail(&$3->head, $1);
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
@@ -4914,7 +4936,7 @@ timeout_state : STRING COLON time_spec_or_num_s
|
||||
ts->timeout_value = $3;
|
||||
ts->location = @1;
|
||||
init_list_head(&ts->head);
|
||||
- $$ = &ts->head;
|
||||
+ $$ = ts;
|
||||
}
|
||||
;
|
||||
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/ct_timeout_memleak b/tests/shell/testcases/bogons/nft-f/ct_timeout_memleak
|
||||
new file mode 100644
|
||||
index 0000000..014525a
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/ct_timeout_memleak
|
||||
@@ -0,0 +1,7 @@
|
||||
+table ip filter {
|
||||
+ ct timeout cttime {
|
||||
+ protocol tcp
|
||||
+ l3proto ip
|
||||
+ policy = { estabQisheestablished : 2m3s, cd : 2m3s, }
|
||||
+ }
|
||||
+}
|
||||
94
0059-tests-shell-prefer-project-nft-to-system-wide-nft.patch
Normal file
94
0059-tests-shell-prefer-project-nft-to-system-wide-nft.patch
Normal file
@ -0,0 +1,94 @@
|
||||
From 21c9b6d963d6aeff380324e411a0a871b422b923 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] tests: shell: prefer project nft to system-wide nft
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 8440983b7671feb3bb86c4c148af743addf3e00b
|
||||
|
||||
commit 8440983b7671feb3bb86c4c148af743addf3e00b
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Sat Jan 6 13:23:24 2024 +0100
|
||||
|
||||
tests: shell: prefer project nft to system-wide nft
|
||||
|
||||
Use $NFT (src/nft, in-tree binary), not the one installed by the distro.
|
||||
Else we may not find newly added bugs unless user did "make install" or
|
||||
bug has propagated to release.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
tests/shell/testcases/packetpath/payload | 38 +++++++++----------
|
||||
tests/shell/testcases/parsing/large_rule_pipe | 2 +-
|
||||
2 files changed, 20 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/tests/shell/testcases/packetpath/payload b/tests/shell/testcases/packetpath/payload
|
||||
index 1a89d85..9f4587d 100755
|
||||
--- a/tests/shell/testcases/packetpath/payload
|
||||
+++ b/tests/shell/testcases/packetpath/payload
|
||||
@@ -102,19 +102,19 @@ table inet payload_inet {
|
||||
|
||||
ip netns exec "$ns1" $NFT list ruleset
|
||||
|
||||
- ip netns exec "$ns1" nft list counter netdev payload_netdev ingress | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter netdev payload_netdev mangle_ingress | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter netdev payload_netdev mangle_ingress_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter netdev payload_netdev egress | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter netdev payload_netdev mangle_egress | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter netdev payload_netdev mangle_egress_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
-
|
||||
- ip netns exec "$ns1" nft list counter inet payload_inet input | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter inet payload_inet mangle_input | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter inet payload_inet mangle_input_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter inet payload_inet output | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter inet payload_inet mangle_output | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter inet payload_inet mangle_output_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter netdev payload_netdev ingress | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter netdev payload_netdev mangle_ingress | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter netdev payload_netdev mangle_ingress_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter netdev payload_netdev egress | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter netdev payload_netdev mangle_egress | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter netdev payload_netdev mangle_egress_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
+
|
||||
+ ip netns exec "$ns1" $NFT list counter inet payload_inet input | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter inet payload_inet mangle_input | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter inet payload_inet mangle_input_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter inet payload_inet output | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter inet payload_inet mangle_output | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter inet payload_inet mangle_output_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
|
||||
#
|
||||
# ... next stage
|
||||
@@ -166,12 +166,12 @@ RULESET="table bridge payload_bridge {
|
||||
|
||||
ip netns exec "$ns1" $NFT list ruleset
|
||||
|
||||
- ip netns exec "$ns1" nft list counter bridge payload_bridge input | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter bridge payload_bridge mangle_input | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter bridge payload_bridge mangle_input_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter bridge payload_bridge output | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter bridge payload_bridge mangle_output | grep -v "packets 0" > /dev/null || exit 1
|
||||
- ip netns exec "$ns1" nft list counter bridge payload_bridge mangle_output_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter bridge payload_bridge input | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter bridge payload_bridge mangle_input | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter bridge payload_bridge mangle_input_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter bridge payload_bridge output | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter bridge payload_bridge mangle_output | grep -v "packets 0" > /dev/null || exit 1
|
||||
+ ip netns exec "$ns1" $NFT list counter bridge payload_bridge mangle_output_match | grep -v "packets 0" > /dev/null || exit 1
|
||||
}
|
||||
|
||||
run_test "4" "10.141.10.2" "10.141.10.3" "24"
|
||||
diff --git a/tests/shell/testcases/parsing/large_rule_pipe b/tests/shell/testcases/parsing/large_rule_pipe
|
||||
index fac0afa..b6760c0 100755
|
||||
--- a/tests/shell/testcases/parsing/large_rule_pipe
|
||||
+++ b/tests/shell/testcases/parsing/large_rule_pipe
|
||||
@@ -566,6 +566,6 @@ table inet firewalld {
|
||||
}
|
||||
}"
|
||||
|
||||
-( echo "flush ruleset;"; echo "${RULESET}" ) | nft -f -
|
||||
+( echo "flush ruleset;"; echo "${RULESET}" ) | $NFT -f -
|
||||
|
||||
exit 0
|
||||
@ -0,0 +1,49 @@
|
||||
From 5104ecc5b5f0726ab58df27742c9c3cf8a65f1b3 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] doc: incorrect datatype description for icmpv6_type and
|
||||
icmpvx_code
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 9caa5142f95557decc19925ad37411f1df4589a2
|
||||
|
||||
commit 9caa5142f95557decc19925ad37411f1df4589a2
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Jan 9 12:42:20 2024 +0100
|
||||
|
||||
doc: incorrect datatype description for icmpv6_type and icmpvx_code
|
||||
|
||||
Fix incorrect description in manpage:
|
||||
|
||||
ICMPV6 TYPE TYPE is icmpv6_type
|
||||
ICMPVX CODE TYPE is icmpx_code
|
||||
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
doc/data-types.txt | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/doc/data-types.txt b/doc/data-types.txt
|
||||
index 961fc62..e5ee91a 100644
|
||||
--- a/doc/data-types.txt
|
||||
+++ b/doc/data-types.txt
|
||||
@@ -270,7 +270,7 @@ ICMPV6 TYPE TYPE
|
||||
|==================
|
||||
|Name | Keyword | Size | Base type
|
||||
|ICMPv6 Type |
|
||||
-icmpx_code |
|
||||
+icmpv6_type |
|
||||
8 bit |
|
||||
integer
|
||||
|===================
|
||||
@@ -364,7 +364,7 @@ ICMPVX CODE TYPE
|
||||
|==================
|
||||
|Name | Keyword | Size | Base type
|
||||
|ICMPvX Code |
|
||||
-icmpv6_type |
|
||||
+icmpx_code |
|
||||
8 bit |
|
||||
integer
|
||||
|===================
|
||||
228
0061-evaluate-add-missing-range-checks-for-dup-fwd-and-pa.patch
Normal file
228
0061-evaluate-add-missing-range-checks-for-dup-fwd-and-pa.patch
Normal file
@ -0,0 +1,228 @@
|
||||
From aaaf1ed4ab6ecb027ea58f49812c05fed9651cba Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:41 +0200
|
||||
Subject: [PATCH] evaluate: add missing range checks for dup,fwd and payload
|
||||
statements
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 4121175cc243a15bdb8c226a335f67cedd98680e
|
||||
|
||||
commit 4121175cc243a15bdb8c226a335f67cedd98680e
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Thu Jan 11 18:14:16 2024 +0100
|
||||
|
||||
evaluate: add missing range checks for dup,fwd and payload statements
|
||||
|
||||
Else we assert with:
|
||||
BUG: unknown expression type range
|
||||
nft: src/netlink_linearize.c:912: netlink_gen_expr: Assertion `0' failed.
|
||||
|
||||
While at it, condense meta and exthdr to reuse the same helper.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 88 +++++++++++--------
|
||||
.../testcases/bogons/nft-f/dup_fwd_ranges | 14 +++
|
||||
.../nft-f/unknown_expr_type_range_assert | 8 +-
|
||||
3 files changed, 69 insertions(+), 41 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/dup_fwd_ranges
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index c655e3a..06ad554 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -74,6 +74,33 @@ static int __fmtstring(3, 4) set_error(struct eval_ctx *ctx,
|
||||
return -1;
|
||||
}
|
||||
|
||||
+static const char *stmt_name(const struct stmt *stmt)
|
||||
+{
|
||||
+ switch (stmt->ops->type) {
|
||||
+ case STMT_NAT:
|
||||
+ switch (stmt->nat.type) {
|
||||
+ case NFT_NAT_SNAT:
|
||||
+ return "snat";
|
||||
+ case NFT_NAT_DNAT:
|
||||
+ return "dnat";
|
||||
+ case NFT_NAT_REDIR:
|
||||
+ return "redirect";
|
||||
+ case NFT_NAT_MASQ:
|
||||
+ return "masquerade";
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return stmt->ops->name;
|
||||
+}
|
||||
+
|
||||
+static int stmt_error_range(struct eval_ctx *ctx, const struct stmt *stmt, const struct expr *e)
|
||||
+{
|
||||
+ return expr_error(ctx->msgs, e, "%s: range argument not supported", stmt_name(stmt));
|
||||
+}
|
||||
+
|
||||
static void key_fix_dtype_byteorder(struct expr *key)
|
||||
{
|
||||
const struct datatype *dtype = key->dtype;
|
||||
@@ -2980,13 +3007,8 @@ static int stmt_evaluate_exthdr(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- switch (stmt->exthdr.val->etype) {
|
||||
- case EXPR_RANGE:
|
||||
- return expr_error(ctx->msgs, stmt->exthdr.val,
|
||||
- "cannot be a range");
|
||||
- default:
|
||||
- break;
|
||||
- }
|
||||
+ if (stmt->exthdr.val->etype == EXPR_RANGE)
|
||||
+ return stmt_error_range(ctx, stmt, stmt->exthdr.val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3019,6 +3041,9 @@ static int stmt_evaluate_payload(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
payload->byteorder) < 0)
|
||||
return -1;
|
||||
|
||||
+ if (stmt->payload.val->etype == EXPR_RANGE)
|
||||
+ return stmt_error_range(ctx, stmt, stmt->payload.val);
|
||||
+
|
||||
need_csum = stmt_evaluate_payload_need_csum(payload);
|
||||
|
||||
if (!payload_needs_adjustment(payload)) {
|
||||
@@ -3178,15 +3203,8 @@ static int stmt_evaluate_meta(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- switch (stmt->meta.expr->etype) {
|
||||
- case EXPR_RANGE:
|
||||
- ret = expr_error(ctx->msgs, stmt->meta.expr,
|
||||
- "Meta expression cannot be a range");
|
||||
- break;
|
||||
- default:
|
||||
- break;
|
||||
-
|
||||
- }
|
||||
+ if (stmt->meta.expr->etype == EXPR_RANGE)
|
||||
+ return stmt_error_range(ctx, stmt, stmt->meta.expr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -3209,6 +3227,9 @@ static int stmt_evaluate_ct(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
return stmt_error(ctx, stmt,
|
||||
"ct secmark must not be set to constant value");
|
||||
|
||||
+ if (stmt->ct.expr->etype == EXPR_RANGE)
|
||||
+ return stmt_error_range(ctx, stmt, stmt->ct.expr);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3719,28 +3740,6 @@ static int nat_evaluate_transport(struct eval_ctx *ctx, struct stmt *stmt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static const char *stmt_name(const struct stmt *stmt)
|
||||
-{
|
||||
- switch (stmt->ops->type) {
|
||||
- case STMT_NAT:
|
||||
- switch (stmt->nat.type) {
|
||||
- case NFT_NAT_SNAT:
|
||||
- return "snat";
|
||||
- case NFT_NAT_DNAT:
|
||||
- return "dnat";
|
||||
- case NFT_NAT_REDIR:
|
||||
- return "redirect";
|
||||
- case NFT_NAT_MASQ:
|
||||
- return "masquerade";
|
||||
- }
|
||||
- break;
|
||||
- default:
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- return stmt->ops->name;
|
||||
-}
|
||||
-
|
||||
static int stmt_evaluate_l3proto(struct eval_ctx *ctx,
|
||||
struct stmt *stmt, uint8_t family)
|
||||
{
|
||||
@@ -4132,6 +4131,9 @@ static int stmt_evaluate_dup(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
&stmt->dup.dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
+
|
||||
+ if (stmt->dup.dev->etype == EXPR_RANGE)
|
||||
+ return stmt_error_range(ctx, stmt, stmt->dup.dev);
|
||||
}
|
||||
break;
|
||||
case NFPROTO_NETDEV:
|
||||
@@ -4150,6 +4152,10 @@ static int stmt_evaluate_dup(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
default:
|
||||
return stmt_error(ctx, stmt, "unsupported family");
|
||||
}
|
||||
+
|
||||
+ if (stmt->dup.to->etype == EXPR_RANGE)
|
||||
+ return stmt_error_range(ctx, stmt, stmt->dup.to);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4171,6 +4177,9 @@ static int stmt_evaluate_fwd(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
+ if (stmt->fwd.dev->etype == EXPR_RANGE)
|
||||
+ return stmt_error_range(ctx, stmt, stmt->fwd.dev);
|
||||
+
|
||||
if (stmt->fwd.addr != NULL) {
|
||||
switch (stmt->fwd.family) {
|
||||
case NFPROTO_IPV4:
|
||||
@@ -4189,6 +4198,9 @@ static int stmt_evaluate_fwd(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
&stmt->fwd.addr);
|
||||
if (err < 0)
|
||||
return err;
|
||||
+
|
||||
+ if (stmt->fwd.addr->etype == EXPR_RANGE)
|
||||
+ return stmt_error_range(ctx, stmt, stmt->fwd.addr);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/dup_fwd_ranges b/tests/shell/testcases/bogons/nft-f/dup_fwd_ranges
|
||||
new file mode 100644
|
||||
index 0000000..efaff9e
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/dup_fwd_ranges
|
||||
@@ -0,0 +1,14 @@
|
||||
+define dev = "1"-"2"
|
||||
+
|
||||
+table netdev t {
|
||||
+ chain c {
|
||||
+ fwd to 1-2
|
||||
+ dup to 1-2
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+table ip t {
|
||||
+ chain c {
|
||||
+ dup to 1-2 device $dev
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/unknown_expr_type_range_assert b/tests/shell/testcases/bogons/nft-f/unknown_expr_type_range_assert
|
||||
index 234dd62..e620673 100644
|
||||
--- a/tests/shell/testcases/bogons/nft-f/unknown_expr_type_range_assert
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/unknown_expr_type_range_assert
|
||||
@@ -1,5 +1,7 @@
|
||||
table ip x {
|
||||
- chain k {
|
||||
- meta mark set 0x001-3434
|
||||
- }
|
||||
+ chain k {
|
||||
+ meta mark set 0x001-3434
|
||||
+ ct mark set 0x001-3434
|
||||
+ tcp dport set 1-3
|
||||
+ }
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
From 475315fb01bac6b53833c727add0cf1c427a75b7 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] evaluate: skip anonymous set optimization for concatenations
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 6bc6673fc88c8a3e3dd5504b2d24a6d6bc2f8427
|
||||
|
||||
commit 6bc6673fc88c8a3e3dd5504b2d24a6d6bc2f8427
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Wed Jan 10 18:18:50 2024 +0100
|
||||
|
||||
evaluate: skip anonymous set optimization for concatenations
|
||||
|
||||
Concatenation is only supported with sets. Moreover, stripping of the
|
||||
set leads to broken ruleset listing, therefore, skip this optimization
|
||||
for the concatenations.
|
||||
|
||||
Fixes: fa17b17ea74a ("evaluate: revisit anonymous set with single element optimization")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 20 +++++++++++---------
|
||||
1 file changed, 11 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 06ad554..8f98b48 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -2507,15 +2507,17 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
|
||||
return expr_binary_error(ctx->msgs, right, left,
|
||||
"Cannot be used with right hand side constant value");
|
||||
|
||||
- switch (rel->op) {
|
||||
- case OP_EQ:
|
||||
- case OP_IMPLICIT:
|
||||
- case OP_NEQ:
|
||||
- if (right->etype == EXPR_SET && right->size == 1)
|
||||
- optimize_singleton_set(rel, &right);
|
||||
- break;
|
||||
- default:
|
||||
- break;
|
||||
+ if (left->etype != EXPR_CONCAT) {
|
||||
+ switch (rel->op) {
|
||||
+ case OP_EQ:
|
||||
+ case OP_IMPLICIT:
|
||||
+ case OP_NEQ:
|
||||
+ if (right->etype == EXPR_SET && right->size == 1)
|
||||
+ optimize_singleton_set(rel, &right);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
switch (rel->op) {
|
||||
@ -0,0 +1,45 @@
|
||||
From bd77070f6c17a0dba479ed5a45b940d8605a91f3 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] evaluate: do not fetch next expression on runaway number of
|
||||
concatenation components
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 955bb6d31c90453e43043346c917646ddc4e5c4e
|
||||
|
||||
commit 955bb6d31c90453e43043346c917646ddc4e5c4e
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Wed Jan 10 18:20:47 2024 +0100
|
||||
|
||||
evaluate: do not fetch next expression on runaway number of concatenation components
|
||||
|
||||
If this is the last expression, then the runaway flag is set on and
|
||||
evaluation bails in the next iteration, do not fetch next list element
|
||||
which refers to the list head.
|
||||
|
||||
I found this by code inspection, I could not trigger any crash with this
|
||||
one.
|
||||
|
||||
Fixes: ae1d54d1343f ("evaluate: do not crash on runaway number of concatenation components")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 8f98b48..079f340 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -1591,8 +1591,8 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
|
||||
if (key && expressions) {
|
||||
if (list_is_last(&key->list, expressions))
|
||||
runaway = true;
|
||||
-
|
||||
- key = list_next_entry(key, list);
|
||||
+ else
|
||||
+ key = list_next_entry(key, list);
|
||||
}
|
||||
|
||||
ctx->inner_desc = NULL;
|
||||
@ -0,0 +1,62 @@
|
||||
From 9f7891ddd76afb0472cad8cec8e7cfed12f55d99 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] evaluate: error out when store needs more than one 128bit
|
||||
register of align fixup
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 8a66de2a15943b2fbf960967cdbcbd0a148cb114
|
||||
|
||||
commit 8a66de2a15943b2fbf960967cdbcbd0a148cb114
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Mon Jan 15 14:11:17 2024 +0100
|
||||
|
||||
evaluate: error out when store needs more than one 128bit register of align fixup
|
||||
|
||||
Else this gives:
|
||||
nft: evaluate.c:2983: stmt_evaluate_payload: Assertion `sizeof(data) * BITS_PER_BYTE >= masklen' failed.
|
||||
|
||||
For loads, this is already prevented via expr_evaluate_bits() which has:
|
||||
|
||||
if (masklen > NFT_REG_SIZE * BITS_PER_BYTE)
|
||||
return expr_error(ctx->msgs, expr, "mask length %u exceeds allowed maximum of %u\n",
|
||||
masklen, NFT_REG_SIZE * BITS_PER_BYTE);
|
||||
|
||||
But for the store path this isn't called.
|
||||
The reproducer asks to store a 128 bit integer at bit offset 1, i.e.
|
||||
17 bytes would need to be munged, but we can only handle up to 16 bytes
|
||||
(one pseudo-register).
|
||||
|
||||
Fixes: 78936d50f306 ("evaluate: add support to set IPv6 non-byte header fields")
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 5 +++++
|
||||
.../testcases/bogons/nft-f/payload_expr_unaligned_store | 1 +
|
||||
2 files changed, 6 insertions(+)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/payload_expr_unaligned_store
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 079f340..541299e 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -3065,6 +3065,11 @@ static int stmt_evaluate_payload(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
payload_byte_size = div_round_up(payload->len + extra_len,
|
||||
BITS_PER_BYTE);
|
||||
|
||||
+ if (payload_byte_size > sizeof(data))
|
||||
+ return expr_error(ctx->msgs, stmt->payload.expr,
|
||||
+ "uneven load cannot span more than %u bytes, got %u",
|
||||
+ sizeof(data), payload_byte_size);
|
||||
+
|
||||
if (need_csum && payload_byte_size & 1) {
|
||||
payload_byte_size++;
|
||||
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/payload_expr_unaligned_store b/tests/shell/testcases/bogons/nft-f/payload_expr_unaligned_store
|
||||
new file mode 100644
|
||||
index 0000000..c1358df
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/payload_expr_unaligned_store
|
||||
@@ -0,0 +1 @@
|
||||
+add rule f i @th,1,128 set 1
|
||||
64
0065-rule-fix-sym-refcount-assertion.patch
Normal file
64
0065-rule-fix-sym-refcount-assertion.patch
Normal file
@ -0,0 +1,64 @@
|
||||
From a7072eb98d9549db87c4d76eb6ca3556728277b5 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] rule: fix sym refcount assertion
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit b73298405cda74b3a87a1818bb92f53298d34170
|
||||
|
||||
commit b73298405cda74b3a87a1818bb92f53298d34170
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Mon Jan 15 14:27:15 2024 +0100
|
||||
|
||||
rule: fix sym refcount assertion
|
||||
|
||||
Scope release must happen last.
|
||||
afl provided a reproducer where policy is a define, because
|
||||
scope is released too early we get:
|
||||
nft: src/rule.c:559: scope_release: Assertion `sym->refcnt == 1' failed.
|
||||
|
||||
... because chain->policy is EXPR_SYMBOL.
|
||||
|
||||
Fixes: 627c451b2351 ("src: allow variables in the chain priority specification")
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/rule.c | 6 +++++-
|
||||
tests/shell/testcases/bogons/nft-f/define_policy_assert | 3 +++
|
||||
2 files changed, 8 insertions(+), 1 deletion(-)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/define_policy_assert
|
||||
|
||||
diff --git a/src/rule.c b/src/rule.c
|
||||
index 633fae7..e2d972c 100644
|
||||
--- a/src/rule.c
|
||||
+++ b/src/rule.c
|
||||
@@ -729,7 +729,6 @@ void chain_free(struct chain *chain)
|
||||
list_for_each_entry_safe(rule, next, &chain->rules, list)
|
||||
rule_free(rule);
|
||||
handle_free(&chain->handle);
|
||||
- scope_release(&chain->scope);
|
||||
free_const(chain->type.str);
|
||||
expr_free(chain->dev_expr);
|
||||
for (i = 0; i < chain->dev_array_len; i++)
|
||||
@@ -738,6 +737,11 @@ void chain_free(struct chain *chain)
|
||||
expr_free(chain->priority.expr);
|
||||
expr_free(chain->policy);
|
||||
free_const(chain->comment);
|
||||
+
|
||||
+ /* MUST be released after all expressions, they could
|
||||
+ * hold refcounts.
|
||||
+ */
|
||||
+ scope_release(&chain->scope);
|
||||
free(chain);
|
||||
}
|
||||
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/define_policy_assert b/tests/shell/testcases/bogons/nft-f/define_policy_assert
|
||||
new file mode 100644
|
||||
index 0000000..f1e58b5
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/define_policy_assert
|
||||
@@ -0,0 +1,3 @@
|
||||
+chain y x { priority filter
|
||||
+define p = foo
|
||||
+policy $p
|
||||
85
0066-json-Support-sets-auto-merge-option.patch
Normal file
85
0066-json-Support-sets-auto-merge-option.patch
Normal file
@ -0,0 +1,85 @@
|
||||
From 6242822b5f19721538fb9296a048ea84acee5092 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] json: Support sets' auto-merge option
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit a4034c66b03e4d526fbad78da9cd38da9f1f43a5
|
||||
|
||||
commit a4034c66b03e4d526fbad78da9cd38da9f1f43a5
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Wed Jan 31 17:30:24 2024 +0100
|
||||
|
||||
json: Support sets' auto-merge option
|
||||
|
||||
If enabled, list the option as additional attribute with boolean value.
|
||||
|
||||
Fixes: e70354f53e9f6 ("libnftables: Implement JSON output support")
|
||||
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1734
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
doc/libnftables-json.adoc | 8 ++++++--
|
||||
src/json.c | 2 ++
|
||||
src/parser_json.c | 1 +
|
||||
3 files changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/doc/libnftables-json.adoc b/doc/libnftables-json.adoc
|
||||
index c5e5f23..3bbb6cd 100644
|
||||
--- a/doc/libnftables-json.adoc
|
||||
+++ b/doc/libnftables-json.adoc
|
||||
@@ -321,7 +321,8 @@ ____
|
||||
"elem":* 'SET_ELEMENTS'*,
|
||||
"timeout":* 'NUMBER'*,
|
||||
"gc-interval":* 'NUMBER'*,
|
||||
- "size":* 'NUMBER'
|
||||
+ "size":* 'NUMBER'*,
|
||||
+ "auto-merge":* 'BOOLEAN'
|
||||
*}}*
|
||||
|
||||
*{ "map": {
|
||||
@@ -336,7 +337,8 @@ ____
|
||||
"elem":* 'SET_ELEMENTS'*,
|
||||
"timeout":* 'NUMBER'*,
|
||||
"gc-interval":* 'NUMBER'*,
|
||||
- "size":* 'NUMBER'
|
||||
+ "size":* 'NUMBER'*,
|
||||
+ "auto-merge":* 'BOOLEAN'
|
||||
*}}*
|
||||
|
||||
'SET_TYPE' := 'STRING' | *[* 'SET_TYPE_LIST' *]*
|
||||
@@ -375,6 +377,8 @@ that they translate a unique key to a value.
|
||||
Garbage collector interval in seconds.
|
||||
*size*::
|
||||
Maximum number of elements supported.
|
||||
+*auto-merge*::
|
||||
+ Automatic merging of adjacent/overlapping set elements in interval sets.
|
||||
|
||||
==== TYPE
|
||||
The set type might be a string, such as *"ipv4_addr"* or an array
|
||||
diff --git a/src/json.c b/src/json.c
|
||||
index 6809cd5..b3e1e4e 100644
|
||||
--- a/src/json.c
|
||||
+++ b/src/json.c
|
||||
@@ -194,6 +194,8 @@ static json_t *set_print_json(struct output_ctx *octx, const struct set *set)
|
||||
tmp = json_pack("i", set->gc_int / 1000);
|
||||
json_object_set_new(root, "gc-interval", tmp);
|
||||
}
|
||||
+ if (set->automerge)
|
||||
+ json_object_set_new(root, "auto-merge", json_true());
|
||||
|
||||
if (!nft_output_terse(octx) && set->init && set->init->size > 0) {
|
||||
json_t *array = json_array();
|
||||
diff --git a/src/parser_json.c b/src/parser_json.c
|
||||
index 2acc248..9537c9d 100644
|
||||
--- a/src/parser_json.c
|
||||
+++ b/src/parser_json.c
|
||||
@@ -3407,6 +3407,7 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root,
|
||||
if (!json_unpack(root, "{s:i}", "gc-interval", &set->gc_int))
|
||||
set->gc_int *= 1000;
|
||||
json_unpack(root, "{s:i}", "size", &set->desc.size);
|
||||
+ json_unpack(root, "{s:b}", "auto-merge", &set->automerge);
|
||||
|
||||
if (!json_unpack(root, "{s:o}", "stmt", &stmt_json))
|
||||
json_parse_set_stmt_list(ctx, &set->stmt_list, stmt_json);
|
||||
181
0067-evaluate-don-t-assert-on-net-transport-header-confli.patch
Normal file
181
0067-evaluate-don-t-assert-on-net-transport-header-confli.patch
Normal file
@ -0,0 +1,181 @@
|
||||
From 9a0ab03e46bcfadf423d284bb90e11c8e6f04fe8 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] evaluate: don't assert on net/transport header conflict
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 3a734d60813193974a4a0e8ed0af3349f8857ec9
|
||||
|
||||
commit 3a734d60813193974a4a0e8ed0af3349f8857ec9
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Tue Jan 16 15:21:00 2024 +0100
|
||||
|
||||
evaluate: don't assert on net/transport header conflict
|
||||
|
||||
before:
|
||||
nft: evaluate.c:467: conflict_resolution_gen_dependency: Assertion `expr->payload.base == PROTO_BASE_LL_HDR' failed.
|
||||
Aborted (core dumped)
|
||||
|
||||
conflict_resolution_gen_dependency() can only handle linklayer
|
||||
conflicts, hence the assert.
|
||||
|
||||
Rename it accordingly. Also rename resolve_protocol_conflict, it doesn't
|
||||
do anything for != PROTO_BASE_LL_HDR and extend the assertion to that
|
||||
function too.
|
||||
|
||||
Callers now enforce PROTO_BASE_LL_HDR prerequisite.
|
||||
|
||||
after:
|
||||
Error: conflicting transport layer protocols specified: comp vs. udp
|
||||
ip6 nexthdr comp udp dport 4789
|
||||
^^^^^^^^^
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 69 +++++++++----------
|
||||
...solution_gen_dependency_base_ll_hdr_assert | 5 ++
|
||||
2 files changed, 38 insertions(+), 36 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/bogons/nft-f/evaluate_conflict_resolution_gen_dependency_base_ll_hdr_assert
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 541299e..98f97bd 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -494,9 +494,9 @@ int stmt_dependency_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
}
|
||||
|
||||
static int
|
||||
-conflict_resolution_gen_dependency(struct eval_ctx *ctx, int protocol,
|
||||
- const struct expr *expr,
|
||||
- struct stmt **res)
|
||||
+ll_conflict_resolution_gen_dependency(struct eval_ctx *ctx, int protocol,
|
||||
+ const struct expr *expr,
|
||||
+ struct stmt **res)
|
||||
{
|
||||
enum proto_bases base = expr->payload.base;
|
||||
const struct proto_hdr_template *tmpl;
|
||||
@@ -750,56 +750,52 @@ static bool proto_is_dummy(const struct proto_desc *desc)
|
||||
return desc == &proto_inet || desc == &proto_netdev;
|
||||
}
|
||||
|
||||
-static int resolve_protocol_conflict(struct eval_ctx *ctx,
|
||||
- const struct proto_desc *desc,
|
||||
- struct expr *payload)
|
||||
+static int resolve_ll_protocol_conflict(struct eval_ctx *ctx,
|
||||
+ const struct proto_desc *desc,
|
||||
+ struct expr *payload)
|
||||
{
|
||||
enum proto_bases base = payload->payload.base;
|
||||
struct stmt *nstmt = NULL;
|
||||
struct proto_ctx *pctx;
|
||||
+ unsigned int i;
|
||||
int link, err;
|
||||
|
||||
+ assert(base == PROTO_BASE_LL_HDR);
|
||||
+
|
||||
pctx = eval_proto_ctx(ctx);
|
||||
|
||||
- if (payload->payload.base == PROTO_BASE_LL_HDR) {
|
||||
- if (proto_is_dummy(desc)) {
|
||||
- if (ctx->inner_desc) {
|
||||
- proto_ctx_update(pctx, PROTO_BASE_LL_HDR, &payload->location, &proto_eth);
|
||||
- } else {
|
||||
- err = meta_iiftype_gen_dependency(ctx, payload, &nstmt);
|
||||
- if (err < 0)
|
||||
- return err;
|
||||
-
|
||||
- desc = payload->payload.desc;
|
||||
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
|
||||
- }
|
||||
+ if (proto_is_dummy(desc)) {
|
||||
+ if (ctx->inner_desc) {
|
||||
+ proto_ctx_update(pctx, PROTO_BASE_LL_HDR, &payload->location, &proto_eth);
|
||||
} else {
|
||||
- unsigned int i;
|
||||
+ err = meta_iiftype_gen_dependency(ctx, payload, &nstmt);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
|
||||
- /* payload desc stored in the L2 header stack? No conflict. */
|
||||
- for (i = 0; i < pctx->stacked_ll_count; i++) {
|
||||
- if (pctx->stacked_ll[i] == payload->payload.desc)
|
||||
- return 0;
|
||||
- }
|
||||
+ desc = payload->payload.desc;
|
||||
+ rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
|
||||
+ }
|
||||
+ } else {
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ /* payload desc stored in the L2 header stack? No conflict. */
|
||||
+ for (i = 0; i < pctx->stacked_ll_count; i++) {
|
||||
+ if (pctx->stacked_ll[i] == payload->payload.desc)
|
||||
+ return 0;
|
||||
}
|
||||
}
|
||||
|
||||
- assert(base <= PROTO_BASE_MAX);
|
||||
/* This payload and the existing context don't match, conflict. */
|
||||
if (pctx->protocol[base + 1].desc != NULL)
|
||||
return 1;
|
||||
|
||||
link = proto_find_num(desc, payload->payload.desc);
|
||||
if (link < 0 ||
|
||||
- conflict_resolution_gen_dependency(ctx, link, payload, &nstmt) < 0)
|
||||
+ ll_conflict_resolution_gen_dependency(ctx, link, payload, &nstmt) < 0)
|
||||
return 1;
|
||||
|
||||
- if (base == PROTO_BASE_LL_HDR) {
|
||||
- unsigned int i;
|
||||
-
|
||||
- for (i = 0; i < pctx->stacked_ll_count; i++)
|
||||
- payload->payload.offset += pctx->stacked_ll[i]->length;
|
||||
- }
|
||||
+ for (i = 0; i < pctx->stacked_ll_count; i++)
|
||||
+ payload->payload.offset += pctx->stacked_ll[i]->length;
|
||||
|
||||
rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
|
||||
|
||||
@@ -841,7 +837,7 @@ static int __expr_evaluate_payload(struct eval_ctx *ctx, struct expr *expr)
|
||||
|
||||
link = proto_find_num(desc, payload->payload.desc);
|
||||
if (link < 0 ||
|
||||
- conflict_resolution_gen_dependency(ctx, link, payload, &nstmt) < 0)
|
||||
+ ll_conflict_resolution_gen_dependency(ctx, link, payload, &nstmt) < 0)
|
||||
return expr_error(ctx->msgs, payload,
|
||||
"conflicting protocols specified: %s vs. %s",
|
||||
desc->name,
|
||||
@@ -898,8 +894,8 @@ check_icmp:
|
||||
/* If we already have context and this payload is on the same
|
||||
* base, try to resolve the protocol conflict.
|
||||
*/
|
||||
- if (payload->payload.base == desc->base) {
|
||||
- err = resolve_protocol_conflict(ctx, desc, payload);
|
||||
+ if (base == PROTO_BASE_LL_HDR) {
|
||||
+ err = resolve_ll_protocol_conflict(ctx, desc, payload);
|
||||
if (err <= 0)
|
||||
return err;
|
||||
|
||||
@@ -908,7 +904,8 @@ check_icmp:
|
||||
return 0;
|
||||
}
|
||||
return expr_error(ctx->msgs, payload,
|
||||
- "conflicting protocols specified: %s vs. %s",
|
||||
+ "conflicting %s protocols specified: %s vs. %s",
|
||||
+ proto_base_names[base],
|
||||
pctx->protocol[base].desc->name,
|
||||
payload->payload.desc->name);
|
||||
}
|
||||
diff --git a/tests/shell/testcases/bogons/nft-f/evaluate_conflict_resolution_gen_dependency_base_ll_hdr_assert b/tests/shell/testcases/bogons/nft-f/evaluate_conflict_resolution_gen_dependency_base_ll_hdr_assert
|
||||
new file mode 100644
|
||||
index 0000000..43d72c4
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/bogons/nft-f/evaluate_conflict_resolution_gen_dependency_base_ll_hdr_assert
|
||||
@@ -0,0 +1,5 @@
|
||||
+table ip6 t {
|
||||
+ chain c {
|
||||
+ ip6 nexthdr comp udp dport 4789
|
||||
+ }
|
||||
+}
|
||||
48
0068-evaluate-fix-check-for-unknown-in-cmd_op_to_name.patch
Normal file
48
0068-evaluate-fix-check-for-unknown-in-cmd_op_to_name.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From e53d46d90f0b73be34c42abfd759b16306da03ac Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] evaluate: fix check for unknown in cmd_op_to_name
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 9f76bb63c0c706ea5c0d55931ee690ca5dccaf16
|
||||
|
||||
commit 9f76bb63c0c706ea5c0d55931ee690ca5dccaf16
|
||||
Author: 谢致邦 (XIE Zhibang) <Yeking@Red54.com>
|
||||
Date: Wed Feb 7 15:10:20 2024 +0000
|
||||
|
||||
evaluate: fix check for unknown in cmd_op_to_name
|
||||
|
||||
Example:
|
||||
nft --debug=all destroy table ip missingtable
|
||||
|
||||
Before:
|
||||
Evaluate unknown
|
||||
|
||||
After:
|
||||
Evaluate destroy
|
||||
|
||||
Fixes: e1dfd5cc4c46 ("src: add support to command "destroy"")
|
||||
Signed-off-by: 谢致邦 (XIE Zhibang) <Yeking@Red54.com>
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 98f97bd..20950fd 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -5886,7 +5886,7 @@ static const char * const cmd_op_name[] = {
|
||||
|
||||
static const char *cmd_op_to_name(enum cmd_ops op)
|
||||
{
|
||||
- if (op > CMD_DESCRIBE)
|
||||
+ if (op >= array_size(cmd_op_name))
|
||||
return "unknown";
|
||||
|
||||
return cmd_op_name[op];
|
||||
49
0069-cache-Optimize-caching-for-list-tables-command.patch
Normal file
49
0069-cache-Optimize-caching-for-list-tables-command.patch
Normal file
@ -0,0 +1,49 @@
|
||||
From 5bc0de5ef742c4746ca45a8940998fcfeef29b6f Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] cache: Optimize caching for 'list tables' command
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 674eb7fa2895813b25f6fbfcc9417fc0788fade1
|
||||
|
||||
commit 674eb7fa2895813b25f6fbfcc9417fc0788fade1
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Tue Feb 6 19:26:57 2024 +0100
|
||||
|
||||
cache: Optimize caching for 'list tables' command
|
||||
|
||||
No point in fetching anything other than existing tables from kernel:
|
||||
'list tables' merely prints existing table names, no contents.
|
||||
|
||||
Also populate filter's family field to reduce overhead when listing
|
||||
tables in one family with many tables in another one. It works without
|
||||
further adjustments because nftnl_nlmsg_build_hdr() will use the value
|
||||
for nfgen_family.
|
||||
|
||||
Reported-by: anton.khazan@gmail.com
|
||||
Link: https://bugzilla.netfilter.org/show_bug.cgi?id=1735
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/cache.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/cache.c b/src/cache.c
|
||||
index a3cd795..c000e32 100644
|
||||
--- a/src/cache.c
|
||||
+++ b/src/cache.c
|
||||
@@ -203,8 +203,12 @@ static unsigned int evaluate_cache_list(struct nft_ctx *nft, struct cmd *cmd,
|
||||
{
|
||||
switch (cmd->obj) {
|
||||
case CMD_OBJ_TABLE:
|
||||
- if (filter && cmd->handle.table.name) {
|
||||
+ if (filter)
|
||||
filter->list.family = cmd->handle.family;
|
||||
+ if (!cmd->handle.table.name) {
|
||||
+ flags |= NFT_CACHE_TABLE;
|
||||
+ break;
|
||||
+ } else if (filter) {
|
||||
filter->list.table = cmd->handle.table.name;
|
||||
}
|
||||
flags |= NFT_CACHE_FULL;
|
||||
209
0070-evaluate-skip-byteorder-conversion-for-selector-smal.patch
Normal file
209
0070-evaluate-skip-byteorder-conversion-for-selector-smal.patch
Normal file
@ -0,0 +1,209 @@
|
||||
From ff07e944ab10459c7fa9b6beac5c622e48eaa2f5 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] evaluate: skip byteorder conversion for selector smaller than
|
||||
2 bytes
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 9fe58952c45a1643dc7df1a0b1f5d88e8ae1a978
|
||||
|
||||
commit 9fe58952c45a1643dc7df1a0b1f5d88e8ae1a978
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Wed Feb 7 23:53:32 2024 +0100
|
||||
|
||||
evaluate: skip byteorder conversion for selector smaller than 2 bytes
|
||||
|
||||
Add unary expression to trigger byteorder conversion for host byteorder
|
||||
selectors only if selectors length is larger or equal than 2 bytes.
|
||||
|
||||
# cat test.nft
|
||||
table ip x {
|
||||
set test {
|
||||
type ipv4_addr . ether_addr . inet_proto
|
||||
flags interval
|
||||
}
|
||||
|
||||
chain y {
|
||||
ip saddr . ether saddr . meta l4proto @test counter
|
||||
}
|
||||
}
|
||||
|
||||
# nft -f test.nft
|
||||
ip x y
|
||||
[ meta load iiftype => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000001 ]
|
||||
[ payload load 4b @ network header + 12 => reg 1 ]
|
||||
[ payload load 6b @ link header + 6 => reg 9 ]
|
||||
[ meta load l4proto => reg 11 ]
|
||||
[ byteorder reg 11 = hton(reg 11, 2, 1) ] <--- should not be here
|
||||
[ lookup reg 1 set test ]
|
||||
[ counter pkts 0 bytes 0 ]
|
||||
|
||||
Fixes: 1017d323cafa ("src: support for selectors with different byteorder with interval concatenations")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 12 ++++++----
|
||||
tests/py/inet/meta.t | 1 +
|
||||
tests/py/inet/meta.t.json | 41 ++++++++++++++++++++++++++++++++
|
||||
tests/py/inet/meta.t.json.output | 41 ++++++++++++++++++++++++++++++++
|
||||
tests/py/inet/meta.t.payload | 14 +++++++++++
|
||||
5 files changed, 104 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 20950fd..e64bc91 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -194,12 +194,14 @@ static int byteorder_conversion(struct eval_ctx *ctx, struct expr **expr,
|
||||
|
||||
assert(basetype == TYPE_INTEGER);
|
||||
|
||||
- op = byteorder_conversion_op(i, byteorder);
|
||||
- unary = unary_expr_alloc(&i->location, op, i);
|
||||
- if (expr_evaluate(ctx, &unary) < 0)
|
||||
- return -1;
|
||||
+ if (div_round_up(i->len, BITS_PER_BYTE) >= 2) {
|
||||
+ op = byteorder_conversion_op(i, byteorder);
|
||||
+ unary = unary_expr_alloc(&i->location, op, i);
|
||||
+ if (expr_evaluate(ctx, &unary) < 0)
|
||||
+ return -1;
|
||||
|
||||
- list_replace(&i->list, &unary->list);
|
||||
+ list_replace(&i->list, &unary->list);
|
||||
+ }
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/tests/py/inet/meta.t b/tests/py/inet/meta.t
|
||||
index 5c062b3..7d2515c 100644
|
||||
--- a/tests/py/inet/meta.t
|
||||
+++ b/tests/py/inet/meta.t
|
||||
@@ -25,6 +25,7 @@ meta mark set ct mark >> 8;ok
|
||||
meta mark . tcp dport { 0x0000000a-0x00000014 . 80-90, 0x00100000-0x00100123 . 100-120 };ok
|
||||
ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 1.2.3.6-1.2.3.8 . 0x00000200-0x00000300 };ok
|
||||
ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 5.6.7.8 . 0x00000200 };ok
|
||||
+ip saddr . ether saddr . meta l4proto { 1.2.3.4 . aa:bb:cc:dd:ee:ff . 6 };ok
|
||||
|
||||
meta mark set ip dscp;ok
|
||||
meta mark set ip dscp | 0x40;ok
|
||||
diff --git a/tests/py/inet/meta.t.json b/tests/py/inet/meta.t.json
|
||||
index 3ba0fd1..0fee165 100644
|
||||
--- a/tests/py/inet/meta.t.json
|
||||
+++ b/tests/py/inet/meta.t.json
|
||||
@@ -526,3 +526,44 @@
|
||||
}
|
||||
]
|
||||
|
||||
+# ip saddr . ether saddr . meta l4proto { 1.2.3.4 . aa:bb:cc:dd:ee:ff . 6 }
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "concat": [
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "saddr",
|
||||
+ "protocol": "ip"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "saddr",
|
||||
+ "protocol": "ether"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "meta": {
|
||||
+ "key": "l4proto"
|
||||
+ }
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": {
|
||||
+ "set": [
|
||||
+ {
|
||||
+ "concat": [
|
||||
+ "1.2.3.4",
|
||||
+ "aa:bb:cc:dd:ee:ff",
|
||||
+ "tcp"
|
||||
+ ]
|
||||
+ }
|
||||
+ ]
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
diff --git a/tests/py/inet/meta.t.json.output b/tests/py/inet/meta.t.json.output
|
||||
index 3e7dd21..8697d5a 100644
|
||||
--- a/tests/py/inet/meta.t.json.output
|
||||
+++ b/tests/py/inet/meta.t.json.output
|
||||
@@ -51,3 +51,44 @@
|
||||
}
|
||||
]
|
||||
|
||||
+# ip saddr . ether saddr . meta l4proto { 1.2.3.4 . aa:bb:cc:dd:ee:ff . 6 }
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "concat": [
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "saddr",
|
||||
+ "protocol": "ip"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "saddr",
|
||||
+ "protocol": "ether"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "meta": {
|
||||
+ "key": "l4proto"
|
||||
+ }
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": {
|
||||
+ "set": [
|
||||
+ {
|
||||
+ "concat": [
|
||||
+ "1.2.3.4",
|
||||
+ "aa:bb:cc:dd:ee:ff",
|
||||
+ 6
|
||||
+ ]
|
||||
+ }
|
||||
+ ]
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
diff --git a/tests/py/inet/meta.t.payload b/tests/py/inet/meta.t.payload
|
||||
index c53b507..7184fa0 100644
|
||||
--- a/tests/py/inet/meta.t.payload
|
||||
+++ b/tests/py/inet/meta.t.payload
|
||||
@@ -173,3 +173,17 @@ inet test-inet input
|
||||
[ bitwise reg 1 = ( reg 1 & 0xffffffbf ) ^ 0x00000040 ]
|
||||
[ meta set mark with reg 1 ]
|
||||
|
||||
+# ip saddr . ether saddr . meta l4proto { 1.2.3.4 . aa:bb:cc:dd:ee:ff . 6 }
|
||||
+__set%d test-inet 3 size 1
|
||||
+__set%d test-inet 0
|
||||
+ element 04030201 ddccbbaa 0000ffee 00000006 : 0 [end]
|
||||
+inet test-inet input
|
||||
+ [ meta load nfproto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000002 ]
|
||||
+ [ meta load iiftype => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000001 ]
|
||||
+ [ payload load 4b @ network header + 12 => reg 1 ]
|
||||
+ [ payload load 6b @ link header + 6 => reg 9 ]
|
||||
+ [ meta load l4proto => reg 11 ]
|
||||
+ [ lookup reg 1 set __set%d ]
|
||||
+
|
||||
132
0071-netlink_delinearize-move-concat-and-value-postproces.patch
Normal file
132
0071-netlink_delinearize-move-concat-and-value-postproces.patch
Normal file
@ -0,0 +1,132 @@
|
||||
From 633d5e7cf14961687216422323b6476775e0086e Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] netlink_delinearize: move concat and value postprocessing to
|
||||
helpers
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 7ef933d16fd1b14afb276ab26f4114a2c9d6a3ea
|
||||
|
||||
commit 7ef933d16fd1b14afb276ab26f4114a2c9d6a3ea
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Fri Jan 19 13:47:08 2024 +0100
|
||||
|
||||
netlink_delinearize: move concat and value postprocessing to helpers
|
||||
|
||||
No functional changes intended.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/netlink_delinearize.c | 82 ++++++++++++++++++++++-----------------
|
||||
1 file changed, 47 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
|
||||
index e214510..27630a8 100644
|
||||
--- a/src/netlink_delinearize.c
|
||||
+++ b/src/netlink_delinearize.c
|
||||
@@ -2720,6 +2720,50 @@ static struct expr *expr_postprocess_string(struct expr *expr)
|
||||
return out;
|
||||
}
|
||||
|
||||
+static void expr_postprocess_value(struct rule_pp_ctx *ctx, struct expr **exprp)
|
||||
+{
|
||||
+ struct expr *expr = *exprp;
|
||||
+
|
||||
+ // FIXME
|
||||
+ if (expr->byteorder == BYTEORDER_HOST_ENDIAN)
|
||||
+ mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE);
|
||||
+
|
||||
+ if (expr_basetype(expr)->type == TYPE_STRING)
|
||||
+ *exprp = expr_postprocess_string(expr);
|
||||
+
|
||||
+ expr = *exprp;
|
||||
+ if (expr->dtype->basetype != NULL &&
|
||||
+ expr->dtype->basetype->type == TYPE_BITMASK)
|
||||
+ *exprp = bitmask_expr_to_binops(expr);
|
||||
+}
|
||||
+
|
||||
+static void expr_postprocess_concat(struct rule_pp_ctx *ctx, struct expr **exprp)
|
||||
+{
|
||||
+ struct expr *i, *n, *expr = *exprp;
|
||||
+ unsigned int type = expr->dtype->type, ntype = 0;
|
||||
+ int off = expr->dtype->subtypes;
|
||||
+ const struct datatype *dtype;
|
||||
+ LIST_HEAD(tmp);
|
||||
+
|
||||
+ assert(expr->etype == EXPR_CONCAT);
|
||||
+
|
||||
+ ctx->flags |= RULE_PP_IN_CONCATENATION;
|
||||
+ list_for_each_entry_safe(i, n, &expr->expressions, list) {
|
||||
+ if (type) {
|
||||
+ dtype = concat_subtype_lookup(type, --off);
|
||||
+ expr_set_type(i, dtype, dtype->byteorder);
|
||||
+ }
|
||||
+ list_del(&i->list);
|
||||
+ expr_postprocess(ctx, &i);
|
||||
+ list_add_tail(&i->list, &tmp);
|
||||
+
|
||||
+ ntype = concat_subtype_add(ntype, i->dtype->type);
|
||||
+ }
|
||||
+ ctx->flags &= ~RULE_PP_IN_CONCATENATION;
|
||||
+ list_splice(&tmp, &expr->expressions);
|
||||
+ __datatype_set(expr, concat_type_alloc(ntype));
|
||||
+}
|
||||
+
|
||||
static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
|
||||
{
|
||||
struct dl_proto_ctx *dl = dl_proto_ctx(ctx);
|
||||
@@ -2746,30 +2790,9 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
|
||||
list_for_each_entry(i, &expr->expressions, list)
|
||||
expr_postprocess(ctx, &i);
|
||||
break;
|
||||
- case EXPR_CONCAT: {
|
||||
- unsigned int type = expr->dtype->type, ntype = 0;
|
||||
- int off = expr->dtype->subtypes;
|
||||
- const struct datatype *dtype;
|
||||
- LIST_HEAD(tmp);
|
||||
- struct expr *n;
|
||||
-
|
||||
- ctx->flags |= RULE_PP_IN_CONCATENATION;
|
||||
- list_for_each_entry_safe(i, n, &expr->expressions, list) {
|
||||
- if (type) {
|
||||
- dtype = concat_subtype_lookup(type, --off);
|
||||
- expr_set_type(i, dtype, dtype->byteorder);
|
||||
- }
|
||||
- list_del(&i->list);
|
||||
- expr_postprocess(ctx, &i);
|
||||
- list_add_tail(&i->list, &tmp);
|
||||
-
|
||||
- ntype = concat_subtype_add(ntype, i->dtype->type);
|
||||
- }
|
||||
- ctx->flags &= ~RULE_PP_IN_CONCATENATION;
|
||||
- list_splice(&tmp, &expr->expressions);
|
||||
- __datatype_set(expr, concat_type_alloc(ntype));
|
||||
+ case EXPR_CONCAT:
|
||||
+ expr_postprocess_concat(ctx, exprp);
|
||||
break;
|
||||
- }
|
||||
case EXPR_UNARY:
|
||||
expr_postprocess(ctx, &expr->arg);
|
||||
expr_set_type(expr, expr->arg->dtype, !expr->arg->byteorder);
|
||||
@@ -2882,18 +2905,7 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
|
||||
payload_dependency_kill(&dl->pdctx, expr, dl->pctx.family);
|
||||
break;
|
||||
case EXPR_VALUE:
|
||||
- // FIXME
|
||||
- if (expr->byteorder == BYTEORDER_HOST_ENDIAN)
|
||||
- mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE);
|
||||
-
|
||||
- if (expr_basetype(expr)->type == TYPE_STRING)
|
||||
- *exprp = expr_postprocess_string(expr);
|
||||
-
|
||||
- expr = *exprp;
|
||||
- if (expr->dtype->basetype != NULL &&
|
||||
- expr->dtype->basetype->type == TYPE_BITMASK)
|
||||
- *exprp = bitmask_expr_to_binops(expr);
|
||||
-
|
||||
+ expr_postprocess_value(ctx, exprp);
|
||||
break;
|
||||
case EXPR_RANGE:
|
||||
expr_postprocess(ctx, &expr->left);
|
||||
@ -0,0 +1,50 @@
|
||||
From 7390323f695abb24d5886f671e4faccd8d44f1eb Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] expression: missing line in describe command with invalid
|
||||
expression
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 2b24dd29c5fa1c7e4cf44f0753752d25106273a0
|
||||
|
||||
commit 2b24dd29c5fa1c7e4cf44f0753752d25106273a0
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Feb 13 17:09:20 2024 +0100
|
||||
|
||||
expression: missing line in describe command with invalid expression
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/expression.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/expression.c b/src/expression.c
|
||||
index dde48b6..cb2573f 100644
|
||||
--- a/src/expression.c
|
||||
+++ b/src/expression.c
|
||||
@@ -140,8 +140,10 @@ void expr_describe(const struct expr *expr, struct output_ctx *octx)
|
||||
nft_print(octx, "%s expression, datatype %s (%s)",
|
||||
expr_name(expr), dtype->name, dtype->desc);
|
||||
|
||||
- if (dtype == &invalid_type)
|
||||
+ if (dtype == &invalid_type) {
|
||||
+ nft_print(octx, "\n");
|
||||
return;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (dtype->basetype != NULL) {
|
||||
137
0073-evaluate-permit-use-of-host-endian-constant-values-i.patch
Normal file
137
0073-evaluate-permit-use-of-host-endian-constant-values-i.patch
Normal file
@ -0,0 +1,137 @@
|
||||
From 20e6758f2cbf8c42e3c58ec10207b12c490c8fb9 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] evaluate: permit use of host-endian constant values in set
|
||||
lookup keys
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit c0080feb0d034913409944d23873cce4bf9edf9e
|
||||
|
||||
commit c0080feb0d034913409944d23873cce4bf9edf9e
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Mon Feb 12 16:46:29 2024 +0100
|
||||
|
||||
evaluate: permit use of host-endian constant values in set lookup keys
|
||||
|
||||
AFL found following crash:
|
||||
|
||||
table ip filter {
|
||||
map ipsec_in {
|
||||
typeof ipsec in reqid . iif : verdict
|
||||
flags interval
|
||||
}
|
||||
|
||||
chain INPUT {
|
||||
type filter hook input priority filter; policy drop;
|
||||
ipsec in reqid . 100 @ipsec_in
|
||||
}
|
||||
}
|
||||
|
||||
Which yields:
|
||||
nft: evaluate.c:1213: expr_evaluate_unary: Assertion `!expr_is_constant(arg)' failed.
|
||||
|
||||
All existing test cases with constant values use big endian values, but
|
||||
"iif" expects host endian values.
|
||||
|
||||
As raw values were not supported before, concat byteorder conversion
|
||||
doesn't handle constants.
|
||||
|
||||
Fix this:
|
||||
|
||||
1. Add constant handling so that the number is converted in-place,
|
||||
without unary expression.
|
||||
|
||||
2. Add the inverse handling on delinearization for non-interval set
|
||||
types.
|
||||
When dissecting the concat data soup, watch for integer constants where
|
||||
the datatype indicates host endian integer.
|
||||
|
||||
Last, extend an existing test case with the afl input to cover
|
||||
in/output.
|
||||
|
||||
A new test case is added to test linearization, delinearization and
|
||||
matching.
|
||||
|
||||
Based on original patch from Florian Westphal, patch subject and
|
||||
description wrote by him.
|
||||
|
||||
Fixes: b422b07ab2f9 ("src: permit use of constant values in set lookup keys")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
include/netlink.h | 1 +
|
||||
src/evaluate.c | 19 +++++++++++++------
|
||||
src/netlink_delinearize.c | 5 ++++-
|
||||
3 files changed, 18 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/include/netlink.h b/include/netlink.h
|
||||
index 6766d7e..2ce4b39 100644
|
||||
--- a/include/netlink.h
|
||||
+++ b/include/netlink.h
|
||||
@@ -61,6 +61,7 @@ struct rule_pp_ctx {
|
||||
struct dl_proto_ctx *dl;
|
||||
struct stmt *stmt;
|
||||
unsigned int flags;
|
||||
+ struct set *set;
|
||||
};
|
||||
|
||||
extern const struct input_descriptor indesc_netlink;
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index e64bc91..89656eb 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -194,13 +194,20 @@ static int byteorder_conversion(struct eval_ctx *ctx, struct expr **expr,
|
||||
|
||||
assert(basetype == TYPE_INTEGER);
|
||||
|
||||
- if (div_round_up(i->len, BITS_PER_BYTE) >= 2) {
|
||||
- op = byteorder_conversion_op(i, byteorder);
|
||||
- unary = unary_expr_alloc(&i->location, op, i);
|
||||
- if (expr_evaluate(ctx, &unary) < 0)
|
||||
- return -1;
|
||||
+ switch (i->etype) {
|
||||
+ case EXPR_VALUE:
|
||||
+ if (i->byteorder == BYTEORDER_HOST_ENDIAN)
|
||||
+ mpz_switch_byteorder(i->value, div_round_up(i->len, BITS_PER_BYTE));
|
||||
+ break;
|
||||
+ default:
|
||||
+ if (div_round_up(i->len, BITS_PER_BYTE) >= 2) {
|
||||
+ op = byteorder_conversion_op(i, byteorder);
|
||||
+ unary = unary_expr_alloc(&i->location, op, i);
|
||||
+ if (expr_evaluate(ctx, &unary) < 0)
|
||||
+ return -1;
|
||||
|
||||
- list_replace(&i->list, &unary->list);
|
||||
+ list_replace(&i->list, &unary->list);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
|
||||
index 27630a8..1d30a78 100644
|
||||
--- a/src/netlink_delinearize.c
|
||||
+++ b/src/netlink_delinearize.c
|
||||
@@ -2722,10 +2722,11 @@ static struct expr *expr_postprocess_string(struct expr *expr)
|
||||
|
||||
static void expr_postprocess_value(struct rule_pp_ctx *ctx, struct expr **exprp)
|
||||
{
|
||||
+ bool interval = (ctx->set && ctx->set->flags & NFT_SET_INTERVAL);
|
||||
struct expr *expr = *exprp;
|
||||
|
||||
// FIXME
|
||||
- if (expr->byteorder == BYTEORDER_HOST_ENDIAN)
|
||||
+ if (expr->byteorder == BYTEORDER_HOST_ENDIAN && !interval)
|
||||
mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE);
|
||||
|
||||
if (expr_basetype(expr)->type == TYPE_STRING)
|
||||
@@ -2869,7 +2870,9 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
|
||||
|
||||
datatype_set(expr->left, expr->right->dtype);
|
||||
}
|
||||
+ ctx->set = expr->right->set;
|
||||
expr_postprocess(ctx, &expr->left);
|
||||
+ ctx->set = NULL;
|
||||
break;
|
||||
default:
|
||||
expr_postprocess(ctx, &expr->left);
|
||||
179
0074-tests-shell-permit-use-of-host-endian-constant-value.patch
Normal file
179
0074-tests-shell-permit-use-of-host-endian-constant-value.patch
Normal file
@ -0,0 +1,179 @@
|
||||
From e5d1dce48ec1e1b4e0f0a4ec552ca6a5af207ddc Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] tests: shell: permit use of host-endian constant values in
|
||||
set lookup keys
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 40afa4bb2c7c7c8d488a8d44830c6b72cd98c640
|
||||
|
||||
commit 40afa4bb2c7c7c8d488a8d44830c6b72cd98c640
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Wed Feb 14 11:41:30 2024 +0100
|
||||
|
||||
tests: shell: permit use of host-endian constant values in set lookup keys
|
||||
|
||||
extend an existing test case with the afl input to cover in/output.
|
||||
|
||||
A new test case is added to test linearization, delinearization and
|
||||
matching
|
||||
|
||||
Fixes: c0080feb0d03 ("evaluate: permit use of host-endian constant values in set lookup keys")
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
.../packetpath/dumps/set_lookups.nft | 51 +++++++++++++++
|
||||
tests/shell/testcases/packetpath/set_lookups | 64 +++++++++++++++++++
|
||||
.../sets/dumps/typeof_sets_concat.nft | 11 ++++
|
||||
3 files changed, 126 insertions(+)
|
||||
create mode 100644 tests/shell/testcases/packetpath/dumps/set_lookups.nft
|
||||
create mode 100755 tests/shell/testcases/packetpath/set_lookups
|
||||
|
||||
diff --git a/tests/shell/testcases/packetpath/dumps/set_lookups.nft b/tests/shell/testcases/packetpath/dumps/set_lookups.nft
|
||||
new file mode 100644
|
||||
index 0000000..7566f55
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/packetpath/dumps/set_lookups.nft
|
||||
@@ -0,0 +1,51 @@
|
||||
+table ip t {
|
||||
+ set s {
|
||||
+ type ipv4_addr . iface_index
|
||||
+ flags interval
|
||||
+ elements = { 127.0.0.1 . "lo",
|
||||
+ 127.0.0.2 . "lo" }
|
||||
+ }
|
||||
+
|
||||
+ set s2 {
|
||||
+ typeof ip saddr . iif
|
||||
+ elements = { 127.0.0.1 . "lo",
|
||||
+ 127.0.0.2 . "lo" }
|
||||
+ }
|
||||
+
|
||||
+ set s3 {
|
||||
+ type iface_index
|
||||
+ elements = { "lo" }
|
||||
+ }
|
||||
+
|
||||
+ set s4 {
|
||||
+ type iface_index
|
||||
+ flags interval
|
||||
+ elements = { "lo" }
|
||||
+ }
|
||||
+
|
||||
+ set nomatch {
|
||||
+ typeof ip saddr . iif
|
||||
+ elements = { 127.0.0.3 . "lo" }
|
||||
+ }
|
||||
+
|
||||
+ set nomatch2 {
|
||||
+ type ipv4_addr . iface_index
|
||||
+ elements = { 127.0.0.2 . 90000 }
|
||||
+ }
|
||||
+
|
||||
+ chain c {
|
||||
+ type filter hook input priority filter; policy accept;
|
||||
+ icmp type echo-request ip saddr . iif @s counter packets 1 bytes 84
|
||||
+ icmp type echo-request ip saddr . "lo" @s counter packets 1 bytes 84
|
||||
+ icmp type echo-request ip saddr . "lo" @s counter packets 1 bytes 84
|
||||
+ icmp type echo-request ip saddr . iif @s2 counter packets 1 bytes 84
|
||||
+ icmp type echo-request ip saddr . "lo" @s2 counter packets 1 bytes 84
|
||||
+ icmp type echo-request ip saddr . "lo" @s2 counter packets 1 bytes 84
|
||||
+ icmp type echo-request ip daddr . "lo" @s counter packets 1 bytes 84
|
||||
+ icmp type echo-request ip daddr . "lo" @s2 counter packets 1 bytes 84
|
||||
+ icmp type echo-request iif @s3 counter packets 1 bytes 84
|
||||
+ icmp type echo-request iif @s4 counter packets 1 bytes 84
|
||||
+ ip daddr . "lo" @nomatch counter packets 0 bytes 0 drop
|
||||
+ ip daddr . iif @nomatch2 counter packets 0 bytes 0 drop
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/packetpath/set_lookups b/tests/shell/testcases/packetpath/set_lookups
|
||||
new file mode 100755
|
||||
index 0000000..84a0000
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/packetpath/set_lookups
|
||||
@@ -0,0 +1,64 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+set -e
|
||||
+
|
||||
+$NFT -f /dev/stdin <<"EOF"
|
||||
+table ip t {
|
||||
+ set s {
|
||||
+ type ipv4_addr . iface_index
|
||||
+ flags interval
|
||||
+ elements = { 127.0.0.1 . 1 }
|
||||
+ }
|
||||
+
|
||||
+ set s2 {
|
||||
+ typeof ip saddr . meta iif
|
||||
+ elements = { 127.0.0.1 . 1 }
|
||||
+ }
|
||||
+
|
||||
+ set s3 {
|
||||
+ type iface_index
|
||||
+ elements = { "lo" }
|
||||
+ }
|
||||
+
|
||||
+ set s4 {
|
||||
+ type iface_index
|
||||
+ flags interval
|
||||
+ elements = { "lo" }
|
||||
+ }
|
||||
+
|
||||
+ set nomatch {
|
||||
+ typeof ip saddr . meta iif
|
||||
+ elements = { 127.0.0.3 . 1 }
|
||||
+ }
|
||||
+
|
||||
+ set nomatch2 {
|
||||
+ type ipv4_addr . iface_index
|
||||
+ elements = { 127.0.0.2 . 90000 }
|
||||
+ }
|
||||
+
|
||||
+ chain c {
|
||||
+ type filter hook input priority filter;
|
||||
+ icmp type echo-request ip saddr . meta iif @s counter
|
||||
+ icmp type echo-request ip saddr . 1 @s counter
|
||||
+ icmp type echo-request ip saddr . "lo" @s counter
|
||||
+ icmp type echo-request ip saddr . meta iif @s2 counter
|
||||
+ icmp type echo-request ip saddr . 1 @s2 counter
|
||||
+ icmp type echo-request ip saddr . "lo" @s2 counter
|
||||
+
|
||||
+ icmp type echo-request ip daddr . "lo" @s counter
|
||||
+ icmp type echo-request ip daddr . "lo" @s2 counter
|
||||
+
|
||||
+ icmp type echo-request meta iif @s3 counter
|
||||
+ icmp type echo-request meta iif @s4 counter
|
||||
+
|
||||
+ ip daddr . 1 @nomatch counter drop
|
||||
+ ip daddr . meta iif @nomatch2 counter drop
|
||||
+ }
|
||||
+}
|
||||
+EOF
|
||||
+
|
||||
+$NFT add element t s { 127.0.0.2 . 1 }
|
||||
+$NFT add element t s2 { 127.0.0.2 . "lo" }
|
||||
+
|
||||
+ip link set lo up
|
||||
+ping -q -c 1 127.0.0.2 > /dev/null
|
||||
diff --git a/tests/shell/testcases/sets/dumps/typeof_sets_concat.nft b/tests/shell/testcases/sets/dumps/typeof_sets_concat.nft
|
||||
index dbaf7cd..348b584 100644
|
||||
--- a/tests/shell/testcases/sets/dumps/typeof_sets_concat.nft
|
||||
+++ b/tests/shell/testcases/sets/dumps/typeof_sets_concat.nft
|
||||
@@ -10,3 +10,14 @@ table netdev t {
|
||||
ether type != 8021q update @s { ether daddr . 123 timeout 1m } counter packets 0 bytes 0 return
|
||||
}
|
||||
}
|
||||
+table ip t {
|
||||
+ set s {
|
||||
+ typeof ipsec in reqid . iif
|
||||
+ size 16
|
||||
+ flags interval
|
||||
+ }
|
||||
+
|
||||
+ chain c2 {
|
||||
+ ipsec in reqid . "lo" @s
|
||||
+ }
|
||||
+}
|
||||
53
0075-src-improve-error-reporting-for-destroy-command.patch
Normal file
53
0075-src-improve-error-reporting-for-destroy-command.patch
Normal file
@ -0,0 +1,53 @@
|
||||
From 1a81b2faa37e30603561d4b10ac007dc29e509b1 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] src: improve error reporting for destroy command
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit f27f032b8da584d4447dc03b3ccd3370433e2c0f
|
||||
|
||||
commit f27f032b8da584d4447dc03b3ccd3370433e2c0f
|
||||
Author: 谢致邦 (XIE Zhibang) <Yeking@Red54.com>
|
||||
Date: Wed Feb 21 15:17:09 2024 +0000
|
||||
|
||||
src: improve error reporting for destroy command
|
||||
|
||||
Example for older kernels (<6.3):
|
||||
nft destroy table ip missingtable
|
||||
|
||||
Before:
|
||||
Error: Could not process rule: Invalid argument
|
||||
|
||||
After:
|
||||
Error: "destroy" command is not supported, perhaps kernel support is
|
||||
missing?
|
||||
|
||||
Fixes: e1dfd5cc4c46 ("src: add support to command "destroy"")
|
||||
Signed-off-by: 谢致邦 (XIE Zhibang) <Yeking@Red54.com>
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/cmd.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/src/cmd.c b/src/cmd.c
|
||||
index 68c476c..21533e0 100644
|
||||
--- a/src/cmd.c
|
||||
+++ b/src/cmd.c
|
||||
@@ -311,6 +311,12 @@ void nft_cmd_error(struct netlink_ctx *ctx, struct cmd *cmd,
|
||||
break;
|
||||
}
|
||||
|
||||
+ if (cmd->op == CMD_DESTROY && err->err == EINVAL) {
|
||||
+ netlink_io_error(ctx, loc,
|
||||
+ "\"destroy\" command is not supported, perhaps kernel support is missing?");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
netlink_io_error(ctx, loc, "Could not process rule: %s",
|
||||
strerror(err->err));
|
||||
}
|
||||
92
0076-parser-compact-interval-typeof-rules.patch
Normal file
92
0076-parser-compact-interval-typeof-rules.patch
Normal file
@ -0,0 +1,92 @@
|
||||
From c9d37a13faaa05ee0d260b3828bc25e612ffae20 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] parser: compact interval typeof rules
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 81fc7aee0d523d61077518534036ff10beddb3e9
|
||||
|
||||
commit 81fc7aee0d523d61077518534036ff10beddb3e9
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Tue Feb 27 15:50:05 2024 +0100
|
||||
|
||||
parser: compact interval typeof rules
|
||||
|
||||
There are two nearly identical blocks for typeof maps:
|
||||
one with INTERVAL keyword present and one without.
|
||||
|
||||
Compact this into a single block.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_bison.y | 34 ++++++++++++++--------------------
|
||||
1 file changed, 14 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index e81336f..82aac8d 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -812,8 +812,8 @@ int nft_lex(void *, void *, void *);
|
||||
|
||||
%type <expr> symbol_expr verdict_expr integer_expr variable_expr chain_expr policy_expr
|
||||
%destructor { expr_free($$); } symbol_expr verdict_expr integer_expr variable_expr chain_expr policy_expr
|
||||
-%type <expr> primary_expr shift_expr and_expr typeof_expr typeof_data_expr
|
||||
-%destructor { expr_free($$); } primary_expr shift_expr and_expr typeof_expr typeof_data_expr
|
||||
+%type <expr> primary_expr shift_expr and_expr typeof_expr typeof_data_expr typeof_verdict_expr
|
||||
+%destructor { expr_free($$); } primary_expr shift_expr and_expr typeof_expr typeof_data_expr typeof_verdict_expr
|
||||
%type <expr> exclusive_or_expr inclusive_or_expr
|
||||
%destructor { expr_free($$); } exclusive_or_expr inclusive_or_expr
|
||||
%type <expr> basic_expr
|
||||
@@ -2115,7 +2115,7 @@ subchain_block : /* empty */ { $$ = $<chain>-1; }
|
||||
}
|
||||
;
|
||||
|
||||
-typeof_data_expr : primary_expr
|
||||
+typeof_verdict_expr : primary_expr
|
||||
{
|
||||
struct expr *e = $1;
|
||||
|
||||
@@ -2147,6 +2147,17 @@ typeof_data_expr : primary_expr
|
||||
}
|
||||
;
|
||||
|
||||
+typeof_data_expr : INTERVAL typeof_expr
|
||||
+ {
|
||||
+ $2->flags |= EXPR_F_INTERVAL;
|
||||
+ $$ = $2;
|
||||
+ }
|
||||
+ | typeof_verdict_expr
|
||||
+ {
|
||||
+ $$ = $1;
|
||||
+ }
|
||||
+ ;
|
||||
+
|
||||
typeof_expr : primary_expr
|
||||
{
|
||||
if (expr_ops($1)->build_udata == NULL) {
|
||||
@@ -2326,23 +2337,6 @@ map_block : /* empty */ { $$ = $<set>-1; }
|
||||
$1->flags |= NFT_SET_MAP;
|
||||
$$ = $1;
|
||||
}
|
||||
- | map_block TYPEOF
|
||||
- typeof_expr COLON INTERVAL typeof_expr
|
||||
- stmt_separator
|
||||
- {
|
||||
- if (already_set($1->key, &@2, state)) {
|
||||
- expr_free($3);
|
||||
- expr_free($6);
|
||||
- YYERROR;
|
||||
- }
|
||||
-
|
||||
- $1->key = $3;
|
||||
- $1->data = $6;
|
||||
- $1->data->flags |= EXPR_F_INTERVAL;
|
||||
-
|
||||
- $1->flags |= NFT_SET_MAP;
|
||||
- $$ = $1;
|
||||
- }
|
||||
| map_block TYPE
|
||||
data_type_expr COLON map_block_obj_type
|
||||
stmt_separator close_scope_type
|
||||
78
0077-parser-compact-type-typeof-set-rules.patch
Normal file
78
0077-parser-compact-type-typeof-set-rules.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From 6bc395ed503556ef05e3db62926226afd6b036a9 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] parser: compact type/typeof set rules
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit fb98cb91c575880617e5da2cb6f094525516cb78
|
||||
|
||||
commit fb98cb91c575880617e5da2cb6f094525516cb78
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Tue Feb 27 15:53:19 2024 +0100
|
||||
|
||||
parser: compact type/typeof set rules
|
||||
|
||||
Set/maps keys can be declared either by 'type' or 'typeof' keyword.
|
||||
|
||||
Compact this to use a common block for both cases.
|
||||
|
||||
The datatype_set call is redundant, remove it:
|
||||
at this point $3 == $1->key, so this is a no-op.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_bison.y | 24 +++++++++---------------
|
||||
1 file changed, 9 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 82aac8d..23b64ce 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -812,8 +812,8 @@ int nft_lex(void *, void *, void *);
|
||||
|
||||
%type <expr> symbol_expr verdict_expr integer_expr variable_expr chain_expr policy_expr
|
||||
%destructor { expr_free($$); } symbol_expr verdict_expr integer_expr variable_expr chain_expr policy_expr
|
||||
-%type <expr> primary_expr shift_expr and_expr typeof_expr typeof_data_expr typeof_verdict_expr
|
||||
-%destructor { expr_free($$); } primary_expr shift_expr and_expr typeof_expr typeof_data_expr typeof_verdict_expr
|
||||
+%type <expr> primary_expr shift_expr and_expr typeof_expr typeof_data_expr typeof_key_expr typeof_verdict_expr
|
||||
+%destructor { expr_free($$); } primary_expr shift_expr and_expr typeof_expr typeof_data_expr typeof_key_expr typeof_verdict_expr
|
||||
%type <expr> exclusive_or_expr inclusive_or_expr
|
||||
%destructor { expr_free($$); } exclusive_or_expr inclusive_or_expr
|
||||
%type <expr> basic_expr
|
||||
@@ -2187,27 +2187,21 @@ set_block_alloc : /* empty */
|
||||
}
|
||||
;
|
||||
|
||||
+typeof_key_expr : TYPEOF typeof_expr { $$ = $2; }
|
||||
+ | TYPE data_type_expr close_scope_type { $$ = $2; }
|
||||
+ ;
|
||||
+
|
||||
set_block : /* empty */ { $$ = $<set>-1; }
|
||||
| set_block common_block
|
||||
| set_block stmt_separator
|
||||
- | set_block TYPE data_type_expr stmt_separator close_scope_type
|
||||
+ | set_block typeof_key_expr stmt_separator
|
||||
{
|
||||
if (already_set($1->key, &@2, state)) {
|
||||
- expr_free($3);
|
||||
+ expr_free($2);
|
||||
YYERROR;
|
||||
}
|
||||
|
||||
- $1->key = $3;
|
||||
- $$ = $1;
|
||||
- }
|
||||
- | set_block TYPEOF typeof_expr stmt_separator
|
||||
- {
|
||||
- if (already_set($1->key, &@2, state)) {
|
||||
- expr_free($3);
|
||||
- YYERROR;
|
||||
- }
|
||||
- $1->key = $3;
|
||||
- datatype_set($1->key, $3->dtype);
|
||||
+ $1->key = $2;
|
||||
$$ = $1;
|
||||
}
|
||||
| set_block FLAGS set_flag_list stmt_separator
|
||||
@ -0,0 +1,82 @@
|
||||
From cbd3c93551dab7359fa72f4a8140032f72a00262 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] rule: fix ASAN errors in chain priority to textual names
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit ff6135270616ccf4712990246cae850e64253516
|
||||
|
||||
commit ff6135270616ccf4712990246cae850e64253516
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Thu Feb 29 16:50:37 2024 +0100
|
||||
|
||||
rule: fix ASAN errors in chain priority to textual names
|
||||
|
||||
ASAN reports several errors when listing this ruleset:
|
||||
|
||||
table ip x {
|
||||
chain y {
|
||||
type filter hook input priority -2147483648; policy accept;
|
||||
}
|
||||
}
|
||||
|
||||
src/rule.c:1002:8: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself
|
||||
src/rule.c:1001:11: runtime error: signed integer overflow: -2147483648 - 50 cannot be represented in type 'int'
|
||||
|
||||
Use int64_t for the offset to avoid an underflow when calculating
|
||||
closest existing priority definition.
|
||||
|
||||
Use llabs() because abs() is undefined with INT32_MIN.
|
||||
|
||||
Fixes: c8a0e8c90e2d ("src: Set/print standard chain prios with textual names")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/rule.c | 15 +++++++++------
|
||||
1 file changed, 9 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/rule.c b/src/rule.c
|
||||
index e2d972c..85718c7 100644
|
||||
--- a/src/rule.c
|
||||
+++ b/src/rule.c
|
||||
@@ -977,10 +977,11 @@ static const char *prio2str(const struct output_ctx *octx,
|
||||
const struct expr *expr)
|
||||
{
|
||||
const struct prio_tag *prio_arr;
|
||||
- int std_prio, offset, prio;
|
||||
+ const uint32_t reach = 10;
|
||||
const char *std_prio_str;
|
||||
- const int reach = 10;
|
||||
+ int std_prio, prio;
|
||||
size_t i, arr_size;
|
||||
+ int64_t offset;
|
||||
|
||||
mpz_export_data(&prio, expr->value, BYTEORDER_HOST_ENDIAN, sizeof(int));
|
||||
if (family == NFPROTO_BRIDGE) {
|
||||
@@ -995,19 +996,21 @@ static const char *prio2str(const struct output_ctx *octx,
|
||||
for (i = 0; i < arr_size; ++i) {
|
||||
std_prio = prio_arr[i].val;
|
||||
std_prio_str = prio_arr[i].str;
|
||||
- if (abs(prio - std_prio) <= reach) {
|
||||
+
|
||||
+ offset = (int64_t)prio - std_prio;
|
||||
+ if (llabs(offset) <= reach) {
|
||||
if (!std_prio_family_hook_compat(std_prio,
|
||||
family, hook))
|
||||
break;
|
||||
- offset = prio - std_prio;
|
||||
+
|
||||
strncpy(buf, std_prio_str, bufsize);
|
||||
if (offset > 0)
|
||||
snprintf(buf + strlen(buf),
|
||||
- bufsize - strlen(buf), " + %d",
|
||||
+ bufsize - strlen(buf), " + %" PRIu64,
|
||||
offset);
|
||||
else if (offset < 0)
|
||||
snprintf(buf + strlen(buf),
|
||||
- bufsize - strlen(buf), " - %d",
|
||||
+ bufsize - strlen(buf), " - %" PRIu64,
|
||||
-offset);
|
||||
return buf;
|
||||
}
|
||||
40
0079-nftables-do-mot-merge-payloads-on-negation.patch
Normal file
40
0079-nftables-do-mot-merge-payloads-on-negation.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From b146a3efdff7e834790e3ee8b605e5e7033fb8c9 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] nftables: do mot merge payloads on negation
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit f35a0d78fe870737fa39d859bd2e3ac25bf1b12e
|
||||
|
||||
commit f35a0d78fe870737fa39d859bd2e3ac25bf1b12e
|
||||
Author: Sriram Rajagopalan <bglsriram@gmail.com>
|
||||
Date: Wed Mar 13 01:32:42 2024 -0700
|
||||
|
||||
nftables: do mot merge payloads on negation
|
||||
|
||||
else, a rule like
|
||||
tcp sport != 22 tcp dport != 23
|
||||
|
||||
will match even if the destination is 23 as long as sport is != 22.
|
||||
(or vice versa).
|
||||
|
||||
Signed-off-by: Sriram Rajagopalan <sriramr@arista.com>
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/rule.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/src/rule.c b/src/rule.c
|
||||
index 85718c7..89101f9 100644
|
||||
--- a/src/rule.c
|
||||
+++ b/src/rule.c
|
||||
@@ -2778,7 +2778,6 @@ static void stmt_reduce(const struct rule *rule)
|
||||
switch (stmt->expr->op) {
|
||||
case OP_EQ:
|
||||
case OP_IMPLICIT:
|
||||
- case OP_NEQ:
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
337
0080-tests-py-add-payload-merging-test-cases.patch
Normal file
337
0080-tests-py-add-payload-merging-test-cases.patch
Normal file
@ -0,0 +1,337 @@
|
||||
From a2ec860212bf27ca45a5c9ec55b91b3eb1c8060f Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] tests: py: add payload merging test cases
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 04fc306359a49bc9f314ae82520218f5dfebfef1
|
||||
|
||||
commit 04fc306359a49bc9f314ae82520218f5dfebfef1
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Fri Mar 8 14:40:12 2024 +0100
|
||||
|
||||
tests: py: add payload merging test cases
|
||||
|
||||
Add a test case that would fail without preceeding fix.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
tests/py/inet/payloadmerge.t | 14 ++
|
||||
tests/py/inet/payloadmerge.t.json | 211 +++++++++++++++++++++++++++
|
||||
tests/py/inet/payloadmerge.t.payload | 66 +++++++++
|
||||
3 files changed, 291 insertions(+)
|
||||
create mode 100644 tests/py/inet/payloadmerge.t
|
||||
create mode 100644 tests/py/inet/payloadmerge.t.json
|
||||
create mode 100644 tests/py/inet/payloadmerge.t.payload
|
||||
|
||||
diff --git a/tests/py/inet/payloadmerge.t b/tests/py/inet/payloadmerge.t
|
||||
new file mode 100644
|
||||
index 0000000..04ba1ce
|
||||
--- /dev/null
|
||||
+++ b/tests/py/inet/payloadmerge.t
|
||||
@@ -0,0 +1,14 @@
|
||||
+:input;type filter hook input priority 0
|
||||
+
|
||||
+*ip;test-ip4;input
|
||||
+*ip6;test-ip6;input
|
||||
+*inet;test-inet;input
|
||||
+
|
||||
+tcp sport 1 tcp dport 2;ok
|
||||
+tcp sport != 1 tcp dport != 2;ok
|
||||
+tcp sport 1 tcp dport != 2;ok
|
||||
+tcp sport != 1 tcp dport 2;ok
|
||||
+meta l4proto != 6 th dport 2;ok
|
||||
+meta l4proto 6 tcp dport 22;ok;tcp dport 22
|
||||
+tcp sport > 1 tcp dport > 2;ok
|
||||
+tcp sport 1 tcp dport > 2;ok
|
||||
diff --git a/tests/py/inet/payloadmerge.t.json b/tests/py/inet/payloadmerge.t.json
|
||||
new file mode 100644
|
||||
index 0000000..e5b66cf
|
||||
--- /dev/null
|
||||
+++ b/tests/py/inet/payloadmerge.t.json
|
||||
@@ -0,0 +1,211 @@
|
||||
+# tcp sport 1 tcp dport 2
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "sport",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": 1
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "dport",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": 2
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# tcp sport != 1 tcp dport != 2
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "sport",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "!=",
|
||||
+ "right": 1
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "dport",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "!=",
|
||||
+ "right": 2
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# tcp sport 1 tcp dport != 2
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "sport",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": 1
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "dport",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "!=",
|
||||
+ "right": 2
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# tcp sport != 1 tcp dport 2
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "sport",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "!=",
|
||||
+ "right": 1
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "dport",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": 2
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# meta l4proto != 6 th dport 2
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "meta": {
|
||||
+ "key": "l4proto"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "!=",
|
||||
+ "right": 6
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "dport",
|
||||
+ "protocol": "th"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": 2
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# meta l4proto 6 tcp dport 22
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "dport",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": 22
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# tcp sport > 1 tcp dport > 2
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "sport",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": ">",
|
||||
+ "right": 1
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "dport",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": ">",
|
||||
+ "right": 2
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# tcp sport 1 tcp dport > 2
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "sport",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": 1
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "payload": {
|
||||
+ "field": "dport",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ "op": ">",
|
||||
+ "right": 2
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
diff --git a/tests/py/inet/payloadmerge.t.payload b/tests/py/inet/payloadmerge.t.payload
|
||||
new file mode 100644
|
||||
index 0000000..a0465cd
|
||||
--- /dev/null
|
||||
+++ b/tests/py/inet/payloadmerge.t.payload
|
||||
@@ -0,0 +1,66 @@
|
||||
+# tcp sport 1 tcp dport 2
|
||||
+ip test-ip4 input
|
||||
+ [ meta load l4proto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 4b @ transport header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x02000100 ]
|
||||
+
|
||||
+# tcp sport != 1 tcp dport != 2
|
||||
+ip test-ip4 input
|
||||
+ [ meta load l4proto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 2b @ transport header + 0 => reg 1 ]
|
||||
+ [ cmp neq reg 1 0x00000100 ]
|
||||
+ [ payload load 2b @ transport header + 2 => reg 1 ]
|
||||
+ [ cmp neq reg 1 0x00000200 ]
|
||||
+
|
||||
+# tcp sport 1 tcp dport != 2
|
||||
+ip test-ip4 input
|
||||
+ [ meta load l4proto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 2b @ transport header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 2b @ transport header + 2 => reg 1 ]
|
||||
+ [ cmp neq reg 1 0x00000200 ]
|
||||
+
|
||||
+# tcp sport != 1 tcp dport 2
|
||||
+ip test-ip4 input
|
||||
+ [ meta load l4proto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 2b @ transport header + 0 => reg 1 ]
|
||||
+ [ cmp neq reg 1 0x00000100 ]
|
||||
+ [ payload load 2b @ transport header + 2 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000200 ]
|
||||
+
|
||||
+# meta l4proto != 6 th dport 2
|
||||
+ip test-ip4 input
|
||||
+ [ meta load l4proto => reg 1 ]
|
||||
+ [ cmp neq reg 1 0x00000006 ]
|
||||
+ [ payload load 2b @ transport header + 2 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000200 ]
|
||||
+
|
||||
+# meta l4proto 6 tcp dport 22
|
||||
+ip test-ip4 input
|
||||
+ [ meta load l4proto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 2b @ transport header + 2 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00001600 ]
|
||||
+
|
||||
+# tcp sport > 1 tcp dport > 2
|
||||
+ip test-ip4 input
|
||||
+ [ meta load l4proto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 2b @ transport header + 0 => reg 1 ]
|
||||
+ [ cmp gt reg 1 0x00000100 ]
|
||||
+ [ payload load 2b @ transport header + 2 => reg 1 ]
|
||||
+ [ cmp gt reg 1 0x00000200 ]
|
||||
+
|
||||
+# tcp sport 1 tcp dport > 2
|
||||
+ip test-ip4 input
|
||||
+ [ meta load l4proto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 2b @ transport header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 2b @ transport header + 2 => reg 1 ]
|
||||
+ [ cmp gt reg 1 0x00000200 ]
|
||||
+
|
||||
65
0081-parser-json-Support-for-synproxy-objects.patch
Normal file
65
0081-parser-json-Support-for-synproxy-objects.patch
Normal file
@ -0,0 +1,65 @@
|
||||
From 215992d2a9c837410eb84bad86307d303d4cd103 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] parser: json: Support for synproxy objects
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 938a135f2200766661e42a20e02d87555f5bacfa
|
||||
|
||||
commit 938a135f2200766661e42a20e02d87555f5bacfa
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Sat Mar 9 00:29:36 2024 +0100
|
||||
|
||||
parser: json: Support for synproxy objects
|
||||
|
||||
Parsing code was there already, merely the entry in json_parse_cmd_add()
|
||||
missing.
|
||||
|
||||
To support maps with synproxy target, an entry in string_to_nft_object()
|
||||
is required. While being at it, add other missing entries as well.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_json.c | 17 +++++++++++------
|
||||
1 file changed, 11 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/parser_json.c b/src/parser_json.c
|
||||
index 9537c9d..b8ed848 100644
|
||||
--- a/src/parser_json.c
|
||||
+++ b/src/parser_json.c
|
||||
@@ -3255,14 +3255,18 @@ err_free_rule:
|
||||
static int string_to_nft_object(const char *str)
|
||||
{
|
||||
const char *obj_tbl[__NFT_OBJECT_MAX] = {
|
||||
- [NFT_OBJECT_COUNTER] = "counter",
|
||||
- [NFT_OBJECT_QUOTA] = "quota",
|
||||
- [NFT_OBJECT_LIMIT] = "limit",
|
||||
- [NFT_OBJECT_SECMARK] = "secmark",
|
||||
+ [NFT_OBJECT_COUNTER] = "counter",
|
||||
+ [NFT_OBJECT_QUOTA] = "quota",
|
||||
+ [NFT_OBJECT_CT_HELPER] = "ct helper",
|
||||
+ [NFT_OBJECT_LIMIT] = "limit",
|
||||
+ [NFT_OBJECT_CT_TIMEOUT] = "ct timeout",
|
||||
+ [NFT_OBJECT_SECMARK] = "secmark",
|
||||
+ [NFT_OBJECT_CT_EXPECT] = "ct expectation",
|
||||
+ [NFT_OBJECT_SYNPROXY] = "synproxy",
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
- for (i = 0; i < NFT_OBJECT_MAX; i++) {
|
||||
+ for (i = 0; i <= NFT_OBJECT_MAX; i++) {
|
||||
if (obj_tbl[i] && !strcmp(str, obj_tbl[i]))
|
||||
return i;
|
||||
}
|
||||
@@ -3789,7 +3793,8 @@ static struct cmd *json_parse_cmd_add(struct json_ctx *ctx,
|
||||
{ "ct timeout", NFT_OBJECT_CT_TIMEOUT, json_parse_cmd_add_object },
|
||||
{ "ct expectation", NFT_OBJECT_CT_EXPECT, json_parse_cmd_add_object },
|
||||
{ "limit", CMD_OBJ_LIMIT, json_parse_cmd_add_object },
|
||||
- { "secmark", CMD_OBJ_SECMARK, json_parse_cmd_add_object }
|
||||
+ { "secmark", CMD_OBJ_SECMARK, json_parse_cmd_add_object },
|
||||
+ { "synproxy", CMD_OBJ_SYNPROXY, json_parse_cmd_add_object }
|
||||
};
|
||||
unsigned int i;
|
||||
json_t *tmp;
|
||||
@ -0,0 +1,40 @@
|
||||
From 86c010da124c480215b3a69fd08d3081b08862b1 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] doc: libnftables-json: Drop invalid ops from match expression
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 840cb6df16973139a1981fcec276f59d3b92bb46
|
||||
|
||||
commit 840cb6df16973139a1981fcec276f59d3b92bb46
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri Sep 22 18:43:11 2023 +0200
|
||||
|
||||
doc: libnftables-json: Drop invalid ops from match expression
|
||||
|
||||
These make no sense there and are listed again in BINARY OPERATION.
|
||||
|
||||
Fixes: 872f373dc50f7 ("doc: Add JSON schema documentation")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
doc/libnftables-json.adoc | 5 -----
|
||||
1 file changed, 5 deletions(-)
|
||||
|
||||
diff --git a/doc/libnftables-json.adoc b/doc/libnftables-json.adoc
|
||||
index 3bbb6cd..cc70f0f 100644
|
||||
--- a/doc/libnftables-json.adoc
|
||||
+++ b/doc/libnftables-json.adoc
|
||||
@@ -695,11 +695,6 @@ processing continues with the next rule in the same chain.
|
||||
==== OPERATORS
|
||||
|
||||
[horizontal]
|
||||
-*&*:: Binary AND
|
||||
-*|*:: Binary OR
|
||||
-*^*:: Binary XOR
|
||||
-*<<*:: Left shift
|
||||
-*>>*:: Right shift
|
||||
*==*:: Equal
|
||||
*!=*:: Not equal
|
||||
*<*:: Less than
|
||||
604
0083-netlink_delinearize-restore-binop-syntax-when-listin.patch
Normal file
604
0083-netlink_delinearize-restore-binop-syntax-when-listin.patch
Normal file
@ -0,0 +1,604 @@
|
||||
From 86c0cc20f38f8503ea670f8be664278c24f9edcf Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:42 +0200
|
||||
Subject: [PATCH] netlink_delinearize: restore binop syntax when listing
|
||||
ruleset for flags
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit b11b6c68e61ea294eb4c313705ccfe3e7b0eda87
|
||||
|
||||
commit b11b6c68e61ea294eb4c313705ccfe3e7b0eda87
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Mon Mar 18 13:10:55 2024 +0100
|
||||
|
||||
netlink_delinearize: restore binop syntax when listing ruleset for flags
|
||||
|
||||
c3d57114f119 ("parser_bison: add shortcut syntax for matching flags
|
||||
without binary operations") provides a similar syntax to iptables using
|
||||
a prefix representation for flag matching.
|
||||
|
||||
Restore original representation using binop when listing the ruleset.
|
||||
The parser still accepts the prefix notation for backward compatibility.
|
||||
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/netlink_delinearize.c | 65 ++--
|
||||
tests/py/inet/tcp.t | 16 +-
|
||||
tests/py/inet/tcp.t.json | 42 ++-
|
||||
tests/py/inet/tcp.t.json.output | 279 ++++++++++++++++++
|
||||
tests/py/inet/tcp.t.payload | 6 +-
|
||||
.../testcases/nft-f/dumps/sample-ruleset.nft | 4 +-
|
||||
tests/shell/testcases/packetpath/tcp_options | 16 +-
|
||||
7 files changed, 346 insertions(+), 82 deletions(-)
|
||||
|
||||
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
|
||||
index 1d30a78..405a065 100644
|
||||
--- a/src/netlink_delinearize.c
|
||||
+++ b/src/netlink_delinearize.c
|
||||
@@ -2517,56 +2517,29 @@ static void relational_binop_postprocess(struct rule_pp_ctx *ctx,
|
||||
|
||||
if (binop->op == OP_AND && (expr->op == OP_NEQ || expr->op == OP_EQ) &&
|
||||
right->dtype->basetype &&
|
||||
- right->dtype->basetype->type == TYPE_BITMASK) {
|
||||
- switch (right->etype) {
|
||||
- case EXPR_VALUE:
|
||||
- if (!mpz_cmp_ui(right->value, 0)) {
|
||||
- /* Flag comparison: data & flags != 0
|
||||
- *
|
||||
- * Split the flags into a list of flag values and convert the
|
||||
- * op to OP_EQ.
|
||||
- */
|
||||
- expr_free(right);
|
||||
-
|
||||
- expr->left = expr_get(binop->left);
|
||||
- expr->right = binop_tree_to_list(NULL, binop->right);
|
||||
- switch (expr->op) {
|
||||
- case OP_NEQ:
|
||||
- expr->op = OP_IMPLICIT;
|
||||
- break;
|
||||
- case OP_EQ:
|
||||
- expr->op = OP_NEG;
|
||||
- break;
|
||||
- default:
|
||||
- BUG("unknown operation type %d\n", expr->op);
|
||||
- }
|
||||
- expr_free(binop);
|
||||
- } else if (binop->right->etype == EXPR_VALUE &&
|
||||
- right->etype == EXPR_VALUE &&
|
||||
- !mpz_cmp(right->value, binop->right->value)) {
|
||||
- /* Skip flag / flag representation for:
|
||||
- * data & flag == flag
|
||||
- * data & flag != flag
|
||||
- */
|
||||
- ;
|
||||
- } else {
|
||||
- *exprp = flagcmp_expr_alloc(&expr->location, expr->op,
|
||||
- expr_get(binop->left),
|
||||
- binop_tree_to_list(NULL, binop->right),
|
||||
- expr_get(right));
|
||||
- expr_free(expr);
|
||||
- }
|
||||
+ right->dtype->basetype->type == TYPE_BITMASK &&
|
||||
+ right->etype == EXPR_VALUE &&
|
||||
+ !mpz_cmp_ui(right->value, 0)) {
|
||||
+ /* Flag comparison: data & flags != 0
|
||||
+ *
|
||||
+ * Split the flags into a list of flag values and convert the
|
||||
+ * op to OP_EQ.
|
||||
+ */
|
||||
+ expr_free(right);
|
||||
+
|
||||
+ expr->left = expr_get(binop->left);
|
||||
+ expr->right = binop_tree_to_list(NULL, binop->right);
|
||||
+ switch (expr->op) {
|
||||
+ case OP_NEQ:
|
||||
+ expr->op = OP_IMPLICIT;
|
||||
break;
|
||||
- case EXPR_BINOP:
|
||||
- *exprp = flagcmp_expr_alloc(&expr->location, expr->op,
|
||||
- expr_get(binop->left),
|
||||
- binop_tree_to_list(NULL, binop->right),
|
||||
- binop_tree_to_list(NULL, right));
|
||||
- expr_free(expr);
|
||||
+ case OP_EQ:
|
||||
+ expr->op = OP_NEG;
|
||||
break;
|
||||
default:
|
||||
- break;
|
||||
+ BUG("unknown operation type %d\n", expr->op);
|
||||
}
|
||||
+ expr_free(binop);
|
||||
} else if (binop->left->dtype->flags & DTYPE_F_PREFIX &&
|
||||
binop->op == OP_AND && expr->right->etype == EXPR_VALUE &&
|
||||
expr_mask_is_prefix(binop->right)) {
|
||||
diff --git a/tests/py/inet/tcp.t b/tests/py/inet/tcp.t
|
||||
index f51ebd3..f4bdac1 100644
|
||||
--- a/tests/py/inet/tcp.t
|
||||
+++ b/tests/py/inet/tcp.t
|
||||
@@ -68,8 +68,8 @@ tcp flags != { fin, urg, ecn, cwr} drop;ok
|
||||
tcp flags cwr;ok
|
||||
tcp flags != cwr;ok
|
||||
tcp flags == syn;ok
|
||||
-tcp flags fin,syn / fin,syn;ok
|
||||
-tcp flags != syn / fin,syn;ok
|
||||
+tcp flags fin,syn / fin,syn;ok;tcp flags & (fin | syn) == fin | syn
|
||||
+tcp flags != syn / fin,syn;ok;tcp flags & (fin | syn) != syn
|
||||
tcp flags & syn != 0;ok;tcp flags syn
|
||||
tcp flags & syn == 0;ok;tcp flags ! syn
|
||||
tcp flags & (syn | ack) != 0;ok;tcp flags syn,ack
|
||||
@@ -77,12 +77,12 @@ tcp flags & (syn | ack) == 0;ok;tcp flags ! syn,ack
|
||||
# it should be possible to transform this to: tcp flags syn
|
||||
tcp flags & syn == syn;ok
|
||||
tcp flags & syn != syn;ok
|
||||
-tcp flags & (fin | syn | rst | ack) syn;ok;tcp flags syn / fin,syn,rst,ack
|
||||
-tcp flags & (fin | syn | rst | ack) == syn;ok;tcp flags syn / fin,syn,rst,ack
|
||||
-tcp flags & (fin | syn | rst | ack) != syn;ok;tcp flags != syn / fin,syn,rst,ack
|
||||
-tcp flags & (fin | syn | rst | ack) == (syn | ack);ok;tcp flags syn,ack / fin,syn,rst,ack
|
||||
-tcp flags & (fin | syn | rst | ack) != (syn | ack);ok;tcp flags != syn,ack / fin,syn,rst,ack
|
||||
-tcp flags & (syn | ack) == (syn | ack);ok;tcp flags syn,ack / syn,ack
|
||||
+tcp flags & (fin | syn | rst | ack) syn;ok;tcp flags & (fin | syn | rst | ack) == syn
|
||||
+tcp flags & (fin | syn | rst | ack) == syn;ok
|
||||
+tcp flags & (fin | syn | rst | ack) != syn;ok
|
||||
+tcp flags & (fin | syn | rst | ack) == syn | ack;ok
|
||||
+tcp flags & (fin | syn | rst | ack) != syn | ack;ok
|
||||
+tcp flags & (syn | ack) == syn | ack;ok
|
||||
tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr;ok;tcp flags == 0xff
|
||||
tcp flags { syn, syn | ack };ok
|
||||
tcp flags & (fin | syn | rst | psh | ack | urg) == { fin, ack, psh | ack, fin | psh | ack };ok
|
||||
diff --git a/tests/py/inet/tcp.t.json b/tests/py/inet/tcp.t.json
|
||||
index 8439c2b..d3a846c 100644
|
||||
--- a/tests/py/inet/tcp.t.json
|
||||
+++ b/tests/py/inet/tcp.t.json
|
||||
@@ -1712,7 +1712,7 @@
|
||||
}
|
||||
]
|
||||
|
||||
-# tcp flags & (fin | syn | rst | ack) == (syn | ack)
|
||||
+# tcp flags & (fin | syn | rst | ack) == syn | ack
|
||||
[
|
||||
{
|
||||
"match": {
|
||||
@@ -1741,7 +1741,7 @@
|
||||
}
|
||||
]
|
||||
|
||||
-# tcp flags & (fin | syn | rst | ack) != (syn | ack)
|
||||
+# tcp flags & (syn | ack) == syn | ack
|
||||
[
|
||||
{
|
||||
"match": {
|
||||
@@ -1754,14 +1754,12 @@
|
||||
}
|
||||
},
|
||||
[
|
||||
- "fin",
|
||||
"syn",
|
||||
- "rst",
|
||||
"ack"
|
||||
]
|
||||
]
|
||||
},
|
||||
- "op": "!=",
|
||||
+ "op": "==",
|
||||
"right": [
|
||||
"syn",
|
||||
"ack"
|
||||
@@ -1770,7 +1768,7 @@
|
||||
}
|
||||
]
|
||||
|
||||
-# tcp flags & (syn | ack) == (syn | ack)
|
||||
+# tcp flags & (fin | syn | rst | ack) != syn | ack
|
||||
[
|
||||
{
|
||||
"match": {
|
||||
@@ -1782,17 +1780,31 @@
|
||||
"protocol": "tcp"
|
||||
}
|
||||
},
|
||||
- [
|
||||
- "syn",
|
||||
- "ack"
|
||||
- ]
|
||||
+ {
|
||||
+ "|": [
|
||||
+ {
|
||||
+ "|": [
|
||||
+ {
|
||||
+ "|": [
|
||||
+ "fin",
|
||||
+ "syn"
|
||||
+ ]
|
||||
+ },
|
||||
+ "rst"
|
||||
+ ]
|
||||
+ },
|
||||
+ "ack"
|
||||
+ ]
|
||||
+ }
|
||||
]
|
||||
},
|
||||
- "op": "==",
|
||||
- "right": [
|
||||
- "syn",
|
||||
- "ack"
|
||||
- ]
|
||||
+ "op": "!=",
|
||||
+ "right": {
|
||||
+ "|": [
|
||||
+ "syn",
|
||||
+ "ack"
|
||||
+ ]
|
||||
+ }
|
||||
}
|
||||
}
|
||||
]
|
||||
diff --git a/tests/py/inet/tcp.t.json.output b/tests/py/inet/tcp.t.json.output
|
||||
index c471e8d..e186e12 100644
|
||||
--- a/tests/py/inet/tcp.t.json.output
|
||||
+++ b/tests/py/inet/tcp.t.json.output
|
||||
@@ -208,3 +208,282 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
+
|
||||
+# tcp flags fin,syn / fin,syn
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "&": [
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "flags",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "|": [
|
||||
+ "fin",
|
||||
+ "syn"
|
||||
+ ]
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": {
|
||||
+ "|": [
|
||||
+ "fin",
|
||||
+ "syn"
|
||||
+ ]
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# tcp flags != syn / fin,syn
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "&": [
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "flags",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "|": [
|
||||
+ "fin",
|
||||
+ "syn"
|
||||
+ ]
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ "op": "!=",
|
||||
+ "right": "syn"
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# tcp flags & (fin | syn | rst | ack) syn
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "&": [
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "flags",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "|": [
|
||||
+ {
|
||||
+ "|": [
|
||||
+ {
|
||||
+ "|": [
|
||||
+ "fin",
|
||||
+ "syn"
|
||||
+ ]
|
||||
+ },
|
||||
+ "rst"
|
||||
+ ]
|
||||
+ },
|
||||
+ "ack"
|
||||
+ ]
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": "syn"
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# tcp flags & (fin | syn | rst | ack) == syn
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "&": [
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "flags",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "|": [
|
||||
+ {
|
||||
+ "|": [
|
||||
+ {
|
||||
+ "|": [
|
||||
+ "fin",
|
||||
+ "syn"
|
||||
+ ]
|
||||
+ },
|
||||
+ "rst"
|
||||
+ ]
|
||||
+ },
|
||||
+ "ack"
|
||||
+ ]
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": "syn"
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# tcp flags & (fin | syn | rst | ack) != syn
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "&": [
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "flags",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "|": [
|
||||
+ {
|
||||
+ "|": [
|
||||
+ {
|
||||
+ "|": [
|
||||
+ "fin",
|
||||
+ "syn"
|
||||
+ ]
|
||||
+ },
|
||||
+ "rst"
|
||||
+ ]
|
||||
+ },
|
||||
+ "ack"
|
||||
+ ]
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ "op": "!=",
|
||||
+ "right": "syn"
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# tcp flags & (fin | syn | rst | ack) == syn | ack
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "&": [
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "flags",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "|": [
|
||||
+ {
|
||||
+ "|": [
|
||||
+ {
|
||||
+ "|": [
|
||||
+ "fin",
|
||||
+ "syn"
|
||||
+ ]
|
||||
+ },
|
||||
+ "rst"
|
||||
+ ]
|
||||
+ },
|
||||
+ "ack"
|
||||
+ ]
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": {
|
||||
+ "|": [
|
||||
+ "syn",
|
||||
+ "ack"
|
||||
+ ]
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# tcp flags & (fin | syn | rst | ack) != syn | ack
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "&": [
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "flags",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "|": [
|
||||
+ {
|
||||
+ "|": [
|
||||
+ {
|
||||
+ "|": [
|
||||
+ "fin",
|
||||
+ "syn"
|
||||
+ ]
|
||||
+ },
|
||||
+ "rst"
|
||||
+ ]
|
||||
+ },
|
||||
+ "ack"
|
||||
+ ]
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ "op": "!=",
|
||||
+ "right": {
|
||||
+ "|": [
|
||||
+ "syn",
|
||||
+ "ack"
|
||||
+ ]
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# tcp flags & (syn | ack) == syn | ack
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "&": [
|
||||
+ {
|
||||
+ "payload": {
|
||||
+ "field": "flags",
|
||||
+ "protocol": "tcp"
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "|": [
|
||||
+ "syn",
|
||||
+ "ack"
|
||||
+ ]
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": {
|
||||
+ "|": [
|
||||
+ "syn",
|
||||
+ "ack"
|
||||
+ ]
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
diff --git a/tests/py/inet/tcp.t.payload b/tests/py/inet/tcp.t.payload
|
||||
index 1cfe500..bc6bb98 100644
|
||||
--- a/tests/py/inet/tcp.t.payload
|
||||
+++ b/tests/py/inet/tcp.t.payload
|
||||
@@ -442,7 +442,7 @@ inet test-inet input
|
||||
[ bitwise reg 1 = ( reg 1 & 0x00000017 ) ^ 0x00000000 ]
|
||||
[ cmp neq reg 1 0x00000002 ]
|
||||
|
||||
-# tcp flags & (fin | syn | rst | ack) == (syn | ack)
|
||||
+# tcp flags & (fin | syn | rst | ack) == syn | ack
|
||||
inet test-inet input
|
||||
[ meta load l4proto => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000006 ]
|
||||
@@ -450,7 +450,7 @@ inet test-inet input
|
||||
[ bitwise reg 1 = ( reg 1 & 0x00000017 ) ^ 0x00000000 ]
|
||||
[ cmp eq reg 1 0x00000012 ]
|
||||
|
||||
-# tcp flags & (fin | syn | rst | ack) != (syn | ack)
|
||||
+# tcp flags & (fin | syn | rst | ack) != syn | ack
|
||||
inet test-inet input
|
||||
[ meta load l4proto => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000006 ]
|
||||
@@ -458,7 +458,7 @@ inet test-inet input
|
||||
[ bitwise reg 1 = ( reg 1 & 0x00000017 ) ^ 0x00000000 ]
|
||||
[ cmp neq reg 1 0x00000012 ]
|
||||
|
||||
-# tcp flags & (syn | ack) == (syn | ack)
|
||||
+# tcp flags & (syn | ack) == syn | ack
|
||||
inet test-inet input
|
||||
[ meta load l4proto => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000006 ]
|
||||
diff --git a/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft b/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft
|
||||
index 480b694..1a9f4e7 100644
|
||||
--- a/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft
|
||||
+++ b/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft
|
||||
@@ -73,7 +73,7 @@ table inet filter {
|
||||
|
||||
chain ct_new_pre {
|
||||
jump rpfilter
|
||||
- tcp flags != syn / fin,syn,rst,ack counter packets 0 bytes 0 drop
|
||||
+ tcp flags & (fin | syn | rst | ack) != syn counter packets 0 bytes 0 drop
|
||||
iifname "eth0" meta nfproto vmap { ipv4 : jump blacklist_input_ipv4, ipv6 : jump blacklist_input_ipv6 }
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ table inet filter {
|
||||
type filter hook forward priority mangle; policy accept;
|
||||
oifname "eth0" jump {
|
||||
ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 }
|
||||
- tcp flags syn / syn,rst tcp option maxseg size set rt mtu
|
||||
+ tcp flags & (syn | rst) == syn tcp option maxseg size set rt mtu
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/tests/shell/testcases/packetpath/tcp_options b/tests/shell/testcases/packetpath/tcp_options
|
||||
index 1c9ee53..8855222 100755
|
||||
--- a/tests/shell/testcases/packetpath/tcp_options
|
||||
+++ b/tests/shell/testcases/packetpath/tcp_options
|
||||
@@ -15,14 +15,14 @@ table inet t {
|
||||
chain c {
|
||||
type filter hook output priority 0;
|
||||
tcp dport != 22345 accept
|
||||
- tcp flags syn / fin,syn,rst,ack tcp option 254 length ge 4 counter name nomatchc drop
|
||||
- tcp flags syn / fin,syn,rst,ack tcp option fastopen length ge 2 reset tcp option fastopen counter name nomatchc
|
||||
- tcp flags syn / fin,syn,rst,ack tcp option sack-perm missing counter name nomatchc
|
||||
- tcp flags syn / fin,syn,rst,ack tcp option sack-perm exists counter name sackpermc
|
||||
- tcp flags syn / fin,syn,rst,ack tcp option maxseg size gt 1400 counter name maxsegc
|
||||
- tcp flags syn / fin,syn,rst,ack tcp option nop missing counter name nomatchc
|
||||
- tcp flags syn / fin,syn,rst,ack tcp option nop exists counter name nopc
|
||||
- tcp flags syn / fin,syn,rst,ack drop
|
||||
+ tcp flags & (fin | syn | rst | ack ) == syn tcp option 254 length ge 4 counter name nomatchc drop
|
||||
+ tcp flags & (fin | syn | rst | ack ) == syn tcp option fastopen length ge 2 reset tcp option fastopen counter name nomatchc
|
||||
+ tcp flags & (fin | syn | rst | ack ) == syn tcp option sack-perm missing counter name nomatchc
|
||||
+ tcp flags & (fin | syn | rst | ack) == syn tcp option sack-perm exists counter name sackpermc
|
||||
+ tcp flags & (fin | syn | rst | ack) == syn tcp option maxseg size gt 1400 counter name maxsegc
|
||||
+ tcp flags & (fin | syn | rst | ack) == syn tcp option nop missing counter name nomatchc
|
||||
+ tcp flags & (fin | syn | rst | ack) == syn tcp option nop exists counter name nopc
|
||||
+ tcp flags & (fin | syn | rst | ack) == syn drop
|
||||
}
|
||||
}
|
||||
EOF
|
||||
40
0084-evaluate-display-Range-negative-size-error.patch
Normal file
40
0084-evaluate-display-Range-negative-size-error.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From 8d0cfbc6790d4206414cf21e6cd65ad4fd275624 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:43 +0200
|
||||
Subject: [PATCH] evaluate: display "Range negative size" error
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit c0a5b8c6a6433ec1d4e41646dc42ccb8444c96be
|
||||
|
||||
commit c0a5b8c6a6433ec1d4e41646dc42ccb8444c96be
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Mar 19 19:50:00 2024 +0100
|
||||
|
||||
evaluate: display "Range negative size" error
|
||||
|
||||
zero length ranges now allowed, therefore, update error message to refer
|
||||
to negative ranges which are not possible.
|
||||
|
||||
Fixes: 7a6e16040d65 ("evaluate: allow for zero length ranges")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 89656eb..38a80f2 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -1255,8 +1255,8 @@ static int expr_evaluate_range(struct eval_ctx *ctx, struct expr **expr)
|
||||
right = range->right;
|
||||
|
||||
if (mpz_cmp(left->value, right->value) > 0)
|
||||
- return expr_error(ctx->msgs, range,
|
||||
- "Range has zero or negative size");
|
||||
+ return expr_error(ctx->msgs, range, "Range negative size");
|
||||
+
|
||||
datatype_set(range, left->dtype);
|
||||
range->flags |= EXPR_F_CONSTANT;
|
||||
return 0;
|
||||
564
0085-src-disentangle-ICMP-code-types.patch
Normal file
564
0085-src-disentangle-ICMP-code-types.patch
Normal file
@ -0,0 +1,564 @@
|
||||
From 094d220d2fcaae5b67789b58f54d59e7b016657e Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:43 +0200
|
||||
Subject: [PATCH] src: disentangle ICMP code types
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 5fecd2a6ef614eca7b0829e684449ee25982c233
|
||||
|
||||
commit 5fecd2a6ef614eca7b0829e684449ee25982c233
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Apr 2 00:28:24 2024 +0200
|
||||
|
||||
src: disentangle ICMP code types
|
||||
|
||||
Currently, ICMP{v4,v6,inet} code datatypes only describe those that are
|
||||
supported by the reject statement, but they can also be used for icmp
|
||||
code matching. Moreover, ICMP code types go hand-to-hand with ICMP
|
||||
types, that is, ICMP code symbols depend on the ICMP type.
|
||||
|
||||
Thus, the output of:
|
||||
|
||||
nft describe icmp_code
|
||||
|
||||
look confusing because that only displays the values that are supported
|
||||
by the reject statement.
|
||||
|
||||
Disentangle this by adding internal datatypes for the reject statement
|
||||
to handle the ICMP code symbol conversion to value as well as ruleset
|
||||
listing.
|
||||
|
||||
The existing icmp_code, icmpv6_code and icmpx_code remain in place. For
|
||||
backward compatibility, a parser function is defined in case an existing
|
||||
ruleset relies on these symbols.
|
||||
|
||||
As for the manpage, move existing ICMP code tables from the DATA TYPES
|
||||
section to the REJECT STATEMENT section, where this really belongs to.
|
||||
But the icmp_code and icmpv6_code table stubs remain in the DATA TYPES
|
||||
section because that describe that this is an 8-bit integer field.
|
||||
|
||||
After this patch:
|
||||
|
||||
# nft describe icmp_code
|
||||
datatype icmp_code (icmp code) (basetype integer), 8 bits
|
||||
# nft describe icmpv6_code
|
||||
datatype icmpv6_code (icmpv6 code) (basetype integer), 8 bits
|
||||
# nft describe icmpx_code
|
||||
datatype icmpx_code (icmpx code) (basetype integer), 8 bits
|
||||
|
||||
do not display the symbol table of the reject statement anymore.
|
||||
|
||||
icmpx_code_type is not used anymore, but keep it in place for backward
|
||||
compatibility reasons.
|
||||
|
||||
And update tests/shell accordingly.
|
||||
|
||||
Fixes: 5fdd0b6a0600 ("nft: complete reject support")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
doc/data-types.txt | 68 -----------------------------------
|
||||
doc/statements.txt | 74 ++++++++++++++++++++++++++++++---------
|
||||
include/datatype.h | 5 +++
|
||||
src/datatype.c | 71 +++++++++++++++++++++++++++++++++----
|
||||
src/netlink_delinearize.c | 10 +++---
|
||||
src/parser_bison.y | 12 +++----
|
||||
src/parser_json.c | 6 ++--
|
||||
tests/py/ip/icmp.t | 6 ++--
|
||||
tests/py/ip6/icmpv6.t | 8 ++---
|
||||
9 files changed, 147 insertions(+), 113 deletions(-)
|
||||
|
||||
diff --git a/doc/data-types.txt b/doc/data-types.txt
|
||||
index e5ee91a..6c0e2f9 100644
|
||||
--- a/doc/data-types.txt
|
||||
+++ b/doc/data-types.txt
|
||||
@@ -242,28 +242,6 @@ integer
|
||||
|
||||
The ICMP Code type is used to conveniently specify the ICMP header's code field.
|
||||
|
||||
-.Keywords may be used when specifying the ICMP code
|
||||
-[options="header"]
|
||||
-|==================
|
||||
-|Keyword | Value
|
||||
-|net-unreachable |
|
||||
-0
|
||||
-|host-unreachable |
|
||||
-1
|
||||
-|prot-unreachable|
|
||||
-2
|
||||
-|port-unreachable|
|
||||
-3
|
||||
-|frag-needed|
|
||||
-4
|
||||
-|net-prohibited|
|
||||
-9
|
||||
-|host-prohibited|
|
||||
-10
|
||||
-|admin-prohibited|
|
||||
-13
|
||||
-|===================
|
||||
-
|
||||
ICMPV6 TYPE TYPE
|
||||
~~~~~~~~~~~~~~~~
|
||||
[options="header"]
|
||||
@@ -340,52 +318,6 @@ integer
|
||||
|
||||
The ICMPv6 Code type is used to conveniently specify the ICMPv6 header's code field.
|
||||
|
||||
-.keywords may be used when specifying the ICMPv6 code
|
||||
-[options="header"]
|
||||
-|==================
|
||||
-|Keyword |Value
|
||||
-|no-route|
|
||||
-0
|
||||
-|admin-prohibited|
|
||||
-1
|
||||
-|addr-unreachable|
|
||||
-3
|
||||
-|port-unreachable|
|
||||
-4
|
||||
-|policy-fail|
|
||||
-5
|
||||
-|reject-route|
|
||||
-6
|
||||
-|==================
|
||||
-
|
||||
-ICMPVX CODE TYPE
|
||||
-~~~~~~~~~~~~~~~~
|
||||
-[options="header"]
|
||||
-|==================
|
||||
-|Name | Keyword | Size | Base type
|
||||
-|ICMPvX Code |
|
||||
-icmpx_code |
|
||||
-8 bit |
|
||||
-integer
|
||||
-|===================
|
||||
-
|
||||
-The ICMPvX Code type abstraction is a set of values which overlap between ICMP
|
||||
-and ICMPv6 Code types to be used from the inet family.
|
||||
-
|
||||
-.keywords may be used when specifying the ICMPvX code
|
||||
-[options="header"]
|
||||
-|==================
|
||||
-|Keyword |Value
|
||||
-|no-route|
|
||||
-0
|
||||
-|port-unreachable|
|
||||
-1
|
||||
-|host-unreachable|
|
||||
-2
|
||||
-|admin-prohibited|
|
||||
-3
|
||||
-|=================
|
||||
-
|
||||
CONNTRACK TYPES
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
diff --git a/doc/statements.txt b/doc/statements.txt
|
||||
index c29a2ff..834adb2 100644
|
||||
--- a/doc/statements.txt
|
||||
+++ b/doc/statements.txt
|
||||
@@ -164,9 +164,9 @@ REJECT STATEMENT
|
||||
____
|
||||
*reject* [ *with* 'REJECT_WITH' ]
|
||||
|
||||
-'REJECT_WITH' := *icmp* 'icmp_code' |
|
||||
- *icmpv6* 'icmpv6_code' |
|
||||
- *icmpx* 'icmpx_code' |
|
||||
+'REJECT_WITH' := *icmp* 'icmp_reject_code' |
|
||||
+ *icmpv6* 'icmpv6_reject_code' |
|
||||
+ *icmpx* 'icmpx_reject_code' |
|
||||
*tcp reset*
|
||||
____
|
||||
|
||||
@@ -177,24 +177,64 @@ using the *input*,
|
||||
*forward* or *output* hooks, and user-defined chains which are only called from
|
||||
those chains.
|
||||
|
||||
-.different ICMP reject variants are meant for use in different table families
|
||||
+.Keywords may be used to reject when specifying the ICMP code
|
||||
[options="header"]
|
||||
|==================
|
||||
-|Variant |Family | Type
|
||||
-|icmp|
|
||||
-ip|
|
||||
-icmp_code
|
||||
-|icmpv6|
|
||||
-ip6|
|
||||
-icmpv6_code
|
||||
-|icmpx|
|
||||
-inet|
|
||||
-icmpx_code
|
||||
+|Keyword | Value
|
||||
+|net-unreachable |
|
||||
+0
|
||||
+|host-unreachable |
|
||||
+1
|
||||
+|prot-unreachable|
|
||||
+2
|
||||
+|port-unreachable|
|
||||
+3
|
||||
+|frag-needed|
|
||||
+4
|
||||
+|net-prohibited|
|
||||
+9
|
||||
+|host-prohibited|
|
||||
+10
|
||||
+|admin-prohibited|
|
||||
+13
|
||||
+|===================
|
||||
+
|
||||
+.keywords may be used to reject when specifying the ICMPv6 code
|
||||
+[options="header"]
|
||||
|==================
|
||||
+|Keyword |Value
|
||||
+|no-route|
|
||||
+0
|
||||
+|admin-prohibited|
|
||||
+1
|
||||
+|addr-unreachable|
|
||||
+3
|
||||
+|port-unreachable|
|
||||
+4
|
||||
+|policy-fail|
|
||||
+5
|
||||
+|reject-route|
|
||||
+6
|
||||
+|==================
|
||||
+
|
||||
+The ICMPvX Code type abstraction is a set of values which overlap between ICMP
|
||||
+and ICMPv6 Code types to be used from the inet family.
|
||||
+
|
||||
+.keywords may be used when specifying the ICMPvX code
|
||||
+[options="header"]
|
||||
+|==================
|
||||
+|Keyword |Value
|
||||
+|no-route|
|
||||
+0
|
||||
+|port-unreachable|
|
||||
+1
|
||||
+|host-unreachable|
|
||||
+2
|
||||
+|admin-prohibited|
|
||||
+3
|
||||
+|=================
|
||||
|
||||
-For a description of the different types and a list of supported keywords refer
|
||||
-to DATA TYPES section above. The common default reject value is
|
||||
-*port-unreachable*. +
|
||||
+The common default ICMP code to reject is *port-unreachable*.
|
||||
|
||||
Note that in bridge family, reject statement is only allowed in base chains
|
||||
which hook into input or prerouting.
|
||||
diff --git a/include/datatype.h b/include/datatype.h
|
||||
index 09a7894..68e12d5 100644
|
||||
--- a/include/datatype.h
|
||||
+++ b/include/datatype.h
|
||||
@@ -280,6 +280,11 @@ extern const struct datatype priority_type;
|
||||
extern const struct datatype policy_type;
|
||||
extern const struct datatype cgroupv2_type;
|
||||
|
||||
+/* private datatypes for reject statement. */
|
||||
+extern const struct datatype reject_icmp_code_type;
|
||||
+extern const struct datatype reject_icmpv6_code_type;
|
||||
+extern const struct datatype reject_icmpx_code_type;
|
||||
+
|
||||
void inet_service_type_print(const struct expr *expr, struct output_ctx *octx);
|
||||
|
||||
extern const struct datatype *concat_type_alloc(uint32_t type);
|
||||
diff --git a/src/datatype.c b/src/datatype.c
|
||||
index a92f41d..46d77eb 100644
|
||||
--- a/src/datatype.c
|
||||
+++ b/src/datatype.c
|
||||
@@ -978,6 +978,7 @@ const struct datatype mark_type = {
|
||||
.flags = DTYPE_F_PREFIX,
|
||||
};
|
||||
|
||||
+/* symbol table for private datatypes for reject statement. */
|
||||
static const struct symbol_table icmp_code_tbl = {
|
||||
.base = BASE_DECIMAL,
|
||||
.symbols = {
|
||||
@@ -993,16 +994,17 @@ static const struct symbol_table icmp_code_tbl = {
|
||||
},
|
||||
};
|
||||
|
||||
-const struct datatype icmp_code_type = {
|
||||
- .type = TYPE_ICMP_CODE,
|
||||
+/* private datatype for reject statement. */
|
||||
+const struct datatype reject_icmp_code_type = {
|
||||
.name = "icmp_code",
|
||||
- .desc = "icmp code",
|
||||
+ .desc = "reject icmp code",
|
||||
.size = BITS_PER_BYTE,
|
||||
.byteorder = BYTEORDER_BIG_ENDIAN,
|
||||
.basetype = &integer_type,
|
||||
.sym_tbl = &icmp_code_tbl,
|
||||
};
|
||||
|
||||
+/* symbol table for private datatypes for reject statement. */
|
||||
static const struct symbol_table icmpv6_code_tbl = {
|
||||
.base = BASE_DECIMAL,
|
||||
.symbols = {
|
||||
@@ -1016,16 +1018,17 @@ static const struct symbol_table icmpv6_code_tbl = {
|
||||
},
|
||||
};
|
||||
|
||||
-const struct datatype icmpv6_code_type = {
|
||||
- .type = TYPE_ICMPV6_CODE,
|
||||
+/* private datatype for reject statement. */
|
||||
+const struct datatype reject_icmpv6_code_type = {
|
||||
.name = "icmpv6_code",
|
||||
- .desc = "icmpv6 code",
|
||||
+ .desc = "reject icmpv6 code",
|
||||
.size = BITS_PER_BYTE,
|
||||
.byteorder = BYTEORDER_BIG_ENDIAN,
|
||||
.basetype = &integer_type,
|
||||
.sym_tbl = &icmpv6_code_tbl,
|
||||
};
|
||||
|
||||
+/* symbol table for private datatypes for reject statement. */
|
||||
static const struct symbol_table icmpx_code_tbl = {
|
||||
.base = BASE_DECIMAL,
|
||||
.symbols = {
|
||||
@@ -1037,6 +1040,60 @@ static const struct symbol_table icmpx_code_tbl = {
|
||||
},
|
||||
};
|
||||
|
||||
+/* private datatype for reject statement. */
|
||||
+const struct datatype reject_icmpx_code_type = {
|
||||
+ .name = "icmpx_code",
|
||||
+ .desc = "reject icmpx code",
|
||||
+ .size = BITS_PER_BYTE,
|
||||
+ .byteorder = BYTEORDER_BIG_ENDIAN,
|
||||
+ .basetype = &integer_type,
|
||||
+ .sym_tbl = &icmpx_code_tbl,
|
||||
+};
|
||||
+
|
||||
+/* Backward compatible parser for the reject statement. */
|
||||
+static struct error_record *icmp_code_parse(struct parse_ctx *ctx,
|
||||
+ const struct expr *sym,
|
||||
+ struct expr **res)
|
||||
+{
|
||||
+ return symbolic_constant_parse(ctx, sym, &icmp_code_tbl, res);
|
||||
+}
|
||||
+
|
||||
+const struct datatype icmp_code_type = {
|
||||
+ .type = TYPE_ICMP_CODE,
|
||||
+ .name = "icmp_code",
|
||||
+ .desc = "icmp code",
|
||||
+ .size = BITS_PER_BYTE,
|
||||
+ .byteorder = BYTEORDER_BIG_ENDIAN,
|
||||
+ .basetype = &integer_type,
|
||||
+ .parse = icmp_code_parse,
|
||||
+};
|
||||
+
|
||||
+/* Backward compatible parser for the reject statement. */
|
||||
+static struct error_record *icmpv6_code_parse(struct parse_ctx *ctx,
|
||||
+ const struct expr *sym,
|
||||
+ struct expr **res)
|
||||
+{
|
||||
+ return symbolic_constant_parse(ctx, sym, &icmpv6_code_tbl, res);
|
||||
+}
|
||||
+
|
||||
+const struct datatype icmpv6_code_type = {
|
||||
+ .type = TYPE_ICMPV6_CODE,
|
||||
+ .name = "icmpv6_code",
|
||||
+ .desc = "icmpv6 code",
|
||||
+ .size = BITS_PER_BYTE,
|
||||
+ .byteorder = BYTEORDER_BIG_ENDIAN,
|
||||
+ .basetype = &integer_type,
|
||||
+ .parse = icmpv6_code_parse,
|
||||
+};
|
||||
+
|
||||
+/* Backward compatible parser for the reject statement. */
|
||||
+static struct error_record *icmpx_code_parse(struct parse_ctx *ctx,
|
||||
+ const struct expr *sym,
|
||||
+ struct expr **res)
|
||||
+{
|
||||
+ return symbolic_constant_parse(ctx, sym, &icmpx_code_tbl, res);
|
||||
+}
|
||||
+
|
||||
const struct datatype icmpx_code_type = {
|
||||
.type = TYPE_ICMPX_CODE,
|
||||
.name = "icmpx_code",
|
||||
@@ -1044,7 +1101,7 @@ const struct datatype icmpx_code_type = {
|
||||
.size = BITS_PER_BYTE,
|
||||
.byteorder = BYTEORDER_BIG_ENDIAN,
|
||||
.basetype = &integer_type,
|
||||
- .sym_tbl = &icmpx_code_tbl,
|
||||
+ .parse = icmpx_code_parse,
|
||||
};
|
||||
|
||||
void time_print(uint64_t ms, struct output_ctx *octx)
|
||||
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
|
||||
index 405a065..1af0278 100644
|
||||
--- a/src/netlink_delinearize.c
|
||||
+++ b/src/netlink_delinearize.c
|
||||
@@ -2930,7 +2930,7 @@ static void stmt_reject_postprocess(struct rule_pp_ctx *rctx)
|
||||
switch (dl->pctx.family) {
|
||||
case NFPROTO_IPV4:
|
||||
stmt->reject.family = dl->pctx.family;
|
||||
- datatype_set(stmt->reject.expr, &icmp_code_type);
|
||||
+ datatype_set(stmt->reject.expr, &reject_icmp_code_type);
|
||||
if (stmt->reject.type == NFT_REJECT_TCP_RST &&
|
||||
payload_dependency_exists(&dl->pdctx,
|
||||
PROTO_BASE_TRANSPORT_HDR))
|
||||
@@ -2939,7 +2939,7 @@ static void stmt_reject_postprocess(struct rule_pp_ctx *rctx)
|
||||
break;
|
||||
case NFPROTO_IPV6:
|
||||
stmt->reject.family = dl->pctx.family;
|
||||
- datatype_set(stmt->reject.expr, &icmpv6_code_type);
|
||||
+ datatype_set(stmt->reject.expr, &reject_icmpv6_code_type);
|
||||
if (stmt->reject.type == NFT_REJECT_TCP_RST &&
|
||||
payload_dependency_exists(&dl->pdctx,
|
||||
PROTO_BASE_TRANSPORT_HDR))
|
||||
@@ -2950,7 +2950,7 @@ static void stmt_reject_postprocess(struct rule_pp_ctx *rctx)
|
||||
case NFPROTO_BRIDGE:
|
||||
case NFPROTO_NETDEV:
|
||||
if (stmt->reject.type == NFT_REJECT_ICMPX_UNREACH) {
|
||||
- datatype_set(stmt->reject.expr, &icmpx_code_type);
|
||||
+ datatype_set(stmt->reject.expr, &reject_icmpx_code_type);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2966,12 +2966,12 @@ static void stmt_reject_postprocess(struct rule_pp_ctx *rctx)
|
||||
case NFPROTO_IPV4: /* INET */
|
||||
case __constant_htons(ETH_P_IP): /* BRIDGE, NETDEV */
|
||||
stmt->reject.family = NFPROTO_IPV4;
|
||||
- datatype_set(stmt->reject.expr, &icmp_code_type);
|
||||
+ datatype_set(stmt->reject.expr, &reject_icmp_code_type);
|
||||
break;
|
||||
case NFPROTO_IPV6: /* INET */
|
||||
case __constant_htons(ETH_P_IPV6): /* BRIDGE, NETDEV */
|
||||
stmt->reject.family = NFPROTO_IPV6;
|
||||
- datatype_set(stmt->reject.expr, &icmpv6_code_type);
|
||||
+ datatype_set(stmt->reject.expr, &reject_icmpv6_code_type);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 23b64ce..e3ac2fb 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -3715,40 +3715,40 @@ reject_opts : /* empty */
|
||||
$<stmt>0->reject.family = NFPROTO_IPV4;
|
||||
$<stmt>0->reject.type = NFT_REJECT_ICMP_UNREACH;
|
||||
$<stmt>0->reject.expr = $4;
|
||||
- datatype_set($<stmt>0->reject.expr, &icmp_code_type);
|
||||
+ datatype_set($<stmt>0->reject.expr, &reject_icmp_code_type);
|
||||
}
|
||||
| WITH ICMP reject_with_expr
|
||||
{
|
||||
$<stmt>0->reject.family = NFPROTO_IPV4;
|
||||
$<stmt>0->reject.type = NFT_REJECT_ICMP_UNREACH;
|
||||
$<stmt>0->reject.expr = $3;
|
||||
- datatype_set($<stmt>0->reject.expr, &icmp_code_type);
|
||||
+ datatype_set($<stmt>0->reject.expr, &reject_icmp_code_type);
|
||||
}
|
||||
| WITH ICMP6 TYPE reject_with_expr close_scope_type close_scope_icmp
|
||||
{
|
||||
$<stmt>0->reject.family = NFPROTO_IPV6;
|
||||
$<stmt>0->reject.type = NFT_REJECT_ICMP_UNREACH;
|
||||
$<stmt>0->reject.expr = $4;
|
||||
- datatype_set($<stmt>0->reject.expr, &icmpv6_code_type);
|
||||
+ datatype_set($<stmt>0->reject.expr, &reject_icmpv6_code_type);
|
||||
}
|
||||
| WITH ICMP6 reject_with_expr
|
||||
{
|
||||
$<stmt>0->reject.family = NFPROTO_IPV6;
|
||||
$<stmt>0->reject.type = NFT_REJECT_ICMP_UNREACH;
|
||||
$<stmt>0->reject.expr = $3;
|
||||
- datatype_set($<stmt>0->reject.expr, &icmpv6_code_type);
|
||||
+ datatype_set($<stmt>0->reject.expr, &reject_icmpv6_code_type);
|
||||
}
|
||||
| WITH ICMPX TYPE reject_with_expr close_scope_type
|
||||
{
|
||||
$<stmt>0->reject.type = NFT_REJECT_ICMPX_UNREACH;
|
||||
$<stmt>0->reject.expr = $4;
|
||||
- datatype_set($<stmt>0->reject.expr, &icmpx_code_type);
|
||||
+ datatype_set($<stmt>0->reject.expr, &reject_icmpx_code_type);
|
||||
}
|
||||
| WITH ICMPX reject_with_expr
|
||||
{
|
||||
$<stmt>0->reject.type = NFT_REJECT_ICMPX_UNREACH;
|
||||
$<stmt>0->reject.expr = $3;
|
||||
- datatype_set($<stmt>0->reject.expr, &icmpx_code_type);
|
||||
+ datatype_set($<stmt>0->reject.expr, &reject_icmpx_code_type);
|
||||
}
|
||||
| WITH TCP close_scope_tcp RESET close_scope_reset
|
||||
{
|
||||
diff --git a/src/parser_json.c b/src/parser_json.c
|
||||
index b8ed848..25483b1 100644
|
||||
--- a/src/parser_json.c
|
||||
+++ b/src/parser_json.c
|
||||
@@ -2318,17 +2318,17 @@ static struct stmt *json_parse_reject_stmt(struct json_ctx *ctx,
|
||||
stmt->reject.icmp_code = 0;
|
||||
} else if (!strcmp(type, "icmpx")) {
|
||||
stmt->reject.type = NFT_REJECT_ICMPX_UNREACH;
|
||||
- dtype = &icmpx_code_type;
|
||||
+ dtype = &reject_icmpx_code_type;
|
||||
stmt->reject.icmp_code = 0;
|
||||
} else if (!strcmp(type, "icmp")) {
|
||||
stmt->reject.type = NFT_REJECT_ICMP_UNREACH;
|
||||
stmt->reject.family = NFPROTO_IPV4;
|
||||
- dtype = &icmp_code_type;
|
||||
+ dtype = &reject_icmp_code_type;
|
||||
stmt->reject.icmp_code = 0;
|
||||
} else if (!strcmp(type, "icmpv6")) {
|
||||
stmt->reject.type = NFT_REJECT_ICMP_UNREACH;
|
||||
stmt->reject.family = NFPROTO_IPV6;
|
||||
- dtype = &icmpv6_code_type;
|
||||
+ dtype = &reject_icmpv6_code_type;
|
||||
stmt->reject.icmp_code = 0;
|
||||
}
|
||||
}
|
||||
diff --git a/tests/py/ip/icmp.t b/tests/py/ip/icmp.t
|
||||
index 7ddf8b3..226c339 100644
|
||||
--- a/tests/py/ip/icmp.t
|
||||
+++ b/tests/py/ip/icmp.t
|
||||
@@ -26,8 +26,8 @@ icmp code 111 accept;ok
|
||||
icmp code != 111 accept;ok
|
||||
icmp code 33-55;ok
|
||||
icmp code != 33-55;ok
|
||||
-icmp code { 2, 4, 54, 33, 56};ok;icmp code { prot-unreachable, frag-needed, 33, 54, 56}
|
||||
-icmp code != { prot-unreachable, frag-needed, 33, 54, 56};ok
|
||||
+icmp code { 2, 4, 54, 33, 56};ok
|
||||
+icmp code != { prot-unreachable, frag-needed, 33, 54, 56};ok;icmp code != { 2, 4, 33, 54, 56}
|
||||
|
||||
icmp checksum 12343 accept;ok
|
||||
icmp checksum != 12343 accept;ok
|
||||
@@ -73,5 +73,5 @@ icmp gateway != { 33, 55, 67, 88};ok
|
||||
icmp gateway != 34;ok
|
||||
icmp gateway != { 333, 334};ok
|
||||
|
||||
-icmp code 1 icmp type 2;ok;icmp type 2 icmp code host-unreachable
|
||||
+icmp code 1 icmp type 2;ok;icmp type 2 icmp code 1
|
||||
icmp code != 1 icmp type 2 icmp mtu 5;fail
|
||||
diff --git a/tests/py/ip6/icmpv6.t b/tests/py/ip6/icmpv6.t
|
||||
index 35dad2b..7632bfd 100644
|
||||
--- a/tests/py/ip6/icmpv6.t
|
||||
+++ b/tests/py/ip6/icmpv6.t
|
||||
@@ -28,10 +28,10 @@ icmpv6 type {router-renumbering, mld-listener-done, time-exceeded, nd-router-sol
|
||||
icmpv6 type {mld-listener-query, time-exceeded, nd-router-advert} accept;ok
|
||||
icmpv6 type != {mld-listener-query, time-exceeded, nd-router-advert} accept;ok
|
||||
|
||||
-icmpv6 code 4;ok;icmpv6 code port-unreachable
|
||||
+icmpv6 code 4;ok
|
||||
icmpv6 code 3-66;ok
|
||||
-icmpv6 code {5, 6, 7} accept;ok;icmpv6 code {policy-fail, reject-route, 7} accept
|
||||
-icmpv6 code != {policy-fail, reject-route, 7} accept;ok
|
||||
+icmpv6 code {5, 6, 7} accept;ok
|
||||
+icmpv6 code != {policy-fail, reject-route, 7} accept;ok;icmpv6 code != {5, 6, 7} accept
|
||||
|
||||
icmpv6 checksum 2222 log;ok
|
||||
icmpv6 checksum != 2222 log;ok
|
||||
@@ -84,7 +84,7 @@ icmpv6 max-delay != 33-45;ok
|
||||
icmpv6 max-delay {33, 55, 67, 88};ok
|
||||
icmpv6 max-delay != {33, 55, 67, 88};ok
|
||||
|
||||
-icmpv6 type parameter-problem icmpv6 code no-route;ok
|
||||
+icmpv6 type parameter-problem icmpv6 code 0;ok
|
||||
|
||||
icmpv6 type mld-listener-query icmpv6 taddr 2001:db8::133;ok
|
||||
icmpv6 type nd-neighbor-solicit icmpv6 taddr 2001:db8::133;ok
|
||||
146
0086-tests-py-complete-icmp-and-icmpv6-update.patch
Normal file
146
0086-tests-py-complete-icmp-and-icmpv6-update.patch
Normal file
@ -0,0 +1,146 @@
|
||||
From 7a57053ed7c9fa767596b33521545c552be89dba Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:43 +0200
|
||||
Subject: [PATCH] tests: py: complete icmp and icmpv6 update
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 1702bfd70b39fe955d5e2c4b93f7dc07acb79027
|
||||
|
||||
commit 1702bfd70b39fe955d5e2c4b93f7dc07acb79027
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Thu Apr 4 13:56:39 2024 +0200
|
||||
|
||||
tests: py: complete icmp and icmpv6 update
|
||||
|
||||
Update json update and leftover payload update to complete
|
||||
5fecd2a6ef61 ("src: disentangle ICMP code types").
|
||||
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
tests/py/ip/icmp.t.json | 6 +++---
|
||||
tests/py/ip/icmp.t.json.output | 4 ++--
|
||||
tests/py/ip6/icmpv6.t.json | 8 ++++----
|
||||
tests/py/ip6/icmpv6.t.json.output | 8 ++++----
|
||||
tests/py/ip6/icmpv6.t.payload.ip6 | 2 +-
|
||||
5 files changed, 14 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/tests/py/ip/icmp.t.json b/tests/py/ip/icmp.t.json
|
||||
index 4f05250..45e04c7 100644
|
||||
--- a/tests/py/ip/icmp.t.json
|
||||
+++ b/tests/py/ip/icmp.t.json
|
||||
@@ -459,8 +459,8 @@
|
||||
"op": "!=",
|
||||
"right": {
|
||||
"set": [
|
||||
- "prot-unreachable",
|
||||
- "frag-needed",
|
||||
+ 2,
|
||||
+ 4,
|
||||
33,
|
||||
54,
|
||||
56
|
||||
@@ -1488,7 +1488,7 @@
|
||||
}
|
||||
},
|
||||
"op": "==",
|
||||
- "right": "host-unreachable"
|
||||
+ "right": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
diff --git a/tests/py/ip/icmp.t.json.output b/tests/py/ip/icmp.t.json.output
|
||||
index 5a07585..52fd601 100644
|
||||
--- a/tests/py/ip/icmp.t.json.output
|
||||
+++ b/tests/py/ip/icmp.t.json.output
|
||||
@@ -11,8 +11,8 @@
|
||||
"op": "==",
|
||||
"right": {
|
||||
"set": [
|
||||
- "prot-unreachable",
|
||||
- "frag-needed",
|
||||
+ 2,
|
||||
+ 4,
|
||||
33,
|
||||
54,
|
||||
56
|
||||
diff --git a/tests/py/ip6/icmpv6.t.json b/tests/py/ip6/icmpv6.t.json
|
||||
index 224a8e8..9df886d 100644
|
||||
--- a/tests/py/ip6/icmpv6.t.json
|
||||
+++ b/tests/py/ip6/icmpv6.t.json
|
||||
@@ -532,8 +532,8 @@
|
||||
"op": "!=",
|
||||
"right": {
|
||||
"set": [
|
||||
- "policy-fail",
|
||||
- "reject-route",
|
||||
+ 5,
|
||||
+ 6,
|
||||
7
|
||||
]
|
||||
}
|
||||
@@ -1136,7 +1136,7 @@
|
||||
}
|
||||
]
|
||||
|
||||
-# icmpv6 type parameter-problem icmpv6 code no-route
|
||||
+# icmpv6 type parameter-problem icmpv6 code 0
|
||||
[
|
||||
{
|
||||
"match": {
|
||||
@@ -1159,7 +1159,7 @@
|
||||
}
|
||||
},
|
||||
"op": "==",
|
||||
- "right": "no-route"
|
||||
+ "right": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
diff --git a/tests/py/ip6/icmpv6.t.json.output b/tests/py/ip6/icmpv6.t.json.output
|
||||
index 7b8f5c1..f29b346 100644
|
||||
--- a/tests/py/ip6/icmpv6.t.json.output
|
||||
+++ b/tests/py/ip6/icmpv6.t.json.output
|
||||
@@ -104,7 +104,7 @@
|
||||
}
|
||||
},
|
||||
"op": "==",
|
||||
- "right": "port-unreachable"
|
||||
+ "right": 4
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -122,7 +122,7 @@
|
||||
"op": "==",
|
||||
"right": {
|
||||
"range": [
|
||||
- "addr-unreachable",
|
||||
+ 3,
|
||||
66
|
||||
]
|
||||
}
|
||||
@@ -143,8 +143,8 @@
|
||||
"op": "==",
|
||||
"right": {
|
||||
"set": [
|
||||
- "policy-fail",
|
||||
- "reject-route",
|
||||
+ 5,
|
||||
+ 6,
|
||||
7
|
||||
]
|
||||
}
|
||||
diff --git a/tests/py/ip6/icmpv6.t.payload.ip6 b/tests/py/ip6/icmpv6.t.payload.ip6
|
||||
index fcaf481..5b6035d 100644
|
||||
--- a/tests/py/ip6/icmpv6.t.payload.ip6
|
||||
+++ b/tests/py/ip6/icmpv6.t.payload.ip6
|
||||
@@ -554,7 +554,7 @@ ip6 test-ip6 input
|
||||
[ payload load 2b @ transport header + 4 => reg 1 ]
|
||||
[ lookup reg 1 set __set%d 0x1 ]
|
||||
|
||||
-# icmpv6 type parameter-problem icmpv6 code no-route
|
||||
+# icmpv6 type parameter-problem icmpv6 code 0
|
||||
ip6
|
||||
[ meta load l4proto => reg 1 ]
|
||||
[ cmp eq reg 1 0x0000003a ]
|
||||
@ -0,0 +1,36 @@
|
||||
From 1b8794fe549b6e242b99eebf477a9508e25e6ac4 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:43 +0200
|
||||
Subject: [PATCH] tests: shell: payload matching requires egress support
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit b13c0379bcf11caf64734240ec8fbcaa668c4016
|
||||
|
||||
commit b13c0379bcf11caf64734240ec8fbcaa668c4016
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Mon Apr 8 20:25:12 2024 +0200
|
||||
|
||||
tests: shell: payload matching requires egress support
|
||||
|
||||
Older kernels do not support for egress hook.
|
||||
|
||||
Fixes: 84da729e067a ("tests: shell: add test to cover payload transport match and mangle")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
tests/shell/testcases/packetpath/payload | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/tests/shell/testcases/packetpath/payload b/tests/shell/testcases/packetpath/payload
|
||||
index 9f4587d..4c5c42d 100755
|
||||
--- a/tests/shell/testcases/packetpath/payload
|
||||
+++ b/tests/shell/testcases/packetpath/payload
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_netdev_egress)
|
||||
+
|
||||
rnd=$(mktemp -u XXXXXXXX)
|
||||
ns1="nft1payload-$rnd"
|
||||
ns2="nft2payload-$rnd"
|
||||
47
0088-tests-shell-check-for-reset-tcp-options-support.patch
Normal file
47
0088-tests-shell-check-for-reset-tcp-options-support.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From 23fdf421ab37132dae2ed324f1e6d6f634d82f56 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:43 +0200
|
||||
Subject: [PATCH] tests: shell: check for reset tcp options support
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 6a39fd3b68ac8a96340b87b9dc8380a9cd4e6398
|
||||
|
||||
commit 6a39fd3b68ac8a96340b87b9dc8380a9cd4e6398
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Mon Apr 8 23:05:28 2024 +0200
|
||||
|
||||
tests: shell: check for reset tcp options support
|
||||
|
||||
Fixes: 59a33d08ab3a ("parser: tcpopt: fix tcp option parsing with NUM + length field")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
tests/shell/features/reset_tcp_options.nft | 5 +++++
|
||||
tests/shell/testcases/packetpath/tcp_options | 2 ++
|
||||
2 files changed, 7 insertions(+)
|
||||
create mode 100644 tests/shell/features/reset_tcp_options.nft
|
||||
|
||||
diff --git a/tests/shell/features/reset_tcp_options.nft b/tests/shell/features/reset_tcp_options.nft
|
||||
new file mode 100644
|
||||
index 0000000..47d1c7b
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/features/reset_tcp_options.nft
|
||||
@@ -0,0 +1,5 @@
|
||||
+table inet t {
|
||||
+ chain c {
|
||||
+ reset tcp option fastopen
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/packetpath/tcp_options b/tests/shell/testcases/packetpath/tcp_options
|
||||
index 8855222..57e228c 100755
|
||||
--- a/tests/shell/testcases/packetpath/tcp_options
|
||||
+++ b/tests/shell/testcases/packetpath/tcp_options
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_reset_tcp_options)
|
||||
+
|
||||
have_socat="no"
|
||||
socat -h > /dev/null && have_socat="yes"
|
||||
|
||||
51
0089-doc-nft.8-Two-minor-synopsis-fixups.patch
Normal file
51
0089-doc-nft.8-Two-minor-synopsis-fixups.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From dd80c4580464f4eb2f27b10d5a42f0e95499383d Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:43 +0200
|
||||
Subject: [PATCH] doc: nft.8: Two minor synopsis fixups
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 3bccc478d27498f7ecc8a0233176accb1b91f584
|
||||
|
||||
commit 3bccc478d27498f7ecc8a0233176accb1b91f584
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Thu Mar 21 14:57:41 2024 +0100
|
||||
|
||||
doc: nft.8: Two minor synopsis fixups
|
||||
|
||||
The curly braces in 'add table' are to be put literally, so need to be
|
||||
bold. Also, they are optional unless either one (or both) of 'comment'
|
||||
and 'flags' are specified.
|
||||
|
||||
The 'add chain' synopsis contained a stray tick, messing up the
|
||||
following markup.
|
||||
|
||||
Fixes: 7fd67ce121f86 ("doc: fix synopsis of named counter, quota and ct {helper,timeout,expect}")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
doc/nft.txt | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/doc/nft.txt b/doc/nft.txt
|
||||
index dba1b60..2080c07 100644
|
||||
--- a/doc/nft.txt
|
||||
+++ b/doc/nft.txt
|
||||
@@ -321,7 +321,7 @@ Effectively, this is the nft-equivalent of *iptables-save* and
|
||||
TABLES
|
||||
------
|
||||
[verse]
|
||||
-{*add* | *create*} *table* ['family'] 'table' [ {*comment* 'comment' *;*'} *{ flags* 'flags' *; }*]
|
||||
+{*add* | *create*} *table* ['family'] 'table' [*{* [*comment* 'comment' *;*] [*flags* 'flags' *;*] *}*]
|
||||
{*delete* | *destroy* | *list* | *flush*} *table* ['family'] 'table'
|
||||
*list tables* ['family']
|
||||
*delete table* ['family'] *handle* 'handle'
|
||||
@@ -385,7 +385,7 @@ add table inet mytable
|
||||
CHAINS
|
||||
------
|
||||
[verse]
|
||||
-{*add* | *create*} *chain* ['family'] 'table' 'chain' [*{ type* 'type' *hook* 'hook' [*device* 'device'] *priority* 'priority' *;* [*policy* 'policy' *;*] [*comment* 'comment' *;*'] *}*]
|
||||
+{*add* | *create*} *chain* ['family'] 'table' 'chain' [*{ type* 'type' *hook* 'hook' [*device* 'device'] *priority* 'priority' *;* [*policy* 'policy' *;*] [*comment* 'comment' *;*] *}*]
|
||||
{*delete* | *destroy* | *list* | *flush*} *chain* ['family'] 'table' 'chain'
|
||||
*list chains* ['family']
|
||||
*delete chain* ['family'] 'table' *handle* 'handle'
|
||||
94
0090-mergesort-Avoid-accidental-set-element-reordering.patch
Normal file
94
0090-mergesort-Avoid-accidental-set-element-reordering.patch
Normal file
@ -0,0 +1,94 @@
|
||||
From 1e8d5235abba36fde530b3613cbea195c4f927f7 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:08:43 +0200
|
||||
Subject: [PATCH] mergesort: Avoid accidental set element reordering
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit bf52af188b306acf5a30134d6a670f41f16a9459
|
||||
Conflicts: Dropped changes to non-existent .json-nft dump
|
||||
|
||||
commit bf52af188b306acf5a30134d6a670f41f16a9459
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri Mar 22 13:31:10 2024 +0100
|
||||
|
||||
mergesort: Avoid accidental set element reordering
|
||||
|
||||
In corner cases, expr_msort_cmp() may return 0 for two non-identical
|
||||
elements. An example are ORed tcp flags: 'syn' and 'syn | ack' are
|
||||
considered the same value since expr_msort_value() reduces the latter to
|
||||
its LHS.
|
||||
|
||||
Keeping the above in mind and looking at how list_expr_sort() works: The
|
||||
list in 'head' is cut in half, the first half put into the temporary
|
||||
list 'list' and finally 'list' is merged back into 'head' considering
|
||||
each element's position. Shall expr_msort_cmp() return 0 for two
|
||||
elements, the one from 'list' ends up after the one in 'head', thus
|
||||
reverting their previous ordering.
|
||||
|
||||
The practical implication is that output never matches input for the
|
||||
sample set '{ syn, syn | ack }' as the sorting after delinearization in
|
||||
netlink_list_setelems() keeps swapping the elements. Out of coincidence,
|
||||
the commit this fixes itself illustrates the use-case this breaks,
|
||||
namely tracking a ruleset in git: Each ruleset reload will trigger an
|
||||
update to the stored dump.
|
||||
|
||||
This change breaks interval set element deletion because __set_delete()
|
||||
implicitly relies upon this reordering of duplicate entries by inserting
|
||||
a clone of the one to delete into the start (via list_move()) and after
|
||||
sorting assumes the clone will end up right behind the original. Fix
|
||||
this by calling list_move_tail() instead.
|
||||
|
||||
Fixes: 14ee0a979b622 ("src: sort set elements in netlink_get_setelems()")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/intervals.c | 2 +-
|
||||
src/mergesort.c | 2 +-
|
||||
tests/shell/testcases/sets/dumps/0055tcpflags_0.nft | 8 ++++----
|
||||
3 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/intervals.c b/src/intervals.c
|
||||
index 85de019..d5406ef 100644
|
||||
--- a/src/intervals.c
|
||||
+++ b/src/intervals.c
|
||||
@@ -461,7 +461,7 @@ static int __set_delete(struct list_head *msgs, struct expr *i, struct set *set,
|
||||
unsigned int debug_mask)
|
||||
{
|
||||
i->flags |= EXPR_F_REMOVE;
|
||||
- list_move(&i->list, &existing_set->init->expressions);
|
||||
+ list_move_tail(&i->list, &existing_set->init->expressions);
|
||||
list_expr_sort(&existing_set->init->expressions);
|
||||
|
||||
return setelem_delete(msgs, set, init, existing_set->init, debug_mask);
|
||||
diff --git a/src/mergesort.c b/src/mergesort.c
|
||||
index 4d0e280..5e676be 100644
|
||||
--- a/src/mergesort.c
|
||||
+++ b/src/mergesort.c
|
||||
@@ -78,7 +78,7 @@ void list_splice_sorted(struct list_head *list, struct list_head *head)
|
||||
while (l != list) {
|
||||
if (h == head ||
|
||||
expr_msort_cmp(list_entry(l, typeof(struct expr), list),
|
||||
- list_entry(h, typeof(struct expr), list)) < 0) {
|
||||
+ list_entry(h, typeof(struct expr), list)) <= 0) {
|
||||
l = l->next;
|
||||
list_add_tail(l->prev, h);
|
||||
continue;
|
||||
diff --git a/tests/shell/testcases/sets/dumps/0055tcpflags_0.nft b/tests/shell/testcases/sets/dumps/0055tcpflags_0.nft
|
||||
index ffed542..22bf5c4 100644
|
||||
--- a/tests/shell/testcases/sets/dumps/0055tcpflags_0.nft
|
||||
+++ b/tests/shell/testcases/sets/dumps/0055tcpflags_0.nft
|
||||
@@ -2,9 +2,9 @@ table ip test {
|
||||
set tcp_good_flags {
|
||||
type tcp_flag
|
||||
flags constant
|
||||
- elements = { fin | psh | ack | urg, fin | psh | ack, fin | ack | urg, fin | ack, syn | psh | ack | urg,
|
||||
- syn | psh | ack, syn | ack | urg, syn | ack, syn, rst | psh | ack | urg,
|
||||
- rst | psh | ack, rst | ack | urg, rst | ack, rst, psh | ack | urg,
|
||||
- psh | ack, ack | urg, ack }
|
||||
+ elements = { fin | ack, fin | ack | urg, fin | psh | ack, fin | psh | ack | urg, syn,
|
||||
+ syn | ack, syn | ack | urg, syn | psh | ack, syn | psh | ack | urg, rst,
|
||||
+ rst | ack, rst | ack | urg, rst | psh | ack, rst | psh | ack | urg, psh | ack,
|
||||
+ psh | ack | urg, ack, ack | urg }
|
||||
}
|
||||
}
|
||||
37
0091-doc-nft.8-Fix-markup-in-ct-expectation-synopsis.patch
Normal file
37
0091-doc-nft.8-Fix-markup-in-ct-expectation-synopsis.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 481a7da59f20b9c1322a5d26a9bce3e94f04443d Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:09:25 +0200
|
||||
Subject: [PATCH] doc: nft.8: Fix markup in ct expectation synopsis
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit ef659df2a45c38ad18f703febeae8c4febf9dd04
|
||||
|
||||
commit ef659df2a45c38ad18f703febeae8c4febf9dd04
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Wed Apr 24 23:46:11 2024 +0200
|
||||
|
||||
doc: nft.8: Fix markup in ct expectation synopsis
|
||||
|
||||
Just a missing asterisk somewhere.
|
||||
|
||||
Fixes: 1dd08fcfa07a4 ("src: add ct expectations support")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
doc/stateful-objects.txt | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/doc/stateful-objects.txt b/doc/stateful-objects.txt
|
||||
index 00d3c5f..5824d53 100644
|
||||
--- a/doc/stateful-objects.txt
|
||||
+++ b/doc/stateful-objects.txt
|
||||
@@ -119,7 +119,7 @@ sport=41360 dport=22
|
||||
CT EXPECTATION
|
||||
~~~~~~~~~~~~~~
|
||||
[verse]
|
||||
-*add* *ct expectation* ['family'] 'table' 'name' *{ protocol* 'protocol' *; dport* 'dport' *; timeout* 'timeout' *; size* 'size' *; [*l3proto* 'family' *;*] *}*
|
||||
+*add* *ct expectation* ['family'] 'table' 'name' *{ protocol* 'protocol' *; dport* 'dport' *; timeout* 'timeout' *; size* 'size' *;* [*l3proto* 'family' *;*] *}*
|
||||
*delete* *ct expectation* ['family'] 'table' 'name'
|
||||
*list* *ct expectations*
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
From 694638b161288c479b28005db67c403903182a66 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:09:25 +0200
|
||||
Subject: [PATCH] cache: check for NFT_CACHE_REFRESH in current requested cache
|
||||
too
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit bbb0e944b59d355085e8f50b4b7b5057ae0d33a4
|
||||
|
||||
commit bbb0e944b59d355085e8f50b4b7b5057ae0d33a4
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Mon May 27 18:12:05 2024 +0200
|
||||
|
||||
cache: check for NFT_CACHE_REFRESH in current requested cache too
|
||||
|
||||
NFT_CACHE_REFRESH is set on inconditionally by ruleset list commands to
|
||||
deal with stateful information in this ruleset. This flag results in
|
||||
dropping the existing cache and fully fetching all objects from the
|
||||
kernel.
|
||||
|
||||
Set on this flag for reset commands too, this is missing.
|
||||
|
||||
List/reset commands allow for filtering by specific family and object,
|
||||
therefore, NFT_CACHE_REFRESH also signals that the cache is partially
|
||||
populated.
|
||||
|
||||
Check if this flag is requested by the current list/reset command, as
|
||||
well as cache->flags which represents the cache after the _previous_
|
||||
list of commands.
|
||||
|
||||
A follow up patch allows to recycle the existing cache if the flags
|
||||
report that the same objects are already available in the cache,
|
||||
NFT_CACHE_REFRESH is useful to report that cache cannot be recycled.
|
||||
|
||||
Fixes: 407c54f71255 ("src: cache gets out of sync in interactive mode")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/cache.c | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/cache.c b/src/cache.c
|
||||
index c000e32..e88cbae 100644
|
||||
--- a/src/cache.c
|
||||
+++ b/src/cache.c
|
||||
@@ -297,6 +297,7 @@ static unsigned int evaluate_cache_reset(struct cmd *cmd, unsigned int flags,
|
||||
flags |= NFT_CACHE_TABLE;
|
||||
break;
|
||||
}
|
||||
+ flags |= NFT_CACHE_REFRESH;
|
||||
|
||||
return flags;
|
||||
}
|
||||
@@ -1177,9 +1178,10 @@ static bool nft_cache_is_complete(struct nft_cache *cache, unsigned int flags)
|
||||
return (cache->flags & flags) == flags;
|
||||
}
|
||||
|
||||
-static bool nft_cache_needs_refresh(struct nft_cache *cache)
|
||||
+static bool nft_cache_needs_refresh(struct nft_cache *cache, unsigned int flags)
|
||||
{
|
||||
- return cache->flags & NFT_CACHE_REFRESH;
|
||||
+ return (cache->flags & NFT_CACHE_REFRESH) ||
|
||||
+ (flags & NFT_CACHE_REFRESH);
|
||||
}
|
||||
|
||||
static bool nft_cache_is_updated(struct nft_cache *cache, uint16_t genid)
|
||||
@@ -1207,7 +1209,7 @@ int nft_cache_update(struct nft_ctx *nft, unsigned int flags,
|
||||
replay:
|
||||
ctx.seqnum = cache->seqnum++;
|
||||
genid = mnl_genid_get(&ctx);
|
||||
- if (!nft_cache_needs_refresh(cache) &&
|
||||
+ if (!nft_cache_needs_refresh(cache, flags) &&
|
||||
nft_cache_is_complete(cache, flags) &&
|
||||
nft_cache_is_updated(cache, genid))
|
||||
return 0;
|
||||
227
0093-evaluate-bogus-protocol-conflicts-in-vlan-with-impli.patch
Normal file
227
0093-evaluate-bogus-protocol-conflicts-in-vlan-with-impli.patch
Normal file
@ -0,0 +1,227 @@
|
||||
From da2b7b622c703aafa4fb42442b5b74da9828f842 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:09:25 +0200
|
||||
Subject: [PATCH] evaluate: bogus protocol conflicts in vlan with implicit
|
||||
dependencies
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit d1a7e74d1e065d244439fdb0f1c1cba83f921609
|
||||
|
||||
commit d1a7e74d1e065d244439fdb0f1c1cba83f921609
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Wed May 15 19:23:49 2024 +0200
|
||||
|
||||
evaluate: bogus protocol conflicts in vlan with implicit dependencies
|
||||
|
||||
The following command:
|
||||
|
||||
# nft add rule netdev x y ip saddr 10.1.1.1 icmp type echo-request vlan id set 321
|
||||
|
||||
fails with:
|
||||
|
||||
Error: conflicting link layer protocols specified: ether vs. vlan
|
||||
netdev x y ip saddr 10.1.1.1 icmp type echo-request vlan id set 321
|
||||
^^^^^^^
|
||||
|
||||
Users can work around this issue by prepending an explicit match for
|
||||
vlan ethertype field, that is:
|
||||
|
||||
ether type vlan ip saddr 10.1.1.1 ...
|
||||
^-------------^
|
||||
|
||||
but nft should really handle this itself.
|
||||
|
||||
The error above is triggered by the following check in
|
||||
resolve_ll_protocol_conflict():
|
||||
|
||||
/* This payload and the existing context don't match, conflict. */
|
||||
if (pctx->protocol[base + 1].desc != NULL)
|
||||
return 1;
|
||||
|
||||
This check was added by 39f15c243912 ("nft: support listing expressions
|
||||
that use non-byte header fields") and f7d5590688a6 ("tests: vlan tests")
|
||||
to deal with conflicting link layer protocols, for instance:
|
||||
|
||||
ether type ip vlan id 1
|
||||
|
||||
this is matching ethertype ip at offset 12, but then it matches for vlan
|
||||
id at offset 14 which is not present given the previous check.
|
||||
|
||||
One possibility is to remove such check, but nft does not bail out for
|
||||
the example above and it results in bytecode that never matches:
|
||||
|
||||
# nft --debug=netlink netdev x y ether type ip vlan id 10
|
||||
netdev x y
|
||||
[ meta load iiftype => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000001 ]
|
||||
[ payload load 2b @ link header + 12 => reg 1 ] <---- ether type
|
||||
[ cmp eq reg 1 0x00000008 ] <---- ip
|
||||
[ payload load 2b @ link header + 12 => reg 1 ] <---- ether type
|
||||
[ cmp eq reg 1 0x00000081 ] <---- vlan
|
||||
[ payload load 2b @ link header + 14 => reg 1 ]
|
||||
[ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
|
||||
[ cmp eq reg 1 0x00000a00 ]
|
||||
|
||||
This is due to resolve_ll_protocol_conflict() which deals with the
|
||||
conflict by updating protocol context and emitting an implicit
|
||||
dependency, but there is already an explicit match coming from the user.
|
||||
|
||||
This patch adds a new helper function to check if an implicit dependency
|
||||
clashes with an existing statement, which results in:
|
||||
|
||||
# nft add rule netdev x y ether type ip vlan id 1
|
||||
Error: conflicting statements
|
||||
add rule netdev x y ether type ip vlan id 1
|
||||
^^^^^^^^^^^^^ ~~~~~~~
|
||||
|
||||
Theoretically, no duplicated implicit dependency should ever be emitted
|
||||
if protocol context is correctly handled.
|
||||
|
||||
Only implicit payload expressions are considered at this stage for this
|
||||
conflict check, this patch can be extended to deal with other dependency
|
||||
types.
|
||||
|
||||
Fixes: 39f15c243912 ("nft: support listing expressions that use non-byte header fields")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 69 +++++++++++++++++++++++++++++++++++++++++---------
|
||||
1 file changed, 57 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 38a80f2..d8e5dfd 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -759,6 +759,46 @@ static bool proto_is_dummy(const struct proto_desc *desc)
|
||||
return desc == &proto_inet || desc == &proto_netdev;
|
||||
}
|
||||
|
||||
+static int stmt_dep_conflict(struct eval_ctx *ctx, const struct stmt *nstmt)
|
||||
+{
|
||||
+ struct stmt *stmt;
|
||||
+
|
||||
+ list_for_each_entry(stmt, &ctx->rule->stmts, list) {
|
||||
+ if (stmt == nstmt)
|
||||
+ break;
|
||||
+
|
||||
+ if (stmt->ops->type != STMT_EXPRESSION ||
|
||||
+ stmt->expr->etype != EXPR_RELATIONAL ||
|
||||
+ stmt->expr->right->etype != EXPR_VALUE ||
|
||||
+ stmt->expr->left->etype != EXPR_PAYLOAD ||
|
||||
+ stmt->expr->left->etype != nstmt->expr->left->etype ||
|
||||
+ stmt->expr->left->len != nstmt->expr->left->len)
|
||||
+ continue;
|
||||
+
|
||||
+ if (stmt->expr->left->payload.desc != nstmt->expr->left->payload.desc ||
|
||||
+ stmt->expr->left->payload.inner_desc != nstmt->expr->left->payload.inner_desc ||
|
||||
+ stmt->expr->left->payload.base != nstmt->expr->left->payload.base ||
|
||||
+ stmt->expr->left->payload.offset != nstmt->expr->left->payload.offset)
|
||||
+ continue;
|
||||
+
|
||||
+ return stmt_binary_error(ctx, stmt, nstmt,
|
||||
+ "conflicting statements");
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int rule_stmt_dep_add(struct eval_ctx *ctx,
|
||||
+ struct stmt *nstmt, struct stmt *stmt)
|
||||
+{
|
||||
+ rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
|
||||
+
|
||||
+ if (stmt_dep_conflict(ctx, nstmt) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int resolve_ll_protocol_conflict(struct eval_ctx *ctx,
|
||||
const struct proto_desc *desc,
|
||||
struct expr *payload)
|
||||
@@ -782,7 +822,8 @@ static int resolve_ll_protocol_conflict(struct eval_ctx *ctx,
|
||||
return err;
|
||||
|
||||
desc = payload->payload.desc;
|
||||
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
|
||||
+ if (rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
|
||||
+ return -1;
|
||||
}
|
||||
} else {
|
||||
unsigned int i;
|
||||
@@ -794,10 +835,6 @@ static int resolve_ll_protocol_conflict(struct eval_ctx *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
- /* This payload and the existing context don't match, conflict. */
|
||||
- if (pctx->protocol[base + 1].desc != NULL)
|
||||
- return 1;
|
||||
-
|
||||
link = proto_find_num(desc, payload->payload.desc);
|
||||
if (link < 0 ||
|
||||
ll_conflict_resolution_gen_dependency(ctx, link, payload, &nstmt) < 0)
|
||||
@@ -806,7 +843,8 @@ static int resolve_ll_protocol_conflict(struct eval_ctx *ctx,
|
||||
for (i = 0; i < pctx->stacked_ll_count; i++)
|
||||
payload->payload.offset += pctx->stacked_ll[i]->length;
|
||||
|
||||
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
|
||||
+ if (rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
|
||||
+ return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -834,7 +872,8 @@ static int __expr_evaluate_payload(struct eval_ctx *ctx, struct expr *expr)
|
||||
if (payload_gen_dependency(ctx, payload, &nstmt) < 0)
|
||||
return -1;
|
||||
|
||||
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
|
||||
+ if (rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
|
||||
+ return -1;
|
||||
|
||||
desc = pctx->protocol[base].desc;
|
||||
|
||||
@@ -854,7 +893,10 @@ static int __expr_evaluate_payload(struct eval_ctx *ctx, struct expr *expr)
|
||||
|
||||
assert(pctx->stacked_ll_count);
|
||||
payload->payload.offset += pctx->stacked_ll[0]->length;
|
||||
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
|
||||
+
|
||||
+ if (rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
return 1;
|
||||
}
|
||||
goto check_icmp;
|
||||
@@ -895,8 +937,8 @@ check_icmp:
|
||||
if (payload_gen_icmp_dependency(ctx, expr, &nstmt) < 0)
|
||||
return -1;
|
||||
|
||||
- if (nstmt)
|
||||
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
|
||||
+ if (nstmt && rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
|
||||
+ return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -968,7 +1010,8 @@ static int expr_evaluate_inner(struct eval_ctx *ctx, struct expr **exprp)
|
||||
if (payload_gen_inner_dependency(ctx, expr, &nstmt) < 0)
|
||||
return -1;
|
||||
|
||||
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
|
||||
+ if (rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
|
||||
+ return -1;
|
||||
|
||||
proto_ctx_update(pctx, PROTO_BASE_TRANSPORT_HDR, &expr->location, expr->payload.inner_desc);
|
||||
}
|
||||
@@ -1099,7 +1142,9 @@ static int ct_gen_nh_dependency(struct eval_ctx *ctx, struct expr *ct)
|
||||
relational_expr_pctx_update(pctx, dep);
|
||||
|
||||
nstmt = expr_stmt_alloc(&dep->location, dep);
|
||||
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
|
||||
+
|
||||
+ if (rule_stmt_dep_add(ctx, nstmt, ctx->stmt) < 0)
|
||||
+ return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
From e4df7c0617f8ed9d9ef2afcbd5acd398f7582b7d Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:09:25 +0200
|
||||
Subject: [PATCH] evaluate: Fix incorrect checking the `base` variable in case
|
||||
of IPV6
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit f6b579344eee17e5587b6a7fcc444fe997cd8cb6
|
||||
|
||||
commit f6b579344eee17e5587b6a7fcc444fe997cd8cb6
|
||||
Author: Maks Mishin <maks.mishinfz@gmail.com>
|
||||
Date: Wed May 15 23:25:03 2024 +0300
|
||||
|
||||
evaluate: Fix incorrect checking the `base` variable in case of IPV6
|
||||
|
||||
Found by RASU JSC.
|
||||
|
||||
Fixes: 2b29ea5f3c3e ("src: ct: add eval part to inject dependencies for ct saddr/daddr")
|
||||
Signed-off-by: Maks Mishin <maks.mishinFZ@gmail.com>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index d8e5dfd..7f5b64b 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -1106,7 +1106,7 @@ static int ct_gen_nh_dependency(struct eval_ctx *ctx, struct expr *ct)
|
||||
base = pctx->protocol[PROTO_BASE_NETWORK_HDR].desc;
|
||||
if (base == &proto_ip)
|
||||
ct->ct.nfproto = NFPROTO_IPV4;
|
||||
- else if (base == &proto_ip)
|
||||
+ else if (base == &proto_ip6)
|
||||
ct->ct.nfproto = NFPROTO_IPV6;
|
||||
|
||||
if (base)
|
||||
106
0095-scanner-inet_pton-allows-for-broader-IPv4-Mapped-IPv.patch
Normal file
106
0095-scanner-inet_pton-allows-for-broader-IPv4-Mapped-IPv.patch
Normal file
@ -0,0 +1,106 @@
|
||||
From b42e655bbc4f9068a450fadacca2e6c50bc7f13c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:09:25 +0200
|
||||
Subject: [PATCH] scanner: inet_pton() allows for broader IPv4-Mapped IPv6
|
||||
addresses
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit fda913d712925e8a8d6460b361d49774dc5d34b8
|
||||
|
||||
commit fda913d712925e8a8d6460b361d49774dc5d34b8
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Jun 4 20:01:51 2024 +0200
|
||||
|
||||
scanner: inet_pton() allows for broader IPv4-Mapped IPv6 addresses
|
||||
|
||||
inet_pton() allows for broader IPv4-Mapped IPv6 address syntax than
|
||||
those specified by rfc4291 Sect.2.5.5. This patch extends the scanner to
|
||||
support them for compatibility reasons. This allows to represent the
|
||||
last 4 bytes of an IPv6 address as an IPv4 address.
|
||||
|
||||
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1730
|
||||
Fixes: fd513de78bc0 ("scanner: IPv4-Mapped IPv6 addresses support")
|
||||
Fixes: 3f82ef3d0dbf ("scanner: Support rfc4291 IPv4-compatible addresses")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/scanner.l | 47 +++++++++++++++++++++++------------------------
|
||||
1 file changed, 23 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/src/scanner.l b/src/scanner.l
|
||||
index 00a0948..28d6da3 100644
|
||||
--- a/src/scanner.l
|
||||
+++ b/src/scanner.l
|
||||
@@ -132,48 +132,47 @@ slash \/
|
||||
timestring ([0-9]+d)?([0-9]+h)?([0-9]+m)?([0-9]+s)?([0-9]+ms)?
|
||||
|
||||
hex4 ([[:xdigit:]]{1,4})
|
||||
+rfc4291_broader (((:{hex4}){2})|(:{ip4addr}))
|
||||
v680 (({hex4}:){7}{hex4})
|
||||
-v670 ((:)((:{hex4}){7}))
|
||||
-v671 ((({hex4}:){1})((:{hex4}){6}))
|
||||
-v672 ((({hex4}:){2})((:{hex4}){5}))
|
||||
-v673 ((({hex4}:){3})((:{hex4}){4}))
|
||||
-v674 ((({hex4}:){4})((:{hex4}){3}))
|
||||
-v675 ((({hex4}:){5})((:{hex4}){2}))
|
||||
+v670 ((:)((:{hex4}){5}){rfc4291_broader})
|
||||
+v671 ((({hex4}:){1})((:{hex4}){4}){rfc4291_broader})
|
||||
+v672 ((({hex4}:){2})((:{hex4}){3}){rfc4291_broader})
|
||||
+v673 ((({hex4}:){3})((:{hex4}){2}){rfc4291_broader})
|
||||
+v674 ((({hex4}:){4})((:{hex4}){1}){rfc4291_broader})
|
||||
+v675 ((({hex4}:){5}){rfc4291_broader})
|
||||
v676 ((({hex4}:){6})(:{hex4}{1}))
|
||||
v677 ((({hex4}:){7})(:))
|
||||
v67 ({v670}|{v671}|{v672}|{v673}|{v674}|{v675}|{v676}|{v677})
|
||||
-v660 ((:)((:{hex4}){6}))
|
||||
-v661 ((({hex4}:){1})((:{hex4}){5}))
|
||||
-v662 ((({hex4}:){2})((:{hex4}){4}))
|
||||
-v663 ((({hex4}:){3})((:{hex4}){3}))
|
||||
-v664 ((({hex4}:){4})((:{hex4}){2}))
|
||||
+v660 ((:)((:{hex4}){4}){rfc4291_broader})
|
||||
+v661 ((({hex4}:){1})((:{hex4}){3}){rfc4291_broader})
|
||||
+v662 ((({hex4}:){2})((:{hex4}){2}){rfc4291_broader})
|
||||
+v663 ((({hex4}:){3})((:{hex4}){1}){rfc4291_broader})
|
||||
+v664 ((({hex4}:){4}){rfc4291_broader})
|
||||
v665 ((({hex4}:){5})((:{hex4}){1}))
|
||||
v666 ((({hex4}:){6})(:))
|
||||
v66 ({v660}|{v661}|{v662}|{v663}|{v664}|{v665}|{v666})
|
||||
-v650 ((:)((:{hex4}){5}))
|
||||
-v651 ((({hex4}:){1})((:{hex4}){4}))
|
||||
-v652 ((({hex4}:){2})((:{hex4}){3}))
|
||||
-v653 ((({hex4}:){3})((:{hex4}){2}))
|
||||
+v650 ((:)((:{hex4}){3}){rfc4291_broader})
|
||||
+v651 ((({hex4}:){1})((:{hex4}){2}){rfc4291_broader})
|
||||
+v652 ((({hex4}:){2})((:{hex4}){1}){rfc4291_broader})
|
||||
+v653 ((({hex4}:){3}){rfc4291_broader})
|
||||
v654 ((({hex4}:){4})(:{hex4}{1}))
|
||||
v655 ((({hex4}:){5})(:))
|
||||
v65 ({v650}|{v651}|{v652}|{v653}|{v654}|{v655})
|
||||
-v640 ((:)((:{hex4}){4}))
|
||||
-v641 ((({hex4}:){1})((:{hex4}){3}))
|
||||
-v642 ((({hex4}:){2})((:{hex4}){2}))
|
||||
+v640 ((:)((:{hex4}){2}){rfc4291_broader})
|
||||
+v641 ((({hex4}:){1})((:{hex4}){1}){rfc4291_broader})
|
||||
+v642 ((({hex4}:){2}){rfc4291_broader})
|
||||
v643 ((({hex4}:){3})((:{hex4}){1}))
|
||||
v644 ((({hex4}:){4})(:))
|
||||
v64 ({v640}|{v641}|{v642}|{v643}|{v644})
|
||||
-v630 ((:)((:{hex4}){3}))
|
||||
-v631 ((({hex4}:){1})((:{hex4}){2}))
|
||||
+v630 ((:)((:{hex4}){1}){rfc4291_broader})
|
||||
+v631 ((({hex4}:){1}){rfc4291_broader})
|
||||
v632 ((({hex4}:){2})((:{hex4}){1}))
|
||||
v633 ((({hex4}:){3})(:))
|
||||
v63 ({v630}|{v631}|{v632}|{v633})
|
||||
-v620 ((:)((:{hex4}){2}))
|
||||
-v620_rfc4291 ((:)(:{ip4addr}))
|
||||
+v620 ((:){rfc4291_broader})
|
||||
v621 ((({hex4}:){1})((:{hex4}){1}))
|
||||
v622 ((({hex4}:){2})(:))
|
||||
-v62_rfc4291 ((:)(:[fF]{4})(:{ip4addr}))
|
||||
-v62 ({v620}|{v621}|{v622}|{v62_rfc4291}|{v620_rfc4291})
|
||||
+v62 ({v620}|{v621}|{v622})
|
||||
v610 ((:)(:{hex4}{1}))
|
||||
v611 ((({hex4}:){1})(:))
|
||||
v61 ({v610}|{v611})
|
||||
@ -0,0 +1,42 @@
|
||||
From ebe774e477b51465c58e58599a23872b82ec644c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:09:25 +0200
|
||||
Subject: [PATCH] monitor: too large shift exponent displaying payload
|
||||
expression
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 016f37f1268fa1003c46c66655697d3f58d86598
|
||||
|
||||
commit 016f37f1268fa1003c46c66655697d3f58d86598
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Mon Jun 10 19:08:20 2024 +0200
|
||||
|
||||
monitor: too large shift exponent displaying payload expression
|
||||
|
||||
ASAN reports too large shift exponent when displaying traces for raw
|
||||
payload expression:
|
||||
|
||||
trace id ec23e848 ip x y packet: oif "wlan0" src/netlink.c:2100:32: runtime error: shift exponent 1431657095 is too large for 32-bit type 'int'
|
||||
|
||||
skip if proto_unknown_template is set on in this payload expression.
|
||||
|
||||
Fixes: be5d9120e81e ("nft monitor [ trace ]")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/netlink.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/netlink.c b/src/netlink.c
|
||||
index 8637186..72f4ba4 100644
|
||||
--- a/src/netlink.c
|
||||
+++ b/src/netlink.c
|
||||
@@ -2082,6 +2082,7 @@ restart:
|
||||
/* Skip unknown and filtered expressions */
|
||||
desc = lhs->payload.desc;
|
||||
if (lhs->dtype == &invalid_type ||
|
||||
+ lhs->payload.tmpl == &proto_unknown_template ||
|
||||
desc->checksum_key == payload_hdr_field(lhs) ||
|
||||
desc->format.filter & (1 << payload_hdr_field(lhs))) {
|
||||
expr_free(lhs);
|
||||
@ -0,0 +1,65 @@
|
||||
From c296c3d263b6bd897fd807ad174d33a3bfd2e015 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:09:25 +0200
|
||||
Subject: [PATCH] cmd: provide better hint if chain is already declared with
|
||||
different type/hook/priority
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 1f321f86c45fce88a5bcd6f8eafa0157248c8b38
|
||||
|
||||
commit 1f321f86c45fce88a5bcd6f8eafa0157248c8b38
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Mon Jun 10 19:36:21 2024 +0200
|
||||
|
||||
cmd: provide better hint if chain is already declared with different type/hook/priority
|
||||
|
||||
Display the following error in such case:
|
||||
|
||||
ruleset.nft:7:9-52: Error: Chain "input" already exists in table ip 'filter' with different declaration
|
||||
type filter hook postrouting priority filter;
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
instead of reporting a misleading unsupported chain type when updating
|
||||
an existing chain with different type/hook/priority.
|
||||
|
||||
Fixes: 573788e05363 ("src: improve error reporting for unsupported chain type")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/cmd.c | 15 ++++++++++++++-
|
||||
1 file changed, 14 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/cmd.c b/src/cmd.c
|
||||
index 21533e0..de11468 100644
|
||||
--- a/src/cmd.c
|
||||
+++ b/src/cmd.c
|
||||
@@ -256,7 +256,8 @@ static void nft_cmd_enoent(struct netlink_ctx *ctx, const struct cmd *cmd,
|
||||
static int nft_cmd_chain_error(struct netlink_ctx *ctx, struct cmd *cmd,
|
||||
struct mnl_err *err)
|
||||
{
|
||||
- struct chain *chain = cmd->chain;
|
||||
+ struct chain *chain = cmd->chain, *existing_chain;
|
||||
+ const struct table *table;
|
||||
int priority;
|
||||
|
||||
switch (err->err) {
|
||||
@@ -270,6 +271,18 @@ static int nft_cmd_chain_error(struct netlink_ctx *ctx, struct cmd *cmd,
|
||||
return netlink_io_error(ctx, &chain->priority.loc,
|
||||
"Chains of type \"nat\" must have a priority value above -200");
|
||||
|
||||
+ table = table_cache_find(&ctx->nft->cache.table_cache,
|
||||
+ cmd->handle.table.name, cmd->handle.family);
|
||||
+ if (table) {
|
||||
+ existing_chain = chain_cache_find(table, cmd->handle.chain.name);
|
||||
+ if (existing_chain && existing_chain != chain &&
|
||||
+ !strcmp(existing_chain->handle.chain.name, chain->handle.chain.name))
|
||||
+ return netlink_io_error(ctx, &chain->loc,
|
||||
+ "Chain \"%s\" already exists in table %s '%s' with different declaration",
|
||||
+ chain->handle.chain.name,
|
||||
+ family2str(table->handle.family), table->handle.table.name);
|
||||
+ }
|
||||
+
|
||||
return netlink_io_error(ctx, &chain->loc,
|
||||
"Chain of type \"%s\" is not supported, perhaps kernel support is missing?",
|
||||
chain->type.str);
|
||||
@ -0,0 +1,88 @@
|
||||
From 5544e2dd7b3f219d54b06dfc779bdff4646ac420 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:09:25 +0200
|
||||
Subject: [PATCH] cmd: skip variable set elements when collapsing commands
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit be055af5c58d9a4751990684d8f83b85082ca443
|
||||
Conflicts: Dropped changes to non-existent .json-nft dump
|
||||
|
||||
commit be055af5c58d9a4751990684d8f83b85082ca443
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Jun 11 17:40:23 2024 +0200
|
||||
|
||||
cmd: skip variable set elements when collapsing commands
|
||||
|
||||
ASAN reports an issue when collapsing commands that represent an element
|
||||
through a variable:
|
||||
|
||||
include/list.h:60:13: runtime error: member access within null pointer of type 'struct list_head'
|
||||
AddressSanitizer:DEADLYSIGNAL
|
||||
=================================================================
|
||||
==11398==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7ffb77cf09c2 bp 0x7ffc818267c0 sp 0x7ffc818267a0 T0)
|
||||
==11398==The signal is caused by a WRITE memory access.
|
||||
==11398==Hint: address points to the zero page.
|
||||
#0 0x7ffb77cf09c2 in __list_add include/list.h:60
|
||||
#1 0x7ffb77cf0ad9 in list_add_tail include/list.h:87
|
||||
#2 0x7ffb77cf0e72 in list_move_tail include/list.h:169
|
||||
#3 0x7ffb77cf86ad in nft_cmd_collapse src/cmd.c:478
|
||||
#4 0x7ffb77da9f16 in nft_evaluate src/libnftables.c:531
|
||||
#5 0x7ffb77dac471 in __nft_run_cmd_from_filename src/libnftables.c:720
|
||||
#6 0x7ffb77dad703 in nft_run_cmd_from_filename src/libnftables.c:807
|
||||
|
||||
Skip such commands to address this issue.
|
||||
|
||||
This patch also extends tests/shell to cover for this bug.
|
||||
|
||||
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1754
|
||||
Fixes: 498a5f0c219d ("rule: collapse set element commands")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/cmd.c | 3 +++
|
||||
tests/shell/testcases/sets/collapse_elem_0 | 6 ++++++
|
||||
tests/shell/testcases/sets/dumps/collapse_elem_0.nft | 2 +-
|
||||
3 files changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/cmd.c b/src/cmd.c
|
||||
index de11468..8f465de 100644
|
||||
--- a/src/cmd.c
|
||||
+++ b/src/cmd.c
|
||||
@@ -455,6 +455,9 @@ bool nft_cmd_collapse(struct list_head *cmds)
|
||||
continue;
|
||||
}
|
||||
|
||||
+ if (cmd->expr->etype == EXPR_VARIABLE)
|
||||
+ continue;
|
||||
+
|
||||
if (!elems) {
|
||||
elems = cmd;
|
||||
continue;
|
||||
diff --git a/tests/shell/testcases/sets/collapse_elem_0 b/tests/shell/testcases/sets/collapse_elem_0
|
||||
index 7699e9d..52a42c2 100755
|
||||
--- a/tests/shell/testcases/sets/collapse_elem_0
|
||||
+++ b/tests/shell/testcases/sets/collapse_elem_0
|
||||
@@ -17,3 +17,9 @@ add element ip a x { 2 }
|
||||
add element ip6 a x { 2 }"
|
||||
|
||||
$NFT -f - <<< $RULESET
|
||||
+
|
||||
+RULESET="define m = { 3, 4 }
|
||||
+add element ip a x \$m
|
||||
+add element ip a x { 5 }"
|
||||
+
|
||||
+$NFT -f - <<< $RULESET
|
||||
diff --git a/tests/shell/testcases/sets/dumps/collapse_elem_0.nft b/tests/shell/testcases/sets/dumps/collapse_elem_0.nft
|
||||
index a3244fc..775f0ab 100644
|
||||
--- a/tests/shell/testcases/sets/dumps/collapse_elem_0.nft
|
||||
+++ b/tests/shell/testcases/sets/dumps/collapse_elem_0.nft
|
||||
@@ -1,7 +1,7 @@
|
||||
table ip a {
|
||||
set x {
|
||||
type inet_service
|
||||
- elements = { 1, 2 }
|
||||
+ elements = { 1, 2, 3, 4, 5 }
|
||||
}
|
||||
}
|
||||
table ip6 a {
|
||||
@ -0,0 +1,51 @@
|
||||
From 09ae9247749aa7768655696fd099561322b1a90e Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:09:42 +0200
|
||||
Subject: [PATCH] tests: shell: skip ip option tests if kernel does not support
|
||||
it
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit c624578ee18131492e7f72b662d5faf7c042e0d8
|
||||
|
||||
commit c624578ee18131492e7f72b662d5faf7c042e0d8
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Thu Jun 13 00:37:48 2024 +0200
|
||||
|
||||
tests: shell: skip ip option tests if kernel does not support it
|
||||
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
tests/shell/features/ip_options.nft | 8 ++++++++
|
||||
tests/shell/testcases/sets/typeof_sets_0 | 2 ++
|
||||
2 files changed, 10 insertions(+)
|
||||
create mode 100644 tests/shell/features/ip_options.nft
|
||||
|
||||
diff --git a/tests/shell/features/ip_options.nft b/tests/shell/features/ip_options.nft
|
||||
new file mode 100644
|
||||
index 0000000..0b8cb09
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/features/ip_options.nft
|
||||
@@ -0,0 +1,8 @@
|
||||
+# dbb5281a1f84 ("netfilter: nf_tables: add support for matching IPv4 options")
|
||||
+# v5.3-rc1~140^2~153^2~1
|
||||
+
|
||||
+table ip x {
|
||||
+ chain y {
|
||||
+ ip option ra value 255
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/sets/typeof_sets_0 b/tests/shell/testcases/sets/typeof_sets_0
|
||||
index 943c9c2..3a4ed94 100755
|
||||
--- a/tests/shell/testcases/sets/typeof_sets_0
|
||||
+++ b/tests/shell/testcases/sets/typeof_sets_0
|
||||
@@ -4,6 +4,8 @@
|
||||
# s1 and s2 are identical, they just use different
|
||||
# ways for declaration.
|
||||
|
||||
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_ip_options)
|
||||
+
|
||||
set -e
|
||||
|
||||
die() {
|
||||
607
0100-src-add-string-preprocessor-and-use-it-for-log-prefi.patch
Normal file
607
0100-src-add-string-preprocessor-and-use-it-for-log-prefi.patch
Normal file
@ -0,0 +1,607 @@
|
||||
From cf8cedf79d49736dad61f01628a0cf738fefad26 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:09:42 +0200
|
||||
Subject: [PATCH] src: add string preprocessor and use it for log prefix string
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 081bf5f0d7952a6e6ac0d23a365ccf1fd27010c0
|
||||
Conflicts: Manually applied Makefile.am change due to missing commit
|
||||
11e62138424ad ("build: no recursive make for "src/Makefile.am"")
|
||||
|
||||
commit 081bf5f0d7952a6e6ac0d23a365ccf1fd27010c0
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Jun 18 14:26:31 2024 +0200
|
||||
|
||||
src: add string preprocessor and use it for log prefix string
|
||||
|
||||
Add a string preprocessor to identify and replace variables in a string.
|
||||
Rework existing support to variables in log prefix strings to use it.
|
||||
|
||||
Fixes: e76bb3794018 ("src: allow for variables in the log prefix string")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
include/expression.h | 2 -
|
||||
include/parser.h | 4 +
|
||||
include/statement.h | 2 +-
|
||||
src/Makefile.am | 1 +
|
||||
src/evaluate.c | 45 +---------
|
||||
src/expression.c | 9 --
|
||||
src/json.c | 7 +-
|
||||
src/netlink_delinearize.c | 6 +-
|
||||
src/netlink_linearize.c | 7 +-
|
||||
src/optimize.c | 6 +-
|
||||
src/parser_bison.y | 126 ++--------------------------
|
||||
src/parser_json.c | 4 +-
|
||||
src/preprocess.c | 168 ++++++++++++++++++++++++++++++++++++++
|
||||
src/statement.c | 10 +--
|
||||
14 files changed, 198 insertions(+), 199 deletions(-)
|
||||
create mode 100644 src/preprocess.c
|
||||
|
||||
diff --git a/include/expression.h b/include/expression.h
|
||||
index 809089c..e143e71 100644
|
||||
--- a/include/expression.h
|
||||
+++ b/include/expression.h
|
||||
@@ -414,8 +414,6 @@ extern const struct datatype *expr_basetype(const struct expr *expr);
|
||||
extern void expr_set_type(struct expr *expr, const struct datatype *dtype,
|
||||
enum byteorder byteorder);
|
||||
|
||||
-void expr_to_string(const struct expr *expr, char *string);
|
||||
-
|
||||
struct eval_ctx;
|
||||
extern int expr_binary_error(struct list_head *msgs,
|
||||
const struct expr *e1, const struct expr *e2,
|
||||
diff --git a/include/parser.h b/include/parser.h
|
||||
index f79a22f..576e5e4 100644
|
||||
--- a/include/parser.h
|
||||
+++ b/include/parser.h
|
||||
@@ -112,4 +112,8 @@ extern void scanner_push_buffer(void *scanner,
|
||||
|
||||
extern void scanner_pop_start_cond(void *scanner, enum startcond_type sc);
|
||||
|
||||
+const char *str_preprocess(struct parser_state *state, struct location *loc,
|
||||
+ struct scope *scope, const char *x,
|
||||
+ struct error_record **rec);
|
||||
+
|
||||
#endif /* NFTABLES_PARSER_H */
|
||||
diff --git a/include/statement.h b/include/statement.h
|
||||
index 662f99d..9376911 100644
|
||||
--- a/include/statement.h
|
||||
+++ b/include/statement.h
|
||||
@@ -90,7 +90,7 @@ enum {
|
||||
};
|
||||
|
||||
struct log_stmt {
|
||||
- struct expr *prefix;
|
||||
+ const char *prefix;
|
||||
unsigned int snaplen;
|
||||
uint16_t group;
|
||||
uint16_t qthreshold;
|
||||
diff --git a/src/Makefile.am b/src/Makefile.am
|
||||
index 63a4ef4..6d7bb89 100644
|
||||
--- a/src/Makefile.am
|
||||
+++ b/src/Makefile.am
|
||||
@@ -75,6 +75,7 @@ libnftables_la_SOURCES = \
|
||||
nfnl_osf.c \
|
||||
tcpopt.c \
|
||||
socket.c \
|
||||
+ preprocess.c \
|
||||
print.c \
|
||||
sctp_chunk.c \
|
||||
dccpopt.c \
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 7f5b64b..c28f693 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -4292,49 +4292,12 @@ static int stmt_evaluate_queue(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
|
||||
static int stmt_evaluate_log_prefix(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
{
|
||||
- char tmp[NF_LOG_PREFIXLEN] = {};
|
||||
- char prefix[NF_LOG_PREFIXLEN];
|
||||
- size_t len = sizeof(prefix);
|
||||
- size_t offset = 0;
|
||||
- struct expr *expr;
|
||||
-
|
||||
- if (stmt->log.prefix->etype != EXPR_LIST) {
|
||||
- if (stmt->log.prefix &&
|
||||
- div_round_up(stmt->log.prefix->len, BITS_PER_BYTE) >= NF_LOG_PREFIXLEN)
|
||||
- return expr_error(ctx->msgs, stmt->log.prefix, "log prefix is too long");
|
||||
-
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- prefix[0] = '\0';
|
||||
-
|
||||
- list_for_each_entry(expr, &stmt->log.prefix->expressions, list) {
|
||||
- int ret;
|
||||
-
|
||||
- switch (expr->etype) {
|
||||
- case EXPR_VALUE:
|
||||
- expr_to_string(expr, tmp);
|
||||
- ret = snprintf(prefix + offset, len, "%s", tmp);
|
||||
- break;
|
||||
- case EXPR_VARIABLE:
|
||||
- ret = snprintf(prefix + offset, len, "%s",
|
||||
- expr->sym->expr->identifier);
|
||||
- break;
|
||||
- default:
|
||||
- BUG("unknown expression type %s\n", expr_name(expr));
|
||||
- break;
|
||||
- }
|
||||
- SNPRINTF_BUFFER_SIZE(ret, &len, &offset);
|
||||
- }
|
||||
+ unsigned int len = strlen(stmt->log.prefix);
|
||||
|
||||
- if (len == 0)
|
||||
+ if (len >= NF_LOG_PREFIXLEN)
|
||||
return stmt_error(ctx, stmt, "log prefix is too long");
|
||||
-
|
||||
- expr = constant_expr_alloc(&stmt->log.prefix->location, &string_type,
|
||||
- BYTEORDER_HOST_ENDIAN,
|
||||
- strlen(prefix) * BITS_PER_BYTE, prefix);
|
||||
- expr_free(stmt->log.prefix);
|
||||
- stmt->log.prefix = expr;
|
||||
+ else if (len == 0)
|
||||
+ return stmt_error(ctx, stmt, "log prefix must have a minimum length of 1 character");
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/src/expression.c b/src/expression.c
|
||||
index cb2573f..992f510 100644
|
||||
--- a/src/expression.c
|
||||
+++ b/src/expression.c
|
||||
@@ -183,15 +183,6 @@ void expr_describe(const struct expr *expr, struct output_ctx *octx)
|
||||
}
|
||||
}
|
||||
|
||||
-void expr_to_string(const struct expr *expr, char *string)
|
||||
-{
|
||||
- int len = expr->len / BITS_PER_BYTE;
|
||||
-
|
||||
- assert(expr->dtype == &string_type);
|
||||
-
|
||||
- mpz_export_data(string, expr->value, BYTEORDER_HOST_ENDIAN, len);
|
||||
-}
|
||||
-
|
||||
void expr_set_type(struct expr *expr, const struct datatype *dtype,
|
||||
enum byteorder byteorder)
|
||||
{
|
||||
diff --git a/src/json.c b/src/json.c
|
||||
index b3e1e4e..5faeb4d 100644
|
||||
--- a/src/json.c
|
||||
+++ b/src/json.c
|
||||
@@ -1319,12 +1319,9 @@ json_t *log_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
||||
{
|
||||
json_t *root = json_object(), *flags;
|
||||
|
||||
- if (stmt->log.flags & STMT_LOG_PREFIX) {
|
||||
- char prefix[NF_LOG_PREFIXLEN] = {};
|
||||
+ if (stmt->log.flags & STMT_LOG_PREFIX)
|
||||
+ json_object_set_new(root, "prefix", json_string(stmt->log.prefix));
|
||||
|
||||
- expr_to_string(stmt->log.prefix, prefix);
|
||||
- json_object_set_new(root, "prefix", json_string(prefix));
|
||||
- }
|
||||
if (stmt->log.flags & STMT_LOG_GROUP)
|
||||
json_object_set_new(root, "group",
|
||||
json_integer(stmt->log.group));
|
||||
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
|
||||
index 1af0278..0ea10ee 100644
|
||||
--- a/src/netlink_delinearize.c
|
||||
+++ b/src/netlink_delinearize.c
|
||||
@@ -1090,11 +1090,7 @@ static void netlink_parse_log(struct netlink_parse_ctx *ctx,
|
||||
stmt = log_stmt_alloc(loc);
|
||||
prefix = nftnl_expr_get_str(nle, NFTNL_EXPR_LOG_PREFIX);
|
||||
if (nftnl_expr_is_set(nle, NFTNL_EXPR_LOG_PREFIX)) {
|
||||
- stmt->log.prefix = constant_expr_alloc(&internal_location,
|
||||
- &string_type,
|
||||
- BYTEORDER_HOST_ENDIAN,
|
||||
- (strlen(prefix) + 1) * BITS_PER_BYTE,
|
||||
- prefix);
|
||||
+ stmt->log.prefix = xstrdup(prefix);
|
||||
stmt->log.flags |= STMT_LOG_PREFIX;
|
||||
}
|
||||
if (nftnl_expr_is_set(nle, NFTNL_EXPR_LOG_GROUP)) {
|
||||
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
|
||||
index df395ba..a2a1cd5 100644
|
||||
--- a/src/netlink_linearize.c
|
||||
+++ b/src/netlink_linearize.c
|
||||
@@ -1141,12 +1141,9 @@ static void netlink_gen_log_stmt(struct netlink_linearize_ctx *ctx,
|
||||
struct nftnl_expr *nle;
|
||||
|
||||
nle = alloc_nft_expr("log");
|
||||
- if (stmt->log.prefix != NULL) {
|
||||
- char prefix[NF_LOG_PREFIXLEN] = {};
|
||||
+ if (stmt->log.prefix != NULL)
|
||||
+ nftnl_expr_set_str(nle, NFTNL_EXPR_LOG_PREFIX, stmt->log.prefix);
|
||||
|
||||
- expr_to_string(stmt->log.prefix, prefix);
|
||||
- nftnl_expr_set_str(nle, NFTNL_EXPR_LOG_PREFIX, prefix);
|
||||
- }
|
||||
if (stmt->log.flags & STMT_LOG_GROUP) {
|
||||
nftnl_expr_set_u16(nle, NFTNL_EXPR_LOG_GROUP, stmt->log.group);
|
||||
if (stmt->log.flags & STMT_LOG_SNAPLEN)
|
||||
diff --git a/src/optimize.c b/src/optimize.c
|
||||
index b90dd99..1dd0858 100644
|
||||
--- a/src/optimize.c
|
||||
+++ b/src/optimize.c
|
||||
@@ -215,9 +215,7 @@ static bool __stmt_type_eq(const struct stmt *stmt_a, const struct stmt *stmt_b,
|
||||
if (!stmt_a->log.prefix)
|
||||
return true;
|
||||
|
||||
- if (stmt_a->log.prefix->etype != EXPR_VALUE ||
|
||||
- stmt_b->log.prefix->etype != EXPR_VALUE ||
|
||||
- mpz_cmp(stmt_a->log.prefix->value, stmt_b->log.prefix->value))
|
||||
+ if (strcmp(stmt_a->log.prefix, stmt_b->log.prefix))
|
||||
return false;
|
||||
break;
|
||||
case STMT_REJECT:
|
||||
@@ -406,7 +404,7 @@ static int rule_collect_stmts(struct optimize_ctx *ctx, struct rule *rule)
|
||||
case STMT_LOG:
|
||||
memcpy(&clone->log, &stmt->log, sizeof(clone->log));
|
||||
if (stmt->log.prefix)
|
||||
- clone->log.prefix = expr_get(stmt->log.prefix);
|
||||
+ clone->log.prefix = xstrdup(stmt->log.prefix);
|
||||
break;
|
||||
case STMT_NAT:
|
||||
if ((stmt->nat.addr &&
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index e3ac2fb..678dd50 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -3338,127 +3338,19 @@ log_args : log_arg
|
||||
log_arg : PREFIX string
|
||||
{
|
||||
struct scope *scope = current_scope(state);
|
||||
- bool done = false, another_var = false;
|
||||
- char *start, *end, scratch = '\0';
|
||||
- struct expr *expr, *item;
|
||||
- struct symbol *sym;
|
||||
- enum {
|
||||
- PARSE_TEXT,
|
||||
- PARSE_VAR,
|
||||
- } prefix_state;
|
||||
-
|
||||
- /* No variables in log prefix, skip. */
|
||||
- if (!strchr($2, '$')) {
|
||||
- expr = constant_expr_alloc(&@$, &string_type,
|
||||
- BYTEORDER_HOST_ENDIAN,
|
||||
- (strlen($2) + 1) * BITS_PER_BYTE, $2);
|
||||
- free_const($2);
|
||||
- $<stmt>0->log.prefix = expr;
|
||||
- $<stmt>0->log.flags |= STMT_LOG_PREFIX;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- /* Parse variables in log prefix string using a
|
||||
- * state machine parser with two states. This
|
||||
- * parser creates list of expressions composed
|
||||
- * of constant and variable expressions.
|
||||
- */
|
||||
- expr = compound_expr_alloc(&@$, EXPR_LIST);
|
||||
-
|
||||
- start = (char *)$2;
|
||||
+ struct error_record *erec;
|
||||
+ const char *prefix;
|
||||
|
||||
- if (*start != '$') {
|
||||
- prefix_state = PARSE_TEXT;
|
||||
- } else {
|
||||
- prefix_state = PARSE_VAR;
|
||||
- start++;
|
||||
- }
|
||||
- end = start;
|
||||
-
|
||||
- /* Not nice, but works. */
|
||||
- while (!done) {
|
||||
- switch (prefix_state) {
|
||||
- case PARSE_TEXT:
|
||||
- while (*end != '\0' && *end != '$')
|
||||
- end++;
|
||||
-
|
||||
- if (*end == '\0')
|
||||
- done = true;
|
||||
-
|
||||
- *end = '\0';
|
||||
- item = constant_expr_alloc(&@$, &string_type,
|
||||
- BYTEORDER_HOST_ENDIAN,
|
||||
- (strlen(start) + 1) * BITS_PER_BYTE,
|
||||
- start);
|
||||
- compound_expr_add(expr, item);
|
||||
-
|
||||
- if (done)
|
||||
- break;
|
||||
-
|
||||
- start = end + 1;
|
||||
- end = start;
|
||||
-
|
||||
- /* fall through */
|
||||
- case PARSE_VAR:
|
||||
- while (isalnum(*end) || *end == '_')
|
||||
- end++;
|
||||
-
|
||||
- if (*end == '\0')
|
||||
- done = true;
|
||||
- else if (*end == '$')
|
||||
- another_var = true;
|
||||
- else
|
||||
- scratch = *end;
|
||||
-
|
||||
- *end = '\0';
|
||||
-
|
||||
- sym = symbol_get(scope, start);
|
||||
- if (!sym) {
|
||||
- sym = symbol_lookup_fuzzy(scope, start);
|
||||
- if (sym) {
|
||||
- erec_queue(error(&@2, "unknown identifier '%s'; "
|
||||
- "did you mean identifier ‘%s’?",
|
||||
- start, sym->identifier),
|
||||
- state->msgs);
|
||||
- } else {
|
||||
- erec_queue(error(&@2, "unknown identifier '%s'",
|
||||
- start),
|
||||
- state->msgs);
|
||||
- }
|
||||
- expr_free(expr);
|
||||
- free_const($2);
|
||||
- YYERROR;
|
||||
- }
|
||||
- item = variable_expr_alloc(&@$, scope, sym);
|
||||
- compound_expr_add(expr, item);
|
||||
-
|
||||
- if (done)
|
||||
- break;
|
||||
-
|
||||
- /* Restore original byte after
|
||||
- * symbol lookup.
|
||||
- */
|
||||
- if (scratch) {
|
||||
- *end = scratch;
|
||||
- scratch = '\0';
|
||||
- }
|
||||
-
|
||||
- start = end;
|
||||
- if (another_var) {
|
||||
- another_var = false;
|
||||
- start++;
|
||||
- prefix_state = PARSE_VAR;
|
||||
- } else {
|
||||
- prefix_state = PARSE_TEXT;
|
||||
- }
|
||||
- end = start;
|
||||
- break;
|
||||
- }
|
||||
+ prefix = str_preprocess(state, &@2, scope, $2, &erec);
|
||||
+ if (!prefix) {
|
||||
+ erec_queue(erec, state->msgs);
|
||||
+ free_const($2);
|
||||
+ YYERROR;
|
||||
}
|
||||
|
||||
free_const($2);
|
||||
- $<stmt>0->log.prefix = expr;
|
||||
- $<stmt>0->log.flags |= STMT_LOG_PREFIX;
|
||||
+ $<stmt>0->log.prefix = prefix;
|
||||
+ $<stmt>0->log.flags |= STMT_LOG_PREFIX;
|
||||
}
|
||||
| GROUP NUM
|
||||
{
|
||||
diff --git a/src/parser_json.c b/src/parser_json.c
|
||||
index 25483b1..ce36397 100644
|
||||
--- a/src/parser_json.c
|
||||
+++ b/src/parser_json.c
|
||||
@@ -2540,9 +2540,7 @@ static struct stmt *json_parse_log_stmt(struct json_ctx *ctx,
|
||||
stmt = log_stmt_alloc(int_loc);
|
||||
|
||||
if (!json_unpack(value, "{s:s}", "prefix", &tmpstr)) {
|
||||
- stmt->log.prefix = constant_expr_alloc(int_loc, &string_type,
|
||||
- BYTEORDER_HOST_ENDIAN,
|
||||
- (strlen(tmpstr) + 1) * BITS_PER_BYTE, tmpstr);
|
||||
+ stmt->log.prefix = xstrdup(tmpstr);
|
||||
stmt->log.flags |= STMT_LOG_PREFIX;
|
||||
}
|
||||
if (!json_unpack(value, "{s:i}", "group", &tmp)) {
|
||||
diff --git a/src/preprocess.c b/src/preprocess.c
|
||||
new file mode 100644
|
||||
index 0000000..619f67a
|
||||
--- /dev/null
|
||||
+++ b/src/preprocess.c
|
||||
@@ -0,0 +1,168 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2013-2024 Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 (or any
|
||||
+ * later) as published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <ctype.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdint.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <string.h>
|
||||
+#include <utils.h>
|
||||
+
|
||||
+#include "list.h"
|
||||
+#include "parser.h"
|
||||
+#include "erec.h"
|
||||
+
|
||||
+struct str_buf {
|
||||
+ uint8_t *str;
|
||||
+ uint32_t len;
|
||||
+ uint32_t size;
|
||||
+};
|
||||
+
|
||||
+#define STR_BUF_LEN 128
|
||||
+
|
||||
+static struct str_buf *str_buf_alloc(void)
|
||||
+{
|
||||
+ struct str_buf *buf;
|
||||
+
|
||||
+ buf = xzalloc(sizeof(*buf));
|
||||
+ buf->str = xzalloc_array(1, STR_BUF_LEN);
|
||||
+ buf->size = STR_BUF_LEN;
|
||||
+
|
||||
+ return buf;
|
||||
+}
|
||||
+
|
||||
+static int str_buf_add(struct str_buf *buf, const char *str, uint32_t len)
|
||||
+{
|
||||
+ uint8_t *tmp;
|
||||
+
|
||||
+ if (len + buf->len > buf->size) {
|
||||
+ buf->size = (len + buf->len) * 2;
|
||||
+ tmp = xrealloc(buf->str, buf->size);
|
||||
+ buf->str = tmp;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(&buf->str[buf->len], str, len);
|
||||
+ buf->len += len;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+struct str_chunk {
|
||||
+ struct list_head list;
|
||||
+ char *str;
|
||||
+ uint32_t len;
|
||||
+ bool is_sym;
|
||||
+};
|
||||
+
|
||||
+static void add_str_chunk(const char *x, int from, int to, struct list_head *list, bool is_sym)
|
||||
+{
|
||||
+ struct str_chunk *chunk;
|
||||
+ int len = to - from;
|
||||
+
|
||||
+ chunk = xzalloc_array(1, sizeof(*chunk));
|
||||
+ chunk->str = xzalloc_array(1, len + 1);
|
||||
+ chunk->is_sym = is_sym;
|
||||
+ chunk->len = len;
|
||||
+ memcpy(chunk->str, &x[from], len);
|
||||
+
|
||||
+ list_add_tail(&chunk->list, list);
|
||||
+}
|
||||
+
|
||||
+static void free_str_chunk(struct str_chunk *chunk)
|
||||
+{
|
||||
+ free(chunk->str);
|
||||
+ free(chunk);
|
||||
+}
|
||||
+
|
||||
+const char *str_preprocess(struct parser_state *state, struct location *loc,
|
||||
+ struct scope *scope, const char *x,
|
||||
+ struct error_record **erec)
|
||||
+{
|
||||
+ struct str_chunk *chunk, *next;
|
||||
+ struct str_buf *buf;
|
||||
+ const char *str;
|
||||
+ int i, j, start;
|
||||
+ LIST_HEAD(list);
|
||||
+
|
||||
+ start = 0;
|
||||
+ i = 0;
|
||||
+ while (1) {
|
||||
+ if (x[i] == '\0') {
|
||||
+ i++;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (x[i] != '$') {
|
||||
+ i++;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (isdigit(x[++i]))
|
||||
+ continue;
|
||||
+
|
||||
+ j = i;
|
||||
+ while (1) {
|
||||
+ if (isalpha(x[i]) ||
|
||||
+ isdigit(x[i]) ||
|
||||
+ x[i] == '_') {
|
||||
+ i++;
|
||||
+ continue;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ add_str_chunk(x, start, j-1, &list, false);
|
||||
+ add_str_chunk(x, j, i, &list, true);
|
||||
+ start = i;
|
||||
+ }
|
||||
+ if (start != i)
|
||||
+ add_str_chunk(x, start, i, &list, false);
|
||||
+
|
||||
+ buf = str_buf_alloc();
|
||||
+
|
||||
+ list_for_each_entry_safe(chunk, next, &list, list) {
|
||||
+ if (chunk->is_sym) {
|
||||
+ struct symbol *sym;
|
||||
+
|
||||
+ sym = symbol_lookup(scope, chunk->str);
|
||||
+ if (!sym) {
|
||||
+ sym = symbol_lookup_fuzzy(scope, chunk->str);
|
||||
+ if (sym) {
|
||||
+ *erec = error(loc, "unknown identifier '%s'; "
|
||||
+ "did you mean identifier '%s'?",
|
||||
+ chunk->str, sym->identifier);
|
||||
+ } else {
|
||||
+ *erec = error(loc, "unknown identifier '%s'",
|
||||
+ chunk->str);
|
||||
+ }
|
||||
+ goto err;
|
||||
+ }
|
||||
+ str_buf_add(buf, sym->expr->identifier,
|
||||
+ strlen(sym->expr->identifier));
|
||||
+ } else {
|
||||
+ str_buf_add(buf, chunk->str, chunk->len);
|
||||
+ }
|
||||
+ list_del(&chunk->list);
|
||||
+ free_str_chunk(chunk);
|
||||
+ }
|
||||
+
|
||||
+ str = (char *)buf->str;
|
||||
+
|
||||
+ free(buf);
|
||||
+
|
||||
+ return (char *)str;
|
||||
+err:
|
||||
+ list_for_each_entry_safe(chunk, next, &list, list) {
|
||||
+ list_del(&chunk->list);
|
||||
+ free_str_chunk(chunk);
|
||||
+ }
|
||||
+ free(buf->str);
|
||||
+ free(buf);
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
diff --git a/src/statement.c b/src/statement.c
|
||||
index ab144d6..551cd13 100644
|
||||
--- a/src/statement.c
|
||||
+++ b/src/statement.c
|
||||
@@ -377,12 +377,8 @@ int log_level_parse(const char *level)
|
||||
static void log_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
|
||||
{
|
||||
nft_print(octx, "log");
|
||||
- if (stmt->log.flags & STMT_LOG_PREFIX) {
|
||||
- char prefix[NF_LOG_PREFIXLEN] = {};
|
||||
-
|
||||
- expr_to_string(stmt->log.prefix, prefix);
|
||||
- nft_print(octx, " prefix \"%s\"", prefix);
|
||||
- }
|
||||
+ if (stmt->log.flags & STMT_LOG_PREFIX)
|
||||
+ nft_print(octx, " prefix \"%s\"", stmt->log.prefix);
|
||||
if (stmt->log.flags & STMT_LOG_GROUP)
|
||||
nft_print(octx, " group %u", stmt->log.group);
|
||||
if (stmt->log.flags & STMT_LOG_SNAPLEN)
|
||||
@@ -419,7 +415,7 @@ static void log_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
|
||||
|
||||
static void log_stmt_destroy(struct stmt *stmt)
|
||||
{
|
||||
- expr_free(stmt->log.prefix);
|
||||
+ free_const(stmt->log.prefix);
|
||||
}
|
||||
|
||||
static const struct stmt_ops log_stmt_ops = {
|
||||
110
0101-intervals-fix-element-deletions-with-maps.patch
Normal file
110
0101-intervals-fix-element-deletions-with-maps.patch
Normal file
@ -0,0 +1,110 @@
|
||||
From bbfd033cb9014f854f6a4db3cec2aafe160847d4 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:08 +0200
|
||||
Subject: [PATCH] intervals: fix element deletions with maps
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 551a4ad68b922fa6c942f5e79ac59f723a12e233
|
||||
|
||||
commit 551a4ad68b922fa6c942f5e79ac59f723a12e233
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Wed Jul 3 16:29:26 2024 +0200
|
||||
|
||||
intervals: fix element deletions with maps
|
||||
|
||||
Set element deletion in maps (including catchall elements) does not work.
|
||||
|
||||
# nft delete element ip x m { \* }
|
||||
BUG: invalid range expression type catch-all set element
|
||||
nft: src/expression.c:1472: range_expr_value_low: Assertion `0' failed.
|
||||
Aborted
|
||||
|
||||
Call interval_expr_key() to fetch expr->left in the mapping but use the
|
||||
expression that represents the mapping because it provides access to the
|
||||
EXPR_F_REMOVE flags.
|
||||
|
||||
Moreover, assume maximum value for catchall expression by means of the
|
||||
expr->len to reuse the existing code to check if the element to be
|
||||
deleted really exists.
|
||||
|
||||
Fixes: 3e8d934e4f72 ("intervals: support to partial deletion with automerge")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/intervals.c | 31 ++++++++++++++++++-------------
|
||||
1 file changed, 18 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/intervals.c b/src/intervals.c
|
||||
index d5406ef..af1415a 100644
|
||||
--- a/src/intervals.c
|
||||
+++ b/src/intervals.c
|
||||
@@ -378,7 +378,7 @@ static int setelem_delete(struct list_head *msgs, struct set *set,
|
||||
struct expr *purge, struct expr *elems,
|
||||
unsigned int debug_mask)
|
||||
{
|
||||
- struct expr *i, *next, *prev = NULL;
|
||||
+ struct expr *i, *next, *elem, *prev = NULL;
|
||||
struct range range, prev_range;
|
||||
int err = 0;
|
||||
mpz_t rop;
|
||||
@@ -389,21 +389,26 @@ static int setelem_delete(struct list_head *msgs, struct set *set,
|
||||
mpz_init(range.high);
|
||||
mpz_init(rop);
|
||||
|
||||
- list_for_each_entry_safe(i, next, &elems->expressions, list) {
|
||||
- if (i->key->etype == EXPR_SET_ELEM_CATCHALL)
|
||||
- continue;
|
||||
+ list_for_each_entry_safe(elem, next, &elems->expressions, list) {
|
||||
+ i = interval_expr_key(elem);
|
||||
|
||||
- range_expr_value_low(range.low, i);
|
||||
- range_expr_value_high(range.high, i);
|
||||
+ if (i->key->etype == EXPR_SET_ELEM_CATCHALL) {
|
||||
+ /* Assume max value to simplify handling. */
|
||||
+ mpz_bitmask(range.low, i->len);
|
||||
+ mpz_bitmask(range.high, i->len);
|
||||
+ } else {
|
||||
+ range_expr_value_low(range.low, i);
|
||||
+ range_expr_value_high(range.high, i);
|
||||
+ }
|
||||
|
||||
- if (!prev && i->flags & EXPR_F_REMOVE) {
|
||||
+ if (!prev && elem->flags & EXPR_F_REMOVE) {
|
||||
expr_error(msgs, i, "element does not exist");
|
||||
err = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
- if (!(i->flags & EXPR_F_REMOVE)) {
|
||||
- prev = i;
|
||||
+ if (!(elem->flags & EXPR_F_REMOVE)) {
|
||||
+ prev = elem;
|
||||
mpz_set(prev_range.low, range.low);
|
||||
mpz_set(prev_range.high, range.high);
|
||||
continue;
|
||||
@@ -411,12 +416,12 @@ static int setelem_delete(struct list_head *msgs, struct set *set,
|
||||
|
||||
if (mpz_cmp(prev_range.low, range.low) == 0 &&
|
||||
mpz_cmp(prev_range.high, range.high) == 0) {
|
||||
- if (i->flags & EXPR_F_REMOVE) {
|
||||
+ if (elem->flags & EXPR_F_REMOVE) {
|
||||
if (prev->flags & EXPR_F_KERNEL)
|
||||
list_move_tail(&prev->list, &purge->expressions);
|
||||
|
||||
- list_del(&i->list);
|
||||
- expr_free(i);
|
||||
+ list_del(&elem->list);
|
||||
+ expr_free(elem);
|
||||
}
|
||||
} else if (set->automerge) {
|
||||
if (setelem_adjust(set, purge, &prev_range, &range, prev, i) < 0) {
|
||||
@@ -424,7 +429,7 @@ static int setelem_delete(struct list_head *msgs, struct set *set,
|
||||
err = -1;
|
||||
goto err;
|
||||
}
|
||||
- } else if (i->flags & EXPR_F_REMOVE) {
|
||||
+ } else if (elem->flags & EXPR_F_REMOVE) {
|
||||
expr_error(msgs, i, "element does not exist");
|
||||
err = -1;
|
||||
goto err;
|
||||
@ -0,0 +1,68 @@
|
||||
From 765603a3236f4d50de140148bd2a0a950c334aab Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:08 +0200
|
||||
Subject: [PATCH] parser_bison: recursive table declaration in deprecated meter
|
||||
statement
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit a70a217079ef83482fc093d8549f8cdeaeaa3cae
|
||||
|
||||
commit a70a217079ef83482fc093d8549f8cdeaeaa3cae
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Wed Jul 3 00:08:01 2024 +0200
|
||||
|
||||
parser_bison: recursive table declaration in deprecated meter statement
|
||||
|
||||
This is allowing for recursive table NAME declarations such as:
|
||||
|
||||
... table xyz1 table xyz2 { ... }
|
||||
|
||||
remove it.
|
||||
|
||||
Fixes: 3ed5e31f4a32 ("src: add flow statement")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_bison.y | 20 ++++----------------
|
||||
1 file changed, 4 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 678dd50..87cf9ae 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -4178,10 +4178,11 @@ map_stmt : set_stmt_op set_ref_expr '{' set_elem_expr_stmt COLON set_elem_expr_
|
||||
}
|
||||
;
|
||||
|
||||
-meter_stmt : flow_stmt_legacy_alloc flow_stmt_opts '{' meter_key_expr stmt '}'
|
||||
+meter_stmt : flow_stmt_legacy_alloc TABLE identifier '{' meter_key_expr stmt '}'
|
||||
{
|
||||
- $1->meter.key = $4;
|
||||
- $1->meter.stmt = $5;
|
||||
+ $1->meter.name = $3;
|
||||
+ $1->meter.key = $5;
|
||||
+ $1->meter.stmt = $6;
|
||||
$$->location = @$;
|
||||
$$ = $1;
|
||||
}
|
||||
@@ -4194,19 +4195,6 @@ flow_stmt_legacy_alloc : FLOW
|
||||
}
|
||||
;
|
||||
|
||||
-flow_stmt_opts : flow_stmt_opt
|
||||
- {
|
||||
- $<stmt>$ = $<stmt>0;
|
||||
- }
|
||||
- | flow_stmt_opts flow_stmt_opt
|
||||
- ;
|
||||
-
|
||||
-flow_stmt_opt : TABLE identifier
|
||||
- {
|
||||
- $<stmt>0->meter.name = $2;
|
||||
- }
|
||||
- ;
|
||||
-
|
||||
meter_stmt_alloc : METER identifier '{' meter_key_expr stmt '}'
|
||||
{
|
||||
$$ = meter_stmt_alloc(&@$);
|
||||
@ -0,0 +1,59 @@
|
||||
From e9372be1f7b089f58c49d3093f0973c2bf5bfc9a Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:08 +0200
|
||||
Subject: [PATCH] evaluate: set on expr->len for catchall set elements
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit b523008535f3de78ed5834a302ba07cda4b4c8fd
|
||||
|
||||
commit b523008535f3de78ed5834a302ba07cda4b4c8fd
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Thu Jul 4 16:38:22 2024 +0200
|
||||
|
||||
evaluate: set on expr->len for catchall set elements
|
||||
|
||||
Catchall elements coming from the parser provide expr->len == 0.
|
||||
However, the existing mergesort implementation requires expr->len to be
|
||||
set up to the length of the set key to properly sort elements.
|
||||
|
||||
In particular, set element deletion leverages such list sorting to find
|
||||
if elements exists in the set.
|
||||
|
||||
Fixes: 419d19688688 ("src: add set element catch-all support")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/evaluate.c | 12 +++++++++++-
|
||||
1 file changed, 11 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index c28f693..af811a7 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -1802,6 +1802,16 @@ err_missing_flag:
|
||||
set_is_map(ctx->set->flags) ? "map" : "set", expr_name(key));
|
||||
}
|
||||
|
||||
+static int expr_evaluate_set_elem_catchall(struct eval_ctx *ctx, struct expr **expr)
|
||||
+{
|
||||
+ struct expr *elem = *expr;
|
||||
+
|
||||
+ if (ctx->set)
|
||||
+ elem->len = ctx->set->key->len;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const struct expr *expr_set_elem(const struct expr *expr)
|
||||
{
|
||||
if (expr->etype == EXPR_MAPPING)
|
||||
@@ -2866,7 +2876,7 @@ static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr)
|
||||
case EXPR_XFRM:
|
||||
return expr_evaluate_xfrm(ctx, expr);
|
||||
case EXPR_SET_ELEM_CATCHALL:
|
||||
- return 0;
|
||||
+ return expr_evaluate_set_elem_catchall(ctx, expr);
|
||||
case EXPR_FLAGCMP:
|
||||
return expr_evaluate_flagcmp(ctx, expr);
|
||||
default:
|
||||
@ -0,0 +1,43 @@
|
||||
From a49ad23fb841de5c9c7debd135eb3cb8fe47d444 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:08 +0200
|
||||
Subject: [PATCH] segtree: set on EXPR_F_KERNEL flag for catchall elements in
|
||||
the cache
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit dc6950a80110d6e6f63bd6f5c308d202db698f46
|
||||
|
||||
commit dc6950a80110d6e6f63bd6f5c308d202db698f46
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Thu Jul 4 14:35:07 2024 +0200
|
||||
|
||||
segtree: set on EXPR_F_KERNEL flag for catchall elements in the cache
|
||||
|
||||
Catchall set element deletion requires this flag to be set on,
|
||||
otherwise it bogusly reports that such element does not exist
|
||||
in the set.
|
||||
|
||||
Fixes: f1cc44edb218 ("src: add EXPR_F_KERNEL to identify expression in the kernel")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/segtree.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/segtree.c b/src/segtree.c
|
||||
index 7d246de..c5f27c9 100644
|
||||
--- a/src/segtree.c
|
||||
+++ b/src/segtree.c
|
||||
@@ -653,8 +653,10 @@ void interval_map_decompose(struct expr *set)
|
||||
expr_free(i);
|
||||
|
||||
out:
|
||||
- if (catchall)
|
||||
+ if (catchall) {
|
||||
+ catchall->flags |= EXPR_F_KERNEL;
|
||||
compound_expr_add(set, catchall);
|
||||
+ }
|
||||
|
||||
free(ranges);
|
||||
free(elements);
|
||||
143
0105-optimize-clone-counter-before-insertion-into-set-ele.patch
Normal file
143
0105-optimize-clone-counter-before-insertion-into-set-ele.patch
Normal file
@ -0,0 +1,143 @@
|
||||
From 6804a55496761b1366ffa5e554f9658cfd55548a Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:08 +0200
|
||||
Subject: [PATCH] optimize: clone counter before insertion into set element
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit ac77f3805c71f14c51730a9c5cb726ee67f14159
|
||||
|
||||
commit ac77f3805c71f14c51730a9c5cb726ee67f14159
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Fri Jul 5 14:03:33 2024 +0200
|
||||
|
||||
optimize: clone counter before insertion into set element
|
||||
|
||||
The counter statement that is zapped from the rule needs to be cloned
|
||||
before inserting it into each set element.
|
||||
|
||||
Fixes: 686ab8b6996e ("optimize: do not remove counter in verdict maps")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/optimize.c | 24 +++++++++++++------
|
||||
.../optimizations/dumps/merge_counter.nft | 8 +++++++
|
||||
.../testcases/optimizations/merge_counter | 20 ++++++++++++++++
|
||||
3 files changed, 45 insertions(+), 7 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/optimizations/dumps/merge_counter.nft
|
||||
create mode 100755 tests/shell/testcases/optimizations/merge_counter
|
||||
|
||||
diff --git a/src/optimize.c b/src/optimize.c
|
||||
index 1dd0858..62dd908 100644
|
||||
--- a/src/optimize.c
|
||||
+++ b/src/optimize.c
|
||||
@@ -692,29 +692,36 @@ static void build_verdict_map(struct expr *expr, struct stmt *verdict,
|
||||
struct expr *set, struct stmt *counter)
|
||||
{
|
||||
struct expr *item, *elem, *mapping;
|
||||
+ struct stmt *counter_elem;
|
||||
|
||||
switch (expr->etype) {
|
||||
case EXPR_LIST:
|
||||
list_for_each_entry(item, &expr->expressions, list) {
|
||||
elem = set_elem_expr_alloc(&internal_location, expr_get(item));
|
||||
- if (counter)
|
||||
- list_add_tail(&counter->list, &elem->stmt_list);
|
||||
+ if (counter) {
|
||||
+ counter_elem = counter_stmt_alloc(&counter->location);
|
||||
+ list_add_tail(&counter_elem->list, &elem->stmt_list);
|
||||
+ }
|
||||
|
||||
mapping = mapping_expr_alloc(&internal_location, elem,
|
||||
expr_get(verdict->expr));
|
||||
compound_expr_add(set, mapping);
|
||||
}
|
||||
+ stmt_free(counter);
|
||||
break;
|
||||
case EXPR_SET:
|
||||
list_for_each_entry(item, &expr->expressions, list) {
|
||||
elem = set_elem_expr_alloc(&internal_location, expr_get(item->key));
|
||||
- if (counter)
|
||||
- list_add_tail(&counter->list, &elem->stmt_list);
|
||||
+ if (counter) {
|
||||
+ counter_elem = counter_stmt_alloc(&counter->location);
|
||||
+ list_add_tail(&counter_elem->list, &elem->stmt_list);
|
||||
+ }
|
||||
|
||||
mapping = mapping_expr_alloc(&internal_location, elem,
|
||||
expr_get(verdict->expr));
|
||||
compound_expr_add(set, mapping);
|
||||
}
|
||||
+ stmt_free(counter);
|
||||
break;
|
||||
case EXPR_PREFIX:
|
||||
case EXPR_RANGE:
|
||||
@@ -819,8 +826,8 @@ static void __merge_concat_stmts_vmap(const struct optimize_ctx *ctx,
|
||||
struct expr *set, struct stmt *verdict)
|
||||
{
|
||||
struct expr *concat, *next, *elem, *mapping;
|
||||
+ struct stmt *counter, *counter_elem;
|
||||
LIST_HEAD(concat_list);
|
||||
- struct stmt *counter;
|
||||
|
||||
counter = zap_counter(ctx, i);
|
||||
__merge_concat(ctx, i, merge, &concat_list);
|
||||
@@ -828,13 +835,16 @@ static void __merge_concat_stmts_vmap(const struct optimize_ctx *ctx,
|
||||
list_for_each_entry_safe(concat, next, &concat_list, list) {
|
||||
list_del(&concat->list);
|
||||
elem = set_elem_expr_alloc(&internal_location, concat);
|
||||
- if (counter)
|
||||
- list_add_tail(&counter->list, &elem->stmt_list);
|
||||
+ if (counter) {
|
||||
+ counter_elem = counter_stmt_alloc(&counter->location);
|
||||
+ list_add_tail(&counter_elem->list, &elem->stmt_list);
|
||||
+ }
|
||||
|
||||
mapping = mapping_expr_alloc(&internal_location, elem,
|
||||
expr_get(verdict->expr));
|
||||
compound_expr_add(set, mapping);
|
||||
}
|
||||
+ stmt_free(counter);
|
||||
}
|
||||
|
||||
static void merge_concat_stmts_vmap(const struct optimize_ctx *ctx,
|
||||
diff --git a/tests/shell/testcases/optimizations/dumps/merge_counter.nft b/tests/shell/testcases/optimizations/dumps/merge_counter.nft
|
||||
new file mode 100644
|
||||
index 0000000..72eed5d
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/optimizations/dumps/merge_counter.nft
|
||||
@@ -0,0 +1,8 @@
|
||||
+table ip x {
|
||||
+ chain y {
|
||||
+ type filter hook input priority filter; policy drop;
|
||||
+ ct state vmap { invalid counter packets 0 bytes 0 : drop, established counter packets 0 bytes 0 : accept, related counter packets 0 bytes 0 : accept }
|
||||
+ tcp dport { 80, 123 } counter packets 0 bytes 0 accept
|
||||
+ ip saddr . ip daddr vmap { 1.1.1.1 . 2.2.2.2 counter packets 0 bytes 0 : accept, 1.1.1.2 . 3.3.3.3 counter packets 0 bytes 0 : drop }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/optimizations/merge_counter b/tests/shell/testcases/optimizations/merge_counter
|
||||
new file mode 100755
|
||||
index 0000000..3b8bbad
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/optimizations/merge_counter
|
||||
@@ -0,0 +1,20 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_expr)
|
||||
+
|
||||
+set -e
|
||||
+
|
||||
+RULESET="table ip x {
|
||||
+ chain y {
|
||||
+ type filter hook input priority 0; policy drop;
|
||||
+
|
||||
+ ct state invalid counter drop
|
||||
+ ct state established,related counter accept
|
||||
+ tcp dport 80 counter accept
|
||||
+ tcp dport 123 counter accept
|
||||
+ ip saddr 1.1.1.1 ip daddr 2.2.2.2 counter accept
|
||||
+ ip saddr 1.1.1.2 ip daddr 3.3.3.3 counter drop
|
||||
+ }
|
||||
+}"
|
||||
+
|
||||
+$NFT -o -f - <<< $RULESET
|
||||
63
0106-libnftables-skip-useable-checks-for-dev-stdin.patch
Normal file
63
0106-libnftables-skip-useable-checks-for-dev-stdin.patch
Normal file
@ -0,0 +1,63 @@
|
||||
From 36abb7d32f0f4af37112fb74b31a7235d029e3e3 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:08 +0200
|
||||
Subject: [PATCH] libnftables: skip useable checks for /dev/stdin
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 477fd8218777b75bdfa3a5643f692adae4f002fe
|
||||
|
||||
commit 477fd8218777b75bdfa3a5643f692adae4f002fe
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Jul 9 16:59:53 2024 +0200
|
||||
|
||||
libnftables: skip useable checks for /dev/stdin
|
||||
|
||||
/dev/stdin is a placeholder, read() from STDIN_FILENO is used to fetch
|
||||
the standard input into a buffer.
|
||||
|
||||
Since 5c2b2b0a2ba7 ("src: error reporting with -f and read from stdin")
|
||||
stdin is stored in a buffer to fix error reporting.
|
||||
|
||||
This patch requires: ("parser_json: use stdin buffer if available")
|
||||
|
||||
Fixes: 149b1c95d129 ("libnftables: refuse to open onput files other than named pipes or regular files")
|
||||
Acked-by: Phil Sutter <phil@nwl.cc>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/libnftables.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/libnftables.c b/src/libnftables.c
|
||||
index 0dee1ba..8f8acd1 100644
|
||||
--- a/src/libnftables.c
|
||||
+++ b/src/libnftables.c
|
||||
@@ -664,6 +664,7 @@ retry:
|
||||
|
||||
/* need to use stat() to, fopen() will block for named fifos and
|
||||
* libjansson makes no checks before or after open either.
|
||||
+ * /dev/stdin is *never* used, read() from STDIN_FILENO is used instead.
|
||||
*/
|
||||
static struct error_record *filename_is_useable(struct nft_ctx *nft, const char *name)
|
||||
{
|
||||
@@ -671,6 +672,9 @@ static struct error_record *filename_is_useable(struct nft_ctx *nft, const char
|
||||
struct stat sb;
|
||||
int err;
|
||||
|
||||
+ if (!strcmp(name, "/dev/stdin"))
|
||||
+ return NULL;
|
||||
+
|
||||
err = stat(name, &sb);
|
||||
if (err)
|
||||
return error(&internal_location, "Could not open file \"%s\": %s\n",
|
||||
@@ -681,9 +685,6 @@ static struct error_record *filename_is_useable(struct nft_ctx *nft, const char
|
||||
if (type == S_IFREG || type == S_IFIFO)
|
||||
return NULL;
|
||||
|
||||
- if (type == S_IFCHR && 0 == strcmp(name, "/dev/stdin"))
|
||||
- return NULL;
|
||||
-
|
||||
return error(&internal_location, "Not a regular file: \"%s\"\n", name);
|
||||
}
|
||||
|
||||
63
0107-parser_json-use-stdin-buffer-if-available.patch
Normal file
63
0107-parser_json-use-stdin-buffer-if-available.patch
Normal file
@ -0,0 +1,63 @@
|
||||
From 50d322fb2d90b0a07b3f2e6544dec853ac22ac85 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:08 +0200
|
||||
Subject: [PATCH] parser_json: use stdin buffer if available
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit e48f32701ff65d522c2f29f34bf4f3ce8e562057
|
||||
|
||||
commit e48f32701ff65d522c2f29f34bf4f3ce8e562057
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue Jul 9 16:59:52 2024 +0200
|
||||
|
||||
parser_json: use stdin buffer if available
|
||||
|
||||
Since 5c2b2b0a2ba7 ("src: error reporting with -f and read from stdin")
|
||||
stdin is stored in a buffer, update json support to use it instead of
|
||||
reading from /dev/stdin.
|
||||
|
||||
Some systems do not provide /dev/stdin symlink to /proc/self/fd/0
|
||||
according to reporter (that mentions Yocto Linux as example).
|
||||
|
||||
Fixes: 935f82e7dd49 ("Support 'nft -f -' to read from stdin")
|
||||
Acked-by: Phil Sutter <phil@nwl.cc>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/libnftables.c | 3 +--
|
||||
src/parser_json.c | 7 +++++++
|
||||
2 files changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/libnftables.c b/src/libnftables.c
|
||||
index 8f8acd1..02570c4 100644
|
||||
--- a/src/libnftables.c
|
||||
+++ b/src/libnftables.c
|
||||
@@ -795,8 +795,7 @@ int nft_run_cmd_from_filename(struct nft_ctx *nft, const char *filename)
|
||||
if (!strcmp(filename, "-"))
|
||||
filename = "/dev/stdin";
|
||||
|
||||
- if (!strcmp(filename, "/dev/stdin") &&
|
||||
- !nft_output_json(&nft->output))
|
||||
+ if (!strcmp(filename, "/dev/stdin"))
|
||||
nft->stdin_buf = stdin_to_buffer();
|
||||
|
||||
if (nft->optimize_flags) {
|
||||
diff --git a/src/parser_json.c b/src/parser_json.c
|
||||
index ce36397..047c6fa 100644
|
||||
--- a/src/parser_json.c
|
||||
+++ b/src/parser_json.c
|
||||
@@ -4333,6 +4333,13 @@ int nft_parse_json_filename(struct nft_ctx *nft, const char *filename,
|
||||
json_error_t err;
|
||||
int ret;
|
||||
|
||||
+ if (nft->stdin_buf) {
|
||||
+ json_indesc.type = INDESC_STDIN;
|
||||
+ json_indesc.name = "/dev/stdin";
|
||||
+
|
||||
+ return nft_parse_json_buffer(nft, nft->stdin_buf, msgs, cmds);
|
||||
+ }
|
||||
+
|
||||
json_indesc.type = INDESC_FILE;
|
||||
json_indesc.name = filename;
|
||||
|
||||
111
0108-optimize-skip-variables-in-nat-statements.patch
Normal file
111
0108-optimize-skip-variables-in-nat-statements.patch
Normal file
@ -0,0 +1,111 @@
|
||||
From 0df57d34d73abae0b0a5e9530cc66aac0eda250b Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:08 +0200
|
||||
Subject: [PATCH] optimize: skip variables in nat statements
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit bc1f910f502701f1a1d28c7bd723e4be3bac1d8c
|
||||
|
||||
commit bc1f910f502701f1a1d28c7bd723e4be3bac1d8c
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Thu Jul 18 18:06:22 2024 +0200
|
||||
|
||||
optimize: skip variables in nat statements
|
||||
|
||||
Do not hit assert():
|
||||
|
||||
nft: optimize.c:486: rule_build_stmt_matrix_stmts: Assertion `k >= 0' failed.
|
||||
|
||||
variables are not supported by -o/--optimize at this stage.
|
||||
|
||||
Fixes: 9be404a153bc ("optimize: ignore existing nat mapping")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/optimize.c | 6 ++-
|
||||
tests/shell/testcases/optimizations/variables | 52 ++++++++++++++++---
|
||||
2 files changed, 49 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/optimize.c b/src/optimize.c
|
||||
index 62dd908..9f0965c 100644
|
||||
--- a/src/optimize.c
|
||||
+++ b/src/optimize.c
|
||||
@@ -408,9 +408,11 @@ static int rule_collect_stmts(struct optimize_ctx *ctx, struct rule *rule)
|
||||
break;
|
||||
case STMT_NAT:
|
||||
if ((stmt->nat.addr &&
|
||||
- stmt->nat.addr->etype == EXPR_MAP) ||
|
||||
+ (stmt->nat.addr->etype == EXPR_MAP ||
|
||||
+ stmt->nat.addr->etype == EXPR_VARIABLE)) ||
|
||||
(stmt->nat.proto &&
|
||||
- stmt->nat.proto->etype == EXPR_MAP)) {
|
||||
+ (stmt->nat.proto->etype == EXPR_MAP ||
|
||||
+ stmt->nat.proto->etype == EXPR_VARIABLE))) {
|
||||
clone->ops = &unsupported_stmt_ops;
|
||||
break;
|
||||
}
|
||||
diff --git a/tests/shell/testcases/optimizations/variables b/tests/shell/testcases/optimizations/variables
|
||||
index fa98606..4cb322d 100755
|
||||
--- a/tests/shell/testcases/optimizations/variables
|
||||
+++ b/tests/shell/testcases/optimizations/variables
|
||||
@@ -2,14 +2,52 @@
|
||||
|
||||
set -e
|
||||
|
||||
-RULESET="define addrv4_vpnnet = 10.1.0.0/16
|
||||
+RULESET='define addrv4_vpnnet = 10.1.0.0/16
|
||||
+define wan = "eth0"
|
||||
+define lan = "eth1"
|
||||
+define vpn = "tun0"
|
||||
+define server = "10.10.10.1"
|
||||
|
||||
-table ip nat {
|
||||
- chain postrouting {
|
||||
- type nat hook postrouting priority 0; policy accept;
|
||||
+table inet filter {
|
||||
+ chain input {
|
||||
+ type filter hook input priority 0; policy drop;
|
||||
+ }
|
||||
+ chain forward {
|
||||
+ type filter hook forward priority 1; policy drop;
|
||||
|
||||
- ip saddr \$addrv4_vpnnet counter masquerade fully-random comment \"masquerade ipv4\"
|
||||
- }
|
||||
-}"
|
||||
+ iifname $lan oifname $lan accept;
|
||||
+
|
||||
+ iifname $lan oifname $wan ct state new accept
|
||||
+ iifname $lan oifname $wan ct state {established, related} accept
|
||||
+
|
||||
+ iifname $wan oifname $lan ct state {established, related} accept
|
||||
+
|
||||
+ iifname $vpn oifname $wan accept
|
||||
+ iifname $wan oifname $vpn accept
|
||||
+ iifname $lan oifname $vpn accept
|
||||
+ iifname $vpn oifname $lan accept
|
||||
+
|
||||
+ iifname $lan oifname $server accept
|
||||
+ iifname $server oifname $lan accept
|
||||
+ iifname $server oifname $wan accept
|
||||
+ iifname $wan oifname $server accept
|
||||
+ }
|
||||
+ chain output {
|
||||
+ type filter hook output priority 0; policy drop;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+table nat {
|
||||
+ chain prerouting {
|
||||
+ type nat hook prerouting priority -100; policy accept;
|
||||
+ iifname $wan tcp dport 10000 dnat to $server:10000;
|
||||
+ }
|
||||
+ chain postrouting {
|
||||
+ type nat hook postrouting priority 100; policy accept;
|
||||
+ ip saddr $addrv4_vpnnet counter masquerade fully-random comment "masquerade ipv4"
|
||||
+ oifname $vpn masquerade
|
||||
+ oifname $wan masquerade
|
||||
+ }
|
||||
+}'
|
||||
|
||||
$NFT -c -o -f - <<< $RULESET
|
||||
77
0109-datatype-reject-rate-in-quota-statement.patch
Normal file
77
0109-datatype-reject-rate-in-quota-statement.patch
Normal file
@ -0,0 +1,77 @@
|
||||
From 2269f1c988af5f779c39b452231c6cd841bdc019 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:09 +0200
|
||||
Subject: [PATCH] datatype: reject rate in quota statement
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 8ed6fa6d66b2df50d118423c1cb0e98cdd45cdbd
|
||||
|
||||
commit 8ed6fa6d66b2df50d118423c1cb0e98cdd45cdbd
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Wed Aug 14 13:02:02 2024 +0200
|
||||
|
||||
datatype: reject rate in quota statement
|
||||
|
||||
Bail out if rate are used:
|
||||
|
||||
ruleset.nft:5:77-106: Error: Wrong rate format, expecting bytes or kbytes or mbytes
|
||||
add rule netdev firewall PROTECTED_IPS update @quota_temp_before { ip daddr quota over 45000 mbytes/second } add @quota_trigger { ip daddr }
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
improve error reporting while at this.
|
||||
|
||||
Fixes: 6615676d825e ("src: add per-bytes limit")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/datatype.c | 20 +++++++++++++-------
|
||||
1 file changed, 13 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/datatype.c b/src/datatype.c
|
||||
index 46d77eb..4cceeb8 100644
|
||||
--- a/src/datatype.c
|
||||
+++ b/src/datatype.c
|
||||
@@ -1432,14 +1432,14 @@ static struct error_record *time_unit_parse(const struct location *loc,
|
||||
struct error_record *data_unit_parse(const struct location *loc,
|
||||
const char *str, uint64_t *rate)
|
||||
{
|
||||
- if (strncmp(str, "bytes", strlen("bytes")) == 0)
|
||||
+ if (strcmp(str, "bytes") == 0)
|
||||
*rate = 1ULL;
|
||||
- else if (strncmp(str, "kbytes", strlen("kbytes")) == 0)
|
||||
+ else if (strcmp(str, "kbytes") == 0)
|
||||
*rate = 1024;
|
||||
- else if (strncmp(str, "mbytes", strlen("mbytes")) == 0)
|
||||
+ else if (strcmp(str, "mbytes") == 0)
|
||||
*rate = 1024 * 1024;
|
||||
else
|
||||
- return error(loc, "Wrong rate format");
|
||||
+ return error(loc, "Wrong unit format, expecting bytes, kbytes or mbytes");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1447,14 +1447,20 @@ struct error_record *data_unit_parse(const struct location *loc,
|
||||
struct error_record *rate_parse(const struct location *loc, const char *str,
|
||||
uint64_t *rate, uint64_t *unit)
|
||||
{
|
||||
+ const char *slash, *rate_str;
|
||||
struct error_record *erec;
|
||||
- const char *slash;
|
||||
|
||||
slash = strchr(str, '/');
|
||||
if (!slash)
|
||||
- return error(loc, "wrong rate format");
|
||||
+ return error(loc, "wrong rate format, expecting {bytes,kbytes,mbytes}/{second,minute,hour,day,week}");
|
||||
+
|
||||
+ rate_str = strndup(str, slash - str);
|
||||
+ if (!rate_str)
|
||||
+ memory_allocation_error();
|
||||
+
|
||||
+ erec = data_unit_parse(loc, rate_str, rate);
|
||||
+ free_const(rate_str);
|
||||
|
||||
- erec = data_unit_parse(loc, str, rate);
|
||||
if (erec != NULL)
|
||||
return erec;
|
||||
|
||||
45
0110-cache-rule-by-index-requires-full-cache.patch
Normal file
45
0110-cache-rule-by-index-requires-full-cache.patch
Normal file
@ -0,0 +1,45 @@
|
||||
From 65ef3c4192edf76e2744646e64003fbf8da01311 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:09 +0200
|
||||
Subject: [PATCH] cache: rule by index requires full cache
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 161beaeacd2e5218d66febc3db825bf6a27119c5
|
||||
|
||||
commit 161beaeacd2e5218d66febc3db825bf6a27119c5
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Thu Aug 15 12:34:08 2024 +0200
|
||||
|
||||
cache: rule by index requires full cache
|
||||
|
||||
In preparation for on-demand cache population with errors, set on
|
||||
NFT_CACHE_FULL if rule index is used since this requires a full cache
|
||||
with rules.
|
||||
|
||||
This is not a fix, index is already fetching a full cache before this
|
||||
patch.
|
||||
|
||||
But follow up patches relax cache requirements, so add this patch in
|
||||
first place to make sure index does not break.
|
||||
|
||||
Tested-by: Eric Garver <eric@garver.life>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/cache.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/cache.c b/src/cache.c
|
||||
index e88cbae..42e60df 100644
|
||||
--- a/src/cache.c
|
||||
+++ b/src/cache.c
|
||||
@@ -68,7 +68,7 @@ static unsigned int evaluate_cache_add(struct cmd *cmd, unsigned int flags)
|
||||
|
||||
if (cmd->handle.index.id ||
|
||||
cmd->handle.position.id)
|
||||
- flags |= NFT_CACHE_RULE | NFT_CACHE_UPDATE;
|
||||
+ flags |= NFT_CACHE_FULL | NFT_CACHE_UPDATE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -0,0 +1,44 @@
|
||||
From 1d307c03b99a145202aa08f28f1665fc739fd686 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:09 +0200
|
||||
Subject: [PATCH] datatype: improve error reporting when time unit is not
|
||||
correct
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 6bcaef6a1ea6dc60250ed6124f3b49a8cd29434c
|
||||
|
||||
commit 6bcaef6a1ea6dc60250ed6124f3b49a8cd29434c
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Wed Aug 14 13:05:54 2024 +0200
|
||||
|
||||
datatype: improve error reporting when time unit is not correct
|
||||
|
||||
Display:
|
||||
|
||||
Wrong unit format, expecting bytes or kbytes or mbytes
|
||||
|
||||
instead of:
|
||||
|
||||
Wrong rate format
|
||||
|
||||
Fixes: 6615676d825e ("src: add per-bytes limit")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/datatype.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/datatype.c b/src/datatype.c
|
||||
index 4cceeb8..c94c839 100644
|
||||
--- a/src/datatype.c
|
||||
+++ b/src/datatype.c
|
||||
@@ -1424,7 +1424,7 @@ static struct error_record *time_unit_parse(const struct location *loc,
|
||||
else if (strcmp(str, "week") == 0)
|
||||
*unit = 1ULL * 60 * 60 * 24 * 7;
|
||||
else
|
||||
- return error(loc, "Wrong rate format");
|
||||
+ return error(loc, "Wrong time format, expecting second, minute, hour, day or week");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
From 98811a10653288ee3ceae5b9b9324ff56d70f507 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:09 +0200
|
||||
Subject: [PATCH] parser_bison: allow 0 burst in limit rate byte mode
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit cea05ae5bdc50949d4c734796d6db5717187055a
|
||||
|
||||
commit cea05ae5bdc50949d4c734796d6db5717187055a
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Thu Aug 15 13:56:21 2024 +0200
|
||||
|
||||
parser_bison: allow 0 burst in limit rate byte mode
|
||||
|
||||
Unbreak restoring elements in set with rate limit that fail with:
|
||||
|
||||
> /dev/stdin:3618:61-61: Error: limit burst must be > 0
|
||||
> elements = { 1.2.3.4 limit rate over 1000 kbytes/second timeout 1s,
|
||||
|
||||
no need for burst != 0 for limit rate byte mode.
|
||||
|
||||
Add tests/shell too.
|
||||
|
||||
Fixes: 702eff5b5b74 ("src: allow burst 0 for byte ratelimit and use it as default")
|
||||
Fixes: 285baccfea46 ("src: disallow burst 0 in ratelimits")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_bison.y | 5 -----
|
||||
.../shell/testcases/sets/dumps/elem_limit_0.nft | 7 +++++++
|
||||
tests/shell/testcases/sets/elem_limit_0 | 17 +++++++++++++++++
|
||||
3 files changed, 24 insertions(+), 5 deletions(-)
|
||||
create mode 100644 tests/shell/testcases/sets/dumps/elem_limit_0.nft
|
||||
create mode 100755 tests/shell/testcases/sets/elem_limit_0
|
||||
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 87cf9ae..c18e739 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -4589,11 +4589,6 @@ set_elem_stmt : COUNTER close_scope_counter
|
||||
}
|
||||
| LIMIT RATE limit_mode limit_rate_bytes limit_burst_bytes close_scope_limit
|
||||
{
|
||||
- if ($5 == 0) {
|
||||
- erec_queue(error(&@6, "limit burst must be > 0"),
|
||||
- state->msgs);
|
||||
- YYERROR;
|
||||
- }
|
||||
$$ = limit_stmt_alloc(&@$);
|
||||
$$->limit.rate = $4.rate;
|
||||
$$->limit.unit = $4.unit;
|
||||
diff --git a/tests/shell/testcases/sets/dumps/elem_limit_0.nft b/tests/shell/testcases/sets/dumps/elem_limit_0.nft
|
||||
new file mode 100644
|
||||
index 0000000..ca5b2b5
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/sets/dumps/elem_limit_0.nft
|
||||
@@ -0,0 +1,7 @@
|
||||
+table netdev filter {
|
||||
+ set test123 {
|
||||
+ typeof ip saddr
|
||||
+ limit rate over 1 mbytes/second
|
||||
+ elements = { 1.2.3.4 limit rate over 1 mbytes/second }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/sets/elem_limit_0 b/tests/shell/testcases/sets/elem_limit_0
|
||||
new file mode 100755
|
||||
index 0000000..b57f927
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/sets/elem_limit_0
|
||||
@@ -0,0 +1,17 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+## requires EXPR
|
||||
+
|
||||
+set -e
|
||||
+
|
||||
+RULESET="table netdev filter {
|
||||
+ set test123 {
|
||||
+ typeof ip saddr
|
||||
+ limit rate over 1024 kbytes/second
|
||||
+ elements = { 1.2.3.4 limit rate over 1024 kbytes/second }
|
||||
+ }
|
||||
+}"
|
||||
+
|
||||
+$NFT -f - <<< $RULESET
|
||||
+
|
||||
+(echo "flush ruleset netdev"; $NFT --stateless list ruleset netdev) | $NFT -f -
|
||||
56
0113-parser_json-fix-crash-in-json_parse_set_stmt_list.patch
Normal file
56
0113-parser_json-fix-crash-in-json_parse_set_stmt_list.patch
Normal file
@ -0,0 +1,56 @@
|
||||
From a15ffca5581d098e3f03cbbe48edae886d0d60df Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:09 +0200
|
||||
Subject: [PATCH] parser_json: fix crash in json_parse_set_stmt_list
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 26d9cbefb10e6bc3765df7e9e7a4fc3b951a80f3
|
||||
|
||||
commit 26d9cbefb10e6bc3765df7e9e7a4fc3b951a80f3
|
||||
Author: Sebastian Walz (sivizius) <sebastian.walz@secunet.com>
|
||||
Date: Tue Aug 20 00:09:26 2024 +0200
|
||||
|
||||
parser_json: fix crash in json_parse_set_stmt_list
|
||||
|
||||
Due to missing `NULL`-check, there will be a segfault for invalid statements.
|
||||
|
||||
Fixes: 07958ec53830 ("json: add set statement list support")
|
||||
Signed-off-by: Sebastian Walz (sivizius) <sebastian.walz@secunet.com>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_json.c | 13 +++++++++----
|
||||
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/parser_json.c b/src/parser_json.c
|
||||
index 047c6fa..523dbd2 100644
|
||||
--- a/src/parser_json.c
|
||||
+++ b/src/parser_json.c
|
||||
@@ -2349,7 +2349,7 @@ static void json_parse_set_stmt_list(struct json_ctx *ctx,
|
||||
json_t *stmt_json)
|
||||
{
|
||||
struct list_head *head;
|
||||
- struct stmt *tmp;
|
||||
+ struct stmt *stmt;
|
||||
json_t *value;
|
||||
size_t index;
|
||||
|
||||
@@ -2361,9 +2361,14 @@ static void json_parse_set_stmt_list(struct json_ctx *ctx,
|
||||
|
||||
head = stmt_list;
|
||||
json_array_foreach(stmt_json, index, value) {
|
||||
- tmp = json_parse_stmt(ctx, value);
|
||||
- list_add(&tmp->list, head);
|
||||
- head = &tmp->list;
|
||||
+ stmt = json_parse_stmt(ctx, value);
|
||||
+ if (!stmt) {
|
||||
+ json_error(ctx, "Parsing set statements array at index %zd failed.", index);
|
||||
+ stmt_list_free(stmt_list);
|
||||
+ return;
|
||||
+ }
|
||||
+ list_add(&stmt->list, head);
|
||||
+ head = &stmt->list;
|
||||
}
|
||||
}
|
||||
|
||||
99
0114-json-Support-maps-with-concatenated-data.patch
Normal file
99
0114-json-Support-maps-with-concatenated-data.patch
Normal file
@ -0,0 +1,99 @@
|
||||
From 47ee410b237d907322baed7f01b6dc0abbb6fe29 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:09 +0200
|
||||
Subject: [PATCH] json: Support maps with concatenated data
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit c56d77cc82988391ab8f2514214c0088cbc7d89e
|
||||
|
||||
commit c56d77cc82988391ab8f2514214c0088cbc7d89e
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Sat Mar 9 00:27:38 2024 +0100
|
||||
|
||||
json: Support maps with concatenated data
|
||||
|
||||
Dump such maps with an array of types in "map" property, make the parser
|
||||
aware of this.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/json.c | 10 +++++-----
|
||||
src/parser_json.c | 18 +++++++++---------
|
||||
2 files changed, 14 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/json.c b/src/json.c
|
||||
index 5faeb4d..90d9795 100644
|
||||
--- a/src/json.c
|
||||
+++ b/src/json.c
|
||||
@@ -130,15 +130,15 @@ static json_t *set_stmt_list_json(const struct list_head *stmt_list,
|
||||
|
||||
static json_t *set_print_json(struct output_ctx *octx, const struct set *set)
|
||||
{
|
||||
- json_t *root, *tmp;
|
||||
- const char *type, *datatype_ext = NULL;
|
||||
+ json_t *root, *tmp, *datatype_ext = NULL;
|
||||
+ const char *type;
|
||||
|
||||
if (set_is_datamap(set->flags)) {
|
||||
type = "map";
|
||||
- datatype_ext = set->data->dtype->name;
|
||||
+ datatype_ext = set_dtype_json(set->data);
|
||||
} else if (set_is_objmap(set->flags)) {
|
||||
type = "map";
|
||||
- datatype_ext = obj_type_name(set->objtype);
|
||||
+ datatype_ext = json_string(obj_type_name(set->objtype));
|
||||
} else if (set_is_meter(set->flags)) {
|
||||
type = "meter";
|
||||
} else {
|
||||
@@ -155,7 +155,7 @@ static json_t *set_print_json(struct output_ctx *octx, const struct set *set)
|
||||
if (set->comment)
|
||||
json_object_set_new(root, "comment", json_string(set->comment));
|
||||
if (datatype_ext)
|
||||
- json_object_set_new(root, "map", json_string(datatype_ext));
|
||||
+ json_object_set_new(root, "map", datatype_ext);
|
||||
|
||||
if (!(set->flags & (NFT_SET_CONSTANT))) {
|
||||
if (set->policy != NFT_SET_POL_PERFORMANCE) {
|
||||
diff --git a/src/parser_json.c b/src/parser_json.c
|
||||
index 523dbd2..a144f4c 100644
|
||||
--- a/src/parser_json.c
|
||||
+++ b/src/parser_json.c
|
||||
@@ -3300,7 +3300,7 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root,
|
||||
enum cmd_ops op, enum cmd_obj obj)
|
||||
{
|
||||
struct handle h = { 0 };
|
||||
- const char *family = "", *policy, *dtype_ext = NULL;
|
||||
+ const char *family = "", *policy;
|
||||
json_t *tmp, *stmt_json;
|
||||
struct set *set;
|
||||
|
||||
@@ -3353,19 +3353,19 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- if (!json_unpack(root, "{s:s}", "map", &dtype_ext)) {
|
||||
- const struct datatype *dtype;
|
||||
+ if (!json_unpack(root, "{s:o}", "map", &tmp)) {
|
||||
+ if (json_is_string(tmp)) {
|
||||
+ const char *s = json_string_value(tmp);
|
||||
|
||||
- set->objtype = string_to_nft_object(dtype_ext);
|
||||
+ set->objtype = string_to_nft_object(s);
|
||||
+ }
|
||||
if (set->objtype) {
|
||||
set->flags |= NFT_SET_OBJECT;
|
||||
- } else if ((dtype = datatype_lookup_byname(dtype_ext))) {
|
||||
- set->data = constant_expr_alloc(&netlink_location,
|
||||
- dtype, dtype->byteorder,
|
||||
- dtype->size, NULL);
|
||||
+ } else if ((set->data = json_parse_dtype_expr(ctx, tmp))) {
|
||||
set->flags |= NFT_SET_MAP;
|
||||
} else {
|
||||
- json_error(ctx, "Invalid map type '%s'.", dtype_ext);
|
||||
+ json_error(ctx, "Invalid map type '%s'.",
|
||||
+ json_dumps(tmp, 0));
|
||||
set_free(set);
|
||||
handle_free(&h);
|
||||
return NULL;
|
||||
62
0115-parser_json-release-buffer-returned-by-json_dumps.patch
Normal file
62
0115-parser_json-release-buffer-returned-by-json_dumps.patch
Normal file
@ -0,0 +1,62 @@
|
||||
From 281ca241e91da463f1f7115acbe25322b5b28b64 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Fri, 17 Jul 2026 11:10:09 +0200
|
||||
Subject: [PATCH] parser_json: release buffer returned by json_dumps
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
||||
Upstream Status: nftables commit 46700fbdbbbaab0d7db716fce3a438334c58ac9e
|
||||
|
||||
commit 46700fbdbbbaab0d7db716fce3a438334c58ac9e
|
||||
Author: Sebastian Walz (sivizius) <sebastian.walz@secunet.com>
|
||||
Date: Mon Aug 19 19:58:14 2024 +0200
|
||||
|
||||
parser_json: release buffer returned by json_dumps
|
||||
|
||||
The signature of `json_dumps` is:
|
||||
|
||||
`char *json_dumps(const json_t *json, size_t flags)`:
|
||||
|
||||
It will return a pointer to an owned string, the caller must free it.
|
||||
However, `json_error` just borrows the string to format it as `%s`, but
|
||||
after printing the formatted error message, the pointer to the string is
|
||||
lost and thus never freed.
|
||||
|
||||
Fixes: 586ad210368b ("libnftables: Implement JSON parser")
|
||||
Signed-off-by: Sebastian Walz (sivizius) <sebastian.walz@secunet.com>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/parser_json.c | 11 ++++++++---
|
||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/parser_json.c b/src/parser_json.c
|
||||
index a144f4c..3473a2a 100644
|
||||
--- a/src/parser_json.c
|
||||
+++ b/src/parser_json.c
|
||||
@@ -181,8 +181,11 @@ static int json_unpack_stmt(struct json_ctx *ctx, json_t *root,
|
||||
assert(value);
|
||||
|
||||
if (json_object_size(root) != 1) {
|
||||
+ const char *dump = json_dumps(root, 0);
|
||||
+
|
||||
json_error(ctx, "Malformed object (too many properties): '%s'.",
|
||||
- json_dumps(root, 0));
|
||||
+ dump);
|
||||
+ free_const(dump);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -3364,8 +3367,10 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root,
|
||||
} else if ((set->data = json_parse_dtype_expr(ctx, tmp))) {
|
||||
set->flags |= NFT_SET_MAP;
|
||||
} else {
|
||||
- json_error(ctx, "Invalid map type '%s'.",
|
||||
- json_dumps(tmp, 0));
|
||||
+ const char *dump = json_dumps(tmp, 0);
|
||||
+
|
||||
+ json_error(ctx, "Invalid map type '%s'.", dump);
|
||||
+ free_const(dump);
|
||||
set_free(set);
|
||||
handle_free(&h);
|
||||
return NULL;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user