aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2015-04-10 21:27:26 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2015-04-13 10:25:49 -0400
commit45d9bcda21f4c13be75e3571b0f0ef39e77934b5 (patch)
tree54312412f1a9253360db901877e8b51991777562
parente60a9de49c3744aa44128eaaed3aca965911ca2e (diff)
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>
-rw-r--r--include/net/netfilter/nf_tables.h2
-rw-r--r--net/bridge/netfilter/nft_meta_bridge.c5
-rw-r--r--net/netfilter/nf_tables_api.c18
-rw-r--r--net/netfilter/nft_bitwise.c8
-rw-r--r--net/netfilter/nft_byteorder.c27
-rw-r--r--net/netfilter/nft_ct.c48
-rw-r--r--net/netfilter/nft_exthdr.c6
-rw-r--r--net/netfilter/nft_immediate.c3
-rw-r--r--net/netfilter/nft_meta.c19
-rw-r--r--net/netfilter/nft_payload.c7
10 files changed, 97 insertions, 46 deletions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index d6a2f0ed5130..f491243ff58b 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -116,7 +116,7 @@ int nft_validate_input_register(enum nft_registers reg);
116int nft_validate_output_register(enum nft_registers reg); 116int nft_validate_output_register(enum nft_registers reg);
117int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg, 117int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg,
118 const struct nft_data *data, 118 const struct nft_data *data,
119 enum nft_data_types type); 119 enum nft_data_types type, unsigned int len);
120 120
121 121
122/** 122/**
diff --git a/net/bridge/netfilter/nft_meta_bridge.c b/net/bridge/netfilter/nft_meta_bridge.c
index 4f02109d708f..2011b89690f7 100644
--- a/net/bridge/netfilter/nft_meta_bridge.c
+++ b/net/bridge/netfilter/nft_meta_bridge.c
@@ -53,12 +53,14 @@ static int nft_meta_bridge_get_init(const struct nft_ctx *ctx,
53 const struct nlattr * const tb[]) 53 const struct nlattr * const tb[])
54{ 54{
55 struct nft_meta *priv = nft_expr_priv(expr); 55 struct nft_meta *priv = nft_expr_priv(expr);
56 unsigned int len;
56 int err; 57 int err;
57 58
58 priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); 59 priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
59 switch (priv->key) { 60 switch (priv->key) {
60 case NFT_META_BRI_IIFNAME: 61 case NFT_META_BRI_IIFNAME:
61 case NFT_META_BRI_OIFNAME: 62 case NFT_META_BRI_OIFNAME:
63 len = IFNAMSIZ;
62 break; 64 break;
63 default: 65 default:
64 return nft_meta_get_init(ctx, expr, tb); 66 return nft_meta_get_init(ctx, expr, tb);
@@ -69,7 +71,8 @@ static int nft_meta_bridge_get_init(const struct nft_ctx *ctx,
69 if (err < 0) 71 if (err < 0)
70 return err; 72 return err;
71 73
72 err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); 74 err = nft_validate_data_load(ctx, priv->dreg, NULL,
75 NFT_DATA_VALUE, len);
73 if (err < 0) 76 if (err < 0)
74 return err; 77 return err;
75 78
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 0b96fa0d64b2..564f9ed6680d 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2799,7 +2799,8 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
2799 dreg = nft_type_to_reg(set->dtype); 2799 dreg = nft_type_to_reg(set->dtype);
2800 return nft_validate_data_load(ctx, dreg, nft_set_ext_data(ext), 2800 return nft_validate_data_load(ctx, dreg, nft_set_ext_data(ext),
2801 set->dtype == NFT_DATA_VERDICT ? 2801 set->dtype == NFT_DATA_VERDICT ?
2802 NFT_DATA_VERDICT : NFT_DATA_VALUE); 2802 NFT_DATA_VERDICT : NFT_DATA_VALUE,
2803 set->dlen);
2803} 2804}
2804 2805
2805int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set, 2806int 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,
3334 continue; 3335 continue;
3335 3336
3336 err = nft_validate_data_load(&bind_ctx, dreg, 3337 err = nft_validate_data_load(&bind_ctx, dreg,
3337 &data, d2.type); 3338 &data, d2.type, d2.len);
3338 if (err < 0) 3339 if (err < 0)
3339 goto err3; 3340 goto err3;
3340 } 3341 }
@@ -4162,15 +4163,16 @@ EXPORT_SYMBOL_GPL(nft_validate_output_register);
4162 * @reg: the destination register number 4163 * @reg: the destination register number
4163 * @data: the data to load 4164 * @data: the data to load
4164 * @type: the data type 4165 * @type: the data type
4166 * @len: the length of the data
4165 * 4167 *
4166 * Validate that a data load uses the appropriate data type for 4168 * Validate that a data load uses the appropriate data type for
4167 * the destination register. A value of NULL for the data means 4169 * the destination register and the length is within the bounds.
4168 * that its runtime gathered data, which is always of type 4170 * A value of NULL for the data means that its runtime gathered
4169 * NFT_DATA_VALUE. 4171 * data, which is always of type NFT_DATA_VALUE.
4170 */ 4172 */
4171int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg, 4173int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg,
4172 const struct nft_data *data, 4174 const struct nft_data *data,
4173 enum nft_data_types type) 4175 enum nft_data_types type, unsigned int len)
4174{ 4176{
4175 int err; 4177 int err;
4176 4178
@@ -4193,6 +4195,10 @@ int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg,
4193 4195
4194 return 0; 4196 return 0;
4195 default: 4197 default:
4198 if (len == 0)
4199 return -EINVAL;
4200 if (len > FIELD_SIZEOF(struct nft_data, data))
4201 return -ERANGE;
4196 if (data != NULL && type != NFT_DATA_VALUE) 4202 if (data != NULL && type != NFT_DATA_VALUE)
4197 return -EINVAL; 4203 return -EINVAL;
4198 return 0; 4204 return 0;
diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c
index 4fb6ee2c1106..fcd951f24779 100644
--- a/net/netfilter/nft_bitwise.c
+++ b/net/netfilter/nft_bitwise.c
@@ -63,6 +63,8 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
63 tb[NFTA_BITWISE_XOR] == NULL) 63 tb[NFTA_BITWISE_XOR] == NULL)
64 return -EINVAL; 64 return -EINVAL;
65 65
66 priv->len = ntohl(nla_get_be32(tb[NFTA_BITWISE_LEN]));
67
66 priv->sreg = ntohl(nla_get_be32(tb[NFTA_BITWISE_SREG])); 68 priv->sreg = ntohl(nla_get_be32(tb[NFTA_BITWISE_SREG]));
67 err = nft_validate_input_register(priv->sreg); 69 err = nft_validate_input_register(priv->sreg);
68 if (err < 0) 70 if (err < 0)
@@ -72,12 +74,12 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
72 err = nft_validate_output_register(priv->dreg); 74 err = nft_validate_output_register(priv->dreg);
73 if (err < 0) 75 if (err < 0)
74 return err; 76 return err;
75 err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); 77
78 err = nft_validate_data_load(ctx, priv->dreg, NULL,
79 NFT_DATA_VALUE, priv->len);
76 if (err < 0) 80 if (err < 0)
77 return err; 81 return err;
78 82
79 priv->len = ntohl(nla_get_be32(tb[NFTA_BITWISE_LEN]));
80
81 err = nft_data_init(NULL, &priv->mask, &d1, tb[NFTA_BITWISE_MASK]); 83 err = nft_data_init(NULL, &priv->mask, &d1, tb[NFTA_BITWISE_MASK]);
82 if (err < 0) 84 if (err < 0)
83 return err; 85 return err;
diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
index c39ed8d29df1..183f13308c94 100644
--- a/net/netfilter/nft_byteorder.c
+++ b/net/netfilter/nft_byteorder.c
@@ -87,19 +87,6 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
87 tb[NFTA_BYTEORDER_OP] == NULL) 87 tb[NFTA_BYTEORDER_OP] == NULL)
88 return -EINVAL; 88 return -EINVAL;
89 89
90 priv->sreg = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_SREG]));
91 err = nft_validate_input_register(priv->sreg);
92 if (err < 0)
93 return err;
94
95 priv->dreg = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_DREG]));
96 err = nft_validate_output_register(priv->dreg);
97 if (err < 0)
98 return err;
99 err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE);
100 if (err < 0)
101 return err;
102
103 priv->op = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_OP])); 90 priv->op = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_OP]));
104 switch (priv->op) { 91 switch (priv->op) {
105 case NFT_BYTEORDER_NTOH: 92 case NFT_BYTEORDER_NTOH:
@@ -122,6 +109,20 @@ static int nft_by