Commit a8f33c03 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net:

1) Missing sanitization of rateest userspace string, bug has been
   triggered by syzbot, patch from Florian Westphal.

2) Report EOPNOTSUPP on missing set features in nft_dynset, otherwise
   error reporting to userspace via EINVAL is misleading since this is
   reserved for malformed netlink requests.

3) New binaries with old kernels might silently accept several set
   element expressions. New binaries set on the NFT_SET_EXPR and
   NFT_DYNSET_F_EXPR flags to request for several expressions per
   element, hence old kernels which do not support for this bail out
   with EOPNOTSUPP.

* git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf:
  netfilter: nftables: add set expression flags
  netfilter: nft_dynset: report EOPNOTSUPP on missing set feature
  netfilter: xt_RATEEST: reject non-null terminated string from userspace
====================

Link: https://lore.kernel.org/r/20210103192920.18639-1-pablo@netfilter.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 08ad4839 b4e70d8d
...@@ -293,6 +293,7 @@ enum nft_rule_compat_attributes { ...@@ -293,6 +293,7 @@ enum nft_rule_compat_attributes {
* @NFT_SET_EVAL: set can be updated from the evaluation path * @NFT_SET_EVAL: set can be updated from the evaluation path
* @NFT_SET_OBJECT: set contains stateful objects * @NFT_SET_OBJECT: set contains stateful objects
* @NFT_SET_CONCAT: set contains a concatenation * @NFT_SET_CONCAT: set contains a concatenation
* @NFT_SET_EXPR: set contains expressions
*/ */
enum nft_set_flags { enum nft_set_flags {
NFT_SET_ANONYMOUS = 0x1, NFT_SET_ANONYMOUS = 0x1,
...@@ -303,6 +304,7 @@ enum nft_set_flags { ...@@ -303,6 +304,7 @@ enum nft_set_flags {
NFT_SET_EVAL = 0x20, NFT_SET_EVAL = 0x20,
NFT_SET_OBJECT = 0x40, NFT_SET_OBJECT = 0x40,
NFT_SET_CONCAT = 0x80, NFT_SET_CONCAT = 0x80,
NFT_SET_EXPR = 0x100,
}; };
/** /**
...@@ -706,6 +708,7 @@ enum nft_dynset_ops { ...@@ -706,6 +708,7 @@ enum nft_dynset_ops {
enum nft_dynset_flags { enum nft_dynset_flags {
NFT_DYNSET_F_INV = (1 << 0), NFT_DYNSET_F_INV = (1 << 0),
NFT_DYNSET_F_EXPR = (1 << 1),
}; };
/** /**
......
...@@ -4162,7 +4162,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, ...@@ -4162,7 +4162,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT | if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
NFT_SET_INTERVAL | NFT_SET_TIMEOUT | NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
NFT_SET_MAP | NFT_SET_EVAL | NFT_SET_MAP | NFT_SET_EVAL |
NFT_SET_OBJECT | NFT_SET_CONCAT)) NFT_SET_OBJECT | NFT_SET_CONCAT | NFT_SET_EXPR))
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* Only one of these operations is supported */ /* Only one of these operations is supported */
if ((flags & (NFT_SET_MAP | NFT_SET_OBJECT)) == if ((flags & (NFT_SET_MAP | NFT_SET_OBJECT)) ==
...@@ -4304,6 +4304,10 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, ...@@ -4304,6 +4304,10 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
struct nlattr *tmp; struct nlattr *tmp;
int left; int left;
if (!(flags & NFT_SET_EXPR)) {
err = -EINVAL;
goto err_set_alloc_name;
}
i = 0; i = 0;
nla_for_each_nested(tmp, nla[NFTA_SET_EXPRESSIONS], left) { nla_for_each_nested(tmp, nla[NFTA_SET_EXPRESSIONS], left) {
if (i == NFT_SET_EXPR_MAX) { if (i == NFT_SET_EXPR_MAX) {
......
...@@ -19,6 +19,7 @@ struct nft_dynset { ...@@ -19,6 +19,7 @@ struct nft_dynset {
enum nft_registers sreg_key:8; enum nft_registers sreg_key:8;
enum nft_registers sreg_data:8; enum nft_registers sreg_data:8;
bool invert; bool invert;
bool expr;
u8 num_exprs; u8 num_exprs;
u64 timeout; u64 timeout;
struct nft_expr *expr_array[NFT_SET_EXPR_MAX]; struct nft_expr *expr_array[NFT_SET_EXPR_MAX];
...@@ -175,11 +176,12 @@ static int nft_dynset_init(const struct nft_ctx *ctx, ...@@ -175,11 +176,12 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
if (tb[NFTA_DYNSET_FLAGS]) { if (tb[NFTA_DYNSET_FLAGS]) {
u32 flags = ntohl(nla_get_be32(tb[NFTA_DYNSET_FLAGS])); u32 flags = ntohl(nla_get_be32(tb[NFTA_DYNSET_FLAGS]));
if (flags & ~(NFT_DYNSET_F_INV | NFT_DYNSET_F_EXPR))
if (flags & ~NFT_DYNSET_F_INV) return -EOPNOTSUPP;
return -EINVAL;
if (flags & NFT_DYNSET_F_INV) if (flags & NFT_DYNSET_F_INV)
priv->invert = true; priv->invert = true;
if (flags & NFT_DYNSET_F_EXPR)
priv->expr = true;
} }
set = nft_set_lookup_global(ctx->net, ctx->table, set = nft_set_lookup_global(ctx->net, ctx->table,
...@@ -210,7 +212,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx, ...@@ -210,7 +212,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
timeout = 0; timeout = 0;
if (tb[NFTA_DYNSET_TIMEOUT] != NULL) { if (tb[NFTA_DYNSET_TIMEOUT] != NULL) {
if (!(set->flags & NFT_SET_TIMEOUT)) if (!(set->flags & NFT_SET_TIMEOUT))
return -EINVAL; return -EOPNOTSUPP;
err = nf_msecs_to_jiffies64(tb[NFTA_DYNSET_TIMEOUT], &timeout); err = nf_msecs_to_jiffies64(tb[NFTA_DYNSET_TIMEOUT], &timeout);
if (err) if (err)
...@@ -224,7 +226,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx, ...@@ -224,7 +226,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
if (tb[NFTA_DYNSET_SREG_DATA] != NULL) { if (tb[NFTA_DYNSET_SREG_DATA] != NULL) {
if (!(set->flags & NFT_SET_MAP)) if (!(set->flags & NFT_SET_MAP))
return -EINVAL; return -EOPNOTSUPP;
if (set->dtype == NFT_DATA_VERDICT) if (set->dtype == NFT_DATA_VERDICT)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -261,6 +263,9 @@ static int nft_dynset_init(const struct nft_ctx *ctx, ...@@ -261,6 +263,9 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
struct nlattr *tmp; struct nlattr *tmp;
int left; int left;
if (!priv->expr)
return -EINVAL;
i = 0; i = 0;
nla_for_each_nested(tmp, tb[NFTA_DYNSET_EXPRESSIONS], left) { nla_for_each_nested(tmp, tb[NFTA_DYNSET_EXPRESSIONS], left) {
if (i == NFT_SET_EXPR_MAX) { if (i == NFT_SET_EXPR_MAX) {
......
...@@ -115,6 +115,9 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) ...@@ -115,6 +115,9 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
} cfg; } cfg;
int ret; int ret;
if (strnlen(info->name, sizeof(est->name)) >= sizeof(est->name))
return -ENAMETOOLONG;
net_get_random_once(&jhash_rnd, sizeof(jhash_rnd)); net_get_random_once(&jhash_rnd, sizeof(jhash_rnd));
mutex_lock(&xn->hash_lock); mutex_lock(&xn->hash_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment