aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/netfilter/nft_compat.c75
1 files changed, 66 insertions, 9 deletions
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index 44ae273b4391..0480f57a4eb6 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -19,9 +19,52 @@
19#include <linux/netfilter/x_tables.h> 19#include <linux/netfilter/x_tables.h>
20#include <linux/netfilter_ipv4/ip_tables.h> 20#include <linux/netfilter_ipv4/ip_tables.h>
21#include <linux/netfilter_ipv6/ip6_tables.h> 21#include <linux/netfilter_ipv6/ip6_tables.h>
22#include <asm/uaccess.h> /* for set_fs */
23#include <net/netfilter/nf_tables.h> 22#include <net/netfilter/nf_tables.h>
24 23
24static const struct {
25 const char *name;
26 u8 type;
27} table_to_chaintype[] = {
28 { "filter", NFT_CHAIN_T_DEFAULT },
29 { "raw", NFT_CHAIN_T_DEFAULT },
30 { "security", NFT_CHAIN_T_DEFAULT },
31 { "mangle", NFT_CHAIN_T_ROUTE },
32 { "nat", NFT_CHAIN_T_NAT },
33 { },
34};
35
36static int nft_compat_table_to_chaintype(const char *table)
37{
38 int i;
39
40 for (i = 0; table_to_chaintype[i].name != NULL; i++) {
41 if (strcmp(table_to_chaintype[i].name, table) == 0)
42 return table_to_chaintype[i].type;
43 }
44
45 return -1;
46}
47
48static int nft_compat_chain_validate_dependency(const char *tablename,
49 const struct nft_chain *chain)
50{
51 enum nft_chain_type type;
52 const struct nft_base_chain *basechain;
53
54 if (!tablename || !(chain->flags & NFT_BASE_CHAIN))
55 return 0;
56
57 type = nft_compat_table_to_chaintype(tablename);
58 if (type < 0)
59 return -EINVAL;
60
61 basechain = nft_base_chain(chain);
62 if (basechain->type->type != type)
63 return -EINVAL;
64
65 return 0;
66}
67
25union nft_entry { 68union nft_entry {
26 struct ipt_entry e4; 69 struct ipt_entry e4;
27 struct ip6t_entry e6; 70 struct ip6t_entry e6;
@@ -153,6 +196,10 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
153 union nft_entry e = {}; 196 union nft_entry e = {};
154 int ret; 197 int ret;
155 198
199 ret = nft_compat_chain_validate_dependency(target->table, ctx->chain);
200 if (ret < 0)
201 goto err;
202
156 target_compat_from_user(target, nla_data(tb[NFTA_TARGET_INFO]), info); 203 target_compat_from_user(target, nla_data(tb[NFTA_TARGET_INFO]), info);
157 204
158 if (ctx->nla[NFTA_RULE_COMPAT]) { 205 if (ctx->nla[NFTA_RULE_COMPAT]) {
@@ -218,6 +265,7 @@ static int nft_target_validate(const struct nft_ctx *ctx,
218{ 265{
219 struct xt_target *target = expr->ops->data; 266 struct xt_target *target = expr->ops->data;
220 unsigned int hook_mask = 0; 267 unsigned int hook_mask = 0;
268 int ret;
221 269
222 if (ctx->chain->flags & NFT_BASE_CHAIN) { 270 if (ctx->chain->flags & NFT_BASE_CHAIN) {
223 const struct nft_base_chain *basechain = 271 const struct nft_base_chain *basechain =
@@ -225,11 +273,13 @@ static int nft_target_validate(const struct nft_ctx *ctx,
225 const struct nf_hook_ops *ops = &basechain->ops[0]; 273 const struct nf_hook_ops *ops = &basechain->ops[0];
226 274
227 hook_mask = 1 << ops->hooknum; 275 hook_mask = 1 << ops->hooknum;
228 if (hook_mask & target->hooks) 276 if (!(hook_mask & target->hooks))
229 return 0; 277 return -EINVAL;
230 278
231 /* This target is being called from an invalid chain */ 279 ret = nft_compat_chain_validate_dependency(target->table,
232 return -EINVAL; 280 ctx->chain);
281 if (ret < 0)
282 return ret;
233 } 283 }
234 return 0; 284 return 0;
235} 285}
@@ -324,6 +374,10 @@ nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
324 union nft_entry e = {}; 374 union nft_entry e = {};
325 int ret; 375 int ret;
326 376
377 ret = nft_compat_chain_validate_dependency(match->name, ctx->chain);
378 if (ret < 0)
379 goto err;
380
327 match_compat_from_user(match, nla_data(tb[NFTA_MATCH_INFO]), info); 381 match_compat_from_user(match, nla_data(tb[NFTA_MATCH_INFO]), info);
328 382
329 if (ctx->nla[NFTA_RULE_COMPAT]) { 383 if (ctx->nla[NFTA_RULE_COMPAT]) {
@@ -383,6 +437,7 @@ static int nft_match_validate(const struct nft_ctx *ctx,
383{ 437{
384 struct xt_match *match = expr->ops->data; 438 struct xt_match *match = expr->ops->data;
385 unsigned int hook_mask = 0; 439 unsigned int hook_mask = 0;
440 int ret;
386 441
387 if (ctx->chain->flags & NFT_BASE_CHAIN) { 442 if (ctx->chain->flags & NFT_BASE_CHAIN) {
388 const struct nft_base_chain *basechain = 443 const struct nft_base_chain *basechain =
@@ -390,11 +445,13 @@ static int nft_match_validate(const struct nft_ctx *ctx,
390 const struct nf_hook_ops *ops = &basechain->ops[0]; 445 const struct nf_hook_ops *ops = &basechain->ops[0];
391 446
392 hook_mask = 1 << ops->hooknum; 447 hook_mask = 1 << ops->hooknum;
393 if (hook_mask & match->hooks) 448 if (!(hook_mask & match->hooks))
394 return 0; 449 return -EINVAL;
395 450
396 /* This match is being called from an invalid chain */ 451 ret = nft_compat_chain_validate_dependency(match->name,
397 return -EINVAL; 452 ctx->chain);
453 if (ret < 0)
454 return ret;
398 } 455 }
399 return 0; 456 return 0;
400} 457}