Skip to content

Commit b4e70d8

Browse files
committed
netfilter: nftables: add set expression flags
The set flag NFT_SET_EXPR provides a hint to the kernel that userspace supports for multiple expressions per set element. In the same direction, NFT_DYNSET_F_EXPR specifies that dynset expression defines multiple expressions per set element. This allows new userspace software with old kernels to bail out with EOPNOTSUPP. This update is similar to ef516e8 ("netfilter: nf_tables: reintroduce the NFT_SET_CONCAT flag"). The NFT_SET_EXPR flag needs to be set on when the NFTA_SET_EXPRESSIONS attribute is specified. The NFT_SET_EXPR flag is not set on with NFTA_SET_EXPR to retain backward compatibility in old userspace binaries. Fixes: 48b0ae0 ("netfilter: nftables: netlink support for several set element expressions") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent 95cd4bc commit b4e70d8

3 files changed

Lines changed: 15 additions & 3 deletions

File tree

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ enum nft_rule_compat_attributes {
293293
* @NFT_SET_EVAL: set can be updated from the evaluation path
294294
* @NFT_SET_OBJECT: set contains stateful objects
295295
* @NFT_SET_CONCAT: set contains a concatenation
296+
* @NFT_SET_EXPR: set contains expressions
296297
*/
297298
enum nft_set_flags {
298299
NFT_SET_ANONYMOUS = 0x1,
@@ -303,6 +304,7 @@ enum nft_set_flags {
303304
NFT_SET_EVAL = 0x20,
304305
NFT_SET_OBJECT = 0x40,
305306
NFT_SET_CONCAT = 0x80,
307+
NFT_SET_EXPR = 0x100,
306308
};
307309

308310
/**
@@ -706,6 +708,7 @@ enum nft_dynset_ops {
706708

707709
enum nft_dynset_flags {
708710
NFT_DYNSET_F_INV = (1 << 0),
711+
NFT_DYNSET_F_EXPR = (1 << 1),
709712
};
710713

711714
/**

net/netfilter/nf_tables_api.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4162,7 +4162,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
41624162
if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
41634163
NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
41644164
NFT_SET_MAP | NFT_SET_EVAL |
4165-
NFT_SET_OBJECT | NFT_SET_CONCAT))
4165+
NFT_SET_OBJECT | NFT_SET_CONCAT | NFT_SET_EXPR))
41664166
return -EOPNOTSUPP;
41674167
/* Only one of these operations is supported */
41684168
if ((flags & (NFT_SET_MAP | NFT_SET_OBJECT)) ==
@@ -4304,6 +4304,10 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
43044304
struct nlattr *tmp;
43054305
int left;
43064306

4307+
if (!(flags & NFT_SET_EXPR)) {
4308+
err = -EINVAL;
4309+
goto err_set_alloc_name;
4310+
}
43074311
i = 0;
43084312
nla_for_each_nested(tmp, nla[NFTA_SET_EXPRESSIONS], left) {
43094313
if (i == NFT_SET_EXPR_MAX) {

net/netfilter/nft_dynset.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ struct nft_dynset {
1919
enum nft_registers sreg_key:8;
2020
enum nft_registers sreg_data:8;
2121
bool invert;
22+
bool expr;
2223
u8 num_exprs;
2324
u64 timeout;
2425
struct nft_expr *expr_array[NFT_SET_EXPR_MAX];
@@ -175,11 +176,12 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
175176

176177
if (tb[NFTA_DYNSET_FLAGS]) {
177178
u32 flags = ntohl(nla_get_be32(tb[NFTA_DYNSET_FLAGS]));
178-
179-
if (flags & ~NFT_DYNSET_F_INV)
179+
if (flags & ~(NFT_DYNSET_F_INV | NFT_DYNSET_F_EXPR))
180180
return -EOPNOTSUPP;
181181
if (flags & NFT_DYNSET_F_INV)
182182
priv->invert = true;
183+
if (flags & NFT_DYNSET_F_EXPR)
184+
priv->expr = true;
183185
}
184186

185187
set = nft_set_lookup_global(ctx->net, ctx->table,
@@ -261,6 +263,9 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
261263
struct nlattr *tmp;
262264
int left;
263265

266+
if (!priv->expr)
267+
return -EINVAL;
268+
264269
i = 0;
265270
nla_for_each_nested(tmp, tb[NFTA_DYNSET_EXPRESSIONS], left) {
266271
if (i == NFT_SET_EXPR_MAX) {

0 commit comments

Comments
 (0)