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

netfilter: nf_tables: support variable sized data in nft_data_init()

Add a size argument to nft_data_init() and pass in the available space.
This will be used by the following patches to support variable sized
set element data.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Patrick McHardy and committed by
Pablo Neira Ayuso
d0a11fc3 49499c3e

+30 -17
+2 -1
include/net/netfilter/nf_tables.h
··· 110 110 unsigned int len; 111 111 }; 112 112 113 - int nft_data_init(const struct nft_ctx *ctx, struct nft_data *data, 113 + int nft_data_init(const struct nft_ctx *ctx, 114 + struct nft_data *data, unsigned int size, 114 115 struct nft_data_desc *desc, const struct nlattr *nla); 115 116 void nft_data_uninit(const struct nft_data *data, enum nft_data_types type); 116 117 int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
+16 -10
net/netfilter/nf_tables_api.c
··· 3299 3299 timeout = set->timeout; 3300 3300 } 3301 3301 3302 - err = nft_data_init(ctx, &elem.key, &d1, nla[NFTA_SET_ELEM_KEY]); 3302 + err = nft_data_init(ctx, &elem.key, sizeof(elem.key), &d1, 3303 + nla[NFTA_SET_ELEM_KEY]); 3303 3304 if (err < 0) 3304 3305 goto err1; 3305 3306 err = -EINVAL; ··· 3315 3314 } 3316 3315 3317 3316 if (nla[NFTA_SET_ELEM_DATA] != NULL) { 3318 - err = nft_data_init(ctx, &data, &d2, nla[NFTA_SET_ELEM_DATA]); 3317 + err = nft_data_init(ctx, &data, sizeof(data), &d2, 3318 + nla[NFTA_SET_ELEM_DATA]); 3319 3319 if (err < 0) 3320 3320 goto err2; 3321 3321 ··· 3460 3458 if (nla[NFTA_SET_ELEM_KEY] == NULL) 3461 3459 goto err1; 3462 3460 3463 - err = nft_data_init(ctx, &elem.key, &desc, nla[NFTA_SET_ELEM_KEY]); 3461 + err = nft_data_init(ctx, &elem.key, sizeof(elem.key), &desc, 3462 + nla[NFTA_SET_ELEM_KEY]); 3464 3463 if (err < 0) 3465 3464 goto err1; 3466 3465 ··· 4342 4339 return -1; 4343 4340 } 4344 4341 4345 - static int nft_value_init(const struct nft_ctx *ctx, struct nft_data *data, 4342 + static int nft_value_init(const struct nft_ctx *ctx, 4343 + struct nft_data *data, unsigned int size, 4346 4344 struct nft_data_desc *desc, const struct nlattr *nla) 4347 4345 { 4348 4346 unsigned int len; ··· 4351 4347 len = nla_len(nla); 4352 4348 if (len == 0) 4353 4349 return -EINVAL; 4354 - if (len > sizeof(data->data)) 4350 + if (len > size) 4355 4351 return -EOVERFLOW; 4356 4352 4357 - nla_memcpy(data->data, nla, sizeof(data->data)); 4353 + nla_memcpy(data->data, nla, len); 4358 4354 desc->type = NFT_DATA_VALUE; 4359 4355 desc->len = len; 4360 4356 return 0; ··· 4367 4363 } 4368 4364 4369 4365 static const struct nla_policy nft_data_policy[NFTA_DATA_MAX + 1] = { 4370 - [NFTA_DATA_VALUE] = { .type = NLA_BINARY, 4371 - .len = FIELD_SIZEOF(struct nft_data, data) }, 4366 + [NFTA_DATA_VALUE] = { .type = NLA_BINARY }, 4372 4367 [NFTA_DATA_VERDICT] = { .type = NLA_NESTED }, 4373 4368 }; 4374 4369 ··· 4376 4373 * 4377 4374 * @ctx: context of the expression using the data 4378 4375 * @data: destination struct nft_data 4376 + * @size: maximum data length 4379 4377 * @desc: data description 4380 4378 * @nla: netlink attribute containing data 4381 4379 * ··· 4386 4382 * The caller can indicate that it only wants to accept data of type 4387 4383 * NFT_DATA_VALUE by passing NULL for the ctx argument. 4388 4384 */ 4389 - int nft_data_init(const struct nft_ctx *ctx, struct nft_data *data, 4385 + int nft_data_init(const struct nft_ctx *ctx, 4386 + struct nft_data *data, unsigned int size, 4390 4387 struct nft_data_desc *desc, const struct nlattr *nla) 4391 4388 { 4392 4389 struct nlattr *tb[NFTA_DATA_MAX + 1]; ··· 4398 4393 return err; 4399 4394 4400 4395 if (tb[NFTA_DATA_VALUE]) 4401 - return nft_value_init(ctx, data, desc, tb[NFTA_DATA_VALUE]); 4396 + return nft_value_init(ctx, data, size, desc, 4397 + tb[NFTA_DATA_VALUE]); 4402 4398 if (tb[NFTA_DATA_VERDICT] && ctx != NULL) 4403 4399 return nft_verdict_init(ctx, data, desc, tb[NFTA_DATA_VERDICT]); 4404 4400 return -EINVAL;
+4 -2
net/netfilter/nft_bitwise.c
··· 73 73 if (err < 0) 74 74 return err; 75 75 76 - err = nft_data_init(NULL, &priv->mask, &d1, tb[NFTA_BITWISE_MASK]); 76 + err = nft_data_init(NULL, &priv->mask, sizeof(priv->mask), &d1, 77 + tb[NFTA_BITWISE_MASK]); 77 78 if (err < 0) 78 79 return err; 79 80 if (d1.len != priv->len) 80 81 return -EINVAL; 81 82 82 - err = nft_data_init(NULL, &priv->xor, &d2, tb[NFTA_BITWISE_XOR]); 83 + err = nft_data_init(NULL, &priv->xor, sizeof(priv->xor), &d2, 84 + tb[NFTA_BITWISE_XOR]); 83 85 if (err < 0) 84 86 return err; 85 87 if (d2.len != priv->len)
+6 -3
net/netfilter/nft_cmp.c
··· 75 75 struct nft_data_desc desc; 76 76 int err; 77 77 78 - err = nft_data_init(NULL, &priv->data, &desc, tb[NFTA_CMP_DATA]); 78 + err = nft_data_init(NULL, &priv->data, sizeof(priv->data), &desc, 79 + tb[NFTA_CMP_DATA]); 79 80 BUG_ON(err < 0); 80 81 81 82 priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]); ··· 126 125 u32 mask; 127 126 int err; 128 127 129 - err = nft_data_init(NULL, &data, &desc, tb[NFTA_CMP_DATA]); 128 + err = nft_data_init(NULL, &data, sizeof(data), &desc, 129 + tb[NFTA_CMP_DATA]); 130 130 BUG_ON(err < 0); 131 131 132 132 priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]); ··· 197 195 return ERR_PTR(-EINVAL); 198 196 } 199 197 200 - err = nft_data_init(NULL, &data, &desc, tb[NFTA_CMP_DATA]); 198 + err = nft_data_init(NULL, &data, sizeof(data), &desc, 199 + tb[NFTA_CMP_DATA]); 201 200 if (err < 0) 202 201 return ERR_PTR(err); 203 202
+2 -1
net/netfilter/nft_immediate.c
··· 49 49 tb[NFTA_IMMEDIATE_DATA] == NULL) 50 50 return -EINVAL; 51 51 52 - err = nft_data_init(ctx, &priv->data, &desc, tb[NFTA_IMMEDIATE_DATA]); 52 + err = nft_data_init(ctx, &priv->data, sizeof(priv->data), &desc, 53 + tb[NFTA_IMMEDIATE_DATA]); 53 54 if (err < 0) 54 55 return err; 55 56 priv->dlen = desc.len;