Skip to content

Commit d07db98

Browse files
kaberummakynes
authored andcommitted
netfilter: nf_tables: introduce nft_validate_register_load()
Change nft_validate_input_register() to not only validate the input register number, but also the length of the load, and rename it to nft_validate_register_load() to reflect that change. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent 27e6d20 commit d07db98

File tree

11 files changed

+62
-40
lines changed

11 files changed

+62
-40
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,12 @@ static inline enum nft_registers nft_type_to_reg(enum nft_data_types type)
112112
return type == NFT_DATA_VERDICT ? NFT_REG_VERDICT : NFT_REG_1;
113113
}
114114

115-
int nft_validate_input_register(enum nft_registers reg);
115+
int nft_validate_register_load(enum nft_registers reg, unsigned int len);
116116
int nft_validate_register_store(const struct nft_ctx *ctx,
117117
enum nft_registers reg,
118118
const struct nft_data *data,
119119
enum nft_data_types type, unsigned int len);
120120

121-
122121
/**
123122
* struct nft_userdata - user defined data associated with an object
124123
*

net/netfilter/nf_tables_api.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4122,22 +4122,27 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
41224122
}
41234123

41244124
/**
4125-
* nft_validate_input_register - validate an expressions' input register
4125+
* nft_validate_register_load - validate a load from a register
41264126
*
41274127
* @reg: the register number
4128+
* @len: the length of the data
41284129
*
41294130
* Validate that the input register is one of the general purpose
4130-
* registers.
4131+
* registers and that the length of the load is within the bounds.
41314132
*/
4132-
int nft_validate_input_register(enum nft_registers reg)
4133+
int nft_validate_register_load(enum nft_registers reg, unsigned int len)
41334134
{
41344135
if (reg <= NFT_REG_VERDICT)
41354136
return -EINVAL;
41364137
if (reg > NFT_REG_MAX)
41374138
return -ERANGE;
4139+
if (len == 0)
4140+
return -EINVAL;
4141+
if (len > FIELD_SIZEOF(struct nft_data, data))
4142+
return -ERANGE;
41384143
return 0;
41394144
}
4140-
EXPORT_SYMBOL_GPL(nft_validate_input_register);
4145+
EXPORT_SYMBOL_GPL(nft_validate_register_load);
41414146

