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

netfilter: nf_tables: validate NFT_DATA_VALUE after nft_data_init()

Userspace might bogusly sent NFT_DATA_VERDICT in several netlink
attributes that assume NFT_DATA_VALUE. Moreover, make sure that error
path invokes nft_data_release() to decrement the reference count on the
chain object.

Fixes: 96518518cc41 ("netfilter: add nftables")
Fixes: 0f3cd9b36977 ("netfilter: nf_tables: add range expression")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

+21 -3
+3 -1
net/netfilter/nf_tables_api.c
··· 4519 4519 return err; 4520 4520 4521 4521 err = -EINVAL; 4522 - if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) 4522 + if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) { 4523 + nft_data_release(&elem.key.val, desc.type); 4523 4524 return err; 4525 + } 4524 4526 4525 4527 priv = set->ops->get(ctx->net, set, &elem, flags); 4526 4528 if (IS_ERR(priv))
+2 -2
net/netfilter/nft_bitwise.c
··· 80 80 tb[NFTA_BITWISE_MASK]); 81 81 if (err < 0) 82 82 return err; 83 - if (d1.len != priv->len) { 83 + if (d1.type != NFT_DATA_VALUE || d1.len != priv->len) { 84 84 err = -EINVAL; 85 85 goto err1; 86 86 } ··· 89 89 tb[NFTA_BITWISE_XOR]); 90 90 if (err < 0) 91 91 goto err1; 92 - if (d2.len != priv->len) { 92 + if (d2.type != NFT_DATA_VALUE || d2.len != priv->len) { 93 93 err = -EINVAL; 94 94 goto err2; 95 95 }
+6
net/netfilter/nft_cmp.c
··· 81 81 if (err < 0) 82 82 return err; 83 83 84 + if (desc.type != NFT_DATA_VALUE) { 85 + err = -EINVAL; 86 + nft_data_release(&priv->data, desc.type); 87 + return err; 88 + } 89 + 84 90 priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]); 85 91 err = nft_validate_register_load(priv->sreg, desc.len); 86 92 if (err < 0)
+10
net/netfilter/nft_range.c
··· 66 66 if (err < 0) 67 67 return err; 68 68 69 + if (desc_from.type != NFT_DATA_VALUE) { 70 + err = -EINVAL; 71 + goto err1; 72 + } 73 + 69 74 err = nft_data_init(NULL, &priv->data_to, sizeof(priv->data_to), 70 75 &desc_to, tb[NFTA_RANGE_TO_DATA]); 71 76 if (err < 0) 72 77 goto err1; 78 + 79 + if (desc_to.type != NFT_DATA_VALUE) { 80 + err = -EINVAL; 81 + goto err2; 82 + } 73 83 74 84 if (desc_from.len != desc_to.len) { 75 85 err = -EINVAL;