netfilter: nft_compat: ebtables emulation must reject non-bridge targets

xtables targets return netfilter verdicts: NF_ACCEPT, NF_DROP, and so
on.  ebtables targets return incompatible verdicts: EBT_ACCEPT,
EBT_DROP, ...   We cannot allow fallback to NFPROTO_UNSPEC.

ebtables doesn't permit this since
11ff7288be ("netfilter: ebtables: reject non-bridge targets")
but that commit missed the nft_compat layer.

Reported-by: Ren Wei <n05ec@lzu.edu.cn>
Reported-by: Wyatt Feng <bronzed_45_vested@icloud.com>
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Fixes: 0ca743a559 ("netfilter: nf_tables: add compatibility layer for x_tables")
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Florian Westphal
2026-06-15 20:10:44 +02:00
committed by Pablo Neira Ayuso
parent a49a8e51ee
commit 9dbba7e694

View File

@@ -397,6 +397,22 @@ static int nft_target_validate(const struct nft_ctx *ctx,
return 0;
}
static int nft_target_bridge_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr)
{
struct xt_target *target = expr->ops->data;
/* Do not allow UNSPEC to stand-in for NFPROTO_BRIDGE
* targets: they are incompatible. ebtables targets return
* EBT_ACCEPT, DROP and so on which are not compatible with
* NF_ACCEPT, NF_DROP and so on.
*/
if (target->family != NFPROTO_BRIDGE)
return -ENOENT;
return nft_target_validate(ctx, expr);
}
static void __nft_match_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt,
@@ -932,13 +948,15 @@ nft_target_select_ops(const struct nft_ctx *ctx,
ops->init = nft_target_init;
ops->destroy = nft_target_destroy;
ops->dump = nft_target_dump;
ops->validate = nft_target_validate;
ops->data = target;
if (family == NFPROTO_BRIDGE)
if (family == NFPROTO_BRIDGE) {
ops->eval = nft_target_eval_bridge;
else
ops->validate = nft_target_bridge_validate;
} else {
ops->eval = nft_target_eval_xt;
ops->validate = nft_target_validate;
}
return ops;
err: