Bug 1576426

Summary: adding element to nft sets with flag "interval" and concatenation results in error
Product: Red Hat Enterprise Linux 7 Reporter: Eric Garver <egarver>
Component: nftablesAssignee: Phil Sutter <psutter>
Status: CLOSED ERRATA QA Contact: Jiri Peska <jpeska>
Severity: medium Docs Contact:
Priority: medium    
Version: 7.6CC: psutter, rkhan, todoleza
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: nftables-0.8-9.el7 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2018-10-30 10:38:13 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Eric Garver 2018-05-09 12:39:36 UTC
To specify IP addresses with masks in a set you must use the flag "interval" when creating the set, but this does not appear to work with set concatenations. It triggers an assertion in nft.

# nft add table inet foobar
# nft add set inet foobar my_set { type ipv4_addr . inet_service \; flags interval \; }
                                                   
# nft add element inet foobar my_set { 10.0.0.1 . tcp }
BUG: invalid range expression type concat
nft: expression.c:1052: range_expr_value_low: Assertion `0' failed.
Aborted (core dumped)

# nft add element inet foobar my_set { 10.0.1.1/24 . tcp }
Error: syntax error, unexpected ., expecting comma or '}'
add element inet foobar my_set { 10.0.1.1/24 . tcp }


Works fine without interval:


# nft add table inet foobar
# nft add set inet foobar my_set { type ipv4_addr . inet_service \; }
# nft add element inet foobar my_set { 10.0.0.1 . tcp }
<no error>

Comment 2 Phil Sutter 2018-06-06 09:04:30 UTC
This issue is consistent with upstream.

Comment 3 Phil Sutter 2018-06-06 11:29:21 UTC
Note that I don't consider this as a bug per se, the only deficit is that nft tool doesn't catch the situation when adding the set itself. My point is that concatenated types are probably not quite useful in interval sets. I didn't test this, but from my understanding of how intervals work, I'd say that an element:

| 10.0.0.1 . 22 - 10.0.0.1 - 25

Would match on address 10.0.0.1 and any port in range 22 - 25, just as one would expect. Though an element:

| 10.0.0.1 . 22 - 10.0.0.2 . 22

Would match on address 10.0.0.1 and any port in range 22 - 65535 as well as address 10.0.0.2 and any port in range 0 - 22.

Patch adding a proper error message submitted upstream:

https://marc.info/?l=netfilter-devel&m=152828412409274&w=2

Comment 4 Phil Sutter 2018-06-06 12:35:07 UTC
Upstream accepted:

commit 9a3d80172a61e89c2862bcf41cb58313c236b308 (origin/master, origin/HEAD)
Author: Phil Sutter <phil>
Date:   Wed Jun 6 13:21:49 2018 +0200

    evaluate: explicitly deny concatenated types in interval sets
    
    Previously, this triggered a program abort:
    
    | # nft add table ip t
    | # nft add set ip t my_set '{ type ipv4_addr . inet_service ; flags interval ; }'
    | # nft add element ip t my_set '{10.0.0.1 . tcp }'
    | BUG: invalid range expression type concat
    | nft: expression.c:1085: range_expr_value_low: Assertion `0' failed.
    
    With this patch in place, the 'add set' command above gives an error
    message:
    
    | # nft add set ip t my_set3 '{ type ipv4_addr . inet_service ; flags interval ; }'
    | Error: concatenated types not supported in interval sets
    | add set ip t my_set3 { type ipv4_addr . inet_service ; flags interval ; }
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    Signed-off-by: Phil Sutter <phil>
    Signed-off-by: Florian Westphal <fw>

Comment 5 Eric Garver 2018-06-06 13:50:12 UTC
(In reply to Phil Sutter from comment #3)
> Note that I don't consider this as a bug per se, the only deficit is that
> nft tool doesn't catch the situation when adding the set itself. My point is
> that concatenated types are probably not quite useful in interval sets. I
> didn't test this, but from my understanding of how intervals work, I'd say

I was attempting to find an equivalent to ipset's hash:net,port. Is there an alternative method?

Comment 7 Phil Sutter 2018-06-20 09:34:34 UTC
Hi Eric,

(In reply to Eric Garver from comment #5)
> (In reply to Phil Sutter from comment #3)
> > Note that I don't consider this as a bug per se, the only deficit is that
> > nft tool doesn't catch the situation when adding the set itself. My point is
> > that concatenated types are probably not quite useful in interval sets. I
> > didn't test this, but from my understanding of how intervals work, I'd say
> 
> I was attempting to find an equivalent to ipset's hash:net,port. Is there an
> alternative method?

As discussed at NFWS, nftables' support for prefixes in sets is not optimal to begin with. A clean solution also requires kernel support, so I consider this ticket resolved with the explicit error message mentioned above. Support for prefixes in concatenated data types is probably something for RHEL8, anyway.

Regarding alternatives:

A "simple" one would be to have the prefix in a verdict map where each entry points to a custom chain which then contains a rule matching the port. Ugly, but may do the trick.

Another one would be to convert the prefix into a list of IP addresses and insert them combined with given port into a set of type 'ipv4_addr . inet_service'. Obviously this works with small subnets only.

Comment 9 Eric Garver 2018-06-20 15:11:34 UTC
(In reply to Phil Sutter from comment #7)
> Hi Eric,
> 
> (In reply to Eric Garver from comment #5)
> > (In reply to Phil Sutter from comment #3)
> > > Note that I don't consider this as a bug per se, the only deficit is that
> > > nft tool doesn't catch the situation when adding the set itself. My point is
> > > that concatenated types are probably not quite useful in interval sets. I
> > > didn't test this, but from my understanding of how intervals work, I'd say
> > 
> > I was attempting to find an equivalent to ipset's hash:net,port. Is there an
> > alternative method?
> 
> As discussed at NFWS, nftables' support for prefixes in sets is not optimal
> to begin with. A clean solution also requires kernel support, so I consider
> this ticket resolved with the explicit error message mentioned above.
> Support for prefixes in concatenated data types is probably something for
> RHEL8, anyway.
> 
> Regarding alternatives:
> 
> A "simple" one would be to have the prefix in a verdict map where each entry
> points to a custom chain which then contains a rule matching the port. Ugly,
> but may do the trick.

Thanks. I think it's okay to just wait on native support as you mention above.

Comment 12 errata-xmlrpc 2018-10-30 10:38:13 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2018:3154