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: Patrick McHardy <kaber@trash.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
e60a9de49c
commit
45d9bcda21
@ -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_output_register(enum nft_registers reg);
|
||||||
int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg,
|
int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg,
|
||||||
const struct nft_data *data,
|
const struct nft_data *data,
|
||||||
enum nft_data_types type);
|
enum nft_data_types type, unsigned int len);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,12 +53,14 @@ static int nft_meta_bridge_get_init(const struct nft_ctx *ctx,
|
|||||||
const struct nlattr * const tb[])
|
const struct nlattr * const tb[])
|
||||||
{
|
{
|
||||||
struct nft_meta *priv = nft_expr_priv(expr);
|
struct nft_meta *priv = nft_expr_priv(expr);
|
||||||
|
unsigned int len;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
|
priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
|
||||||
switch (priv->key) {
|
switch (priv->key) {
|
||||||
case NFT_META_BRI_IIFNAME:
|
case NFT_META_BRI_IIFNAME:
|
||||||
case NFT_META_BRI_OIFNAME:
|
case NFT_META_BRI_OIFNAME:
|
||||||
|
len = IFNAMSIZ;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return nft_meta_get_init(ctx, expr, tb);
|
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)
|
if (err < 0)
|
||||||
return err;
|
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)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -2799,7 +2799,8 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
|
|||||||
dreg = nft_type_to_reg(set->dtype);
|
dreg = nft_type_to_reg(set->dtype);
|
||||||
return nft_validate_data_load(ctx, dreg, nft_set_ext_data(ext),
|
return nft_validate_data_load(ctx, dreg, nft_set_ext_data(ext),
|
||||||
set->dtype == NFT_DATA_VERDICT ?
|
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,
|
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;
|
continue;
|
||||||
|
|
||||||
err = nft_validate_data_load(&bind_ctx, dreg,
|
err = nft_validate_data_load(&bind_ctx, dreg,
|
||||||
&data, d2.type);
|
&data, d2.type, d2.len);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto err3;
|
goto err3;
|
||||||
}
|
}
|
||||||
@ -4162,15 +4163,16 @@ EXPORT_SYMBOL_GPL(nft_validate_output_register);
|
|||||||
* @reg: the destination register number
|
* @reg: the destination register number
|
||||||
* @data: the data to load
|
* @data: the data to load
|
||||||
* @type: the data type
|
* @type: the data type
|
||||||
|
* @len: the length of the data
|
||||||
*
|
*
|
||||||
* Validate that a data load uses the appropriate data type for
|
* Validate that a data load uses the appropriate data type for
|
||||||
* the destination register. A value of NULL for the data means
|
* the destination register and the length is within the bounds.
|
||||||
* that its runtime gathered data, which is always of type
|
* A value of NULL for the data means that its runtime gathered
|
||||||
* NFT_DATA_VALUE.
|
* data, which is always of type NFT_DATA_VALUE.
|
||||||
*/
|
*/
|
||||||
int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg,
|
int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg,
|
||||||
const struct nft_data *data,
|
const struct nft_data *data,
|
||||||
enum nft_data_types type)
|
enum nft_data_types type, unsigned int len)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -4193,6 +4195,10 @@ int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
|
if (len == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (len > FIELD_SIZEOF(struct nft_data, data))
|
||||||
|
return -ERANGE;
|
||||||
if (data != NULL && type != NFT_DATA_VALUE)
|
if (data != NULL && type != NFT_DATA_VALUE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -63,6 +63,8 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
|
|||||||
tb[NFTA_BITWISE_XOR] == NULL)
|
tb[NFTA_BITWISE_XOR] == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
priv->len = ntohl(nla_get_be32(tb[NFTA_BITWISE_LEN]));
|
||||||
|
|
||||||
priv->sreg = ntohl(nla_get_be32(tb[NFTA_BITWISE_SREG]));
|
priv->sreg = ntohl(nla_get_be32(tb[NFTA_BITWISE_SREG]));
|
||||||
err = nft_validate_input_register(priv->sreg);
|
err = nft_validate_input_register(priv->sreg);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -72,12 +74,12 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
|
|||||||
err = nft_validate_output_register(priv->dreg);
|
err = nft_validate_output_register(priv->dreg);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
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)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
priv->len = ntohl(nla_get_be32(tb[NFTA_BITWISE_LEN]));
|
|
||||||
|
|
||||||
err = nft_data_init(NULL, &priv->mask, &d1, tb[NFTA_BITWISE_MASK]);
|
err = nft_data_init(NULL, &priv->mask, &d1, tb[NFTA_BITWISE_MASK]);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
@ -87,19 +87,6 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
|
|||||||
tb[NFTA_BYTEORDER_OP] == NULL)
|
tb[NFTA_BYTEORDER_OP] == NULL)
|
||||||
return -EINVAL;
|
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]));
|
priv->op = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_OP]));
|
||||||
switch (priv->op) {
|
switch (priv->op) {
|
||||||
case NFT_BYTEORDER_NTOH:
|
case NFT_BYTEORDER_NTOH:
|
||||||
@ -122,6 +109,20 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
|
|||||||
return -EINVAL;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,8 +95,6 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
|
|||||||
helper = rcu_dereference(help->helper);
|
helper = rcu_dereference(help->helper);
|
||||||
if (helper == NULL)
|
if (helper == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
if (strlen(helper->name) >= sizeof(dest->data))
|
|
||||||
goto err;
|
|
||||||
strncpy((char *)dest->data, helper->name, sizeof(dest->data));
|
strncpy((char *)dest->data, helper->name, sizeof(dest->data));
|
||||||
return;
|
return;
|
||||||
#ifdef CONFIG_NF_CONNTRACK_LABELS
|
#ifdef CONFIG_NF_CONNTRACK_LABELS
|
||||||
@ -109,9 +107,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE > sizeof(dest->data));
|
|
||||||
size = labels->words * sizeof(long);
|
size = labels->words * sizeof(long);
|
||||||
|
|
||||||
memcpy(dest->data, labels->bits, size);
|
memcpy(dest->data, labels->bits, size);
|
||||||
if (size < sizeof(dest->data))
|
if (size < sizeof(dest->data))
|
||||||
memset(((char *) dest->data) + size, 0,
|
memset(((char *) dest->data) + size, 0,
|
||||||
@ -228,12 +224,17 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
|
|||||||
const struct nlattr * const tb[])
|
const struct nlattr * const tb[])
|
||||||
{
|
{
|
||||||
struct nft_ct *priv = nft_expr_priv(expr);
|
struct nft_ct *priv = nft_expr_priv(expr);
|
||||||
|
unsigned int len;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY]));
|
priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY]));
|
||||||
switch (priv->key) {
|
switch (priv->key) {
|
||||||
case NFT_CT_STATE:
|
|
||||||
case NFT_CT_DIRECTION:
|
case NFT_CT_DIRECTION:
|
||||||
|
if (tb[NFTA_CT_DIRECTION] != NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
len = sizeof(u8);
|
||||||
|
break;
|
||||||
|
case NFT_CT_STATE:
|
||||||
case NFT_CT_STATUS:
|
case NFT_CT_STATUS:
|
||||||
#ifdef CONFIG_NF_CONNTRACK_MARK
|
#ifdef CONFIG_NF_CONNTRACK_MARK
|
||||||
case NFT_CT_MARK:
|
case NFT_CT_MARK:
|
||||||
@ -241,22 +242,54 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
|
|||||||
#ifdef CONFIG_NF_CONNTRACK_SECMARK
|
#ifdef CONFIG_NF_CONNTRACK_SECMARK
|
||||||
case NFT_CT_SECMARK:
|
case NFT_CT_SECMARK:
|
||||||
#endif
|
#endif
|
||||||
|
case NFT_CT_EXPIRATION:
|
||||||
|
if (tb[NFTA_CT_DIRECTION] != NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
len = sizeof(u32);
|
||||||
|
break;
|
||||||
#ifdef CONFIG_NF_CONNTRACK_LABELS
|
#ifdef CONFIG_NF_CONNTRACK_LABELS
|
||||||
case NFT_CT_LABELS:
|
case NFT_CT_LABELS:
|
||||||
|
if (tb[NFTA_CT_DIRECTION] != NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
len = NF_CT_LABELS_MAX_SIZE;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
case NFT_CT_EXPIRATION:
|
|
||||||
case NFT_CT_HELPER:
|
case NFT_CT_HELPER:
|
||||||
if (tb[NFTA_CT_DIRECTION] != NULL)
|
if (tb[NFTA_CT_DIRECTION] != NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
len = NF_CT_HELPER_NAME_LEN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NFT_CT_L3PROTOCOL:
|
case NFT_CT_L3PROTOCOL:
|
||||||
case NFT_CT_PROTOCOL:
|
case NFT_CT_PROTOCOL:
|
||||||
|
if (tb[NFTA_CT_DIRECTION] == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
len = sizeof(u8);
|
||||||
|
break;
|
||||||
case NFT_CT_SRC:
|
case NFT_CT_SRC:
|
||||||
case NFT_CT_DST:
|
case NFT_CT_DST:
|
||||||
|
if (tb[NFTA_CT_DIRECTION] == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (ctx->afi->family) {
|
||||||
|
case NFPROTO_IPV4:
|
||||||
|
len = FIELD_SIZEOF(struct nf_conntrack_tuple,
|
||||||
|
src.u3.ip);
|
||||||
|
break;
|
||||||
|
case NFPROTO_IPV6:
|
||||||
|
case NFPROTO_INET:
|
||||||
|
len = FIELD_SIZEOF(struct nf_conntrack_tuple,
|
||||||
|
src.u3.ip6);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case NFT_CT_PROTO_SRC:
|
case NFT_CT_PROTO_SRC:
|
||||||
case NFT_CT_PROTO_DST:
|
case NFT_CT_PROTO_DST:
|
||||||
if (tb[NFTA_CT_DIRECTION] == NULL)
|
if (tb[NFTA_CT_DIRECTION] == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u.all);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
@ -278,7 +311,8 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
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)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -69,15 +69,13 @@ static int nft_exthdr_init(const struct nft_ctx *ctx,
|
|||||||
priv->type = nla_get_u8(tb[NFTA_EXTHDR_TYPE]);
|
priv->type = nla_get_u8(tb[NFTA_EXTHDR_TYPE]);
|
||||||
priv->offset = ntohl(nla_get_be32(tb[NFTA_EXTHDR_OFFSET]));
|
priv->offset = ntohl(nla_get_be32(tb[NFTA_EXTHDR_OFFSET]));
|
||||||
priv->len = ntohl(nla_get_be32(tb[NFTA_EXTHDR_LEN]));
|
priv->len = ntohl(nla_get_be32(tb[NFTA_EXTHDR_LEN]));
|
||||||
if (priv->len == 0 ||
|
|
||||||
priv->len > FIELD_SIZEOF(struct nft_data, data))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
priv->dreg = ntohl(nla_get_be32(tb[NFTA_EXTHDR_DREG]));
|
priv->dreg = ntohl(nla_get_be32(tb[NFTA_EXTHDR_DREG]));
|
||||||
err = nft_validate_output_register(priv->dreg);
|
err = nft_validate_output_register(priv->dreg);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
return nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE);
|
return nft_validate_data_load(ctx, priv->dreg, NULL,
|
||||||
|
NFT_DATA_VALUE, priv->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nft_exthdr_dump(struct sk_buff *skb, const struct nft_expr *expr)
|
static int nft_exthdr_dump(struct sk_buff *skb, const struct nft_expr *expr)
|
||||||
|
@ -59,7 +59,8 @@ static int nft_immediate_init(const struct nft_ctx *ctx,
|
|||||||
return err;
|
return err;
|
||||||
priv->dlen = desc.len;
|
priv->dlen = desc.len;
|
||||||
|
|
||||||
err = nft_validate_data_load(ctx, priv->dreg, &priv->data, desc.type);
|
err = nft_validate_data_load(ctx, priv->dreg, &priv->data,
|
||||||
|
desc.type, desc.len);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
|
@ -217,22 +217,23 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
|
|||||||
const struct nlattr * const tb[])
|
const struct nlattr * const tb[])
|
||||||
{
|
{
|
||||||
struct nft_meta *priv = nft_expr_priv(expr);
|
struct nft_meta *priv = nft_expr_priv(expr);
|
||||||
|
unsigned int len;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
|
priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
|
||||||
switch (priv->key) {
|
switch (priv->key) {
|
||||||
case NFT_META_LEN:
|
|
||||||
case NFT_META_PROTOCOL:
|
case NFT_META_PROTOCOL:
|
||||||
|
case NFT_META_IIFTYPE:
|
||||||
|
case NFT_META_OIFTYPE:
|
||||||
|
len = sizeof(u16);
|
||||||
|
break;
|
||||||
case NFT_META_NFPROTO:
|
case NFT_META_NFPROTO:
|
||||||
case NFT_META_L4PROTO:
|
case NFT_META_L4PROTO:
|
||||||
|
case NFT_META_LEN:
|
||||||
case NFT_META_PRIORITY:
|
case NFT_META_PRIORITY:
|
||||||
case NFT_META_MARK:
|
case NFT_META_MARK:
|
||||||
case NFT_META_IIF:
|
case NFT_META_IIF:
|
||||||
case NFT_META_OIF:
|
case NFT_META_OIF:
|
||||||
case NFT_META_IIFNAME:
|
|
||||||
case NFT_META_OIFNAME:
|
|
||||||
case NFT_META_IIFTYPE:
|
|
||||||
case NFT_META_OIFTYPE:
|
|
||||||
case NFT_META_SKUID:
|
case NFT_META_SKUID:
|
||||||
case NFT_META_SKGID:
|
case NFT_META_SKGID:
|
||||||
#ifdef CONFIG_IP_ROUTE_CLASSID
|
#ifdef CONFIG_IP_ROUTE_CLASSID
|
||||||
@ -246,6 +247,11 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
|
|||||||
case NFT_META_IIFGROUP:
|
case NFT_META_IIFGROUP:
|
||||||
case NFT_META_OIFGROUP:
|
case NFT_META_OIFGROUP:
|
||||||
case NFT_META_CGROUP:
|
case NFT_META_CGROUP:
|
||||||
|
len = sizeof(u32);
|
||||||
|
break;
|
||||||
|
case NFT_META_IIFNAME:
|
||||||
|
case NFT_META_OIFNAME:
|
||||||
|
len = IFNAMSIZ;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
@ -256,7 +262,8 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
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)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -72,7 +72,8 @@ static int nft_payload_init(const struct nft_ctx *ctx,
|
|||||||
err = nft_validate_output_register(priv->dreg);
|
err = nft_validate_output_register(priv->dreg);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
return nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE);
|
return nft_validate_data_load(ctx, priv->dreg, NULL,
|
||||||
|
NFT_DATA_VALUE, priv->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr)
|
static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr)
|
||||||
@ -131,9 +132,7 @@ nft_payload_select_ops(const struct nft_ctx *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
|
offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
|
||||||
len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
|
len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
|
||||||
if (len == 0 || len > FIELD_SIZEOF(struct nft_data, data))
|
|
||||||
return ERR_PTR(-EINVAL);
|
|
||||||
|
|
||||||
if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) &&
|
if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) &&
|
||||||
base != NFT_PAYLOAD_LL_HEADER)
|
base != NFT_PAYLOAD_LL_HEADER)
|
||||||
|
Loading…
Reference in New Issue
Block a user