Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nft_meta: improve the validity check of pkttype set expr

"meta pkttype set" is only supported on prerouting chain with bridge
family and ingress chain with netdev family.

But the validate check is incomplete, and the user can add the nft
rules on input chain with bridge family, for example:
# nft add table bridge filter
# nft add chain bridge filter input {type filter hook input \
priority 0 \;}
# nft add chain bridge filter test
# nft add rule bridge filter test meta pkttype set unicast
# nft add rule bridge filter input jump test

This patch fixes the problem.

Signed-off-by: Liping Zhang <liping.zhang@spreadtrum.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Liping Zhang and committed by
Pablo Neira Ayuso
960fa72f 533e3300

+18 -4
+4
include/net/netfilter/nft_meta.h
··· 36 36 void nft_meta_set_destroy(const struct nft_ctx *ctx, 37 37 const struct nft_expr *expr); 38 38 39 + int nft_meta_set_validate(const struct nft_ctx *ctx, 40 + const struct nft_expr *expr, 41 + const struct nft_data **data); 42 + 39 43 #endif
+1
net/bridge/netfilter/nft_meta_bridge.c
··· 86 86 .init = nft_meta_set_init, 87 87 .destroy = nft_meta_set_destroy, 88 88 .dump = nft_meta_set_dump, 89 + .validate = nft_meta_set_validate, 89 90 }; 90 91 91 92 static const struct nft_expr_ops *
+13 -4
net/netfilter/nft_meta.c
··· 291 291 } 292 292 EXPORT_SYMBOL_GPL(nft_meta_get_init); 293 293 294 - static int nft_meta_set_init_pkttype(const struct nft_ctx *ctx) 294 + int nft_meta_set_validate(const struct nft_ctx *ctx, 295 + const struct nft_expr *expr, 296 + const struct nft_data **data) 295 297 { 298 + struct nft_meta *priv = nft_expr_priv(expr); 296 299 unsigned int hooks; 300 + 301 + if (priv->key != NFT_META_PKTTYPE) 302 + return 0; 297 303 298 304 switch (ctx->afi->family) { 299 305 case NFPROTO_BRIDGE: ··· 314 308 315 309 return nft_chain_validate_hooks(ctx->chain, hooks); 316 310 } 311 + EXPORT_SYMBOL_GPL(nft_meta_set_validate); 317 312 318 313 int nft_meta_set_init(const struct nft_ctx *ctx, 319 314 const struct nft_expr *expr, ··· 334 327 len = sizeof(u8); 335 328 break; 336 329 case NFT_META_PKTTYPE: 337 - err = nft_meta_set_init_pkttype(ctx); 338 - if (err) 339 - return err; 340 330 len = sizeof(u8); 341 331 break; 342 332 default: 343 333 return -EOPNOTSUPP; 344 334 } 335 + 336 + err = nft_meta_set_validate(ctx, expr, NULL); 337 + if (err < 0) 338 + return err; 345 339 346 340 priv->sreg = nft_parse_register(tb[NFTA_META_SREG]); 347 341 err = nft_validate_register_load(priv->sreg, len); ··· 415 407 .init = nft_meta_set_init, 416 408 .destroy = nft_meta_set_destroy, 417 409 .dump = nft_meta_set_dump, 410 + .validate = nft_meta_set_validate, 418 411 }; 419 412 420 413 static const struct nft_expr_ops *