Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45d9bcda authored by Patrick McHardy's avatar Patrick McHardy Committed by Pablo Neira Ayuso
Browse files

netfilter: nf_tables: validate len in nft_validate_data_load()



For values spanning multiple registers, we need to validate that enough
space is available from the destination register onwards. Add a len
argument to nft_validate_data_load() and consolidate the existing length
validations in preparation of that.

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent e60a9de4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@ int nft_validate_input_register(enum nft_registers reg);
int nft_validate_output_register(enum nft_registers reg);
int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg,
			   const struct nft_data *data,
			   enum nft_data_types type);
			   enum nft_data_types type, unsigned int len);


/**
+4 −1
Original line number Diff line number Diff line
@@ -53,12 +53,14 @@ static int nft_meta_bridge_get_init(const struct nft_ctx *ctx,
				    const struct nlattr * const tb[])
{
	struct nft_meta *priv = nft_expr_priv(expr);
	unsigned int len;
	int err;

	priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
	switch (priv->key) {
	case NFT_META_BRI_IIFNAME:
	case NFT_META_BRI_OIFNAME:
		len = IFNAMSIZ;
		break;
	default:
		return nft_meta_get_init(ctx, expr, tb);
@@ -69,7 +71,8 @@ static int nft_meta_bridge_get_init(const struct nft_ctx *ctx,
	if (err < 0)
		return err;

	err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE);
	err = nft_validate_data_load(ctx, priv->dreg, NULL,
				     NFT_DATA_VALUE, len);
	if (err < 0)
		return err;

+12 −6
Original line number Diff line number Diff line
@@ -2799,7 +2799,8 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
	dreg = nft_type_to_reg(set->dtype);
	return nft_validate_data_load(ctx, dreg, nft_set_ext_data(ext),
				      set->dtype == NFT_DATA_VERDICT ?
				      NFT_DATA_VERDICT : NFT_DATA_VALUE);
				      NFT_DATA_VERDICT : NFT_DATA_VALUE,
				      set->dlen);
}

int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
@@ -3334,7 +3335,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
				continue;

			err = nft_validate_data_load(&bind_ctx, dreg,
						     &data, d2.type);
						     &data, d2.type, d2.len);
			if (err < 0)
				goto err3;
		}
@@ -4162,15 +4163,16 @@ EXPORT_SYMBOL_GPL(nft_validate_output_register);
 * 	@reg: the destination register number
 * 	@data: the data to load
 * 	@type: the data type
 * 	@len: the length of the data
 *
 * 	Validate that a data load uses the appropriate data type for
 * 	the destination register. A value of NULL for the data means
 * 	that its runtime gathered data, which is always of type
 * 	NFT_DATA_VALUE.
 * 	the destination register and the length is within the bounds.
 * 	A value of NULL for the data means that its runtime gathered
 * 	data, which is always of type NFT_DATA_VALUE.
 */
int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg,
			   const struct nft_data *data,
			   enum nft_data_types type)
			   enum nft_data_types type, unsigned int len)
{
	int err;

@@ -4193,6 +4195,10 @@ int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg,

		return 0;
	default:
		if (len == 0)
			return -EINVAL;
		if (len > FIELD_SIZEOF(struct nft_data, data))
			return -ERANGE;
		if (data != NULL && type != NFT_DATA_VALUE)
			return -EINVAL;
		return 0;
+5 −3
Original line number Diff line number Diff line
@@ -63,6 +63,8 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
	    tb[NFTA_BITWISE_XOR] == NULL)
		return -EINVAL;

	priv->len = ntohl(nla_get_be32(tb[NFTA_BITWISE_LEN]));

	priv->sreg = ntohl(nla_get_be32(tb[NFTA_BITWISE_SREG]));
	err = nft_validate_input_register(priv->sreg);
	if (err < 0)
@@ -72,12 +74,12 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
	err = nft_validate_output_register(priv->dreg);
	if (err < 0)
		return err;
	err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE);

	err = nft_validate_data_load(ctx, priv->dreg, NULL,
				     NFT_DATA_VALUE, priv->len);
	if (err < 0)
		return err;

	priv->len = ntohl(nla_get_be32(tb[NFTA_BITWISE_LEN]));

	err = nft_data_init(NULL, &priv->mask, &d1, tb[NFTA_BITWISE_MASK]);
	if (err < 0)
		return err;
+14 −13
Original line number Diff line number Diff line
@@ -87,19 +87,6 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
	    tb[NFTA_BYTEORDER_OP] == NULL)
		return -EINVAL;

	priv->sreg = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_SREG]));
	err = nft_validate_input_register(priv->sreg);
	if (err < 0)
		return err;

	priv->dreg = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_DREG]));
	err = nft_validate_output_register(priv->dreg);
	if (err < 0)
		return err;
	err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE);
	if (err < 0)
		return err;

	priv->op = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_OP]));
	switch (priv->op) {
	case NFT_BYTEORDER_NTOH:
@@ -122,6 +109,20 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
		return -EINVAL;
	}

	priv->sreg = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_SREG]));
	err = nft_validate_input_register(priv->sreg);
	if (err < 0)
		return err;

	priv->dreg = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_DREG]));
	err = nft_validate_output_register(priv->dreg);
	if (err < 0)
		return err;
	err = nft_validate_data_load(ctx, priv->dreg, NULL,
				     NFT_DATA_VALUE, priv->len);
	if (err < 0)
		return err;

	return 0;
}

Loading