41424147
/**
41434148
* nft_validate_register_store - validate an expressions' register store

net/netfilter/nft_bitwise.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,9 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
6363
tb[NFTA_BITWISE_XOR] == NULL)
6464
return -EINVAL;
6565

66-
priv->len = ntohl(nla_get_be32(tb[NFTA_BITWISE_LEN]));
67-
66+
priv->len = ntohl(nla_get_be32(tb[NFTA_BITWISE_LEN]));
6867
priv->sreg = ntohl(nla_get_be32(tb[NFTA_BITWISE_SREG]));
69-
err = nft_validate_input_register(priv->sreg);
68+
err = nft_validate_register_load(priv->sreg, priv->len);
7069
if (err < 0)
7170
return err;
7271

net/netfilter/nft_byteorder.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,6 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
9696
return -EINVAL;
9797
}
9898

99-
priv->len = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_LEN]));
100-
if (priv->len == 0 || priv->len > FIELD_SIZEOF(struct nft_data, data))
101-
return -EINVAL;
102-
10399
priv->size = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_SIZE]));
104100
switch (priv->size) {
105101
case 2:
@@ -110,7 +106,8 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
110106
}
111107

112108
priv->sreg = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_SREG]));
113-
err = nft_validate_input_register(priv->sreg);
109+
priv->len = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_LEN]));
110+
err = nft_validate_register_load(priv->sreg, priv->len);
114111
if (err < 0)
115112
return err;
116113

net/netfilter/nft_cmp.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,15 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
7575
struct nft_data_desc desc;
7676
int err;
7777

78-
priv->sreg = ntohl(nla_get_be32(tb[NFTA_CMP_SREG]));
79-
priv->op = ntohl(nla_get_be32(tb[NFTA_CMP_OP]));
80-
8178
err = nft_data_init(NULL, &priv->data, &desc, tb[NFTA_CMP_DATA]);
8279
BUG_ON(err < 0);
8380

81+
priv->sreg = ntohl(nla_get_be32(tb[NFTA_CMP_SREG]));
82+
err = nft_validate_register_load(priv->sreg, desc.len);
83+
if (err < 0)
84+
return err;
85+
86+
priv->op = ntohl(nla_get_be32(tb[NFTA_CMP_OP]));
8487
priv->len = desc.len;
8588
return 0;
8689
}
@@ -122,13 +125,17 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx,
122125
u32 mask;
123126
int err;
124127

125-
priv->sreg = ntohl(nla_get_be32(tb[NFTA_CMP_SREG]));
126-
127128
err = nft_data_init(NULL, &data, &desc, tb[NFTA_CMP_DATA]);
128129
BUG_ON(err < 0);
129-
desc.len *= BITS_PER_BYTE;
130130

131+
priv->sreg = ntohl(nla_get_be32(tb[NFTA_CMP_SREG]));
132+
err = nft_validate_register_load(priv->sreg, desc.len);
133+
if (err < 0)
134+
return err;
135+
136+
desc.len *= BITS_PER_BYTE;
131137
mask = nft_cmp_fast_mask(desc.len);
138+
132139
priv->data = data.data[0] & mask;
133140
priv->len = desc.len;
134141
return 0;
@@ -167,7 +174,6 @@ nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[])
167174
{
168175
struct nft_data_desc desc;
169176
struct nft_data data;
170-
enum nft_registers sreg;
171177
enum nft_cmp_ops op;
172178
int err;
173179

@@ -176,11 +182,6 @@ nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[])
176182
tb[NFTA_CMP_DATA] == NULL)
177183
return ERR_PTR(-EINVAL);
178184

179-
sreg = ntohl(nla_get_be32(tb[NFTA_CMP_SREG]));
180-
err = nft_validate_input_register(sreg);
181-
if (err < 0)
182-
return ERR_PTR(err);
183-
184185
op = ntohl(nla_get_be32(tb[NFTA_CMP_OP]));
185186
switch (op) {
186187
case NFT_CMP_EQ:

net/netfilter/nft_ct.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,20 +324,22 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
324324
const struct nlattr * const tb[])
325325
{
326326
struct nft_ct *priv = nft_expr_priv(expr);
327+
unsigned int len;
327328
int err;
328329

329330
priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY]));
330331
switch (priv->key) {
331332
#ifdef CONFIG_NF_CONNTRACK_MARK
332333
case NFT_CT_MARK:
334+
len = FIELD_SIZEOF(struct nf_conn, mark);
333335
break;
334336
#endif
335337
default:
336338
return -EOPNOTSUPP;
337339
}
338340

339341
priv->sreg = ntohl(nla_get_be32(tb[NFTA_CT_SREG]));
340-
err = nft_validate_input_register(priv->sreg);
342+
err = nft_validate_register_load(priv->sreg, len);
341343
if (err < 0)
342344
return err;
343345

net/netfilter/nft_dynset.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
124124
}
125125

126126
priv->sreg_key = ntohl(nla_get_be32(tb[NFTA_DYNSET_SREG_KEY]));
127-
err = nft_validate_input_register(priv->sreg_key);
127+
err = nft_validate_register_load(priv->sreg_key, set->klen);;
128128
if (err < 0)
129129
return err;
130130

@@ -135,7 +135,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
135135
return -EOPNOTSUPP;
136136

137137
priv->sreg_data = ntohl(nla_get_be32(tb[NFTA_DYNSET_SREG_DATA]));
138-
err = nft_validate_input_register(priv->sreg_data);
138+
err = nft_validate_register_load(priv->sreg_data, set->dlen);
139139
if (err < 0)
140140
return err;
141141
} else if (set->flags & NFT_SET_MAP)

net/netfilter/nft_lookup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
7171
}
7272

7373
priv->sreg = ntohl(nla_get_be32(tb[NFTA_LOOKUP_SREG]));
74-
err = nft_validate_input_register(priv->sreg);
74+
err = nft_validate_register_load(priv->sreg, set->klen);
7575
if (err < 0)
7676
return err;
7777

net/netfilter/nft_meta.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,20 +267,24 @@ int nft_meta_set_init(const struct nft_ctx *ctx,
267267
const struct nlattr * const tb[])
268268
{
269269
struct nft_meta *priv = nft_expr_priv(expr);
270+
unsigned int len;
270271
int err;
271272

272273
priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
273274
switch (priv->key) {
274275
case NFT_META_MARK:
275276
case NFT_META_PRIORITY:
277+
len = sizeof(u32);
278+
break;
276279
case NFT_META_NFTRACE:
280+
len = sizeof(u8);
277281
break;
278282
default:
279283
return -EOPNOTSUPP;
280284
}
281285

282286
priv->sreg = ntohl(nla_get_be32(tb[NFTA_META_SREG]));
283-
err = nft_validate_input_register(priv->sreg);
287+
err = nft_validate_register_load(priv->sreg, len);
284288
if (err < 0)
285289
return err;
286290

net/netfilter/nft_nat.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
119119
const struct nlattr * const tb[])
120120
{
121121
struct nft_nat *priv = nft_expr_priv(expr);
122+
unsigned int alen, plen;
122123
u32 family;
123124
int err;
124125

@@ -146,45 +147,56 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
146147
return -EINVAL;
147148

148149
family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY]));
149-
if (family != AF_INET && family != AF_INET6)
150-
return -EAFNOSUPPORT;
151150
if (family != ctx->afi->family)
152151
return -EOPNOTSUPP;
152+
153+
switch (family) {
154+
case NFPROTO_IPV4:
155+
alen = FIELD_SIZEOF(struct nf_nat_range, min_addr.ip);
156+
break;
157+
case NFPROTO_IPV6:
158+
alen = FIELD_SIZEOF(struct nf_nat_range, min_addr.ip6);
159+
break;
160+
default:
161+
return -EAFNOSUPPORT;
162+
}
153163
priv->family = family;
154164

155165
if (tb[NFTA_NAT_REG_ADDR_MIN]) {
156166
priv->sreg_addr_min =
157167
ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MIN]));
158-
159-
err = nft_validate_input_register(priv->sreg_addr_min);
168+
err = nft_validate_register_load(priv->sreg_addr_min, alen);
160169
if (err < 0)
161170
return err;
162171

163172
if (tb[NFTA_NAT_REG_ADDR_MAX]) {
164173
priv->sreg_addr_max =
165174
ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MAX]));
166175

167-
err = nft_validate_input_register(priv->sreg_addr_max);
176+
err = nft_validate_register_load(priv->sreg_addr_max,
177+
alen);
168178
if (err < 0)
169179
return err;
170180
} else {
171181
priv->sreg_addr_max = priv->sreg_addr_min;
172182
}
173183
}
174184

185+
plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);
175186
if (tb[NFTA_NAT_REG_PROTO_MIN]) {
176187
priv->sreg_proto_min =
177188
ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MIN]));
178189

179-
err = nft_validate_input_register(priv->sreg_proto_min);
190+
err = nft_validate_register_load(priv->sreg_proto_min, plen);
180191
if (err < 0)
181192
return err;
182193

183194
if (tb[NFTA_NAT_REG_PROTO_MAX]) {
184195
priv->sreg_proto_max =
185196
ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MAX]));
186197

187-
err = nft_validate_input_register(priv->sreg_proto_max);
198+
err = nft_validate_register_load(priv->sreg_proto_max,
199+
plen);
188200
if (err < 0)
189201
return err;
190202
} else {

0 commit comments

Comments
 (0)