History

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 ef516e8625dd ("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.

Pablo Neira Ayuso committed 5 years ago

Commit b4e70d81 parent 95cd4bc3 files · +15 −3Browse files

Unified · Split

3 files
  1. include/uapi/linux/netfilter/nf_tables.h +3 −0
  2. net/netfilter/nf_tables_api.c +5 −1
  3. net/netfilter/nft_dynset.c +7 −2
include/uapi/linux/netfilter/nf_tables.h+3−0
@@ -293,6 +293,7 @@ enum nft_rule_compat_attributes { · 292 unmodified lines
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 { · 4 unmodified lines
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 { · 397 unmodified lines
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+5−1
@@ -4162,7 +4162,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, · 4161 unmodified lines
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, · 135 unmodified lines
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+7−2
@@ -19,6 +19,7 @@ struct nft_dynset { · 18 unmodified lines
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, · 150 unmodified lines
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, · 75 unmodified lines
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) {