[PATCH 6.12 046/337] netfilter: xt_hashlimit: validate hashtable supports XT_HASHLIMIT_RATE_MATCH
Greg Kroah-Hartman <[email protected]>
| Newsgroups | dev.linux.lists.patches,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
6.12-stable review patch. If anyone has any objections, please let me know. ------------------ From: Pablo Neira Ayuso <[email protected]> [ Upstream commit 305b63e1402267459fdabb183af4527f6799eebf ] The XT_HASHLIMIT_RATE_MATCH flag mode changes the semantics of the dsthash_ent structure which represents an entry in the hashtable. There is a union area which uses a different layout to express the rate match mode. Update .checkentry path to validate the XT_HASHLIMIT_RATE_MATCH mode flag is requested by two or more different rules that refer to the same hashtable. Otherwise, uninitialized access to the burst field in the union is possible. Reject the use of the XT_HASHLIMIT_RATE_MATCH mode flag if set on by revision less than 3 too. Fixes: bea74641e378 ("netfilter: xt_hashlimit: add rate match mode") Reported-and-tested-by: Talha Berk Arslan <[email protected]> Link: https://patch.msgid.link/[email protected]/ Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: Sasha Levin <[email protected]> --- net/netfilter/xt_hashlimit.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 0859b8f767645..61813010cd319 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -118,6 +118,7 @@ struct xt_hashlimit_htable { refcount_t use; u_int8_t family; bool rnd_initialized; + bool ratematch; struct hashlimit_cfg3 cfg; /* config */ @@ -325,6 +326,7 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg, vfree(hinfo); return -ENOMEM; } + hinfo->ratematch = !!(cfg->mode & XT_HASHLIMIT_RATE_MATCH); spin_lock_init(&hinfo->lock); switch (revision) { @@ -868,7 +870,10 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par, } /* Check for overflow. */ - if (revision >= 3 && cfg->mode & XT_HASHLIMIT_RATE_MATCH) { + if (cfg->mode & XT_HASHLIMIT_RATE_MATCH) { + if (revision < 3) + return -EINVAL; + if (cfg->avg == 0 || cfg->avg > U32_MAX) { pr_info_ratelimited("invalid rate\n"); return -ERANGE; @@ -901,6 +906,15 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par, mutex_unlock(&hashlimit_mutex); return ret; } + } else { + if ((cfg->mode & XT_HASHLIMIT_RATE_MATCH && + !(*hinfo)->ratematch) || + (!(cfg->mode & XT_HASHLIMIT_RATE_MATCH) && + (*hinfo)->ratematch)) { + mutex_unlock(&hashlimit_mutex); + htable_put(*hinfo); + return -EINVAL; + } } mutex_unlock(&hashlimit_mutex); -- 2.53.0